+
+ getEl: function() {
+ if (!this._domRef) {
+ this._domRef = Ext.getDom(this.id);
+ }
+
+ return this._domRef;
+ },
+
+
+ getDragEl: function() {
+ return Ext.getDom(this.dragElId);
+ },
+
+
+ init: function(id, sGroup, config) {
+ this.initTarget(id, sGroup, config);
+ Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this);
+
+ },
+
+
+ initTarget: function(id, sGroup, config) {
+
+
+ this.config = config || {};
+
+
+ this.DDMInstance = Ext.dd.DragDropManager;
+
+ this.groups = {};
+
+
+
+ if (typeof id !== "string") {
+ id = Ext.id(id);
+ }
+
+
+ this.id = id;
+
+
+ this.addToGroup((sGroup) ? sGroup : "default");
+
+
+
+ this.handleElId = id;
+
+
+ this.setDragElId(id);
+
+
+ this.invalidHandleTypes = { A: "A" };
+ this.invalidHandleIds = {};
+ this.invalidHandleClasses = [];
+
+ this.applyConfig();
+
+ this.handleOnAvailable();
+ },
+
+
+ applyConfig: function() {
+
+
+
+ this.padding = this.config.padding || [0, 0, 0, 0];
+ this.isTarget = (this.config.isTarget !== false);
+ this.maintainOffset = (this.config.maintainOffset);
+ this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
+
+ },
+
+
+ handleOnAvailable: function() {
+ this.available = true;
+ this.resetConstraints();
+ this.onAvailable();
+ },
+
+
+ setPadding: function(iTop, iRight, iBot, iLeft) {
+
+ if (!iRight && 0 !== iRight) {
+ this.padding = [iTop, iTop, iTop, iTop];
+ } else if (!iBot && 0 !== iBot) {
+ this.padding = [iTop, iRight, iTop, iRight];
+ } else {
+ this.padding = [iTop, iRight, iBot, iLeft];
+ }
+ },
+
+
+ setInitPosition: function(diffX, diffY) {
+ var el = this.getEl();
+
+ if (!this.DDMInstance.verifyEl(el)) {
+ return;
+ }
+
+ var dx = diffX || 0;
+ var dy = diffY || 0;
+
+ var p = Ext.core.Element.getXY( el );
+
+ this.initPageX = p[0] - dx;
+ this.initPageY = p[1] - dy;
+
+ this.lastPageX = p[0];
+ this.lastPageY = p[1];
+
+ this.setStartPosition(p);
+ },
+
+
+ setStartPosition: function(pos) {
+ var p = pos || Ext.core.Element.getXY( this.getEl() );
+ this.deltaSetXY = null;
+
+ this.startPageX = p[0];
+ this.startPageY = p[1];
+ },
+
+
+ addToGroup: function(sGroup) {
+ this.groups[sGroup] = true;
+ this.DDMInstance.regDragDrop(this, sGroup);
+ },
+
+
+ removeFromGroup: function(sGroup) {
+ if (this.groups[sGroup]) {
+ delete this.groups[sGroup];
+ }
+
+ this.DDMInstance.removeDDFromGroup(this, sGroup);
+ },
+
+
+ setDragElId: function(id) {
+ this.dragElId = id;
+ },
+
+
+ setHandleElId: function(id) {
+ if (typeof id !== "string") {
+ id = Ext.id(id);
+ }
+ this.handleElId = id;
+ this.DDMInstance.regHandle(this.id, id);
+ },
+
+
+ setOuterHandleElId: function(id) {
+ if (typeof id !== "string") {
+ id = Ext.id(id);
+ }
+ Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this);
+ this.setHandleElId(id);
+
+ this.hasOuterHandles = true;
+ },
+
+
+ unreg: function() {
+ Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
+ this._domRef = null;
+ this.DDMInstance._remove(this);
+ },
+
+ destroy : function(){
+ this.unreg();
+ },
+
+
+ isLocked: function() {
+ return (this.DDMInstance.isLocked() || this.locked);
+ },
+
+
+ handleMouseDown: function(e, oDD){
+ if (this.primaryButtonOnly && e.button != 0) {
+ return;
+ }
+
+ if (this.isLocked()) {
+ return;
+ }
+
+ this.DDMInstance.refreshCache(this.groups);
+
+ var pt = e.getPoint();
+ if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) ) {
+ } else {
+ if (this.clickValidator(e)) {
+
+ this.setStartPosition();
+ this.b4MouseDown(e);
+ this.onMouseDown(e);
+
+ this.DDMInstance.handleMouseDown(e, this);
+
+ this.DDMInstance.stopEvent(e);
+ } else {
+
+
+ }
+ }
+ },
+
+ clickValidator: function(e) {
+ var target = e.getTarget();
+ return ( this.isValidHandleChild(target) &&
+ (this.id == this.handleElId ||
+ this.DDMInstance.handleWasClicked(target, this.id)) );
+ },
+
+
+ addInvalidHandleType: function(tagName) {
+ var type = tagName.toUpperCase();
+ this.invalidHandleTypes[type] = type;
+ },
+
+
+ addInvalidHandleId: function(id) {
+ if (typeof id !== "string") {
+ id = Ext.id(id);
+ }
+ this.invalidHandleIds[id] = id;
+ },
+
+
+ addInvalidHandleClass: function(cssClass) {
+ this.invalidHandleClasses.push(cssClass);
+ },
+
+
+ removeInvalidHandleType: function(tagName) {
+ var type = tagName.toUpperCase();
+
+ delete this.invalidHandleTypes[type];
+ },
+
+
+ removeInvalidHandleId: function(id) {
+ if (typeof id !== "string") {
+ id = Ext.id(id);
+ }
+ delete this.invalidHandleIds[id];
+ },
+
+
+ removeInvalidHandleClass: function(cssClass) {
+ for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
+ if (this.invalidHandleClasses[i] == cssClass) {
+ delete this.invalidHandleClasses[i];
+ }
+ }
+ },
+
+
+ isValidHandleChild: function(node) {
+
+ var valid = true;
+
+ var nodeName;
+ try {
+ nodeName = node.nodeName.toUpperCase();
+ } catch(e) {
+ nodeName = node.nodeName;
+ }
+ valid = valid && !this.invalidHandleTypes[nodeName];
+ valid = valid && !this.invalidHandleIds[node.id];
+
+ for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
+ valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
+ }
+
+
+ return valid;
+
+ },
+
+
+ setXTicks: function(iStartX, iTickSize) {
+ this.xTicks = [];
+ this.xTickSize = iTickSize;
+
+ var tickMap = {};
+
+ for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
+ if (!tickMap[i]) {
+ this.xTicks[this.xTicks.length] = i;
+ tickMap[i] = true;
+ }
+ }
+
+ for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
+ if (!tickMap[i]) {
+ this.xTicks[this.xTicks.length] = i;
+ tickMap[i] = true;
+ }
+ }
+
+ Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort);
+ },
+
+
+ setYTicks: function(iStartY, iTickSize) {
+ this.yTicks = [];
+ this.yTickSize = iTickSize;
+
+ var tickMap = {};
+
+ for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
+ if (!tickMap[i]) {
+ this.yTicks[this.yTicks.length] = i;
+ tickMap[i] = true;
+ }
+ }
+
+ for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
+ if (!tickMap[i]) {
+ this.yTicks[this.yTicks.length] = i;
+ tickMap[i] = true;
+ }
+ }
+
+ Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort);
+ },
+
+
+ setXConstraint: function(iLeft, iRight, iTickSize) {
+ this.leftConstraint = iLeft;
+ this.rightConstraint = iRight;
+
+ this.minX = this.initPageX - iLeft;
+ this.maxX = this.initPageX + iRight;
+ if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
+
+ this.constrainX = true;
+ },
+
+
+ clearConstraints: function() {
+ this.constrainX = false;
+ this.constrainY = false;
+ this.clearTicks();
+ },
+
+
+ clearTicks: function() {
+ this.xTicks = null;
+ this.yTicks = null;
+ this.xTickSize = 0;
+ this.yTickSize = 0;
+ },
+
+
+ setYConstraint: function(iUp, iDown, iTickSize) {
+ this.topConstraint = iUp;
+ this.bottomConstraint = iDown;
+
+ this.minY = this.initPageY - iUp;
+ this.maxY = this.initPageY + iDown;
+ if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
+
+ this.constrainY = true;
+
+ },
+
+
+ resetConstraints: function() {
+
+ if (this.initPageX || this.initPageX === 0) {
+
+ var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
+ var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
+
+ this.setInitPosition(dx, dy);
+
+
+ } else {
+ this.setInitPosition();
+ }
+
+ if (this.constrainX) {
+ this.setXConstraint( this.leftConstraint,
+ this.rightConstraint,
+ this.xTickSize );
+ }
+
+ if (this.constrainY) {
+ this.setYConstraint( this.topConstraint,
+ this.bottomConstraint,
+ this.yTickSize );
+ }
+ },
+
+
+ getTick: function(val, tickArray) {
+ if (!tickArray) {
+
+
+ return val;
+ } else if (tickArray[0] >= val) {
+
+
+ return tickArray[0];
+ } else {
+ for (var i=0, len=tickArray.length; i<len; ++i) {
+ var next = i + 1;
+ if (tickArray[next] && tickArray[next] >= val) {
+ var diff1 = val - tickArray[i];
+ var diff2 = tickArray[next] - val;
+ return (diff2 > diff1) ? tickArray[i] : tickArray[next];
+ }
+ }
+
+
+
+ return tickArray[tickArray.length - 1];
+ }
+ },
+
+
+ toString: function() {
+ return ("DragDrop " + this.id);
+ }
+
+});
+
+
+
+
+
+Ext.define('Ext.dd.DD', {
+ extend: 'Ext.dd.DragDrop',
+ requires: ['Ext.dd.DragDropManager'],
+ constructor: function(id, sGroup, config) {
+ if (id) {
+ this.init(id, sGroup, config);
+ }
+ },
+
+
+ scroll: true,
+
+
+ autoOffset: function(iPageX, iPageY) {
+ var x = iPageX - this.startPageX;
+ var y = iPageY - this.startPageY;
+ this.setDelta(x, y);
+ },
+
+
+ setDelta: function(iDeltaX, iDeltaY) {
+ this.deltaX = iDeltaX;
+ this.deltaY = iDeltaY;
+ },
+
+
+ setDragElPos: function(iPageX, iPageY) {
+
+
+
+ var el = this.getDragEl();
+ this.alignElWithMouse(el, iPageX, iPageY);
+ },
+
+
+ alignElWithMouse: function(el, iPageX, iPageY) {
+ var oCoord = this.getTargetCoord(iPageX, iPageY),
+ fly = el.dom ? el : Ext.fly(el, '_dd'),
+ elSize = fly.getSize(),
+ EL = Ext.core.Element,
+ vpSize;
+
+ if (!this.deltaSetXY) {
+ vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
+ var aCoord = [
+ Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
+ Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
+ ];
+ fly.setXY(aCoord);
+ var newLeft = fly.getLeft(true);
+ var newTop = fly.getTop(true);
+ this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
+ } else {
+ vpSize = this.cachedViewportSize;
+ fly.setLeftTop(
+ Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)),
+ Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height))
+ );
+ }
+
+ this.cachePosition(oCoord.x, oCoord.y);
+ this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
+ return oCoord;
+ },
+
+
+ cachePosition: function(iPageX, iPageY) {
+ if (iPageX) {
+ this.lastPageX = iPageX;
+ this.lastPageY = iPageY;
+ } else {
+ var aCoord = Ext.core.Element.getXY(this.getEl());
+ this.lastPageX = aCoord[0];
+ this.lastPageY = aCoord[1];
+ }
+ },
+
+
+ autoScroll: function(x, y, h, w) {
+
+ if (this.scroll) {
+
+ var clientH = Ext.core.Element.getViewHeight();
+
+
+ var clientW = Ext.core.Element.getViewWidth();
+
+
+ var st = this.DDMInstance.getScrollTop();
+
+
+ var sl = this.DDMInstance.getScrollLeft();
+
+
+ var bot = h + y;
+
+
+ var right = w + x;
+
+
+
+
+ var toBot = (clientH + st - y - this.deltaY);
+
+
+ var toRight = (clientW + sl - x - this.deltaX);
+
+
+
+
+ var thresh = 40;
+
+
+
+
+ var scrAmt = (document.all) ? 80 : 30;
+
+
+
+ if ( bot > clientH && toBot < thresh ) {
+ window.scrollTo(sl, st + scrAmt);
+ }
+
+
+
+ if ( y < st && st > 0 && y - st < thresh ) {
+ window.scrollTo(sl, st - scrAmt);
+ }
+
+
+
+ if ( right > clientW && toRight < thresh ) {
+ window.scrollTo(sl + scrAmt, st);
+ }
+
+
+
+ if ( x < sl && sl > 0 && x - sl < thresh ) {
+ window.scrollTo(sl - scrAmt, st);
+ }
+ }
+ },
+
+
+ getTargetCoord: function(iPageX, iPageY) {
+ var x = iPageX - this.deltaX;
+ var y = iPageY - this.deltaY;
+
+ if (this.constrainX) {
+ if (x < this.minX) {
+ x = this.minX;
+ }
+ if (x > this.maxX) {
+ x = this.maxX;
+ }
+ }
+
+ if (this.constrainY) {
+ if (y < this.minY) {
+ y = this.minY;
+ }
+ if (y > this.maxY) {
+ y = this.maxY;
+ }
+ }
+
+ x = this.getTick(x, this.xTicks);
+ y = this.getTick(y, this.yTicks);
+
+
+ return {x: x, y: y};
+ },
+
+
+ applyConfig: function() {
+ this.callParent();
+ this.scroll = (this.config.scroll !== false);
+ },
+
+
+ b4MouseDown: function(e) {
+
+ this.autoOffset(e.getPageX(), e.getPageY());
+ },
+
+
+ b4Drag: function(e) {
+ this.setDragElPos(e.getPageX(), e.getPageY());
+ },
+
+ toString: function() {
+ return ("DD " + this.id);
+ }
+
+
+
+
+
+
+});
+
+
+
+
+Ext.define('Ext.dd.DDProxy', {
+ extend: 'Ext.dd.DD',
+
+ statics: {
+
+ dragElId: "ygddfdiv"
+ },
+
+ constructor: function(id, sGroup, config) {
+ if (id) {
+ this.init(id, sGroup, config);
+ this.initFrame();
+ }
+ },
+
+
+ resizeFrame: true,
+
+
+ centerFrame: false,
+
+
+ createFrame: function() {
+ var self = this;
+ var body = document.body;
+
+ if (!body || !body.firstChild) {
+ setTimeout( function() { self.createFrame(); }, 50 );
+ return;
+ }
+
+ var div = this.getDragEl();
+
+ if (!div) {
+ div = document.createElement("div");
+ div.id = this.dragElId;
+ var s = div.style;
+
+ s.position = "absolute";
+ s.visibility = "hidden";
+ s.cursor = "move";
+ s.border = "2px solid #aaa";
+ s.zIndex = 999;
+
+
+
+
+ body.insertBefore(div, body.firstChild);
+ }
+ },
+
+
+ initFrame: function() {
+ this.createFrame();
+ },
+
+ applyConfig: function() {
+ this.callParent();
+
+ this.resizeFrame = (this.config.resizeFrame !== false);
+ this.centerFrame = (this.config.centerFrame);
+ this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
+ },
+
+
+ showFrame: function(iPageX, iPageY) {
+ var el = this.getEl();
+ var dragEl = this.getDragEl();
+ var s = dragEl.style;
+
+ this._resizeProxy();
+
+ if (this.centerFrame) {
+ this.setDelta( Math.round(parseInt(s.width, 10)/2),
+ Math.round(parseInt(s.height, 10)/2) );
+ }
+
+ this.setDragElPos(iPageX, iPageY);
+
+ Ext.fly(dragEl).show();
+ },
+
+
+ _resizeProxy: function() {
+ if (this.resizeFrame) {
+ var el = this.getEl();
+ Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
+ }
+ },
+
+
+ b4MouseDown: function(e) {
+ var x = e.getPageX();
+ var y = e.getPageY();
+ this.autoOffset(x, y);
+ this.setDragElPos(x, y);
+ },
+
+
+ b4StartDrag: function(x, y) {
+
+ this.showFrame(x, y);
+ },
+
+
+ b4EndDrag: function(e) {
+ Ext.fly(this.getDragEl()).hide();
+ },
+
+
+
+
+ endDrag: function(e) {
+
+ var lel = this.getEl();
+ var del = this.getDragEl();
+
+
+ del.style.visibility = "";
+
+ this.beforeMove();
+
+
+ lel.style.visibility = "hidden";
+ Ext.dd.DDM.moveToEl(lel, del);
+ del.style.visibility = "hidden";
+ lel.style.visibility = "";
+
+ this.afterDrag();
+ },
+
+ beforeMove : function(){
+
+ },
+
+ afterDrag : function(){
+
+ },
+
+ toString: function() {
+ return ("DDProxy " + this.id);
+ }
+
+});
+
+
+Ext.define('Ext.dd.DragSource', {
+ extend: 'Ext.dd.DDProxy',
+ requires: [
+ 'Ext.dd.StatusProxy',
+ 'Ext.dd.DragDropManager'
+ ],
+
+
+
+
+
+ dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
+
+ dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
+
+
+ animRepair: true,
+
+
+ repairHighlightColor: 'c3daf9',
+
+ constructor: function(el, config) {
+ this.el = Ext.get(el);
+ if(!this.dragData){
+ this.dragData = {};
+ }
+
+ Ext.apply(this, config);
+
+ if(!this.proxy){
+ this.proxy = Ext.create('Ext.dd.StatusProxy', {
+ animRepair: this.animRepair
+ });
+ }
+ this.callParent([this.el.dom, this.ddGroup || this.group,
+ {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true}]);
+
+ this.dragging = false;
+ },
+
+
+ getDragData : function(e){
+ return this.dragData;
+ },
+
+
+ onDragEnter : function(e, id){
+ var target = Ext.dd.DragDropManager.getDDById(id);
+ this.cachedTarget = target;
+ if (this.beforeDragEnter(target, e, id) !== false) {
+ if (target.isNotifyTarget) {
+ var status = target.notifyEnter(this, e, this.dragData);
+ this.proxy.setStatus(status);
+ } else {
+ this.proxy.setStatus(this.dropAllowed);
+ }
+
+ if (this.afterDragEnter) {
+
+ this.afterDragEnter(target, e, id);
+ }
+ }
+ },
+
+
+ beforeDragEnter: function(target, e, id) {
+ return true;
+ },
+
+
+ alignElWithMouse: function() {
+ this.callParent(arguments);
+ this.proxy.sync();
+ },
+
+
+ onDragOver: function(e, id) {
+ var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+ if (this.beforeDragOver(target, e, id) !== false) {
+ if(target.isNotifyTarget){
+ var status = target.notifyOver(this, e, this.dragData);
+ this.proxy.setStatus(status);
+ }
+
+ if (this.afterDragOver) {
+
+ this.afterDragOver(target, e, id);
+ }
+ }
+ },
+
+
+ beforeDragOver: function(target, e, id) {
+ return true;
+ },
+
+
+ onDragOut: function(e, id) {
+ var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+ if (this.beforeDragOut(target, e, id) !== false) {
+ if (target.isNotifyTarget) {
+ target.notifyOut(this, e, this.dragData);
+ }
+ this.proxy.reset();
+ if (this.afterDragOut) {
+
+ this.afterDragOut(target, e, id);
+ }
+ }
+ this.cachedTarget = null;
+ },
+
+
+ beforeDragOut: function(target, e, id){
+ return true;
+ },
+
+
+ onDragDrop: function(e, id){
+ var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+ if (this.beforeDragDrop(target, e, id) !== false) {
+ if (target.isNotifyTarget) {
+ if (target.notifyDrop(this, e, this.dragData) !== false) {
+ this.onValidDrop(target, e, id);
+ } else {
+ this.onInvalidDrop(target, e, id);
+ }
+ } else {
+ this.onValidDrop(target, e, id);
+ }
+
+ if (this.afterDragDrop) {
+
+ this.afterDragDrop(target, e, id);
+ }
+ }
+ delete this.cachedTarget;
+ },
+
+
+ beforeDragDrop: function(target, e, id){
+ return true;
+ },
+
+
+ onValidDrop: function(target, e, id){
+ this.hideProxy();
+ if(this.afterValidDrop){
+
+ this.afterValidDrop(target, e, id);
+ }
+ },
+
+
+ getRepairXY: function(e, data){
+ return this.el.getXY();
+ },
+
+
+ onInvalidDrop: function(target, e, id) {
+ this.beforeInvalidDrop(target, e, id);
+ if (this.cachedTarget) {
+ if(this.cachedTarget.isNotifyTarget){
+ this.cachedTarget.notifyOut(this, e, this.dragData);
+ }
+ this.cacheTarget = null;
+ }
+ this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
+
+ if (this.afterInvalidDrop) {
+
+ this.afterInvalidDrop(e, id);
+ }
+ },
+
+
+ afterRepair: function() {
+ var me = this;
+ if (Ext.enableFx) {
+ me.el.highlight(me.repairHighlightColor);
+ }
+ me.dragging = false;
+ },
+
+
+ beforeInvalidDrop: function(target, e, id) {
+ return true;
+ },
+
+
+ handleMouseDown: function(e) {
+ if (this.dragging) {
+ return;
+ }
+ var data = this.getDragData(e);
+ if (data && this.onBeforeDrag(data, e) !== false) {
+ this.dragData = data;
+ this.proxy.stop();
+ this.callParent(arguments);
+ }
+ },
+
+
+ onBeforeDrag: function(data, e){
+ return true;
+ },
+
+
+ onStartDrag: Ext.emptyFn,
+
+
+ startDrag: function(x, y) {
+ this.proxy.reset();
+ this.dragging = true;
+ this.proxy.update("");
+ this.onInitDrag(x, y);
+ this.proxy.show();
+ },
+
+
+ onInitDrag: function(x, y) {
+ var clone = this.el.dom.cloneNode(true);
+ clone.id = Ext.id();
+ this.proxy.update(clone);
+ this.onStartDrag(x, y);
+ return true;
+ },
+
+
+ getProxy: function() {
+ return this.proxy;
+ },
+
+
+ hideProxy: function() {
+ this.proxy.hide();
+ this.proxy.reset(true);
+ this.dragging = false;
+ },
+
+
+ triggerCacheRefresh: function() {
+ Ext.dd.DDM.refreshCache(this.groups);
+ },
+
+
+ b4EndDrag: function(e) {
+ },
+
+
+ endDrag : function(e){
+ this.onEndDrag(this.dragData, e);
+ },
+
+
+ onEndDrag : function(data, e){
+ },
+
+
+ autoOffset : function(x, y) {
+ this.setDelta(-12, -20);
+ },
+
+ destroy: function(){
+ this.callParent();
+ Ext.destroy(this.proxy);
+ }
+});
+
+
+Ext.define('Ext.panel.DD', {
+ extend: 'Ext.dd.DragSource',
+ requires: ['Ext.panel.Proxy'],
+
+ constructor : function(panel, cfg){
+ this.panel = panel;
+ this.dragData = {panel: panel};
+ this.proxy = Ext.create('Ext.panel.Proxy', panel, cfg);
+
+ this.callParent([panel.el, cfg]);
+
+ Ext.defer(function() {
+ var header = panel.header,
+ el = panel.body;
+
+ if(header){
+ this.setHandleElId(header.id);
+ el = header.el;
+ }
+ el.setStyle('cursor', 'move');
+ this.scroll = false;
+ }, 200, this);
+ },
+
+ showFrame: Ext.emptyFn,
+ startDrag: Ext.emptyFn,
+ b4StartDrag: function(x, y) {
+ this.proxy.show();
+ },
+ b4MouseDown: function(e) {
+ var x = e.getPageX(),
+ y = e.getPageY();
+ this.autoOffset(x, y);
+ },
+ onInitDrag : function(x, y){
+ this.onStartDrag(x, y);
+ return true;
+ },
+ createFrame : Ext.emptyFn,
+ getDragEl : function(e){
+ return this.proxy.ghost.el.dom;
+ },
+ endDrag : function(e){
+ this.proxy.hide();
+ this.panel.saveState();
+ },
+
+ autoOffset : function(x, y) {
+ x -= this.startPageX;
+ y -= this.startPageY;
+ this.setDelta(x, y);
+ }
+});
+
+
+Ext.define('Ext.layout.component.Dock', {
+
+
+
+ alias: ['layout.dock'],
+
+ extend: 'Ext.layout.component.AbstractDock'
+
+
+
+});
+
+Ext.define('Ext.panel.Panel', {
+ extend: 'Ext.panel.AbstractPanel',
+ requires: [
+ 'Ext.panel.Header',
+ 'Ext.fx.Anim',
+ 'Ext.util.KeyMap',
+ 'Ext.panel.DD',
+ 'Ext.XTemplate',
+ 'Ext.layout.component.Dock'
+ ],
+ alias: 'widget.panel',
+ alternateClassName: 'Ext.Panel',
+
+
+ collapsedCls: 'collapsed',
+
+
+ animCollapse: Ext.enableFx,
+
+
+ minButtonWidth: 75,
+
+
+ collapsed: false,
+
+
+ collapseFirst: true,
+
+
+ hideCollapseTool: false,
+
+
+ titleCollapse: false,
+
+
+
+
+
+
+ floatable: true,
+
+
+ collapsible: false,
+
+
+
+
+ closable: false,
+
+
+ closeAction: 'destroy',
+
+
+
+
+ preventHeader: false,
+
+
+ headerPosition: 'top',
+
+
+ frame: false,
+
+
+ frameHeader: true,
+
+
+
+
+ initComponent: function() {
+ var me = this,
+ cls;
+
+ me.addEvents(
+
+ 'titlechange',
+
+ 'iconchange'
+ );
+
+ if (me.unstyled) {
+ me.setUI('plain');
+ }
+
+ if (me.frame) {
+ me.setUI('default-framed');
+ }
+
+ me.callParent();
+
+ me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
+
+
+ me.bridgeToolbars();
+ },
+
+ setBorder: function(border) {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ this.callParent(arguments);
+ },
+
+ beforeDestroy: function() {
+ Ext.destroy(
+ this.ghostPanel,
+ this.dd
+ );
+ this.callParent();
+ },
+
+ initAria: function() {
+ this.callParent();
+ this.initHeaderAria();
+ },
+
+ initHeaderAria: function() {
+ var me = this,
+ el = me.el,
+ header = me.header;
+ if (el && header) {
+ el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
+ }
+ },
+
+ getHeader: function() {
+ return this.header;
+ },
+
+
+ setTitle: function(newTitle) {
+ var me = this,
+ oldTitle = this.title;
+
+ me.title = newTitle;
+ if (me.header) {
+ me.header.setTitle(newTitle);
+ } else {
+ me.updateHeader();
+ }
+
+ if (me.reExpander) {
+ me.reExpander.setTitle(newTitle);
+ }
+ me.fireEvent('titlechange', me, newTitle, oldTitle);
+ },
+
+
+ setIconCls: function(newIconCls) {
+ var me = this,
+ oldIconCls = me.iconCls;
+
+ me.iconCls = newIconCls;
+ var header = me.header;
+ if (header) {
+ header.setIconCls(newIconCls);
+ }
+ me.fireEvent('iconchange', me, newIconCls, oldIconCls);
+ },
+
+ bridgeToolbars: function() {
+ var me = this,
+ fbar,
+ fbarDefaults,
+ minButtonWidth = me.minButtonWidth;
+
+ function initToolbar (toolbar, pos) {
+ if (Ext.isArray(toolbar)) {
+ toolbar = {
+ xtype: 'toolbar',
+ items: toolbar
+ };
+ }
+ else if (!toolbar.xtype) {
+ toolbar.xtype = 'toolbar';
+ }
+ toolbar.dock = pos;
+ if (pos == 'left' || pos == 'right') {
+ toolbar.vertical = true;
+ }
+ return toolbar;
+ }
+
+
+
+
+ if (me.tbar) {
+ me.addDocked(initToolbar(me.tbar, 'top'));
+ me.tbar = null;
+ }
+
+
+ if (me.bbar) {
+ me.addDocked(initToolbar(me.bbar, 'bottom'));
+ me.bbar = null;
+ }
+
+
+ if (me.buttons) {
+ me.fbar = me.buttons;
+ me.buttons = null;
+ }
+
+
+ if (me.fbar) {
+ fbar = initToolbar(me.fbar, 'bottom');
+ fbar.ui = 'footer';
+
+
+ if (minButtonWidth) {
+ fbarDefaults = fbar.defaults;
+ fbar.defaults = function(config) {
+ var defaults = fbarDefaults || {};
+ if ((!config.xtype || config.xtype === 'button' || (config.isComponent && config.isXType('button'))) &&
+ !('minWidth' in defaults)) {
+ defaults = Ext.apply({minWidth: minButtonWidth}, defaults);
+ }
+ return defaults;
+ };
+ }
+
+ fbar = me.addDocked(fbar)[0];
+ fbar.insert(0, {
+ flex: 1,
+ xtype: 'component',
+ focusable: false
+ });
+ me.fbar = null;
+ }
+
+
+ if (me.lbar) {
+ me.addDocked(initToolbar(me.lbar, 'left'));
+ me.lbar = null;
+ }
+
+
+ if (me.rbar) {
+ me.addDocked(initToolbar(me.rbar, 'right'));
+ me.rbar = null;
+ }
+ },
+
+
+ initTools: function() {
+ var me = this;
+
+ me.tools = me.tools || [];
+
+
+
+ if (me.collapsible && !(me.hideCollapseTool || me.header === false)) {
+ me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
+ me.collapseTool = me.expandTool = me.createComponent({
+ xtype: 'tool',
+ type: 'collapse-' + me.collapseDirection,
+ expandType: me.getOppositeDirection(me.collapseDirection),
+ handler: me.toggleCollapse,
+ scope: me
+ });
+
+
+ if (me.collapseFirst) {
+ me.tools.unshift(me.collapseTool);
+ }
+ }
+
+
+ me.addTools();
+
+
+ if (me.closable) {
+ me.addClsWithUI('closable');
+ me.addTool({
+ type: 'close',
+ handler: Ext.Function.bind(me.close, this, [])
+ });
+ }
+
+
+ if (me.collapseTool && !me.collapseFirst) {
+ me.tools.push(me.collapseTool);
+ }
+ },
+
+
+ addTools: Ext.emptyFn,
+
+
+ close: function() {
+ if (this.fireEvent('beforeclose', this) !== false) {
+ this.doClose();
+ }
+ },
+
+
+ doClose: function() {
+ this.fireEvent('close', this);
+ this[this.closeAction]();
+ },
+
+ onRender: function(ct, position) {
+ var me = this,
+ topContainer;
+
+
+
+ me.initTools();
+
+
+ me.updateHeader();
+
+
+
+ if (me.collapsed) {
+ me.collapsed = false;
+ topContainer = me.findLayoutController();
+ if (!me.hidden && topContainer) {
+ topContainer.on({
+ afterlayout: function() {
+ me.collapse(null, false, true);
+ },
+ single: true
+ });
+ } else {
+ me.afterComponentLayout = function() {
+ delete me.afterComponentLayout;
+ Ext.getClass(me).prototype.afterComponentLayout.apply(me, arguments);
+ me.collapse(null, false, true);
+ };
+ }
+ }
+
+
+ me.callParent(arguments);
+ },
+
+
+ updateHeader: function(force) {
+ var me = this,
+ header = me.header,
+ title = me.title,
+ tools = me.tools;
+
+ if (!me.preventHeader && (force || title || (tools && tools.length))) {
+ if (!header) {
+ header = me.header = Ext.create('Ext.panel.Header', {
+ title : title,
+ orientation : (me.headerPosition == 'left' || me.headerPosition == 'right') ? 'vertical' : 'horizontal',
+ dock : me.headerPosition || 'top',
+ textCls : me.headerTextCls,
+ iconCls : me.iconCls,
+ baseCls : me.baseCls + '-header',
+ tools : tools,
+ ui : me.ui,
+ indicateDrag: me.draggable,
+ border : me.border,
+ frame : me.frame && me.frameHeader,
+ ignoreParentFrame : me.frame || me.overlapHeader,
+ ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
+ listeners : me.collapsible && me.titleCollapse ? {
+ click: me.toggleCollapse,
+ scope: me
+ } : null
+ });
+ me.addDocked(header, 0);
+
+
+
+ me.tools = header.tools;
+ }
+ header.show();
+ me.initHeaderAria();
+ } else if (header) {
+ header.hide();
+ }
+ },
+
+
+ setUI: function(ui) {
+ var me = this;
+
+ me.callParent(arguments);
+
+ if (me.header) {
+ me.header.setUI(ui);
+ }
+ },
+
+
+ getContentTarget: function() {
+ return this.body;
+ },
+
+ getTargetEl: function() {
+ return this.body || this.frameBody || this.el;
+ },
+
+ addTool: function(tool) {
+ this.tools.push(tool);
+ var header = this.header;
+ if (header) {
+ header.addTool(tool);
+ }
+ this.updateHeader();
+ },
+
+ getOppositeDirection: function(d) {
+ var c = Ext.Component;
+ switch (d) {
+ case c.DIRECTION_TOP:
+ return c.DIRECTION_BOTTOM;
+ case c.DIRECTION_RIGHT:
+ return c.DIRECTION_LEFT;
+ case c.DIRECTION_BOTTOM:
+ return c.DIRECTION_TOP;
+ case c.DIRECTION_LEFT:
+ return c.DIRECTION_RIGHT;
+ }
+ },
+
+
+ collapse: function(direction, animate, internal) {
+ var me = this,
+ c = Ext.Component,
+ height = me.getHeight(),
+ width = me.getWidth(),
+ frameInfo,
+ newSize = 0,
+ dockedItems = me.dockedItems.items,
+ dockedItemCount = dockedItems.length,
+ i = 0,
+ comp,
+ pos,
+ anim = {
+ from: {
+ height: height,
+ width: width
+ },
+ to: {
+ height: height,
+ width: width
+ },
+ listeners: {
+ afteranimate: me.afterCollapse,
+ scope: me
+ },
+ duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
+ },
+ reExpander,
+ reExpanderOrientation,
+ reExpanderDock,
+ getDimension,
+ setDimension,
+ collapseDimension;
+
+ if (!direction) {
+ direction = me.collapseDirection;
+ }
+
+
+ if (internal) {
+ animate = false;
+ } else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
+ return false;
+ }
+
+ reExpanderDock = direction;
+ me.expandDirection = me.getOppositeDirection(direction);
+
+
+ me.hiddenDocked = [];
+
+ switch (direction) {
+ case c.DIRECTION_TOP:
+ case c.DIRECTION_BOTTOM:
+ me.expandedSize = me.getHeight();
+ reExpanderOrientation = 'horizontal';
+ collapseDimension = 'height';
+ getDimension = 'getHeight';
+ setDimension = 'setHeight';
+
+
+
+
+ for (; i < dockedItemCount; i++) {
+ comp = dockedItems[i];
+ if (comp.isVisible()) {
+ if (comp.isHeader && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
+ reExpander = comp;
+ } else {
+ me.hiddenDocked.push(comp);
+ }
+ }
+ }
+
+ if (direction == Ext.Component.DIRECTION_BOTTOM) {
+ pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
+ anim.from.top = pos;
+ }
+ break;
+
+ case c.DIRECTION_LEFT:
+ case c.DIRECTION_RIGHT:
+ me.expandedSize = me.getWidth();
+ reExpanderOrientation = 'vertical';
+ collapseDimension = 'width';
+ getDimension = 'getWidth';
+ setDimension = 'setWidth';
+
+
+
+
+ for (; i < dockedItemCount; i++) {
+ comp = dockedItems[i];
+ if (comp.isVisible()) {
+ if (comp.isHeader && (comp.dock == 'left' || comp.dock == 'right')) {
+ reExpander = comp;
+ } else {
+ me.hiddenDocked.push(comp);
+ }
+ }
+ }
+
+ if (direction == Ext.Component.DIRECTION_RIGHT) {
+ pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
+ anim.from.left = pos;
+ }
+ break;
+
+ default:
+ throw('Panel collapse must be passed a valid Component collapse direction');
+ }
+
+
+
+ me.setAutoScroll(false);
+ me.suspendLayout = true;
+ me.body.setVisibilityMode(Ext.core.Element.DISPLAY);
+
+
+ if (animate && me.collapseTool) {
+ me.collapseTool.disable();
+ }
+
+
+ me.addClsWithUI(me.collapsedCls);
+
+
+
+
+
+ if (reExpander) {
+
+ reExpander.addClsWithUI(me.collapsedCls);
+ reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
+ if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+ reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
+ }
+
+ frameInfo = reExpander.getFrameInfo();
+
+
+ newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
+
+
+ reExpander.removeClsWithUI(me.collapsedCls);
+ reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);
+ if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+ reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
+ }
+ }
+
+ else {
+ reExpander = {
+ hideMode: 'offsets',
+ temporary: true,
+ title: me.title,
+ orientation: reExpanderOrientation,
+ dock: reExpanderDock,
+ textCls: me.headerTextCls,
+ iconCls: me.iconCls,
+ baseCls: me.baseCls + '-header',
+ ui: me.ui,
+ frame: me.frame && me.frameHeader,
+ ignoreParentFrame: me.frame || me.overlapHeader,
+ indicateDrag: me.draggable,
+ cls: me.baseCls + '-collapsed-placeholder ' + ' ' + Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed',
+ renderTo: me.el
+ };
+ reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
+ xtype: 'tool',
+ type: 'expand-' + me.expandDirection,
+ handler: me.toggleCollapse,
+ scope: me
+ }];
+
+
+
+ reExpander = me.reExpander = Ext.create('Ext.panel.Header', reExpander);
+ newSize = reExpander[getDimension]() + ((reExpander.frame) ? reExpander.frameSize[direction] : 0);
+ reExpander.hide();
+
+
+ me.insertDocked(0, reExpander);
+ }
+
+ me.reExpander = reExpander;
+ me.reExpander.addClsWithUI(me.collapsedCls);
+ me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
+ if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+ me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
+ }
+
+
+ if (direction == Ext.Component.DIRECTION_RIGHT) {
+ anim.to.left = pos + (width - newSize);
+ } else if (direction == Ext.Component.DIRECTION_BOTTOM) {
+ anim.to.top = pos + (height - newSize);
+ }
+
+
+ anim.to[collapseDimension] = newSize;
+
+
+ me.savedFlex = me.flex;
+ me.savedMinWidth = me.minWidth;
+ me.savedMinHeight = me.minHeight;
+ me.minWidth = 0;
+ me.minHeight = 0;
+ delete me.flex;
+
+ if (animate) {
+ me.animate(anim);
+ } else {
+ me.setSize(anim.to.width, anim.to.height);
+ if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
+ me.setPosition(anim.to.left, anim.to.top);
+ }
+ me.afterCollapse(false, internal);
+ }
+ return me;
+ },
+
+ afterCollapse: function(animated, internal) {
+ var me = this,
+ i = 0,
+ l = me.hiddenDocked.length;
+
+ me.minWidth = me.savedMinWidth;
+ me.minHeight = me.savedMinHeight;
+
+ me.body.hide();
+ for (; i < l; i++) {
+ me.hiddenDocked[i].hide();
+ }
+ if (me.reExpander) {
+ me.reExpander.updateFrame();
+ me.reExpander.show();
+ }
+ me.collapsed = true;
+
+ if (!internal) {
+ me.doComponentLayout();
+ }
+
+ if (me.resizer) {
+ me.resizer.disable();
+ }
+
+
+ if (me.collapseTool) {
+ me.collapseTool.setType('expand-' + me.expandDirection);
+ }
+ if (!internal) {
+ me.fireEvent('collapse', me);
+ }
+
+
+ if (animated && me.collapseTool) {
+ me.collapseTool.enable();
+ }
+ },
+
+
+ expand: function(animate) {
+ if (!this.collapsed || this.fireEvent('beforeexpand', this, animate) === false) {
+ return false;
+ }
+ var me = this,
+ i = 0,
+ l = me.hiddenDocked.length,
+ direction = me.expandDirection,
+ height = me.getHeight(),
+ width = me.getWidth(),
+ pos, anim, satisfyJSLint;
+
+
+ if (animate && me.collapseTool) {
+ me.collapseTool.disable();
+ }
+
+
+
+ for (; i < l; i++) {
+ me.hiddenDocked[i].hidden = false;
+ me.hiddenDocked[i].el.show();
+ }
+ if (me.reExpander) {
+ if (me.reExpander.temporary) {
+ me.reExpander.hide();
+ } else {
+ me.reExpander.removeClsWithUI(me.collapsedCls);
+ me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
+ if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+ me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
+ }
+ me.reExpander.updateFrame();
+ }
+ }
+
+
+ if (me.collapseTool) {
+ me.collapseTool.setType('collapse-' + me.collapseDirection);
+ }
+
+
+ me.collapsed = false;
+
+
+ me.body.show();
+
+
+ me.removeClsWithUI(me.collapsedCls);
+
+
+
+
+ anim = {
+ to: {
+ },
+ from: {
+ height: height,
+ width: width
+ },
+ listeners: {
+ afteranimate: me.afterExpand,
+ scope: me
+ }
+ };
+
+ if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
+
+
+ if (me.autoHeight) {
+ me.setCalculatedSize(me.width, null);
+ anim.to.height = me.getHeight();
+
+
+ me.setCalculatedSize(me.width, anim.from.height);
+ }
+
+
+ else if (me.savedFlex) {
+ me.flex = me.savedFlex;
+ anim.to.height = me.ownerCt.layout.calculateChildBox(me).height;
+ delete me.flex;
+ }
+
+ else {
+ anim.to.height = me.expandedSize;
+ }
+
+
+ if (direction == Ext.Component.DIRECTION_TOP) {
+ pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
+ anim.from.top = pos;
+ anim.to.top = pos - (anim.to.height - height);
+ }
+ } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
+
+
+ if (me.autoWidth) {
+ me.setCalculatedSize(null, me.height);
+ anim.to.width = me.getWidth();
+
+
+ me.setCalculatedSize(anim.from.width, me.height);
+ }
+
+
+ else if (me.savedFlex) {
+ me.flex = me.savedFlex;
+ anim.to.width = me.ownerCt.layout.calculateChildBox(me).width;
+ delete me.flex;
+ }
+
+ else {
+ anim.to.width = me.expandedSize;
+ }
+
+
+ if (direction == Ext.Component.DIRECTION_LEFT) {
+ pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
+ anim.from.left = pos;
+ anim.to.left = pos - (anim.to.width - width);
+ }
+ }
+
+ if (animate) {
+ me.animate(anim);
+ } else {
+ me.setSize(anim.to.width, anim.to.height);
+ if (anim.to.x) {
+ me.setLeft(anim.to.x);
+ }
+ if (anim.to.y) {
+ me.setTop(anim.to.y);
+ }
+ me.afterExpand(false);
+ }
+
+ return me;
+ },
+
+ afterExpand: function(animated) {
+ var me = this;
+ me.setAutoScroll(me.initialConfig.autoScroll);
+
+
+ if (me.savedFlex) {
+ me.flex = me.savedFlex;
+ delete me.savedFlex;
+ delete me.width;
+ delete me.height;
+ }
+
+
+ delete me.suspendLayout;
+ if (animated && me.ownerCt) {
+ me.ownerCt.doLayout();
+ }
+
+ if (me.resizer) {
+ me.resizer.enable();
+ }
+
+ me.fireEvent('expand', me);
+
+
+ if (animated && me.collapseTool) {
+ me.collapseTool.enable();
+ }
+ },
+
+
+ toggleCollapse: function() {
+ if (this.collapsed) {
+ this.expand(this.animCollapse);
+ } else {
+ this.collapse(this.collapseDirection, this.animCollapse);
+ }
+ return this;
+ },
+
+
+ getKeyMap : function(){
+ if(!this.keyMap){
+ this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
+ }
+ return this.keyMap;
+ },
+
+
+ initDraggable : function(){
+
+ this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
+ },
+
+
+ ghostTools : function() {
+ var tools = [],
+ origTools = this.initialConfig.tools;
+
+ if (origTools) {
+ Ext.each(origTools, function(tool) {
+
+
+
+
+ tools.push({
+ type: tool.type
+ });
+ });
+ }
+ else {
+ tools = [{
+ type: 'placeholder'
+ }];
+ }
+ return tools;
+ },
+
+
+ ghost: function(cls) {
+ var me = this,
+ ghostPanel = me.ghostPanel,
+ box = me.getBox();
+
+ if (!ghostPanel) {
+ ghostPanel = Ext.create('Ext.panel.Panel', {
+ renderTo: document.body,
+ floating: {
+ shadow: false
+ },
+ frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
+ title: me.title,
+ overlapHeader: me.overlapHeader,
+ headerPosition: me.headerPosition,
+ width: me.getWidth(),
+ height: me.getHeight(),
+ iconCls: me.iconCls,
+ baseCls: me.baseCls,
+ tools: me.ghostTools(),
+ cls: me.baseCls + '-ghost ' + (cls ||'')
+ });
+ me.ghostPanel = ghostPanel;
+ }
+ ghostPanel.floatParent = me.floatParent;
+ if (me.floating) {
+ ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
+ } else {
+ ghostPanel.toFront();
+ }
+ ghostPanel.el.show();
+ ghostPanel.setPosition(box.x, box.y);
+ ghostPanel.setSize(box.width, box.height);
+ me.el.hide();
+ if (me.floatingItems) {
+ me.floatingItems.hide();
+ }
+ return ghostPanel;
+ },
+
+
+ unghost: function(show, matchPosition) {
+ var me = this;
+ if (!me.ghostPanel) {
+ return;
+ }
+ if (show !== false) {
+ me.el.show();
+ if (matchPosition !== false) {
+ me.setPosition(me.ghostPanel.getPosition());
+ }
+ if (me.floatingItems) {
+ me.floatingItems.show();
+ }
+ Ext.defer(me.focus, 10, me);
+ }
+ me.ghostPanel.el.hide();
+ },
+
+ initResizable: function(resizable) {
+ if (this.collapsed) {
+ resizable.disabled = true;
+ }
+ this.callParent([resizable]);
+ }
+});
+
+
+
+Ext.define('Ext.layout.component.Tip', {
+
+
+
+ alias: ['layout.tip'],
+
+ extend: 'Ext.layout.component.Dock',
+
+
+
+ type: 'tip',
+
+ onLayout: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ el = owner.el,
+ minWidth,
+ maxWidth,
+ naturalWidth,
+ constrainedWidth,
+ xy = el.getXY();
+
+
+ el.setXY([-9999,-9999]);
+
+
+ this.callParent(arguments);
+
+
+ if (!Ext.isNumber(width)) {
+ minWidth = owner.minWidth;
+ maxWidth = owner.maxWidth;
+
+ if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
+ constrainedWidth = me.doAutoWidth();
+ } else {
+ naturalWidth = el.getWidth();
+ }
+ if (naturalWidth < minWidth) {
+ constrainedWidth = minWidth;
+ }
+ else if (naturalWidth > maxWidth) {
+ constrainedWidth = maxWidth;
+ }
+ if (constrainedWidth) {
+ this.callParent([constrainedWidth, height]);
+ }
+ }
+
+
+ el.setXY(xy);
+ },
+
+ doAutoWidth: function(){
+ var me = this,
+ owner = me.owner,
+ body = owner.body,
+ width = body.getTextWidth();
+
+ if (owner.header) {
+ width = Math.max(width, owner.header.getWidth());
+ }
+ if (!Ext.isDefined(me.frameWidth)) {
+ me.frameWidth = owner.el.getWidth() - body.getWidth();
+ }
+ width += me.frameWidth + body.getPadding('lr');
+ return width;
+ }
+});
+
+
+Ext.define('Ext.tip.Tip', {
+ extend: 'Ext.panel.Panel',
+ requires: [ 'Ext.layout.component.Tip' ],
+ alternateClassName: 'Ext.Tip',
+
+
+
+ minWidth : 40,
+
+ maxWidth : 300,
+
+ shadow : "sides",
+
+
+ defaultAlign : "tl-bl?",
+
+ constrainPosition : true,
+
+
+ frame: false,
+
+
+ autoRender: true,
+ hidden: true,
+ baseCls: Ext.baseCSSPrefix + 'tip',
+ floating: {
+ shadow: true,
+ shim: true,
+ constrain: true
+ },
+ focusOnToFront: false,
+ componentLayout: 'tip',
+
+ closeAction: 'hide',
+
+ ariaRole: 'tooltip',
+
+ initComponent: function() {
+ this.callParent(arguments);
+
+
+ this.constrain = this.constrain || this.constrainPosition;
+ },
+
+
+ showAt : function(xy){
+ var me = this;
+ this.callParent();
+
+ if (me.isVisible()) {
+ me.setPagePosition(xy[0], xy[1]);
+ if (me.constrainPosition || me.constrain) {
+ me.doConstrain();
+ }
+ me.toFront(true);
+ }
+ },
+
+
+ showBy : function(el, pos) {
+ this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
+ },
+
+
+ initDraggable : function(){
+ var me = this;
+ me.draggable = {
+ el: me.getDragEl(),
+ delegate: me.header.el,
+ constrain: me,
+ constrainTo: me.el.dom.parentNode
+ };
+
+ Ext.Component.prototype.initDraggable.call(me);
+ },
+
+
+ ghost: undefined,
+ unghost: undefined
+});
+
+
+Ext.define('Ext.tip.ToolTip', {
+ extend: 'Ext.tip.Tip',
+ alias: 'widget.tooltip',
+ alternateClassName: 'Ext.ToolTip',
+
+
+
+
+ showDelay: 500,
+
+ hideDelay: 200,
+
+ dismissDelay: 5000,
+
+
+ trackMouse: false,
+
+
+ anchorToTarget: true,
+
+ anchorOffset: 0,
+
+
+
+ targetCounter: 0,
+ quickShowInterval: 250,
+
+
+ initComponent: function() {
+ var me = this;
+ me.callParent(arguments);
+ me.lastActive = new Date();
+ me.setTarget(me.target);
+ me.origAnchor = me.anchor;
+ },
+
+
+ onRender: function(ct, position) {
+ var me = this;
+ me.callParent(arguments);
+ me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
+ me.anchorEl = me.el.createChild({
+ cls: Ext.baseCSSPrefix + 'tip-anchor ' + me.anchorCls
+ });
+ },
+
+
+ afterRender: function() {
+ var me = this,
+ zIndex;
+
+ me.callParent(arguments);
+ zIndex = parseInt(me.el.getZIndex(), 10) || 0;
+ me.anchorEl.setStyle('z-index', zIndex + 1).setVisibilityMode(Ext.core.Element.DISPLAY);
+ },
+
+
+ setTarget: function(target) {
+ var me = this,
+ t = Ext.get(target),
+ tg;
+
+ if (me.target) {
+ tg = Ext.get(me.target);
+ me.mun(tg, 'mouseover', me.onTargetOver, me);
+ me.mun(tg, 'mouseout', me.onTargetOut, me);
+ me.mun(tg, 'mousemove', me.onMouseMove, me);
+ }
+
+ me.target = t;
+ if (t) {
+
+ me.mon(t, {
+
+
+ freezeEvent: true,
+
+ mouseover: me.onTargetOver,
+ mouseout: me.onTargetOut,
+ mousemove: me.onMouseMove,
+ scope: me
+ });
+ }
+ if (me.anchor) {
+ me.anchorTarget = me.target;
+ }
+ },
+
+
+ onMouseMove: function(e) {
+ var me = this,
+ t = me.delegate ? e.getTarget(me.delegate) : me.triggerElement = true,
+ xy;
+ if (t) {
+ me.targetXY = e.getXY();
+ if (t === me.triggerElement) {
+ if (!me.hidden && me.trackMouse) {
+ xy = me.getTargetXY();
+ if (me.constrainPosition) {
+ xy = me.el.adjustForConstraints(xy, me.el.dom.parentNode);
+ }
+ me.setPagePosition(xy);
+ }
+ } else {
+ me.hide();
+ me.lastActive = new Date(0);
+ me.onTargetOver(e);
+ }
+ } else if ((!me.closable && me.isVisible()) && me.autoHide !== false) {
+ me.hide();
+ }
+ },
+
+
+ getTargetXY: function() {
+ var me = this,
+ mouseOffset;
+ if (me.delegate) {
+ me.anchorTarget = me.triggerElement;
+ }
+ if (me.anchor) {
+ me.targetCounter++;
+ var offsets = me.getOffsets(),
+ xy = (me.anchorToTarget && !me.trackMouse) ? me.el.getAlignToXY(me.anchorTarget, me.getAnchorAlign()) : me.targetXY,
+ dw = Ext.core.Element.getViewWidth() - 5,
+ dh = Ext.core.Element.getViewHeight() - 5,
+ de = document.documentElement,
+ bd = document.body,
+ scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
+ scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
+ axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
+ sz = me.getSize(),
+ constrainPosition = me.constrainPosition;
+
+ me.anchorEl.removeCls(me.anchorCls);
+
+ if (me.targetCounter < 2 && constrainPosition) {
+ if (axy[0] < scrollX) {
+ if (me.anchorToTarget) {
+ me.defaultAlign = 'l-r';
+ if (me.mouseOffset) {
+ me.mouseOffset[0] *= -1;
+ }
+ }
+ me.anchor = 'left';
+ return me.getTargetXY();
+ }
+ if (axy[0] + sz.width > dw) {
+ if (me.anchorToTarget) {
+ me.defaultAlign = 'r-l';
+ if (me.mouseOffset) {
+ me.mouseOffset[0] *= -1;
+ }
+ }
+ me.anchor = 'right';
+ return me.getTargetXY();
+ }
+ if (axy[1] < scrollY) {
+ if (me.anchorToTarget) {
+ me.defaultAlign = 't-b';
+ if (me.mouseOffset) {
+ me.mouseOffset[1] *= -1;
+ }
+ }
+ me.anchor = 'top';
+ return me.getTargetXY();
+ }
+ if (axy[1] + sz.height > dh) {
+ if (me.anchorToTarget) {
+ me.defaultAlign = 'b-t';
+ if (me.mouseOffset) {
+ me.mouseOffset[1] *= -1;
+ }
+ }
+ me.anchor = 'bottom';
+ return me.getTargetXY();
+ }
+ }
+
+ me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
+ me.anchorEl.addCls(me.anchorCls);
+ me.targetCounter = 0;
+ return axy;
+ } else {
+ mouseOffset = me.getMouseOffset();
+ return (me.targetXY) ? [me.targetXY[0] + mouseOffset[0], me.targetXY[1] + mouseOffset[1]] : mouseOffset;
+ }
+ },
+
+ getMouseOffset: function() {
+ var me = this,
+ offset = me.anchor ? [0, 0] : [15, 18];
+ if (me.mouseOffset) {
+ offset[0] += me.mouseOffset[0];
+ offset[1] += me.mouseOffset[1];
+ }
+ return offset;
+ },
+
+
+ getAnchorPosition: function() {
+ var me = this,
+ m;
+ if (me.anchor) {
+ me.tipAnchor = me.anchor.charAt(0);
+ } else {
+ m = me.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
+ if (!m) {
+ Ext.Error.raise('The AnchorTip.defaultAlign value "' + me.defaultAlign + '" is invalid.');
+ }
+ me.tipAnchor = m[1].charAt(0);
+ }
+
+ switch (me.tipAnchor) {
+ case 't':
+ return 'top';
+ case 'b':
+ return 'bottom';
+ case 'r':
+ return 'right';
+ }
+ return 'left';
+ },
+
+
+ getAnchorAlign: function() {
+ switch (this.anchor) {
+ case 'top':
+ return 'tl-bl';
+ case 'left':
+ return 'tl-tr';
+ case 'right':
+ return 'tr-tl';
+ default:
+ return 'bl-tl';
+ }
+ },
+
+
+ getOffsets: function() {
+ var me = this,
+ mouseOffset,
+ offsets,
+ ap = me.getAnchorPosition().charAt(0);
+ if (me.anchorToTarget && !me.trackMouse) {
+ switch (ap) {
+ case 't':
+ offsets = [0, 9];
+ break;
+ case 'b':
+ offsets = [0, -13];
+ break;
+ case 'r':
+ offsets = [ - 13, 0];
+ break;
+ default:
+ offsets = [9, 0];
+ break;
+ }
+ } else {
+ switch (ap) {
+ case 't':
+ offsets = [ - 15 - me.anchorOffset, 30];
+ break;
+ case 'b':
+ offsets = [ - 19 - me.anchorOffset, -13 - me.el.dom.offsetHeight];
+ break;
+ case 'r':
+ offsets = [ - 15 - me.el.dom.offsetWidth, -13 - me.anchorOffset];
+ break;
+ default:
+ offsets = [25, -13 - me.anchorOffset];
+ break;
+ }
+ }
+ mouseOffset = me.getMouseOffset();
+ offsets[0] += mouseOffset[0];
+ offsets[1] += mouseOffset[1];
+
+ return offsets;
+ },
+
+
+ onTargetOver: function(e) {
+ var me = this,
+ t;
+
+ if (me.disabled || e.within(me.target.dom, true)) {
+ return;
+ }
+ t = e.getTarget(me.delegate);
+ if (t) {
+ me.triggerElement = t;
+ me.clearTimer('hide');
+ me.targetXY = e.getXY();
+ me.delayShow();
+ }
+ },
+
+
+ delayShow: function() {
+ var me = this;
+ if (me.hidden && !me.showTimer) {
+ if (Ext.Date.getElapsed(me.lastActive) < me.quickShowInterval) {
+ me.show();
+ } else {
+ me.showTimer = Ext.defer(me.show, me.showDelay, me);
+ }
+ }
+ else if (!me.hidden && me.autoHide !== false) {
+ me.show();
+ }
+ },
+
+
+ onTargetOut: function(e) {
+ var me = this;
+ if (me.disabled || e.within(me.target.dom, true)) {
+ return;
+ }
+ me.clearTimer('show');
+ if (me.autoHide !== false) {
+ me.delayHide();
+ }
+ },
+
+
+ delayHide: function() {
+ var me = this;
+ if (!me.hidden && !me.hideTimer) {
+ me.hideTimer = Ext.defer(me.hide, me.hideDelay, me);
+ }
+ },
+
+
+ hide: function() {
+ var me = this;
+ me.clearTimer('dismiss');
+ me.lastActive = new Date();
+ if (me.anchorEl) {
+ me.anchorEl.hide();
+ }
+ me.callParent(arguments);
+ delete me.triggerElement;
+ },
+
+
+ show: function() {
+ var me = this;
+
+
+
+ this.callParent();
+ if (this.hidden === false) {
+ me.setPagePosition(-10000, -10000);
+
+ if (me.anchor) {
+ me.anchor = me.origAnchor;
+ }
+ me.showAt(me.getTargetXY());
+
+ if (me.anchor) {
+ me.syncAnchor();
+ me.anchorEl.show();
+ } else {
+ me.anchorEl.hide();
+ }
+ }
+ },
+
+
+ showAt: function(xy) {
+ var me = this;
+ me.lastActive = new Date();
+ me.clearTimers();
+
+
+ if (!me.isVisible()) {
+ this.callParent(arguments);
+ }
+
+
+ if (me.isVisible()) {
+ me.setPagePosition(xy[0], xy[1]);
+ if (me.constrainPosition || me.constrain) {
+ me.doConstrain();
+ }
+ me.toFront(true);
+ }
+
+ if (me.dismissDelay && me.autoHide !== false) {
+ me.dismissTimer = Ext.defer(me.hide, me.dismissDelay, me);
+ }
+ if (me.anchor) {
+ me.syncAnchor();
+ if (!me.anchorEl.isVisible()) {
+ me.anchorEl.show();
+ }
+ } else {
+ me.anchorEl.hide();
+ }
+ },
+
+
+ syncAnchor: function() {
+ var me = this,
+ anchorPos,
+ targetPos,
+ offset;
+ switch (me.tipAnchor.charAt(0)) {
+ case 't':
+ anchorPos = 'b';
+ targetPos = 'tl';
+ offset = [20 + me.anchorOffset, 1];
+ break;
+ case 'r':
+ anchorPos = 'l';
+ targetPos = 'tr';
+ offset = [ - 1, 12 + me.anchorOffset];
+ break;
+ case 'b':
+ anchorPos = 't';
+ targetPos = 'bl';
+ offset = [20 + me.anchorOffset, -1];
+ break;
+ default:
+ anchorPos = 'r';
+ targetPos = 'tl';
+ offset = [1, 12 + me.anchorOffset];
+ break;
+ }
+ me.anchorEl.alignTo(me.el, anchorPos + '-' + targetPos, offset);
+ },
+
+
+ setPagePosition: function(x, y) {
+ var me = this;
+ me.callParent(arguments);
+ if (me.anchor) {
+ me.syncAnchor();
+ }
+ },
+
+
+ clearTimer: function(name) {
+ name = name + 'Timer';
+ clearTimeout(this[name]);
+ delete this[name];
+ },
+
+
+ clearTimers: function() {
+ var me = this;
+ me.clearTimer('show');
+ me.clearTimer('dismiss');
+ me.clearTimer('hide');
+ },
+
+
+ onShow: function() {
+ var me = this;
+ me.callParent();
+ me.mon(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
+ },
+
+
+ onHide: function() {
+ var me = this;
+ me.callParent();
+ me.mun(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
+ },
+
+
+ onDocMouseDown: function(e) {
+ var me = this;
+ if (me.autoHide !== true && !me.closable && !e.within(me.el.dom)) {
+ me.disable();
+ Ext.defer(me.doEnable, 100, me);
+ }
+ },
+
+
+ doEnable: function() {
+ if (!this.isDestroyed) {
+ this.enable();
+ }
+ },
+
+
+ onDisable: function() {
+ this.callParent();
+ this.clearTimers();
+ this.hide();
+ },
+
+ beforeDestroy: function() {
+ var me = this;
+ me.clearTimers();
+ Ext.destroy(me.anchorEl);
+ delete me.anchorEl;
+ delete me.target;
+ delete me.anchorTarget;
+ delete me.triggerElement;
+ me.callParent();
+ },
+
+
+ onDestroy: function() {
+ Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
+ this.callParent();
+ }
+});
+
+
+Ext.define('Ext.tip.QuickTip', {
+ extend: 'Ext.tip.ToolTip',
+ alternateClassName: 'Ext.QuickTip',
+
+
+ interceptTitles : false,
+
+
+ title: ' ',
+
+
+ tagConfig : {
+ namespace : "data-",
+ attribute : "qtip",
+ width : "qwidth",
+ target : "target",
+ title : "qtitle",
+ hide : "hide",
+ cls : "qclass",
+ align : "qalign",
+ anchor : "anchor"
+ },
+
+
+ initComponent : function(){
+ var me = this;
+
+ me.target = me.target || Ext.getDoc();
+ me.targets = me.targets || {};
+ me.callParent();
+ },
+
+
+ register : function(config){
+ var configs = Ext.isArray(config) ? config : arguments,
+ i = 0,
+ len = configs.length,
+ target, j, targetLen;
+
+ for (; i < len; i++) {
+ config = configs[i];
+ target = config.target;
+ if (target) {
+ if (Ext.isArray(target)) {
+ for (j = 0, targetLen = target.length; j < targetLen; j++) {
+ this.targets[Ext.id(target[j])] = config;
+ }
+ } else{
+ this.targets[Ext.id(target)] = config;
+ }
+ }
+ }
+ },
+
+
+ unregister : function(el){
+ delete this.targets[Ext.id(el)];
+ },
+
+
+ cancelShow: function(el){
+ var me = this,
+ activeTarget = me.activeTarget;
+
+ el = Ext.get(el).dom;
+ if (me.isVisible()) {
+ if (activeTarget && activeTarget.el == el) {
+ me.hide();
+ }
+ } else if (activeTarget && activeTarget.el == el) {
+ me.clearTimer('show');
+ }
+ },
+
+ getTipCfg: function(e) {
+ var t = e.getTarget(),
+ ttp,
+ cfg;
+
+ if(this.interceptTitles && t.title && Ext.isString(t.title)){
+ ttp = t.title;
+ t.qtip = ttp;
+ t.removeAttribute("title");
+ e.preventDefault();
+ }
+ else {
+ cfg = this.tagConfig;
+ t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']');
+ if (t) {
+ ttp = t.getAttribute(cfg.namespace + cfg.attribute);
+ }
+ }
+ return ttp;
+ },
+
+
+ onTargetOver : function(e){
+ var me = this,
+ target = e.getTarget(),
+ elTarget,
+ cfg,
+ ns,
+ ttp,
+ autoHide;
+
+ if (me.disabled) {
+ return;
+ }
+
+
+
+
+ me.targetXY = e.getXY();
+
+ if(!target || target.nodeType !== 1 || target == document || target == document.body){
+ return;
+ }
+
+ if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) {
+ me.clearTimer('hide');
+ me.show();
+ return;
+ }
+
+ if (target) {
+ Ext.Object.each(me.targets, function(key, value) {
+ var targetEl = Ext.fly(value.target);
+ if (targetEl && (targetEl.dom === target || targetEl.contains(target))) {
+ elTarget = targetEl.dom;
+ return false;
+ }
+ });
+ if (elTarget) {
+ me.activeTarget = me.targets[elTarget.id];
+ me.activeTarget.el = target;
+ me.anchor = me.activeTarget.anchor;
+ if (me.anchor) {
+ me.anchorTarget = target;
+ }
+ me.delayShow();
+ return;
+ }
+ }
+
+ elTarget = Ext.get(target);
+ cfg = me.tagConfig;
+ ns = cfg.namespace;
+ ttp = me.getTipCfg(e);
+
+ if (ttp) {
+ autoHide = elTarget.getAttribute(ns + cfg.hide);
+
+ me.activeTarget = {
+ el: target,
+ text: ttp,
+ width: +elTarget.getAttribute(ns + cfg.width) || null,
+ autoHide: autoHide != "user" && autoHide !== 'false',
+ title: elTarget.getAttribute(ns + cfg.title),
+ cls: elTarget.getAttribute(ns + cfg.cls),
+ align: elTarget.getAttribute(ns + cfg.align)
+
+ };
+ me.anchor = elTarget.getAttribute(ns + cfg.anchor);
+ if (me.anchor) {
+ me.anchorTarget = target;
+ }
+ me.delayShow();
+ }
+ },
+
+
+ onTargetOut : function(e){
+ var me = this;
+
+
+ if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) {
+ return;
+ }
+
+ me.clearTimer('show');
+ if (me.autoHide !== false) {
+ me.delayHide();
+ }
+ },
+
+
+ showAt : function(xy){
+ var me = this,
+ target = me.activeTarget;
+
+ if (target) {
+ if (!me.rendered) {
+ me.render(Ext.getBody());
+ me.activeTarget = target;
+ }
+ if (target.title) {
+ me.setTitle(target.title || '');
+ me.header.show();
+ } else {
+ me.header.hide();
+ }
+ me.body.update(target.text);
+ me.autoHide = target.autoHide;
+ me.dismissDelay = target.dismissDelay || me.dismissDelay;
+ if (me.lastCls) {
+ me.el.removeCls(me.lastCls);
+ delete me.lastCls;
+ }
+ if (target.cls) {
+ me.el.addCls(target.cls);
+ me.lastCls = target.cls;
+ }
+
+ me.setWidth(target.width);
+
+ if (me.anchor) {
+ me.constrainPosition = false;
+ } else if (target.align) {
+ xy = me.el.getAlignToXY(target.el, target.align);
+ me.constrainPosition = false;
+ }else{
+ me.constrainPosition = true;
+ }
+ }
+ me.callParent([xy]);
+ },
+
+
+ hide: function(){
+ delete this.activeTarget;
+ this.callParent();
+ }
+});
+
+
+Ext.define('Ext.tip.QuickTipManager', function() {
+ var tip,
+ disabled = false;
+
+ return {
+ requires: ['Ext.tip.QuickTip'],
+ singleton: true,
+ alternateClassName: 'Ext.QuickTips',
+
+ init : function(autoRender){
+ if (!tip) {
+ if (!Ext.isReady) {
+ Ext.onReady(function(){
+ Ext.tip.QuickTipManager.init(autoRender);
+ });
+ return;
+ }
+ tip = Ext.create('Ext.tip.QuickTip', {
+ disabled: disabled,
+ renderTo: autoRender !== false ? document.body : undefined
+ });
+ }
+ },
+
+
+ destroy: function() {
+ if (tip) {
+ var undef;
+ tip.destroy();
+ tip = undef;
+ }
+ },
+
+
+ ddDisable : function(){
+
+ if(tip && !disabled){
+ tip.disable();
+ }
+ },
+
+
+ ddEnable : function(){
+
+ if(tip && !disabled){
+ tip.enable();
+ }
+ },
+
+
+ enable : function(){
+ if(tip){
+ tip.enable();
+ }
+ disabled = false;
+ },
+
+
+ disable : function(){
+ if(tip){
+ tip.disable();
+ }
+ disabled = true;
+ },
+
+
+ isEnabled : function(){
+ return tip !== undefined && !tip.disabled;
+ },
+
+
+ getQuickTip : function(){
+ return tip;
+ },
+
+
+ register : function(){
+ tip.register.apply(tip, arguments);
+ },
+
+
+ unregister : function(){
+ tip.unregister.apply(tip, arguments);
+ },
+
+
+ tips : function(){
+ tip.register.apply(tip, arguments);
+ }
+ };
+}());
+
+Ext.define('Ext.app.Application', {
+ extend: 'Ext.app.Controller',
+
+ requires: [
+ 'Ext.ModelManager',
+ 'Ext.data.Model',
+ 'Ext.data.StoreManager',
+ 'Ext.tip.QuickTipManager',
+ 'Ext.ComponentManager',
+ 'Ext.app.EventBus'
+ ],
+
+
+
+
+ scope: undefined,
+
+
+ enableQuickTips: true,
+
+
+
+
+ appFolder: 'app',
+
+
+ autoCreateViewport: true,
+
+ constructor: function(config) {
+ config = config || {};
+ Ext.apply(this, config);
+
+ var requires = config.requires || [];
+
+ Ext.Loader.setPath(this.name, this.appFolder);
+
+ if (this.paths) {
+ Ext.Object.each(this.paths, function(key, value) {
+ Ext.Loader.setPath(key, value);
+ });
+ }
+
+ this.callParent(arguments);
+
+ this.eventbus = Ext.create('Ext.app.EventBus');
+
+ var controllers = this.controllers,
+ ln = controllers.length,
+ i, controller;
+
+ this.controllers = Ext.create('Ext.util.MixedCollection');
+
+ if (this.autoCreateViewport) {
+ requires.push(this.getModuleClassName('Viewport', 'view'));
+ }
+
+ for (i = 0; i < ln; i++) {
+ requires.push(this.getModuleClassName(controllers[i], 'controller'));
+ }
+
+ Ext.require(requires);
+
+ Ext.onReady(function() {
+ for (i = 0; i < ln; i++) {
+ controller = this.getController(controllers[i]);
+ controller.init(this);
+ }
+
+ this.onBeforeLaunch.call(this);
+ }, this);
+ },
+
+ control: function(selectors, listeners, controller) {
+ this.eventbus.control(selectors, listeners, controller);
+ },
+
+
+ launch: Ext.emptyFn,
+
+
+ onBeforeLaunch: function() {
+ if (this.enableQuickTips) {
+ Ext.tip.QuickTipManager.init();
+ }
+
+ if (this.autoCreateViewport) {
+ this.getView('Viewport').create();
+ }
+
+ this.launch.call(this.scope || this);
+ this.launched = true;
+ this.fireEvent('launch', this);
+
+ this.controllers.each(function(controller) {
+ controller.onLaunch(this);
+ }, this);
+ },
+
+ getModuleClassName: function(name, type) {
+ var namespace = Ext.Loader.getPrefix(name);
+
+ if (namespace.length > 0 && namespace !== name) {
+ return name;
+ }
+
+ return this.name + '.' + type + '.' + name;
+ },
+
+ getController: function(name) {
+ var controller = this.controllers.get(name);
+
+ if (!controller) {
+ controller = Ext.create(this.getModuleClassName(name, 'controller'), {
+ application: this,
+ id: name
+ });
+
+ this.controllers.add(controller);
+ }
+
+ return controller;
+ },
+
+ getStore: function(name) {
+ var store = Ext.StoreManager.get(name);
+
+ if (!store) {
+ store = Ext.create(this.getModuleClassName(name, 'store'), {
+ storeId: name
+ });
+ }
+
+ return store;
+ },
+
+ getModel: function(model) {
+ model = this.getModuleClassName(model, 'model');
+
+ return Ext.ModelManager.getModel(model);
+ },
+
+ getView: function(view) {
+ view = this.getModuleClassName(view, 'view');
+
+ return Ext.ClassManager.get(view);
+ }
+});
+
+
+Ext.define('Ext.chart.Callout', {
+
+
+
+
+
+ constructor: function(config) {
+ if (config.callouts) {
+ config.callouts.styles = Ext.applyIf(config.callouts.styles || {}, {
+ color: "#000",
+ font: "11px Helvetica, sans-serif"
+ });
+ this.callouts = Ext.apply(this.callouts || {}, config.callouts);
+ this.calloutsArray = [];
+ }
+ },
+
+ renderCallouts: function() {
+ if (!this.callouts) {
+ return;
+ }
+
+ var me = this,
+ items = me.items,
+ animate = me.chart.animate,
+ config = me.callouts,
+ styles = config.styles,
+ group = me.calloutsArray,
+ store = me.chart.store,
+ len = store.getCount(),
+ ratio = items.length / len,
+ previouslyPlacedCallouts = [],
+ i,
+ count,
+ j,
+ p;
+
+ for (i = 0, count = 0; i < len; i++) {
+ for (j = 0; j < ratio; j++) {
+ var item = items[count],
+ label = group[count],
+ storeItem = store.getAt(i),
+ display;
+
+ display = config.filter(storeItem);
+
+ if (!display && !label) {
+ count++;
+ continue;
+ }
+
+ if (!label) {
+ group[count] = label = me.onCreateCallout(storeItem, item, i, display, j, count);
+ }
+ for (p in label) {
+ if (label[p] && label[p].setAttributes) {
+ label[p].setAttributes(styles, true);
+ }
+ }
+ if (!display) {
+ for (p in label) {
+ if (label[p]) {
+ if (label[p].setAttributes) {
+ label[p].setAttributes({
+ hidden: true
+ }, true);
+ } else if(label[p].setVisible) {
+ label[p].setVisible(false);
+ }
+ }
+ }
+ }
+ config.renderer(label, storeItem);
+ me.onPlaceCallout(label, storeItem, item, i, display, animate,
+ j, count, previouslyPlacedCallouts);
+ previouslyPlacedCallouts.push(label);
+ count++;
+ }
+ }
+ this.hideCallouts(count);
+ },
+
+ onCreateCallout: function(storeItem, item, i, display) {
+ var me = this,
+ group = me.calloutsGroup,
+ config = me.callouts,
+ styles = config.styles,
+ width = styles.width,
+ height = styles.height,
+ chart = me.chart,
+ surface = chart.surface,
+ calloutObj = {
+
+
+ lines: false
+ };
+
+ calloutObj.lines = surface.add(Ext.apply({},
+ {
+ type: 'path',
+ path: 'M0,0',
+ stroke: me.getLegendColor() || '#555'
+ },
+ styles));
+
+ if (config.items) {
+ calloutObj.panel = Ext.create('widget.panel', {
+ style: "position: absolute;",
+ width: width,
+ height: height,
+ items: config.items,
+ renderTo: chart.el
+ });
+ }
+
+ return calloutObj;
+ },
+
+ hideCallouts: function(index) {
+ var calloutsArray = this.calloutsArray,
+ len = calloutsArray.length,
+ co,
+ p;
+ while (len-->index) {
+ co = calloutsArray[len];
+ for (p in co) {
+ if (co[p]) {
+ co[p].hide(true);
+ }
+ }
+ }
+ }
+});
+
+
+Ext.define('Ext.draw.CompositeSprite', {
+
+
+
+ extend: 'Ext.util.MixedCollection',
+ mixins: {
+ animate: 'Ext.util.Animate'
+ },
+
+
+ isCompositeSprite: true,
+ constructor: function(config) {
+ var me = this;
+
+ config = config || {};
+ Ext.apply(me, config);
+
+ me.addEvents(
+ 'mousedown',
+ 'mouseup',
+ 'mouseover',
+ 'mouseout',
+ 'click'
+ );
+ me.id = Ext.id(null, 'ext-sprite-group-');
+ me.callParent();
+ },
+
+
+ onClick: function(e) {
+ this.fireEvent('click', e);
+ },
+
+
+ onMouseUp: function(e) {
+ this.fireEvent('mouseup', e);
+ },
+
+
+ onMouseDown: function(e) {
+ this.fireEvent('mousedown', e);
+ },
+
+
+ onMouseOver: function(e) {
+ this.fireEvent('mouseover', e);
+ },
+
+
+ onMouseOut: function(e) {
+ this.fireEvent('mouseout', e);
+ },
+
+ attachEvents: function(o) {
+ var me = this;
+
+ o.on({
+ scope: me,
+ mousedown: me.onMouseDown,
+ mouseup: me.onMouseUp,
+ mouseover: me.onMouseOver,
+ mouseout: me.onMouseOut,
+ click: me.onClick
+ });
+ },
+
+
+ add: function(key, o) {
+ var result = this.callParent(arguments);
+ this.attachEvents(result);
+ return result;
+ },
+
+ insert: function(index, key, o) {
+ return this.callParent(arguments);
+ },
+
+
+ remove: function(o) {
+ var me = this;
+
+ o.un({
+ scope: me,
+ mousedown: me.onMouseDown,
+ mouseup: me.onMouseUp,
+ mouseover: me.onMouseOver,
+ mouseout: me.onMouseOut,
+ click: me.onClick
+ });
+ me.callParent(arguments);
+ },
+
+
+ getBBox: function() {
+ var i = 0,
+ sprite,
+ bb,
+ items = this.items,
+ len = this.length,
+ infinity = Infinity,
+ minX = infinity,
+ maxHeight = -infinity,
+ minY = infinity,
+ maxWidth = -infinity,
+ maxWidthBBox, maxHeightBBox;
+
+ for (; i < len; i++) {
+ sprite = items[i];
+ if (sprite.el) {
+ bb = sprite.getBBox();
+ minX = Math.min(minX, bb.x);
+ minY = Math.min(minY, bb.y);
+ maxHeight = Math.max(maxHeight, bb.height + bb.y);
+ maxWidth = Math.max(maxWidth, bb.width + bb.x);
+ }
+ }
+
+ return {
+ x: minX,
+ y: minY,
+ height: maxHeight - minY,
+ width: maxWidth - minX
+ };
+ },
+
+
+ setAttributes: function(attrs, redraw) {
+ var i = 0,
+ items = this.items,
+ len = this.length;
+
+ for (; i < len; i++) {
+ items[i].setAttributes(attrs, redraw);
+ }
+ return this;
+ },
+
+
+ hide: function(attrs) {
+ var i = 0,
+ items = this.items,
+ len = this.length;
+
+ for (; i < len; i++) {
+ items[i].hide();
+ }
+ return this;
+ },
+
+
+ show: function(attrs) {
+ var i = 0,
+ items = this.items,
+ len = this.length;
+
+ for (; i < len; i++) {
+ items[i].show();
+ }
+ return this;
+ },
+
+ redraw: function() {
+ var me = this,
+ i = 0,
+ items = me.items,
+ surface = me.getSurface(),
+ len = me.length;
+
+ if (surface) {
+ for (; i < len; i++) {
+ surface.renderItem(items[i]);
+ }
+ }
+ return me;
+ },
+
+ setStyle: function(obj) {
+ var i = 0,
+ items = this.items,
+ len = this.length,
+ item, el;
+
+ for (; i < len; i++) {
+ item = items[i];
+ el = item.el;
+ if (el) {
+ el.setStyle(obj);
+ }
+ }
+ },
+
+ addCls: function(obj) {
+ var i = 0,
+ items = this.items,
+ surface = this.getSurface(),
+ len = this.length;
+
+ if (surface) {
+ for (; i < len; i++) {
+ surface.addCls(items[i], obj);
+ }
+ }
+ },
+
+ removeCls: function(obj) {
+ var i = 0,
+ items = this.items,
+ surface = this.getSurface(),
+ len = this.length;
+
+ if (surface) {
+ for (; i < len; i++) {
+ surface.removeCls(items[i], obj);
+ }
+ }
+ },
+
+
+ getSurface: function(){
+ var first = this.first();
+ if (first) {
+ return first.surface;
+ }
+ return null;
+ },
+
+
+ destroy: function(){
+ var me = this,
+ surface = me.getSurface(),
+ item;
+
+ if (surface) {
+ while (me.getCount() > 0) {
+ item = me.first();
+ me.remove(item);
+ surface.remove(item);
+ }
+ }
+ me.clearListeners();
+ }
+});
+
+
+
+Ext.define('Ext.layout.component.Draw', {
+
+
+
+ alias: 'layout.draw',
+
+ extend: 'Ext.layout.component.Auto',
+
+
+
+ type: 'draw',
+
+ onLayout : function(width, height) {
+ this.owner.surface.setSize(width, height);
+ this.callParent(arguments);
+ }
+});
+
+Ext.define('Ext.chart.theme.Theme', {
+
+
+
+ requires: ['Ext.draw.Color'],
+
+
+
+ theme: 'Base',
+ themeAttrs: false,
+
+ initTheme: function(theme) {
+ var me = this,
+ themes = Ext.chart.theme,
+ key, gradients;
+ if (theme) {
+ theme = theme.split(':');
+ for (key in themes) {
+ if (key == theme[0]) {
+ gradients = theme[1] == 'gradients';
+ me.themeAttrs = new themes[key]({
+ useGradients: gradients
+ });
+ if (gradients) {
+ me.gradients = me.themeAttrs.gradients;
+ }
+ if (me.themeAttrs.background) {
+ me.background = me.themeAttrs.background;
+ }
+ return;
+ }
+ }
+ Ext.Error.raise('No theme found named "' + theme + '"');
+ }
+ }
+},
+
+function() {
+
+
+(function() {
+ Ext.chart.theme = function(config, base) {
+ config = config || {};
+ var i = 0, l, colors, color,
+ seriesThemes, markerThemes,
+ seriesTheme, markerTheme,
+ key, gradients = [],
+ midColor, midL;
+
+ if (config.baseColor) {
+ midColor = Ext.draw.Color.fromString(config.baseColor);
+ midL = midColor.getHSL()[2];
+ if (midL < 0.15) {
+ midColor = midColor.getLighter(0.3);
+ } else if (midL < 0.3) {
+ midColor = midColor.getLighter(0.15);
+ } else if (midL > 0.85) {
+ midColor = midColor.getDarker(0.3);
+ } else if (midL > 0.7) {
+ midColor = midColor.getDarker(0.15);
+ }
+ config.colors = [ midColor.getDarker(0.3).toString(),
+ midColor.getDarker(0.15).toString(),
+ midColor.toString(),
+ midColor.getLighter(0.15).toString(),
+ midColor.getLighter(0.3).toString()];
+
+ delete config.baseColor;
+ }
+ if (config.colors) {
+ colors = config.colors.slice();
+ markerThemes = base.markerThemes;
+ seriesThemes = base.seriesThemes;
+ l = colors.length;
+ base.colors = colors;
+ for (; i < l; i++) {
+ color = colors[i];
+ markerTheme = markerThemes[i] || {};
+ seriesTheme = seriesThemes[i] || {};
+ markerTheme.fill = seriesTheme.fill = markerTheme.stroke = seriesTheme.stroke = color;
+ markerThemes[i] = markerTheme;
+ seriesThemes[i] = seriesTheme;
+ }
+ base.markerThemes = markerThemes.slice(0, l);
+ base.seriesThemes = seriesThemes.slice(0, l);
+
+ }
+ for (key in base) {
+ if (key in config) {
+ if (Ext.isObject(config[key]) && Ext.isObject(base[key])) {
+ Ext.apply(base[key], config[key]);
+ } else {
+ base[key] = config[key];
+ }
+ }
+ }
+ if (config.useGradients) {
+ colors = base.colors || (function () {
+ var ans = [];
+ for (i = 0, seriesThemes = base.seriesThemes, l = seriesThemes.length; i < l; i++) {
+ ans.push(seriesThemes[i].fill || seriesThemes[i].stroke);
+ }
+ return ans;
+ })();
+ for (i = 0, l = colors.length; i < l; i++) {
+ midColor = Ext.draw.Color.fromString(colors[i]);
+ if (midColor) {
+ color = midColor.getDarker(0.1).toString();
+ midColor = midColor.toString();
+ key = 'theme-' + midColor.substr(1) + '-' + color.substr(1);
+ gradients.push({
+ id: key,
+ angle: 45,
+ stops: {
+ 0: {
+ color: midColor.toString()
+ },
+ 100: {
+ color: color.toString()
+ }
+ }
+ });
+ colors[i] = 'url(#' + key + ')';
+ }
+ }
+ base.gradients = gradients;
+ base.colors = colors;
+ }
+
+ Ext.apply(this, base);
+ };
+})();
+});
+
+
+Ext.define('Ext.chart.Mask', {
+ constructor: function(config) {
+ var me = this;
+
+ me.addEvents('select');
+
+ if (config) {
+ Ext.apply(me, config);
+ }
+ if (me.mask) {
+ me.on('afterrender', function() {
+
+ var comp = Ext.create('Ext.chart.MaskLayer', {
+ renderTo: me.el
+ });
+ comp.el.on({
+ 'mousemove': function(e) {
+ me.onMouseMove(e);
+ },
+ 'mouseup': function(e) {
+ me.resized(e);
+ }
+ });
+
+ var resizeHandler = Ext.create('Ext.resizer.Resizer', {
+ el: comp.el,
+ handles: 'all',
+ pinned: true
+ });
+ resizeHandler.on({
+ 'resize': function(e) {
+ me.resized(e);
+ }
+ });
+ comp.initDraggable();
+ me.maskType = me.mask;
+ me.mask = comp;
+ me.maskSprite = me.surface.add({
+ type: 'path',
+ path: ['M', 0, 0],
+ zIndex: 1001,
+ opacity: 0.7,
+ hidden: true,
+ stroke: '#444'
+ });
+ }, me, { single: true });
+ }
+ },
+
+ resized: function(e) {
+ var me = this,
+ bbox = me.bbox || me.chartBBox,
+ x = bbox.x,
+ y = bbox.y,
+ width = bbox.width,
+ height = bbox.height,
+ box = me.mask.getBox(true),
+ max = Math.max,
+ min = Math.min,
+ staticX = box.x - x,
+ staticY = box.y - y;
+
+ staticX = max(staticX, x);
+ staticY = max(staticY, y);
+ staticX = min(staticX, width);
+ staticY = min(staticY, height);
+ box.x = staticX;
+ box.y = staticY;
+ me.fireEvent('select', me, box);
+ },
+
+ onMouseUp: function(e) {
+ var me = this,
+ bbox = me.bbox || me.chartBBox,
+ sel = me.maskSelection;
+ me.maskMouseDown = false;
+ me.mouseDown = false;
+ if (me.mouseMoved) {
+ me.onMouseMove(e);
+ me.mouseMoved = false;
+ me.fireEvent('select', me, {
+ x: sel.x - bbox.x,
+ y: sel.y - bbox.y,
+ width: sel.width,
+ height: sel.height
+ });
+ }
+ },
+
+ onMouseDown: function(e) {
+ var me = this;
+ me.mouseDown = true;
+ me.mouseMoved = false;
+ me.maskMouseDown = {
+ x: e.getPageX() - me.el.getX(),
+ y: e.getPageY() - me.el.getY()
+ };
+ },
+
+ onMouseMove: function(e) {
+ var me = this,
+ mask = me.maskType,
+ bbox = me.bbox || me.chartBBox,
+ x = bbox.x,
+ y = bbox.y,
+ math = Math,
+ floor = math.floor,
+ abs = math.abs,
+ min = math.min,
+ max = math.max,
+ height = floor(y + bbox.height),
+ width = floor(x + bbox.width),
+ posX = e.getPageX(),
+ posY = e.getPageY(),
+ staticX = posX - me.el.getX(),
+ staticY = posY - me.el.getY(),
+ maskMouseDown = me.maskMouseDown,
+ path;
+
+ me.mouseMoved = me.mouseDown;
+ staticX = max(staticX, x);
+ staticY = max(staticY, y);
+ staticX = min(staticX, width);
+ staticY = min(staticY, height);
+ if (maskMouseDown && me.mouseDown) {
+ if (mask == 'horizontal') {
+ staticY = y;
+ maskMouseDown.y = height;
+ posY = me.el.getY() + bbox.height + me.insetPadding;
+ }
+ else if (mask == 'vertical') {
+ staticX = x;
+ maskMouseDown.x = width;
+ }
+ width = maskMouseDown.x - staticX;
+ height = maskMouseDown.y - staticY;
+ path = ['M', staticX, staticY, 'l', width, 0, 0, height, -width, 0, 'z'];
+ me.maskSelection = {
+ x: width > 0 ? staticX : staticX + width,
+ y: height > 0 ? staticY : staticY + height,
+ width: abs(width),
+ height: abs(height)
+ };
+ me.mask.updateBox({
+ x: posX - abs(width),
+ y: posY - abs(height),
+ width: abs(width),
+ height: abs(height)
+ });
+ me.mask.show();
+ me.maskSprite.setAttributes({
+ hidden: true
+ }, true);
+ }
+ else {
+ if (mask == 'horizontal') {
+ path = ['M', staticX, y, 'L', staticX, height];
+ }
+ else if (mask == 'vertical') {
+ path = ['M', x, staticY, 'L', width, staticY];
+ }
+ else {
+ path = ['M', staticX, y, 'L', staticX, height, 'M', x, staticY, 'L', width, staticY];
+ }
+ me.maskSprite.setAttributes({
+ path: path,
+ fill: me.maskMouseDown ? me.maskSprite.stroke : false,
+ 'stroke-width': mask === true ? 1 : 3,
+ hidden: false
+ }, true);
+ }
+ },
+
+ onMouseLeave: function(e) {
+ var me = this;
+ me.mouseMoved = false;
+ me.mouseDown = false;
+ me.maskMouseDown = false;
+ me.mask.hide();
+ me.maskSprite.hide(true);
+ }
+});
+
+
+Ext.define('Ext.chart.Navigation', {
+
+ constructor: function() {
+ this.originalStore = this.store;
+ },
+
+
+ setZoom: function(zoomConfig) {
+ var me = this,
+ store = me.substore || me.store,
+ bbox = me.chartBBox,
+ len = store.getCount(),
+ from = (zoomConfig.x / bbox.width * len) >> 0,
+ to = Math.ceil(((zoomConfig.x + zoomConfig.width) / bbox.width * len)),
+ recFieldsLen, recFields = [], curField, json = [], obj;
+
+ store.each(function(rec, i) {
+ if (i < from || i > to) {
+ return;
+ }
+ obj = {};
+
+ if (!recFields.length) {
+ rec.fields.each(function(f) {
+ recFields.push(f.name);
+ });
+ recFieldsLen = recFields.length;
+ }
+
+ for (i = 0; i < recFieldsLen; i++) {
+ curField = recFields[i];
+ obj[curField] = rec.get(curField);
+ }
+ json.push(obj);
+ });
+ me.store = me.substore = Ext.create('Ext.data.JsonStore', {
+ fields: recFields,
+ data: json
+ });
+ me.redraw(true);
+ },
+
+ restoreZoom: function() {
+ this.store = this.substore = this.originalStore;
+ this.redraw(true);
+ }
+
+});
+
+Ext.define('Ext.chart.Shape', {
+
+
+
+ singleton: true,
+
+
+
+ circle: function (surface, opts) {
+ return surface.add(Ext.apply({
+ type: 'circle',
+ x: opts.x,
+ y: opts.y,
+ stroke: null,
+ radius: opts.radius
+ }, opts));
+ },
+ line: function (surface, opts) {
+ return surface.add(Ext.apply({
+ type: 'rect',
+ x: opts.x - opts.radius,
+ y: opts.y - opts.radius,
+ height: 2 * opts.radius,
+ width: 2 * opts.radius / 5
+ }, opts));
+ },
+ square: function (surface, opts) {
+ return surface.add(Ext.applyIf({
+ type: 'rect',
+ x: opts.x - opts.radius,
+ y: opts.y - opts.radius,
+ height: 2 * opts.radius,
+ width: 2 * opts.radius,
+ radius: null
+ }, opts));
+ },
+ triangle: function (surface, opts) {
+ opts.radius *= 1.75;
+ return surface.add(Ext.apply({
+ type: 'path',
+ stroke: null,
+ path: "M".concat(opts.x, ",", opts.y, "m0-", opts.radius * 0.58, "l", opts.radius * 0.5, ",", opts.radius * 0.87, "-", opts.radius, ",0z")
+ }, opts));
+ },
+ diamond: function (surface, opts) {
+ var r = opts.radius;
+ r *= 1.5;
+ return surface.add(Ext.apply({
+ type: 'path',
+ stroke: null,
+ path: ["M", opts.x, opts.y - r, "l", r, r, -r, r, -r, -r, r, -r, "z"]
+ }, opts));
+ },
+ cross: function (surface, opts) {
+ var r = opts.radius;
+ r = r / 1.7;
+ return surface.add(Ext.apply({
+ type: 'path',
+ stroke: null,
+ path: "M".concat(opts.x - r, ",", opts.y, "l", [-r, -r, r, -r, r, r, r, -r, r, r, -r, r, r, r, -r, r, -r, -r, -r, r, -r, -r, "z"])
+ }, opts));
+ },
+ plus: function (surface, opts) {
+ var r = opts.radius / 1.3;
+ return surface.add(Ext.apply({
+ type: 'path',
+ stroke: null,
+ path: "M".concat(opts.x - r / 2, ",", opts.y - r / 2, "l", [0, -r, r, 0, 0, r, r, 0, 0, r, -r, 0, 0, r, -r, 0, 0, -r, -r, 0, 0, -r, "z"])
+ }, opts));
+ },
+ arrow: function (surface, opts) {
+ var r = opts.radius;
+ return surface.add(Ext.apply({
+ type: 'path',
+ path: "M".concat(opts.x - r * 0.7, ",", opts.y - r * 0.4, "l", [r * 0.6, 0, 0, -r * 0.4, r, r * 0.8, -r, r * 0.8, 0, -r * 0.4, -r * 0.6, 0], "z")
+ }, opts));
+ },
+ drop: function (surface, x, y, text, size, angle) {
+ size = size || 30;
+ angle = angle || 0;
+ surface.add({
+ type: 'path',
+ path: ['M', x, y, 'l', size, 0, 'A', size * 0.4, size * 0.4, 0, 1, 0, x + size * 0.7, y - size * 0.7, 'z'],
+ fill: '#000',
+ stroke: 'none',
+ rotate: {
+ degrees: 22.5 - angle,
+ x: x,
+ y: y
+ }
+ });
+ angle = (angle + 90) * Math.PI / 180;
+ surface.add({
+ type: 'text',
+ x: x + size * Math.sin(angle) - 10,
+ y: y + size * Math.cos(angle) + 5,
+ text: text,
+ 'font-size': size * 12 / 40,
+ stroke: 'none',
+ fill: '#fff'
+ });
+ }
+});
+
+Ext.define('Ext.draw.Surface', {
+
+
+
+ mixins: {
+ observable: 'Ext.util.Observable'
+ },
+
+ requires: ['Ext.draw.CompositeSprite'],
+ uses: ['Ext.draw.engine.Svg', 'Ext.draw.engine.Vml'],
+
+ separatorRe: /[, ]+/,
+
+ statics: {
+
+ create: function(config, enginePriority) {
+ enginePriority = enginePriority || ['Svg', 'Vml'];
+
+ var i = 0,
+ len = enginePriority.length,
+ surfaceClass;
+
+ for (; i < len; i++) {
+ if (Ext.supports[enginePriority[i]]) {
+ return Ext.create('Ext.draw.engine.' + enginePriority[i], config);
+ }
+ }
+ return false;
+ }
+ },
+
+
+
+
+ availableAttrs: {
+ blur: 0,
+ "clip-rect": "0 0 1e9 1e9",
+ cursor: "default",
+ cx: 0,
+ cy: 0,
+ 'dominant-baseline': 'auto',
+ fill: "none",
+ "fill-opacity": 1,
+ font: '10px "Arial"',
+ "font-family": '"Arial"',
+ "font-size": "10",
+ "font-style": "normal",
+ "font-weight": 400,
+ gradient: "",
+ height: 0,
+ hidden: false,
+ href: "http://sencha.com/",
+ opacity: 1,
+ path: "M0,0",
+ radius: 0,
+ rx: 0,
+ ry: 0,
+ scale: "1 1",
+ src: "",
+ stroke: "#000",
+ "stroke-dasharray": "",
+ "stroke-linecap": "butt",
+ "stroke-linejoin": "butt",
+ "stroke-miterlimit": 0,
+ "stroke-opacity": 1,
+ "stroke-width": 1,
+ target: "_blank",
+ text: "",
+ "text-anchor": "middle",
+ title: "Ext Draw",
+ width: 0,
+ x: 0,
+ y: 0,
+ zIndex: 0
+ },
+
+
+
+ container: undefined,
+ height: 352,
+ width: 512,
+ x: 0,
+ y: 0,
+
+ constructor: function(config) {
+ var me = this;
+ config = config || {};
+ Ext.apply(me, config);
+
+ me.domRef = Ext.getDoc().dom;
+
+ me.customAttributes = {};
+
+ me.addEvents(
+ 'mousedown',
+ 'mouseup',
+ 'mouseover',
+ 'mouseout',
+ 'mousemove',
+ 'mouseenter',
+ 'mouseleave',
+ 'click'
+ );
+
+ me.mixins.observable.constructor.call(me);
+
+ me.getId();
+ me.initGradients();
+ me.initItems();
+ if (me.renderTo) {
+ me.render(me.renderTo);
+ delete me.renderTo;
+ }
+ me.initBackground(config.background);
+ },
+
+
+
+ initSurface: Ext.emptyFn,
+
+
+
+ renderItem: Ext.emptyFn,
+
+
+ renderItems: Ext.emptyFn,
+
+
+ setViewBox: Ext.emptyFn,
+
+
+ addCls: Ext.emptyFn,
+
+
+ removeCls: Ext.emptyFn,
+
+
+ setStyle: Ext.emptyFn,
+
+
+ initGradients: function() {
+ var gradients = this.gradients;
+ if (gradients) {
+ Ext.each(gradients, this.addGradient, this);
+ }
+ },
+
+
+ initItems: function() {
+ var items = this.items;
+ this.items = Ext.create('Ext.draw.CompositeSprite');
+ this.groups = Ext.create('Ext.draw.CompositeSprite');
+ if (items) {
+ this.add(items);
+ }
+ },
+
+
+ initBackground: function(config) {
+ var gradientId,
+ gradient,
+ backgroundSprite,
+ width = this.width,
+ height = this.height;
+ if (config) {
+ if (config.gradient) {
+ gradient = config.gradient;
+ gradientId = gradient.id;
+ this.addGradient(gradient);
+ this.background = this.add({
+ type: 'rect',
+ x: 0,
+ y: 0,
+ width: width,
+ height: height,
+ fill: 'url(#' + gradientId + ')'
+ });
+ } else if (config.fill) {
+ this.background = this.add({
+ type: 'rect',
+ x: 0,
+ y: 0,
+ width: width,
+ height: height,
+ fill: config.fill
+ });
+ } else if (config.image) {
+ this.background = this.add({
+ type: 'image',
+ x: 0,
+ y: 0,
+ width: width,
+ height: height,
+ src: config.image
+ });
+ }
+ }
+ },
+
+
+ setSize: function(w, h) {
+ if (this.background) {
+ this.background.setAttributes({
+ width: w,
+ height: h,
+ hidden: false
+ }, true);
+ }
+ },
+
+
+ scrubAttrs: function(sprite) {
+ var i,
+ attrs = {},
+ exclude = {},
+ sattr = sprite.attr;
+ for (i in sattr) {
+
+ if (this.translateAttrs.hasOwnProperty(i)) {
+
+ attrs[this.translateAttrs[i]] = sattr[i];
+ exclude[this.translateAttrs[i]] = true;
+ }
+ else if (this.availableAttrs.hasOwnProperty(i) && !exclude[i]) {
+
+ attrs[i] = sattr[i];
+ }
+ }
+ return attrs;
+ },
+
+
+ onClick: function(e) {
+ this.processEvent('click', e);
+ },
+
+
+ onMouseUp: function(e) {
+ this.processEvent('mouseup', e);
+ },
+
+
+ onMouseDown: function(e) {
+ this.processEvent('mousedown', e);
+ },
+
+
+ onMouseOver: function(e) {
+ this.processEvent('mouseover', e);
+ },
+
+
+ onMouseOut: function(e) {
+ this.processEvent('mouseout', e);
+ },
+
+
+ onMouseMove: function(e) {
+ this.fireEvent('mousemove', e);
+ },
+
+
+ onMouseEnter: Ext.emptyFn,
+
+
+ onMouseLeave: Ext.emptyFn,
+
+
+ addGradient: Ext.emptyFn,
+
+
+ add: function() {
+ var args = Array.prototype.slice.call(arguments),
+ sprite,
+ index;
+
+ var hasMultipleArgs = args.length > 1;
+ if (hasMultipleArgs || Ext.isArray(args[0])) {
+ var items = hasMultipleArgs ? args : args[0],
+ results = [],
+ i, ln, item;
+
+ for (i = 0, ln = items.length; i < ln; i++) {
+ item = items[i];
+ item = this.add(item);
+ results.push(item);
+ }
+
+ return results;
+ }
+ sprite = this.prepareItems(args[0], true)[0];
+ this.normalizeSpriteCollection(sprite);
+ this.onAdd(sprite);
+ return sprite;
+ },
+
+
+ normalizeSpriteCollection: function(sprite) {
+ var items = this.items,
+ zIndex = sprite.attr.zIndex,
+ idx = items.indexOf(sprite);
+
+ if (idx < 0 || (idx > 0 && items.getAt(idx - 1).attr.zIndex > zIndex) ||
+ (idx < items.length - 1 && items.getAt(idx + 1).attr.zIndex < zIndex)) {
+ items.removeAt(idx);
+ idx = items.findIndexBy(function(otherSprite) {
+ return otherSprite.attr.zIndex > zIndex;
+ });
+ if (idx < 0) {
+ idx = items.length;
+ }
+ items.insert(idx, sprite);
+ }
+ return idx;
+ },
+
+ onAdd: function(sprite) {
+ var group = sprite.group,
+ draggable = sprite.draggable,
+ groups, ln, i;
+ if (group) {
+ groups = [].concat(group);
+ ln = groups.length;
+ for (i = 0; i < ln; i++) {
+ group = groups[i];
+ this.getGroup(group).add(sprite);
+ }
+ delete sprite.group;
+ }
+ if (draggable) {
+ sprite.initDraggable();
+ }
+ },
+
+
+ remove: function(sprite, destroySprite) {
+ if (sprite) {
+ this.items.remove(sprite);
+ this.groups.each(function(item) {
+ item.remove(sprite);
+ });
+ sprite.onRemove();
+ if (destroySprite === true) {
+ sprite.destroy();
+ }
+ }
+ },
+
+
+ removeAll: function(destroySprites) {
+ var items = this.items.items,
+ ln = items.length,
+ i;
+ for (i = ln - 1; i > -1; i--) {
+ this.remove(items[i], destroySprites);
+ }
+ },
+
+ onRemove: Ext.emptyFn,
+
+ onDestroy: Ext.emptyFn,
+
+
+ applyTransformations: function(sprite) {
+ sprite.bbox.transform = 0;
+ this.transform(sprite);
+
+ var me = this,
+ dirty = false,
+ attr = sprite.attr;
+
+ if (attr.translation.x != null || attr.translation.y != null) {
+ me.translate(sprite);
+ dirty = true;
+ }
+ if (attr.scaling.x != null || attr.scaling.y != null) {
+ me.scale(sprite);
+ dirty = true;
+ }
+ if (attr.rotation.degrees != null) {
+ me.rotate(sprite);
+ dirty = true;
+ }
+ if (dirty) {
+ sprite.bbox.transform = 0;
+ this.transform(sprite);
+ sprite.transformations = [];
+ }
+ },
+
+
+ rotate: function (sprite) {
+ var bbox,
+ deg = sprite.attr.rotation.degrees,
+ centerX = sprite.attr.rotation.x,
+ centerY = sprite.attr.rotation.y;
+ if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
+ bbox = this.getBBox(sprite);
+ centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
+ centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
+ }
+ sprite.transformations.push({
+ type: "rotate",
+ degrees: deg,
+ x: centerX,
+ y: centerY
+ });
+ },
+
+
+ translate: function(sprite) {
+ var x = sprite.attr.translation.x || 0,
+ y = sprite.attr.translation.y || 0;
+ sprite.transformations.push({
+ type: "translate",
+ x: x,
+ y: y
+ });
+ },
+
+
+ scale: function(sprite) {
+ var bbox,
+ x = sprite.attr.scaling.x || 1,
+ y = sprite.attr.scaling.y || 1,
+ centerX = sprite.attr.scaling.centerX,
+ centerY = sprite.attr.scaling.centerY;
+
+ if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
+ bbox = this.getBBox(sprite);
+ centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
+ centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
+ }
+ sprite.transformations.push({
+ type: "scale",
+ x: x,
+ y: y,
+ centerX: centerX,
+ centerY: centerY
+ });
+ },
+
+
+ rectPath: function (x, y, w, h, r) {
+ if (r) {
+ return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]];
+ }
+ return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
+ },
+
+
+ ellipsePath: function (x, y, rx, ry) {
+ if (ry == null) {
+ ry = rx;
+ }
+ return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]];
+ },
+
+
+ getPathpath: function (el) {
+ return el.attr.path;
+ },
+
+
+ getPathcircle: function (el) {
+ var a = el.attr;
+ return this.ellipsePath(a.x, a.y, a.radius, a.radius);
+ },
+
+
+ getPathellipse: function (el) {
+ var a = el.attr;
+ return this.ellipsePath(a.x, a.y, a.radiusX, a.radiusY);
+ },
+
+
+ getPathrect: function (el) {
+ var a = el.attr;
+ return this.rectPath(a.x, a.y, a.width, a.height, a.r);
+ },
+
+
+ getPathimage: function (el) {
+ var a = el.attr;
+ return this.rectPath(a.x || 0, a.y || 0, a.width, a.height);
+ },
+
+
+ getPathtext: function (el) {
+ var bbox = this.getBBoxText(el);
+ return this.rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
+ },
+
+ createGroup: function(id) {
+ var group = this.groups.get(id);
+ if (!group) {
+ group = Ext.create('Ext.draw.CompositeSprite', {
+ surface: this
+ });
+ group.id = id || Ext.id(null, 'ext-surface-group-');
+ this.groups.add(group);
+ }
+ return group;
+ },
+
+
+ getGroup: function(id) {
+ if (typeof id == "string") {
+ var group = this.groups.get(id);
+ if (!group) {
+ group = this.createGroup(id);
+ }
+ } else {
+ group = id;
+ }
+ return group;
+ },
+
+
+ prepareItems: function(items, applyDefaults) {
+ items = [].concat(items);
+
+ var item, i, ln;
+ for (i = 0, ln = items.length; i < ln; i++) {
+ item = items[i];
+ if (!(item instanceof Ext.draw.Sprite)) {
+
+ item.surface = this;
+ items[i] = this.createItem(item);
+ } else {
+ item.surface = this;
+ }
+ }
+ return items;
+ },
+
+
+ setText: Ext.emptyFn,
+
+ //@private Creates an item and appends it to the surface. Called
+
+
+ createItem: Ext.emptyFn,
+
+
+ getId: function() {
+ return this.id || (this.id = Ext.id(null, 'ext-surface-'));
+ },
+
+
+ destroy: function() {
+ delete this.domRef;
+ this.removeAll();
+ }
+});
+
+Ext.define('Ext.draw.Component', {
+
+
+
+ alias: 'widget.draw',
+
+ extend: 'Ext.Component',
+
+ requires: [
+ 'Ext.draw.Surface',
+ 'Ext.layout.component.Draw'
+ ],
+
+
+
+
+ enginePriority: ['Svg', 'Vml'],
+
+ baseCls: Ext.baseCSSPrefix + 'surface',
+
+ componentLayout: 'draw',
+
+
+ viewBox: true,
+
+
+ autoSize: false,
+
+
+
+ initComponent: function() {
+ this.callParent(arguments);
+
+ this.addEvents(
+ 'mousedown',
+ 'mouseup',
+ 'mousemove',
+ 'mouseenter',
+ 'mouseleave',
+ 'click'
+ );
+ },
+
+
+ onRender: function() {
+ var me = this,
+ viewBox = me.viewBox,
+ autoSize = me.autoSize,
+ bbox, items, width, height, x, y;
+ me.callParent(arguments);
+
+ me.createSurface();
+
+ items = me.surface.items;
+
+ if (viewBox || autoSize) {
+ bbox = items.getBBox();
+ width = bbox.width;
+ height = bbox.height;
+ x = bbox.x;
+ y = bbox.y;
+ if (me.viewBox) {
+ me.surface.setViewBox(x, y, width, height);
+ }
+ else {
+
+ me.autoSizeSurface();
+ }
+ }
+ },
+
+ //@private
+
+ autoSizeSurface: function() {
+ var me = this,
+ items = me.surface.items,
+ bbox = items.getBBox(),
+ width = bbox.width,
+ height = bbox.height;
+ items.setAttributes({
+ translate: {
+ x: -bbox.x,
+
+ y: -bbox.y + (+Ext.isOpera)
+ }
+ }, true);
+ if (me.rendered) {
+ me.setSize(width, height);
+ }
+ else {
+ me.surface.setSize(width, height);
+ }
+ me.el.setSize(width, height);
+ },
+
+
+ createSurface: function() {
+ var surface = Ext.draw.Surface.create(Ext.apply({}, {
+ width: this.width,
+ height: this.height,
+ renderTo: this.el
+ }, this.initialConfig));
+ this.surface = surface;
+
+ function refire(eventName) {
+ return function(e) {
+ this.fireEvent(eventName, e);
+ };
+ }
+
+ surface.on({
+ scope: this,
+ mouseup: refire('mouseup'),
+ mousedown: refire('mousedown'),
+ mousemove: refire('mousemove'),
+ mouseenter: refire('mouseenter'),
+ mouseleave: refire('mouseleave'),
+ click: refire('click')
+ });
+ },
+
+
+
+ onDestroy: function() {
+ var surface = this.surface;
+ if (surface) {
+ surface.destroy();
+ }
+ this.callParent(arguments);
+ }
+
+});
+
+
+Ext.define('Ext.chart.LegendItem', {
+
+
+
+ extend: 'Ext.draw.CompositeSprite',
+
+ requires: ['Ext.chart.Shape'],
+
+
+
+
+ x: 0,
+ y: 0,
+ zIndex: 500,
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ this.createLegend(config);
+ },
+
+
+ createLegend: function(config) {
+ var me = this,
+ index = config.yFieldIndex,
+ series = me.series,
+ seriesType = series.type,
+ idx = me.yFieldIndex,
+ legend = me.legend,
+ surface = me.surface,
+ refX = legend.x + me.x,
+ refY = legend.y + me.y,
+ bbox, z = me.zIndex,
+ markerConfig, label, mask,
+ radius, toggle = false,
+ seriesStyle = Ext.apply(series.seriesStyle, series.style);
+
+ function getSeriesProp(name) {
+ var val = series[name];
+ return (Ext.isArray(val) ? val[idx] : val);
+ }
+
+ label = me.add('label', surface.add({
+ type: 'text',
+ x: 20,
+ y: 0,
+ zIndex: z || 0,
+ font: legend.labelFont,
+ text: getSeriesProp('title') || getSeriesProp('yField')
+ }));
+
+
+ if (seriesType === 'line' || seriesType === 'scatter') {
+ if(seriesType === 'line') {
+ me.add('line', surface.add({
+ type: 'path',
+ path: 'M0.5,0.5L16.5,0.5',
+ zIndex: z,
+ "stroke-width": series.lineWidth,
+ "stroke-linejoin": "round",
+ "stroke-dasharray": series.dash,
+ stroke: seriesStyle.stroke || '#000',
+ style: {
+ cursor: 'pointer'
+ }
+ }));
+ }
+ if (series.showMarkers || seriesType === 'scatter') {
+ markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {});
+ me.add('marker', Ext.chart.Shape[markerConfig.type](surface, {
+ fill: markerConfig.fill,
+ x: 8.5,
+ y: 0.5,
+ zIndex: z,
+ radius: markerConfig.radius || markerConfig.size,
+ style: {
+ cursor: 'pointer'
+ }
+ }));
+ }
+ }
+
+ else {
+ me.add('box', surface.add({
+ type: 'rect',
+ zIndex: z,
+ x: 0,
+ y: 0,
+ width: 12,
+ height: 12,
+ fill: series.getLegendColor(index),
+ style: {
+ cursor: 'pointer'
+ }
+ }));
+ }
+
+ me.setAttributes({
+ hidden: false
+ }, true);
+
+ bbox = me.getBBox();
+
+ mask = me.add('mask', surface.add({
+ type: 'rect',
+ x: bbox.x,
+ y: bbox.y,
+ width: bbox.width || 20,
+ height: bbox.height || 20,
+ zIndex: (z || 0) + 1000,
+ fill: '#f00',
+ opacity: 0,
+ style: {
+ 'cursor': 'pointer'
+ }
+ }));
+
+
+ me.on('mouseover', function() {
+ label.setStyle({
+ 'font-weight': 'bold'
+ });
+ mask.setStyle({
+ 'cursor': 'pointer'
+ });
+ series._index = index;
+ series.highlightItem();
+ }, me);
+
+ me.on('mouseout', function() {
+ label.setStyle({
+ 'font-weight': 'normal'
+ });
+ series._index = index;
+ series.unHighlightItem();
+ }, me);
+
+ if (!series.visibleInLegend(index)) {
+ toggle = true;
+ label.setAttributes({
+ opacity: 0.5
+ }, true);
+ }
+
+ me.on('mousedown', function() {
+ if (!toggle) {
+ series.hideAll();
+ label.setAttributes({
+ opacity: 0.5
+ }, true);
+ } else {
+ series.showAll();
+ label.setAttributes({
+ opacity: 1
+ }, true);
+ }
+ toggle = !toggle;
+ }, me);
+ me.updatePosition({x:0, y:0});
+ },
+
+
+ updatePosition: function(relativeTo) {
+ var me = this,
+ items = me.items,
+ ln = items.length,
+ i = 0,
+ item;
+ if (!relativeTo) {
+ relativeTo = me.legend;
+ }
+ for (; i < ln; i++) {
+ item = items[i];
+ switch (item.type) {
+ case 'text':
+ item.setAttributes({
+ x: 20 + relativeTo.x + me.x,
+ y: relativeTo.y + me.y
+ }, true);
+ break;
+ case 'rect':
+ item.setAttributes({
+ translate: {
+ x: relativeTo.x + me.x,
+ y: relativeTo.y + me.y - 6
+ }
+ }, true);
+ break;
+ default:
+ item.setAttributes({
+ translate: {
+ x: relativeTo.x + me.x,
+ y: relativeTo.y + me.y
+ }
+ }, true);
+ }
+ }
+ }
+});
+
+Ext.define('Ext.chart.Legend', {
+
+
+
+ requires: ['Ext.chart.LegendItem'],
+
+
+
+
+ visible: true,
+
+
+ position: 'bottom',
+
+
+ x: 0,
+
+
+ y: 0,
+
+
+ labelFont: '12px Helvetica, sans-serif',
+
+
+ boxStroke: '#000',
+
+
+ boxStrokeWidth: 1,
+
+
+ boxFill: '#FFF',
+
+
+ itemSpacing: 10,
+
+
+ padding: 5,
+
+
+ width: 0,
+
+ height: 0,
+
+
+ boxZIndex: 100,
+
+ constructor: function(config) {
+ var me = this;
+ if (config) {
+ Ext.apply(me, config);
+ }
+ me.items = [];
+
+ me.isVertical = ("left|right|float".indexOf(me.position) !== -1);
+
+
+ me.origX = me.x;
+ me.origY = me.y;
+ },
+
+
+ create: function() {
+ var me = this;
+ me.createItems();
+ if (!me.created && me.isDisplayed()) {
+ me.createBox();
+ me.created = true;
+
+
+ me.chart.series.each(function(series) {
+ series.on('titlechange', function() {
+ me.create();
+ me.updatePosition();
+ });
+ });
+ }
+ },
+
+
+ isDisplayed: function() {
+ return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1;
+ },
+
+
+ createItems: function() {
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ items = me.items,
+ padding = me.padding,
+ itemSpacing = me.itemSpacing,
+ spacingOffset = 2,
+ maxWidth = 0,
+ maxHeight = 0,
+ totalWidth = 0,
+ totalHeight = 0,
+ vertical = me.isVertical,
+ math = Math,
+ mfloor = math.floor,
+ mmax = math.max,
+ index = 0,
+ i = 0,
+ len = items ? items.length : 0,
+ x, y, spacing, item, bbox, height, width;
+
+
+ if (len) {
+ for (; i < len; i++) {
+ items[i].destroy();
+ }
+ }
+
+ items.length = [];
+
+
+ chart.series.each(function(series, i) {
+ if (series.showInLegend) {
+ Ext.each([].concat(series.yField), function(field, j) {
+ item = Ext.create('Ext.chart.LegendItem', {
+ legend: this,
+ series: series,
+ surface: chart.surface,
+ yFieldIndex: j
+ });
+ bbox = item.getBBox();
+
+
+ width = bbox.width;
+ height = bbox.height;
+
+ if (i + j === 0) {
+ spacing = vertical ? padding + height / 2 : padding;
+ }
+ else {
+ spacing = itemSpacing / (vertical ? 2 : 1);
+ }
+
+ item.x = mfloor(vertical ? padding : totalWidth + spacing);
+ item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
+
+
+ totalWidth += width + spacing;
+ totalHeight += height + spacing;
+ maxWidth = mmax(maxWidth, width);
+ maxHeight = mmax(maxHeight, height);
+
+ items.push(item);
+ }, this);
+ }
+ }, me);
+
+
+ me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
+ if (vertical && items.length === 1) {
+ spacingOffset = 1;
+ }
+ me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
+ me.itemHeight = maxHeight;
+ },
+
+
+ getBBox: function() {
+ var me = this;
+ return {
+ x: Math.round(me.x) - me.boxStrokeWidth / 2,
+ y: Math.round(me.y) - me.boxStrokeWidth / 2,
+ width: me.width,
+ height: me.height
+ };
+ },
+
+
+ createBox: function() {
+ var me = this,
+ box = me.boxSprite = me.chart.surface.add(Ext.apply({
+ type: 'rect',
+ stroke: me.boxStroke,
+ "stroke-width": me.boxStrokeWidth,
+ fill: me.boxFill,
+ zIndex: me.boxZIndex
+ }, me.getBBox()));
+ box.redraw();
+ },
+
+
+ updatePosition: function() {
+ var me = this,
+ x, y,
+ legendWidth = me.width,
+ legendHeight = me.height,
+ padding = me.padding,
+ chart = me.chart,
+ chartBBox = chart.chartBBox,
+ insets = chart.insetPadding,
+ chartWidth = chartBBox.width - (insets * 2),
+ chartHeight = chartBBox.height - (insets * 2),
+ chartX = chartBBox.x + insets,
+ chartY = chartBBox.y + insets,
+ surface = chart.surface,
+ mfloor = Math.floor;
+
+ if (me.isDisplayed()) {
+
+ switch(me.position) {
+ case "left":
+ x = insets;
+ y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
+ break;
+ case "right":
+ x = mfloor(surface.width - legendWidth) - insets;
+ y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
+ break;
+ case "top":
+ x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
+ y = insets;
+ break;
+ case "bottom":
+ x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
+ y = mfloor(surface.height - legendHeight) - insets;
+ break;
+ default:
+ x = mfloor(me.origX) + insets;
+ y = mfloor(me.origY) + insets;
+ }
+ me.x = x;
+ me.y = y;
+
+
+ Ext.each(me.items, function(item) {
+ item.updatePosition();
+ });
+
+ me.boxSprite.setAttributes(me.getBBox(), true);
+ }
+ }
+});
+
+
+Ext.define('Ext.chart.Chart', {
+
+
+
+ alias: 'widget.chart',
+
+ extend: 'Ext.draw.Component',
+
+ mixins: {
+ themeManager: 'Ext.chart.theme.Theme',
+ mask: 'Ext.chart.Mask',
+ navigation: 'Ext.chart.Navigation'
+ },
+
+ requires: [
+ 'Ext.util.MixedCollection',
+ 'Ext.data.StoreManager',
+ 'Ext.chart.Legend',
+ 'Ext.util.DelayedTask'
+ ],
+
+
+
+
+ viewBox: false,
+
+
+
+
+ animate: false,
+
+
+ legend: false,
+
+
+ insetPadding: 10,
+
+
+ enginePriority: ['Svg', 'Vml'],
+
+
+ background: false,
+
+
+
+
+ constructor: function(config) {
+ var me = this,
+ defaultAnim;
+ me.initTheme(config.theme || me.theme);
+ if (me.gradients) {
+ Ext.apply(config, { gradients: me.gradients });
+ }
+ if (me.background) {
+ Ext.apply(config, { background: me.background });
+ }
+ if (config.animate) {
+ defaultAnim = {
+ easing: 'ease',
+ duration: 500
+ };
+ if (Ext.isObject(config.animate)) {
+ config.animate = Ext.applyIf(config.animate, defaultAnim);
+ }
+ else {
+ config.animate = defaultAnim;
+ }
+ }
+ me.mixins.mask.constructor.call(me, config);
+ me.mixins.navigation.constructor.call(me, config);
+ me.callParent([config]);
+ },
+
+ initComponent: function() {
+ var me = this,
+ axes,
+ series;
+ me.callParent();
+ me.addEvents(
+ 'itemmousedown',
+ 'itemmouseup',
+ 'itemmouseover',
+ 'itemmouseout',
+ 'itemclick',
+ 'itemdoubleclick',
+ 'itemdragstart',
+ 'itemdrag',
+ 'itemdragend',
+
+ 'beforerefresh',
+
+ 'refresh'
+ );
+ Ext.applyIf(me, {
+ zoom: {
+ width: 1,
+ height: 1,
+ x: 0,
+ y: 0
+ }
+ });
+ me.maxGutter = [0, 0];
+ me.store = Ext.data.StoreManager.lookup(me.store);
+ axes = me.axes;
+ me.axes = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.position; });
+ if (axes) {
+ me.axes.addAll(axes);
+ }
+ series = me.series;
+ me.series = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.seriesId || (a.seriesId = Ext.id(null, 'ext-chart-series-')); });
+ if (series) {
+ me.series.addAll(series);
+ }
+ if (me.legend !== false) {
+ me.legend = Ext.create('Ext.chart.Legend', Ext.applyIf({chart:me}, me.legend));
+ }
+
+ me.on({
+ mousemove: me.onMouseMove,
+ mouseleave: me.onMouseLeave,
+ mousedown: me.onMouseDown,
+ mouseup: me.onMouseUp,
+ scope: me
+ });
+ },
+
+
+ afterComponentLayout: function(width, height) {
+ var me = this;
+ if (Ext.isNumber(width) && Ext.isNumber(height)) {
+ me.curWidth = width;
+ me.curHeight = height;
+ me.redraw(true);
+ }
+ this.callParent(arguments);
+ },
+
+
+ redraw: function(resize) {
+ var me = this,
+ chartBBox = me.chartBBox = {
+ x: 0,
+ y: 0,
+ height: me.curHeight,
+ width: me.curWidth
+ },
+ legend = me.legend;
+ me.surface.setSize(chartBBox.width, chartBBox.height);
+
+ me.series.each(me.initializeSeries, me);
+ me.axes.each(me.initializeAxis, me);
+
+
+ me.axes.each(function(axis) {
+ axis.processView();
+ });
+ me.axes.each(function(axis) {
+ axis.drawAxis(true);
+ });
+
+
+ if (legend !== false) {
+ legend.create();
+ }
+
+
+ me.alignAxes();
+
+
+ if (me.legend !== false) {
+ legend.updatePosition();
+ }
+
+
+ me.getMaxGutter();
+
+
+ me.resizing = !!resize;
+
+ me.axes.each(me.drawAxis, me);
+ me.series.each(me.drawCharts, me);
+ me.resizing = false;
+ },
+
+
+ afterRender: function() {
+ var ref,
+ me = this;
+ this.callParent();
+
+ if (me.categoryNames) {
+ me.setCategoryNames(me.categoryNames);
+ }
+
+ if (me.tipRenderer) {
+ ref = me.getFunctionRef(me.tipRenderer);
+ me.setTipRenderer(ref.fn, ref.scope);
+ }
+ me.bindStore(me.store, true);
+ me.refresh();
+ },
+
+
+ getEventXY: function(e) {
+ var me = this,
+ box = this.surface.getRegion(),
+ pageXY = e.getXY(),
+ x = pageXY[0] - box.left,
+ y = pageXY[1] - box.top;
+ return [x, y];
+ },
+
+
+ onClick: function(e) {
+ var me = this,
+ position = me.getEventXY(e),
+ item;
+
+
+
+ me.series.each(function(series) {
+ if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+ if (series.getItemForPoint) {
+ item = series.getItemForPoint(position[0], position[1]);
+ if (item) {
+ series.fireEvent('itemclick', item);
+ }
+ }
+ }
+ }, me);
+ },
+
+
+ onMouseDown: function(e) {
+ var me = this,
+ position = me.getEventXY(e),
+ item;
+
+ if (me.mask) {
+ me.mixins.mask.onMouseDown.call(me, e);
+ }
+
+
+ me.series.each(function(series) {
+ if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+ if (series.getItemForPoint) {
+ item = series.getItemForPoint(position[0], position[1]);
+ if (item) {
+ series.fireEvent('itemmousedown', item);
+ }
+ }
+ }
+ }, me);
+ },
+
+
+ onMouseUp: function(e) {
+ var me = this,
+ position = me.getEventXY(e),
+ item;
+
+ if (me.mask) {
+ me.mixins.mask.onMouseUp.call(me, e);
+ }
+
+
+ me.series.each(function(series) {
+ if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+ if (series.getItemForPoint) {
+ item = series.getItemForPoint(position[0], position[1]);
+ if (item) {
+ series.fireEvent('itemmouseup', item);
+ }
+ }
+ }
+ }, me);
+ },
+
+
+ onMouseMove: function(e) {
+ var me = this,
+ position = me.getEventXY(e),
+ item, last, storeItem, storeField;
+
+ if (me.mask) {
+ me.mixins.mask.onMouseMove.call(me, e);
+ }
+
+
+ me.series.each(function(series) {
+ if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+ if (series.getItemForPoint) {
+ item = series.getItemForPoint(position[0], position[1]);
+ last = series._lastItemForPoint;
+ storeItem = series._lastStoreItem;
+ storeField = series._lastStoreField;
+
+
+ if (item !== last || item && (item.storeItem != storeItem || item.storeField != storeField)) {
+ if (last) {
+ series.fireEvent('itemmouseout', last);
+ delete series._lastItemForPoint;
+ delete series._lastStoreField;
+ delete series._lastStoreItem;
+ }
+ if (item) {
+ series.fireEvent('itemmouseover', item);
+ series._lastItemForPoint = item;
+ series._lastStoreItem = item.storeItem;
+ series._lastStoreField = item.storeField;
+ }
+ }
+ }
+ } else {
+ last = series._lastItemForPoint;
+ if (last) {
+ series.fireEvent('itemmouseout', last);
+ delete series._lastItemForPoint;
+ delete series._lastStoreField;
+ delete series._lastStoreItem;
+ }
+ }
+ }, me);
+ },
+
+
+ onMouseLeave: function(e) {
+ var me = this;
+ if (me.mask) {
+ me.mixins.mask.onMouseLeave.call(me, e);
+ }
+ me.series.each(function(series) {
+ delete series._lastItemForPoint;
+ });
+ },
+
+
+ delayRefresh: function() {
+ var me = this;
+ if (!me.refreshTask) {
+ me.refreshTask = Ext.create('Ext.util.DelayedTask', me.refresh, me);
+ }
+ me.refreshTask.delay(me.refreshBuffer);
+ },
+
+
+ refresh: function() {
+ var me = this;
+ if (me.rendered && me.curWidth != undefined && me.curHeight != undefined) {
+ if (me.fireEvent('beforerefresh', me) !== false) {
+ me.redraw();
+ me.fireEvent('refresh', me);
+ }
+ }
+ },
+
+
+ bindStore: function(store, initial) {
+ var me = this;
+ if (!initial && me.store) {
+ if (store !== me.store && me.store.autoDestroy) {
+ me.store.destroy();
+ }
+ else {
+ me.store.un('datachanged', me.refresh, me);
+ me.store.un('add', me.delayRefresh, me);
+ me.store.un('remove', me.delayRefresh, me);
+ me.store.un('update', me.delayRefresh, me);
+ me.store.un('clear', me.refresh, me);
+ }
+ }
+ if (store) {
+ store = Ext.data.StoreManager.lookup(store);
+ store.on({
+ scope: me,
+ datachanged: me.refresh,
+ add: me.delayRefresh,
+ remove: me.delayRefresh,
+ update: me.delayRefresh,
+ clear: me.refresh
+ });
+ }
+ me.store = store;
+ if (store && !initial) {
+ me.refresh();
+ }
+ },
+
+
+ initializeAxis: function(axis) {
+ var me = this,
+ chartBBox = me.chartBBox,
+ w = chartBBox.width,
+ h = chartBBox.height,
+ x = chartBBox.x,
+ y = chartBBox.y,
+ themeAttrs = me.themeAttrs,
+ config = {
+ chart: me
+ };
+ if (themeAttrs) {
+ config.axisStyle = Ext.apply({}, themeAttrs.axis);
+ config.axisLabelLeftStyle = Ext.apply({}, themeAttrs.axisLabelLeft);
+ config.axisLabelRightStyle = Ext.apply({}, themeAttrs.axisLabelRight);
+ config.axisLabelTopStyle = Ext.apply({}, themeAttrs.axisLabelTop);
+ config.axisLabelBottomStyle = Ext.apply({}, themeAttrs.axisLabelBottom);
+ config.axisTitleLeftStyle = Ext.apply({}, themeAttrs.axisTitleLeft);
+ config.axisTitleRightStyle = Ext.apply({}, themeAttrs.axisTitleRight);
+ config.axisTitleTopStyle = Ext.apply({}, themeAttrs.axisTitleTop);
+ config.axisTitleBottomStyle = Ext.apply({}, themeAttrs.axisTitleBottom);
+ }
+ switch (axis.position) {
+ case 'top':
+ Ext.apply(config, {
+ length: w,
+ width: h,
+ x: x,
+ y: y
+ });
+ break;
+ case 'bottom':
+ Ext.apply(config, {
+ length: w,
+ width: h,
+ x: x,
+ y: h
+ });
+ break;
+ case 'left':
+ Ext.apply(config, {
+ length: h,
+ width: w,
+ x: x,
+ y: h
+ });
+ break;
+ case 'right':
+ Ext.apply(config, {
+ length: h,
+ width: w,
+ x: w,
+ y: h
+ });
+ break;
+ }
+ if (!axis.chart) {
+ Ext.apply(config, axis);
+ axis = me.axes.replace(Ext.createByAlias('axis.' + axis.type.toLowerCase(), config));
+ }
+ else {
+ Ext.apply(axis, config);
+ }
+ },
+
+
+
+ alignAxes: function() {
+ var me = this,
+ axes = me.axes,
+ legend = me.legend,
+ edges = ['top', 'right', 'bottom', 'left'],
+ chartBBox,
+ insetPadding = me.insetPadding,
+ insets = {
+ top: insetPadding,
+ right: insetPadding,
+ bottom: insetPadding,
+ left: insetPadding
+ };
+
+ function getAxis(edge) {
+ var i = axes.findIndex('position', edge);
+ return (i < 0) ? null : axes.getAt(i);
+ }
+
+
+ Ext.each(edges, function(edge) {
+ var isVertical = (edge === 'left' || edge === 'right'),
+ axis = getAxis(edge),
+ bbox;
+
+
+ if (legend !== false) {
+ if (legend.position === edge) {
+ bbox = legend.getBBox();
+ insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
+ }
+ }
+
+
+
+ if (axis && axis.bbox) {
+ bbox = axis.bbox;
+ insets[edge] += (isVertical ? bbox.width : bbox.height);
+ }
+ });
+
+ chartBBox = {
+ x: insets.left,
+ y: insets.top,
+ width: me.curWidth - insets.left - insets.right,
+ height: me.curHeight - insets.top - insets.bottom
+ };
+ me.chartBBox = chartBBox;
+
+
+
+ axes.each(function(axis) {
+ var pos = axis.position,
+ isVertical = (pos === 'left' || pos === 'right');
+
+ axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x);
+ axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height);
+ axis.width = (isVertical ? chartBBox.width : chartBBox.height);
+ axis.length = (isVertical ? chartBBox.height : chartBBox.width);
+ });
+ },
+
+
+ initializeSeries: function(series, idx) {
+ var me = this,
+ themeAttrs = me.themeAttrs,
+ seriesObj, markerObj, seriesThemes, st,
+ markerThemes, colorArrayStyle = [],
+ i = 0, l,
+ config = {
+ chart: me,
+ seriesId: series.seriesId
+ };
+ if (themeAttrs) {
+ seriesThemes = themeAttrs.seriesThemes;
+ markerThemes = themeAttrs.markerThemes;
+ seriesObj = Ext.apply({}, themeAttrs.series);
+ markerObj = Ext.apply({}, themeAttrs.marker);
+ config.seriesStyle = Ext.apply(seriesObj, seriesThemes[idx % seriesThemes.length]);
+ config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel);
+ config.markerStyle = Ext.apply(markerObj, markerThemes[idx % markerThemes.length]);
+ if (themeAttrs.colors) {
+ config.colorArrayStyle = themeAttrs.colors;
+ } else {
+ colorArrayStyle = [];
+ for (l = seriesThemes.length; i < l; i++) {
+ st = seriesThemes[i];
+ if (st.fill || st.stroke) {
+ colorArrayStyle.push(st.fill || st.stroke);
+ }
+ }
+ if (colorArrayStyle.length) {
+ config.colorArrayStyle = colorArrayStyle;
+ }
+ }
+ config.seriesIdx = idx;
+ }
+ if (series instanceof Ext.chart.series.Series) {
+ Ext.apply(series, config);
+ } else {
+ Ext.applyIf(config, series);
+ series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config));
+ }
+ if (series.initialize) {
+ series.initialize();
+ }
+ },
+
+
+ getMaxGutter: function() {
+ var me = this,
+ maxGutter = [0, 0];
+ me.series.each(function(s) {
+ var gutter = s.getGutters && s.getGutters() || [0, 0];
+ maxGutter[0] = Math.max(maxGutter[0], gutter[0]);
+ maxGutter[1] = Math.max(maxGutter[1], gutter[1]);
+ });
+ me.maxGutter = maxGutter;
+ },
+
+
+ drawAxis: function(axis) {
+ axis.drawAxis();
+ },
+
+
+ drawCharts: function(series) {
+ series.triggerafterrender = false;
+ series.drawSeries();
+ if (!this.animate) {
+ series.fireEvent('afterrender');
+ }
+ },
+
+
+ destroy: function() {
+ this.surface.destroy();
+ this.bindStore(null);
+ this.callParent(arguments);
+ }
+});
+
+
+Ext.define('Ext.chart.Highlight', {
+
+
+
+ requires: ['Ext.fx.Anim'],
+
+
+
+
+ highlight: false,
+
+ highlightCfg : null,
+
+ constructor: function(config) {
+ if (config.highlight) {
+ if (config.highlight !== true) {
+ this.highlightCfg = Ext.apply({}, config.highlight);
+ }
+ else {
+ this.highlightCfg = {
+ fill: '#fdd',
+ radius: 20,
+ lineWidth: 5,
+ stroke: '#f55'
+ };
+ }
+ }
+ },
+
+
+ highlightItem: function(item) {
+ if (!item) {
+ return;
+ }
+
+ var me = this,
+ sprite = item.sprite,
+ opts = me.highlightCfg,
+ surface = me.chart.surface,
+ animate = me.chart.animate,
+ p,
+ from,
+ to,
+ pi;
+
+ if (!me.highlight || !sprite || sprite._highlighted) {
+ return;
+ }
+ if (sprite._anim) {
+ sprite._anim.paused = true;
+ }
+ sprite._highlighted = true;
+ if (!sprite._defaults) {
+ sprite._defaults = Ext.apply(sprite._defaults || {},
+ sprite.attr);
+ from = {};
+ to = {};
+ for (p in opts) {
+ if (! (p in sprite._defaults)) {
+ sprite._defaults[p] = surface.availableAttrs[p];
+ }
+ from[p] = sprite._defaults[p];
+ to[p] = opts[p];
+ if (Ext.isObject(opts[p])) {
+ from[p] = {};
+ to[p] = {};
+ Ext.apply(sprite._defaults[p], sprite.attr[p]);
+ Ext.apply(from[p], sprite._defaults[p]);
+ for (pi in sprite._defaults[p]) {
+ if (! (pi in opts[p])) {
+ to[p][pi] = from[p][pi];
+ } else {
+ to[p][pi] = opts[p][pi];
+ }
+ }
+ for (pi in opts[p]) {
+ if (! (pi in to[p])) {
+ to[p][pi] = opts[p][pi];
+ }
+ }
+ }
+ }
+ sprite._from = from;
+ sprite._to = to;
+ }
+ if (animate) {
+ sprite._anim = Ext.create('Ext.fx.Anim', {
+ target: sprite,
+ from: sprite._from,
+ to: sprite._to,
+ duration: 150
+ });
+ } else {
+ sprite.setAttributes(sprite._to, true);
+ }
+ },
+
+
+ unHighlightItem: function() {
+ if (!this.highlight || !this.items) {
+ return;
+ }
+
+ var me = this,
+ items = me.items,
+ len = items.length,
+ opts = me.highlightCfg,
+ animate = me.chart.animate,
+ i = 0,
+ obj,
+ p,
+ sprite;
+
+ for (; i < len; i++) {
+ if (!items[i]) {
+ continue;
+ }
+ sprite = items[i].sprite;
+ if (sprite && sprite._highlighted) {
+ if (sprite._anim) {
+ sprite._anim.paused = true;
+ }
+ obj = {};
+ for (p in opts) {
+ if (Ext.isObject(sprite._defaults[p])) {
+ obj[p] = {};
+ Ext.apply(obj[p], sprite._defaults[p]);
+ }
+ else {
+ obj[p] = sprite._defaults[p];
+ }
+ }
+ if (animate) {
+ sprite._anim = Ext.create('Ext.fx.Anim', {
+ target: sprite,
+ to: obj,
+ duration: 150
+ });
+ }
+ else {
+ sprite.setAttributes(obj, true);
+ }
+ delete sprite._highlighted;
+
+ }
+ }
+ },
+
+ cleanHighlights: function() {
+ if (!this.highlight) {
+ return;
+ }
+
+ var group = this.group,
+ markerGroup = this.markerGroup,
+ i = 0,
+ l;
+ for (l = group.getCount(); i < l; i++) {
+ delete group.getAt(i)._defaults;
+ }
+ if (markerGroup) {
+ for (l = markerGroup.getCount(); i < l; i++) {
+ delete markerGroup.getAt(i)._defaults;
+ }
+ }
+ }
+});
+
+Ext.define('Ext.chart.Label', {
+
+
+
+ requires: ['Ext.draw.Color'],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //@private a regex to parse url type colors.
+
+ colorStringRe: /url\s*\(\s*#([^\/)]+)\s*\)/,
+
+ //@private the mixin constructor. Used internally by Series.
+
+ constructor: function(config) {
+ var me = this;
+ me.label = Ext.applyIf(me.label || {},
+ {
+ display: "none",
+ color: "#000",
+ field: "name",
+ minMargin: 50,
+ font: "11px Helvetica, sans-serif",
+ orientation: "horizontal",
+ renderer: function(v) {
+ return v;
+ }
+ });
+
+ if (me.label.display !== 'none') {
+ me.labelsGroup = me.chart.surface.getGroup(me.seriesId + '-labels');
+ }
+ },
+
+ //@private a method to render all labels in the labelGroup
+
+ renderLabels: function() {
+ var me = this,
+ chart = me.chart,
+ gradients = chart.gradients,
+ gradient,
+ items = me.items,
+ animate = chart.animate,
+ config = me.label,
+ display = config.display,
+ color = config.color,
+ field = [].concat(config.field),
+ group = me.labelsGroup,
+ store = me.chart.store,
+ len = store.getCount(),
+ ratio = items.length / len,
+ i, count, j,
+ k, gradientsCount = (gradients || 0) && gradients.length,
+ colorStopTotal, colorStopIndex, colorStop,
+ item, label, storeItem,
+ sprite, spriteColor, spriteBrightness, labelColor,
+ Color = Ext.draw.Color,
+ colorString;
+
+ if (display == 'none') {
+ return;
+ }
+
+ for (i = 0, count = 0; i < len; i++) {
+ for (j = 0; j < ratio; j++) {
+ item = items[count];
+ label = group.getAt(count);
+ storeItem = store.getAt(i);
+
+ if (!item && label) {
+ label.hide(true);
+ }
+
+ if (item && field[j]) {
+ if (!label) {
+ label = me.onCreateLabel(storeItem, item, i, display, j, count);
+ }
+ me.onPlaceLabel(label, storeItem, item, i, display, animate, j, count);
+
+
+ if (config.contrast && item.sprite) {
+ sprite = item.sprite;
+ colorString = sprite._to && sprite._to.fill || sprite.attr.fill;
+ spriteColor = Color.fromString(colorString);
+
+ if (colorString && !spriteColor) {
+ colorString = colorString.match(me.colorStringRe)[1];
+ for (k = 0; k < gradientsCount; k++) {
+ gradient = gradients[k];
+ if (gradient.id == colorString) {
+
+ colorStop = 0; colorStopTotal = 0;
+ for (colorStopIndex in gradient.stops) {
+ colorStop++;
+ colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale();
+ }
+ spriteBrightness = (colorStopTotal / colorStop) / 255;
+ break;
+ }
+ }
+ }
+ else {
+ spriteBrightness = spriteColor.getGrayscale() / 255;
+ }
+ labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
+
+ labelColor[2] = spriteBrightness > 0.5? 0.2 : 0.8;
+ label.setAttributes({
+ fill: String(Color.fromHSL.apply({}, labelColor))
+ }, true);
+ }
+ }
+ count++;
+ }
+ }
+ me.hideLabels(count);
+ },
+
+ //@private a method to hide labels.
+
+ hideLabels: function(index) {
+ var labelsGroup = this.labelsGroup, len;
+ if (labelsGroup) {
+ len = labelsGroup.getCount();
+ while (len-->index) {
+ labelsGroup.getAt(len).hide(true);
+ }
+ }
+ }
+});
+Ext.define('Ext.chart.MaskLayer', {
+ extend: 'Ext.Component',
+
+ constructor: function(config) {
+ config = Ext.apply(config || {}, {
+ style: 'position:absolute;background-color:#888;cursor:move;opacity:0.6;border:1px solid #222;'
+ });
+ this.callParent([config]);
+ },
+
+ initComponent: function() {
+ var me = this;
+ me.callParent(arguments);
+ me.addEvents(
+ 'mousedown',
+ 'mouseup',
+ 'mousemove',
+ 'mouseenter',
+ 'mouseleave'
+ );
+ },
+
+ initDraggable: function() {
+ this.callParent(arguments);
+ this.dd.onStart = function (e) {
+ var me = this,
+ comp = me.comp;
+
+
+ this.startPosition = comp.getPosition(true);
+
+
+
+ if (comp.ghost && !comp.liveDrag) {
+ me.proxy = comp.ghost();
+ me.dragTarget = me.proxy.header.el;
+ }
+
+
+ if (me.constrain || me.constrainDelegate) {
+ me.constrainTo = me.calculateConstrainRegion();
+ }
+ };
+ }
+});
+
+Ext.define('Ext.chart.TipSurface', {
+
+
+
+ extend: 'Ext.draw.Component',
+
+
+
+ spriteArray: false,
+ renderFirst: true,
+
+ constructor: function(config) {
+ this.callParent([config]);
+ if (config.sprites) {
+ this.spriteArray = [].concat(config.sprites);
+ delete config.sprites;
+ }
+ },
+
+ onRender: function() {
+ var me = this,
+ i = 0,
+ l = 0,
+ sp,
+ sprites;
+ this.callParent(arguments);
+ sprites = me.spriteArray;
+ if (me.renderFirst && sprites) {
+ me.renderFirst = false;
+ for (l = sprites.length; i < l; i++) {
+ sp = me.surface.add(sprites[i]);
+ sp.setAttributes({
+ hidden: false
+ },
+ true);
+ }
+ }
+ }
+});
+
+
+Ext.define('Ext.chart.Tip', {
+
+
+
+ requires: ['Ext.tip.ToolTip', 'Ext.chart.TipSurface'],
+
+
+
+ constructor: function(config) {
+ var me = this,
+ surface,
+ sprites,
+ tipSurface;
+ if (config.tips) {
+ me.tipTimeout = null;
+ me.tipConfig = Ext.apply({}, config.tips, {
+ renderer: Ext.emptyFn,
+ constrainPosition: false
+ });
+ me.tooltip = Ext.create('Ext.tip.ToolTip', me.tipConfig);
+ Ext.getBody().on('mousemove', me.tooltip.onMouseMove, me.tooltip);
+ if (me.tipConfig.surface) {
+
+ surface = me.tipConfig.surface;
+ sprites = surface.sprites;
+ tipSurface = Ext.create('Ext.chart.TipSurface', {
+ id: 'tipSurfaceComponent',
+ sprites: sprites
+ });
+ if (surface.width && surface.height) {
+ tipSurface.setSize(surface.width, surface.height);
+ }
+ me.tooltip.add(tipSurface);
+ me.spriteTip = tipSurface;
+ }
+ }
+ },
+
+ showTip: function(item) {
+ var me = this;
+ if (!me.tooltip) {
+ return;
+ }
+ clearTimeout(me.tipTimeout);
+ var tooltip = me.tooltip,
+ spriteTip = me.spriteTip,
+ tipConfig = me.tipConfig,
+ trackMouse = tooltip.trackMouse,
+ sprite, surface, surfaceExt, pos, x, y;
+ if (!trackMouse) {
+ tooltip.trackMouse = true;
+ sprite = item.sprite;
+ surface = sprite.surface;
+ surfaceExt = Ext.get(surface.getId());
+ if (surfaceExt) {
+ pos = surfaceExt.getXY();
+ x = pos[0] + (sprite.attr.x || 0) + (sprite.attr.translation && sprite.attr.translation.x || 0);
+ y = pos[1] + (sprite.attr.y || 0) + (sprite.attr.translation && sprite.attr.translation.y || 0);
+ tooltip.targetXY = [x, y];
+ }
+ }
+ if (spriteTip) {
+ tipConfig.renderer.call(tooltip, item.storeItem, item, spriteTip.surface);
+ } else {
+ tipConfig.renderer.call(tooltip, item.storeItem, item);
+ }
+ tooltip.show();
+ tooltip.trackMouse = trackMouse;
+ },
+
+ hideTip: function(item) {
+ var tooltip = this.tooltip;
+ if (!tooltip) {
+ return;
+ }
+ clearTimeout(this.tipTimeout);
+ this.tipTimeout = setTimeout(function() {
+ tooltip.hide();
+ }, 0);
+ }
+});
+
+Ext.define('Ext.chart.axis.Abstract', {
+
+
+
+ requires: ['Ext.chart.Chart'],
+
+
+
+ constructor: function(config) {
+ config = config || {};
+
+ var me = this,
+ pos = config.position || 'left';
+
+ pos = pos.charAt(0).toUpperCase() + pos.substring(1);
+
+ config.label = Ext.apply(config['axisLabel' + pos + 'Style'] || {}, config.label || {});
+ config.axisTitleStyle = Ext.apply(config['axisTitle' + pos + 'Style'] || {}, config.labelTitle || {});
+ Ext.apply(me, config);
+ me.fields = [].concat(me.fields);
+ this.callParent();
+ me.labels = [];
+ me.getId();
+ me.labelGroup = me.chart.surface.getGroup(me.axisId + "-labels");
+ },
+
+ alignment: null,
+ grid: false,
+ steps: 10,
+ x: 0,
+ y: 0,
+ minValue: 0,
+ maxValue: 0,
+
+ getId: function() {
+ return this.axisId || (this.axisId = Ext.id(null, 'ext-axis-'));
+ },
+
+
+ processView: Ext.emptyFn,
+
+ drawAxis: Ext.emptyFn,
+ addDisplayAndLabels: Ext.emptyFn
+});
+
+
+Ext.define('Ext.chart.axis.Axis', {
+
+
+
+ extend: 'Ext.chart.axis.Abstract',
+
+ alternateClassName: 'Ext.chart.Axis',
+
+ requires: ['Ext.draw.Draw'],
+
+
+
+
+
+
+
+
+ dashSize: 3,
+
+
+ position: 'bottom',
+
+
+ skipFirst: false,
+
+
+ length: 0,
+
+
+ width: 0,
+
+ majorTickSteps: false,
+
+
+ applyData: Ext.emptyFn,
+
+
+ calcEnds: function() {
+ var me = this,
+ math = Math,
+ mmax = math.max,
+ mmin = math.min,
+ store = me.chart.substore || me.chart.store,
+ series = me.chart.series.items,
+ fields = me.fields,
+ ln = fields.length,
+ min = isNaN(me.minimum) ? Infinity : me.minimum,
+ max = isNaN(me.maximum) ? -Infinity : me.maximum,
+ prevMin = me.prevMin,
+ prevMax = me.prevMax,
+ aggregate = false,
+ total = 0,
+ excludes = [],
+ outfrom, outto,
+ i, l, values, rec, out;
+
+
+
+ for (i = 0, l = series.length; !aggregate && i < l; i++) {
+ aggregate = aggregate || series[i].stacked;
+ excludes = series[i].__excludes || excludes;
+ }
+ store.each(function(record) {
+ if (aggregate) {
+ if (!isFinite(min)) {
+ min = 0;
+ }
+ for (values = [0, 0], i = 0; i < ln; i++) {
+ if (excludes[i]) {
+ continue;
+ }
+ rec = record.get(fields[i]);
+ values[+(rec > 0)] += math.abs(rec);
+ }
+ max = mmax(max, -values[0], values[1]);
+ min = mmin(min, -values[0], values[1]);
+ }
+ else {
+ for (i = 0; i < ln; i++) {
+ if (excludes[i]) {
+ continue;
+ }
+ value = record.get(fields[i]);
+ max = mmax(max, value);
+ min = mmin(min, value);
+ }
+ }
+ });
+ if (!isFinite(max)) {
+ max = me.prevMax || 0;
+ }
+ if (!isFinite(min)) {
+ min = me.prevMin || 0;
+ }
+
+ if (min != max && (max != (max >> 0))) {
+ max = (max >> 0) + 1;
+ }
+ out = Ext.draw.Draw.snapEnds(min, max, me.majorTickSteps !== false ? (me.majorTickSteps +1) : me.steps);
+ outfrom = out.from;
+ outto = out.to;
+ if (!isNaN(me.maximum)) {
+
+
+ out.to = me.maximum;
+ }
+ if (!isNaN(me.minimum)) {
+
+
+ out.from = me.minimum;
+ }
+
+
+ out.step = (out.to - out.from) / (outto - outfrom) * out.step;
+
+ if (me.adjustMaximumByMajorUnit) {
+ out.to += out.step;
+ }
+ if (me.adjustMinimumByMajorUnit) {
+ out.from -= out.step;
+ }
+ me.prevMin = min == max? 0 : min;
+ me.prevMax = max;
+ return out;
+ },
+
+
+ drawAxis: function (init) {
+ var me = this,
+ i, j,
+ x = me.x,
+ y = me.y,
+ gutterX = me.chart.maxGutter[0],
+ gutterY = me.chart.maxGutter[1],
+ dashSize = me.dashSize,
+ subDashesX = me.minorTickSteps || 0,
+ subDashesY = me.minorTickSteps || 0,
+ length = me.length,
+ position = me.position,
+ inflections = [],
+ calcLabels = false,
+ stepCalcs = me.applyData(),
+ step = stepCalcs.step,
+ steps = stepCalcs.steps,
+ from = stepCalcs.from,
+ to = stepCalcs.to,
+ trueLength,
+ currentX,
+ currentY,
+ path,
+ prev,
+ dashesX,
+ dashesY,
+ delta;
+
+
+
+
+ if (me.hidden || isNaN(step) || (from == to)) {
+ return;
+ }
+
+ me.from = stepCalcs.from;
+ me.to = stepCalcs.to;
+ if (position == 'left' || position == 'right') {
+ currentX = Math.floor(x) + 0.5;
+ path = ["M", currentX, y, "l", 0, -length];
+ trueLength = length - (gutterY * 2);
+ }
+ else {
+ currentY = Math.floor(y) + 0.5;
+ path = ["M", x, currentY, "l", length, 0];
+ trueLength = length - (gutterX * 2);
+ }
+
+ delta = trueLength / (steps || 1);
+ dashesX = Math.max(subDashesX +1, 0);
+ dashesY = Math.max(subDashesY +1, 0);
+ if (me.type == 'Numeric') {
+ calcLabels = true;
+ me.labels = [stepCalcs.from];
+ }
+ if (position == 'right' || position == 'left') {
+ currentY = y - gutterY;
+ currentX = x - ((position == 'left') * dashSize * 2);
+ while (currentY >= y - gutterY - trueLength) {
+ path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
+ if (currentY != y - gutterY) {
+ for (i = 1; i < dashesY; i++) {
+ path.push("M", currentX + dashSize, Math.floor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
+ }
+ }
+ inflections.push([ Math.floor(x), Math.floor(currentY) ]);
+ currentY -= delta;
+ if (calcLabels) {
+ me.labels.push(me.labels[me.labels.length -1] + step);
+ }
+ if (delta === 0) {
+ break;
+ }
+ }
+ if (Math.round(currentY + delta - (y - gutterY - trueLength))) {
+ path.push("M", currentX, Math.floor(y - length + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
+ for (i = 1; i < dashesY; i++) {
+ path.push("M", currentX + dashSize, Math.floor(y - length + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
+ }
+ inflections.push([ Math.floor(x), Math.floor(currentY) ]);
+ if (calcLabels) {
+ me.labels.push(me.labels[me.labels.length -1] + step);
+ }
+ }
+ } else {
+ currentX = x + gutterX;
+ currentY = y - ((position == 'top') * dashSize * 2);
+ while (currentX <= x + gutterX + trueLength) {
+ path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
+ if (currentX != x + gutterX) {
+ for (i = 1; i < dashesX; i++) {
+ path.push("M", Math.floor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
+ }
+ }
+ inflections.push([ Math.floor(currentX), Math.floor(y) ]);
+ currentX += delta;
+ if (calcLabels) {
+ me.labels.push(me.labels[me.labels.length -1] + step);
+ }
+ if (delta === 0) {
+ break;
+ }
+ }
+ if (Math.round(currentX - delta - (x + gutterX + trueLength))) {
+ path.push("M", Math.floor(x + length - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
+ for (i = 1; i < dashesX; i++) {
+ path.push("M", Math.floor(x + length - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
+ }
+ inflections.push([ Math.floor(currentX), Math.floor(y) ]);
+ if (calcLabels) {
+ me.labels.push(me.labels[me.labels.length -1] + step);
+ }
+ }
+ }
+ if (!me.axis) {
+ me.axis = me.chart.surface.add(Ext.apply({
+ type: 'path',
+ path: path
+ }, me.axisStyle));
+ }
+ me.axis.setAttributes({
+ path: path
+ }, true);
+ me.inflections = inflections;
+ if (!init && me.grid) {
+ me.drawGrid();
+ }
+ me.axisBBox = me.axis.getBBox();
+ me.drawLabel();
+ },
+
+
+ drawGrid: function() {
+ var me = this,
+ surface = me.chart.surface,
+ grid = me.grid,
+ odd = grid.odd,
+ even = grid.even,
+ inflections = me.inflections,
+ ln = inflections.length - ((odd || even)? 0 : 1),
+ position = me.position,
+ gutter = me.chart.maxGutter,
+ width = me.width - 2,
+ vert = false,
+ point, prevPoint,
+ i = 1,
+ path = [], styles, lineWidth, dlineWidth,
+ oddPath = [], evenPath = [];
+
+ if ((gutter[1] !== 0 && (position == 'left' || position == 'right')) ||
+ (gutter[0] !== 0 && (position == 'top' || position == 'bottom'))) {
+ i = 0;
+ ln++;
+ }
+ for (; i < ln; i++) {
+ point = inflections[i];
+ prevPoint = inflections[i - 1];
+ if (odd || even) {
+ path = (i % 2)? oddPath : evenPath;
+ styles = ((i % 2)? odd : even) || {};
+ lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2;
+ dlineWidth = 2 * lineWidth;
+ if (position == 'left') {
+ path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth,
+ "L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth,
+ "L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth,
+ "L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z");
+ }
+ else if (position == 'right') {
+ path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth,
+ "L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth,
+ "L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth,
+ "L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z");
+ }
+ else if (position == 'top') {
+ path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth,
+ "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth,
+ "L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth,
+ "L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z");
+ }
+ else {
+ path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth,
+ "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth,
+ "L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth,
+ "L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z");
+ }
+ } else {
+ if (position == 'left') {
+ path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]);
+ }
+ else if (position == 'right') {
+ path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]);
+ }
+ else if (position == 'top') {
+ path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]);
+ }
+ else {
+ path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]);
+ }
+ }
+ }
+ if (odd || even) {
+ if (oddPath.length) {
+ if (!me.gridOdd && oddPath.length) {
+ me.gridOdd = surface.add({
+ type: 'path',
+ path: oddPath
+ });
+ }
+ me.gridOdd.setAttributes(Ext.apply({
+ path: oddPath,
+ hidden: false
+ }, odd || {}), true);
+ }
+ if (evenPath.length) {
+ if (!me.gridEven) {
+ me.gridEven = surface.add({
+ type: 'path',
+ path: evenPath
+ });
+ }
+ me.gridEven.setAttributes(Ext.apply({
+ path: evenPath,
+ hidden: false
+ }, even || {}), true);
+ }
+ }
+ else {
+ if (path.length) {
+ if (!me.gridLines) {
+ me.gridLines = me.chart.surface.add({
+ type: 'path',
+ path: path,
+ "stroke-width": me.lineWidth || 1,
+ stroke: me.gridColor || '#ccc'
+ });
+ }
+ me.gridLines.setAttributes({
+ hidden: false,
+ path: path
+ }, true);
+ }
+ else if (me.gridLines) {
+ me.gridLines.hide(true);
+ }
+ }
+ },
+
+ //@private
+
+ getOrCreateLabel: function(i, text) {
+ var me = this,
+ labelGroup = me.labelGroup,
+ textLabel = labelGroup.getAt(i),
+ surface = me.chart.surface;
+ if (textLabel) {
+ if (text != textLabel.attr.text) {
+ textLabel.setAttributes(Ext.apply({
+ text: text
+ }, me.label), true);
+ textLabel._bbox = textLabel.getBBox();
+ }
+ }
+ else {
+ textLabel = surface.add(Ext.apply({
+ group: labelGroup,
+ type: 'text',
+ x: 0,
+ y: 0,
+ text: text
+ }, me.label));
+ surface.renderItem(textLabel);
+ textLabel._bbox = textLabel.getBBox();
+ }
+
+ if (me.label.rotation) {
+ textLabel.setAttributes({
+ rotation: {
+ degrees: 0
+ }
+ }, true);
+ textLabel._ubbox = textLabel.getBBox();
+ textLabel.setAttributes(me.label, true);
+ } else {
+ textLabel._ubbox = textLabel._bbox;
+ }
+ return textLabel;
+ },
+
+ rect2pointArray: function(sprite) {
+ var surface = this.chart.surface,
+ rect = surface.getBBox(sprite, true),
+ p1 = [rect.x, rect.y],
+ p1p = p1.slice(),
+ p2 = [rect.x + rect.width, rect.y],
+ p2p = p2.slice(),
+ p3 = [rect.x + rect.width, rect.y + rect.height],
+ p3p = p3.slice(),
+ p4 = [rect.x, rect.y + rect.height],
+ p4p = p4.slice(),
+ matrix = sprite.matrix;
+
+ p1[0] = matrix.x.apply(matrix, p1p);
+ p1[1] = matrix.y.apply(matrix, p1p);
+
+ p2[0] = matrix.x.apply(matrix, p2p);
+ p2[1] = matrix.y.apply(matrix, p2p);
+
+ p3[0] = matrix.x.apply(matrix, p3p);
+ p3[1] = matrix.y.apply(matrix, p3p);
+
+ p4[0] = matrix.x.apply(matrix, p4p);
+ p4[1] = matrix.y.apply(matrix, p4p);
+ return [p1, p2, p3, p4];
+ },
+
+ intersect: function(l1, l2) {
+ var r1 = this.rect2pointArray(l1),
+ r2 = this.rect2pointArray(l2);
+ return !!Ext.draw.Draw.intersect(r1, r2).length;
+ },
+
+ drawHorizontalLabels: function() {
+ var me = this,
+ labelConf = me.label,
+ floor = Math.floor,
+ max = Math.max,
+ axes = me.chart.axes,
+ position = me.position,
+ inflections = me.inflections,
+ ln = inflections.length,
+ labels = me.labels,
+ labelGroup = me.labelGroup,
+ maxHeight = 0,
+ ratio,
+ gutterY = me.chart.maxGutter[1],
+ ubbox, bbox, point, prevX, prevLabel,
+ projectedWidth = 0,
+ textLabel, attr, textRight, text,
+ label, last, x, y, i, firstLabel;
+
+ last = ln - 1;
+
+ point = inflections[0];
+ firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
+ ratio = Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)) >> 0;
+
+ for (i = 0; i < ln; i++) {
+ point = inflections[i];
+ text = me.label.renderer(labels[i]);
+ textLabel = me.getOrCreateLabel(i, text);
+ bbox = textLabel._bbox;
+ maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
+ x = floor(point[0] - (ratio? bbox.height : bbox.width) / 2);
+ if (me.chart.maxGutter[0] == 0) {
+ if (i == 0 && axes.findIndex('position', 'left') == -1) {
+ x = point[0];
+ }
+ else if (i == last && axes.findIndex('position', 'right') == -1) {
+ x = point[0] - bbox.width;
+ }
+ }
+ if (position == 'top') {
+ y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
+ }
+ else {
+ y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
+ }
+
+ textLabel.setAttributes({
+ hidden: false,
+ x: x,
+ y: y
+ }, true);
+
+
+ if (i != 0 && (me.intersect(textLabel, prevLabel)
+ || me.intersect(textLabel, firstLabel))) {
+ textLabel.hide(true);
+ continue;
+ }
+
+ prevLabel = textLabel;
+ }
+
+ return maxHeight;
+ },
+
+ drawVerticalLabels: function() {
+ var me = this,
+ inflections = me.inflections,
+ position = me.position,
+ ln = inflections.length,
+ labels = me.labels,
+ maxWidth = 0,
+ max = Math.max,
+ floor = Math.floor,
+ ceil = Math.ceil,
+ axes = me.chart.axes,
+ gutterY = me.chart.maxGutter[1],
+ ubbox, bbox, point, prevLabel,
+ projectedWidth = 0,
+ textLabel, attr, textRight, text,
+ label, last, x, y, i;
+
+ last = ln;
+ for (i = 0; i < last; i++) {
+ point = inflections[i];
+ text = me.label.renderer(labels[i]);
+ textLabel = me.getOrCreateLabel(i, text);
+ bbox = textLabel._bbox;
+
+ maxWidth = max(maxWidth, bbox.width + me.dashSize + me.label.padding);
+ y = point[1];
+ if (gutterY < bbox.height / 2) {
+ if (i == last - 1 && axes.findIndex('position', 'top') == -1) {
+ y = me.y - me.length + ceil(bbox.height / 2);
+ }
+ else if (i == 0 && axes.findIndex('position', 'bottom') == -1) {
+ y = me.y - floor(bbox.height / 2);
+ }
+ }
+ if (position == 'left') {
+ x = point[0] - bbox.width - me.dashSize - me.label.padding - 2;
+ }
+ else {
+ x = point[0] + me.dashSize + me.label.padding + 2;
+ }
+ textLabel.setAttributes(Ext.apply({
+ hidden: false,
+ x: x,
+ y: y
+ }, me.label), true);
+
+ if (i != 0 && me.intersect(textLabel, prevLabel)) {
+ textLabel.hide(true);
+ continue;
+ }
+ prevLabel = textLabel;
+ }
+
+ return maxWidth;
+ },
+
+
+ drawLabel: function() {
+ var me = this,
+ position = me.position,
+ labelGroup = me.labelGroup,
+ inflections = me.inflections,
+ maxWidth = 0,
+ maxHeight = 0,
+ ln, i;
+
+ if (position == 'left' || position == 'right') {
+ maxWidth = me.drawVerticalLabels();
+ } else {
+ maxHeight = me.drawHorizontalLabels();
+ }
+
+
+ ln = labelGroup.getCount();
+ i = inflections.length;
+ for (; i < ln; i++) {
+ labelGroup.getAt(i).hide(true);
+ }
+
+ me.bbox = {};
+ Ext.apply(me.bbox, me.axisBBox);
+ me.bbox.height = maxHeight;
+ me.bbox.width = maxWidth;
+ if (Ext.isString(me.title)) {
+ me.drawTitle(maxWidth, maxHeight);
+ }
+ },
+
+
+ elipsis: function(sprite, text, desiredWidth, minWidth, center) {
+ var bbox,
+ x;
+
+ if (desiredWidth < minWidth) {
+ sprite.hide(true);
+ return false;
+ }
+ while (text.length > 4) {
+ text = text.substr(0, text.length - 4) + "...";
+ sprite.setAttributes({
+ text: text
+ }, true);
+ bbox = sprite.getBBox();
+ if (bbox.width < desiredWidth) {
+ if (typeof center == 'number') {
+ sprite.setAttributes({
+ x: Math.floor(center - (bbox.width / 2))
+ }, true);
+ }
+ break;
+ }
+ }
+ return true;
+ },
+
+
+ setTitle: function(title) {
+ this.title = title;
+ this.drawLabel();
+ },
+
+
+ drawTitle: function(maxWidth, maxHeight) {
+ var me = this,
+ position = me.position,
+ surface = me.chart.surface,
+ displaySprite = me.displaySprite,
+ title = me.title,
+ rotate = (position == 'left' || position == 'right'),
+ x = me.x,
+ y = me.y,
+ base, bbox, pad;
+
+ if (displaySprite) {
+ displaySprite.setAttributes({text: title}, true);
+ } else {
+ base = {
+ type: 'text',
+ x: 0,
+ y: 0,
+ text: title
+ };
+ displaySprite = me.displaySprite = surface.add(Ext.apply(base, me.axisTitleStyle, me.labelTitle));
+ surface.renderItem(displaySprite);
+ }
+ bbox = displaySprite.getBBox();
+ pad = me.dashSize + me.label.padding;
+
+ if (rotate) {
+ y -= ((me.length / 2) - (bbox.height / 2));
+ if (position == 'left') {
+ x -= (maxWidth + pad + (bbox.width / 2));
+ }
+ else {
+ x += (maxWidth + pad + bbox.width - (bbox.width / 2));
+ }
+ me.bbox.width += bbox.width + 10;
+ }
+ else {
+ x += (me.length / 2) - (bbox.width * 0.5);
+ if (position == 'top') {
+ y -= (maxHeight + pad + (bbox.height * 0.3));
+ }
+ else {
+ y += (maxHeight + pad + (bbox.height * 0.8));
+ }
+ me.bbox.height += bbox.height + 10;
+ }
+ displaySprite.setAttributes({
+ translate: {
+ x: x,
+ y: y
+ }
+ }, true);
+ }
+});
+
+
+Ext.define('Ext.chart.axis.Category', {
+
+
+
+ extend: 'Ext.chart.axis.Axis',
+
+ alternateClassName: 'Ext.chart.CategoryAxis',
+
+ alias: 'axis.category',
+
+
+
+
+ categoryNames: null,
+
+
+ calculateCategoryCount: false,
+
+
+ setLabels: function() {
+ var store = this.chart.store,
+ fields = this.fields,
+ ln = fields.length,
+ i;
+
+ this.labels = [];
+ store.each(function(record) {
+ for (i = 0; i < ln; i++) {
+ this.labels.push(record.get(fields[i]));
+ }
+ }, this);
+ },
+
+
+ applyData: function() {
+ this.callParent();
+ this.setLabels();
+ var count = this.chart.store.getCount();
+ return {
+ from: 0,
+ to: count,
+ power: 1,
+ step: 1,
+ steps: count - 1
+ };
+ }
+});
+
+
+Ext.define('Ext.chart.axis.Gauge', {
+
+
+
+ extend: 'Ext.chart.axis.Abstract',
+
+
+
+
+
+
+
+
+
+
+
+ position: 'gauge',
+
+ alias: 'axis.gauge',
+
+ drawAxis: function(init) {
+ var chart = this.chart,
+ surface = chart.surface,
+ bbox = chart.chartBBox,
+ centerX = bbox.x + (bbox.width / 2),
+ centerY = bbox.y + bbox.height,
+ margin = this.margin || 10,
+ rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
+ sprites = [], sprite,
+ steps = this.steps,
+ i, pi = Math.PI,
+ cos = Math.cos,
+ sin = Math.sin;
+
+ if (this.sprites && !chart.resizing) {
+ this.drawLabel();
+ return;
+ }
+
+ if (this.margin >= 0) {
+ if (!this.sprites) {
+
+ for (i = 0; i <= steps; i++) {
+ sprite = surface.add({
+ type: 'path',
+ path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+ centerY + (rho - margin) * sin(i / steps * pi - pi),
+ 'L', centerX + rho * cos(i / steps * pi - pi),
+ centerY + rho * sin(i / steps * pi - pi), 'Z'],
+ stroke: '#ccc'
+ });
+ sprite.setAttributes({
+ hidden: false
+ }, true);
+ sprites.push(sprite);
+ }
+ } else {
+ sprites = this.sprites;
+
+ for (i = 0; i <= steps; i++) {
+ sprites[i].setAttributes({
+ path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+ centerY + (rho - margin) * sin(i / steps * pi - pi),
+ 'L', centerX + rho * cos(i / steps * pi - pi),
+ centerY + rho * sin(i / steps * pi - pi), 'Z'],
+ stroke: '#ccc'
+ }, true);
+ }
+ }
+ }
+ this.sprites = sprites;
+ this.drawLabel();
+ if (this.title) {
+ this.drawTitle();
+ }
+ },
+
+ drawTitle: function() {
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ bbox = chart.chartBBox,
+ labelSprite = me.titleSprite,
+ labelBBox;
+
+ if (!labelSprite) {
+ me.titleSprite = labelSprite = surface.add({
+ type: 'text',
+ zIndex: 2
+ });
+ }
+ labelSprite.setAttributes(Ext.apply({
+ text: me.title
+ }, me.label || {}), true);
+ labelBBox = labelSprite.getBBox();
+ labelSprite.setAttributes({
+ x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
+ y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
+ }, true);
+ },
+
+
+ setTitle: function(title) {
+ this.title = title;
+ this.drawTitle();
+ },
+
+ drawLabel: function() {
+ var chart = this.chart,
+ surface = chart.surface,
+ bbox = chart.chartBBox,
+ centerX = bbox.x + (bbox.width / 2),
+ centerY = bbox.y + bbox.height,
+ margin = this.margin || 10,
+ rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
+ round = Math.round,
+ labelArray = [], label,
+ maxValue = this.maximum || 0,
+ steps = this.steps, i = 0,
+ adjY,
+ pi = Math.PI,
+ cos = Math.cos,
+ sin = Math.sin,
+ labelConf = this.label,
+ renderer = labelConf.renderer || function(v) { return v; };
+
+ if (!this.labelArray) {
+
+ for (i = 0; i <= steps; i++) {
+
+ adjY = (i === 0 || i === steps) ? 7 : 0;
+ label = surface.add({
+ type: 'text',
+ text: renderer(round(i / steps * maxValue)),
+ x: centerX + rho * cos(i / steps * pi - pi),
+ y: centerY + rho * sin(i / steps * pi - pi) - adjY,
+ 'text-anchor': 'middle',
+ 'stroke-width': 0.2,
+ zIndex: 10,
+ stroke: '#333'
+ });
+ label.setAttributes({
+ hidden: false
+ }, true);
+ labelArray.push(label);
+ }
+ }
+ else {
+ labelArray = this.labelArray;
+
+ for (i = 0; i <= steps; i++) {
+
+ adjY = (i === 0 || i === steps) ? 7 : 0;
+ labelArray[i].setAttributes({
+ text: renderer(round(i / steps * maxValue)),
+ x: centerX + rho * cos(i / steps * pi - pi),
+ y: centerY + rho * sin(i / steps * pi - pi) - adjY
+ }, true);
+ }
+ }
+ this.labelArray = labelArray;
+ }
+});
+
+Ext.define('Ext.chart.axis.Numeric', {
+
+
+
+ extend: 'Ext.chart.axis.Axis',
+
+ alternateClassName: 'Ext.chart.NumericAxis',
+
+
+
+ type: 'numeric',
+
+ alias: 'axis.numeric',
+
+ constructor: function(config) {
+ var me = this, label, f;
+ me.callParent([config]);
+ label = me.label;
+ if (me.roundToDecimal === false) {
+ return;
+ }
+ if (label.renderer) {
+ f = label.renderer;
+ label.renderer = function(v) {
+ return me.roundToDecimal( f(v), me.decimals );
+ };
+ } else {
+ label.renderer = function(v) {
+ return me.roundToDecimal(v, me.decimals);
+ };
+ }
+ },
+
+ roundToDecimal: function(v, dec) {
+ var val = Math.pow(10, dec || 0);
+ return ((v * val) >> 0) / val;
+ },
+
+
+ minimum: NaN,
+
+
+ maximum: NaN,
+
+
+ decimals: 2,
+
+
+ scale: "linear",
+
+
+ position: 'left',
+
+
+ adjustMaximumByMajorUnit: false,
+
+
+ adjustMinimumByMajorUnit: false,
+
+
+ applyData: function() {
+ this.callParent();
+ return this.calcEnds();
+ }
+});
+
+
+Ext.define('Ext.chart.axis.Radial', {
+
+
+
+ extend: 'Ext.chart.axis.Abstract',
+
+
+
+ position: 'radial',
+
+ alias: 'axis.radial',
+
+ drawAxis: function(init) {
+ var chart = this.chart,
+ surface = chart.surface,
+ bbox = chart.chartBBox,
+ store = chart.store,
+ l = store.getCount(),
+ centerX = bbox.x + (bbox.width / 2),
+ centerY = bbox.y + (bbox.height / 2),
+ rho = Math.min(bbox.width, bbox.height) /2,
+ sprites = [], sprite,
+ steps = this.steps,
+ i, j, pi2 = Math.PI * 2,
+ cos = Math.cos, sin = Math.sin;
+
+ if (this.sprites && !chart.resizing) {
+ this.drawLabel();
+ return;
+ }
+
+ if (!this.sprites) {
+
+ for (i = 1; i <= steps; i++) {
+ sprite = surface.add({
+ type: 'circle',
+ x: centerX,
+ y: centerY,
+ radius: Math.max(rho * i / steps, 0),
+ stroke: '#ccc'
+ });
+ sprite.setAttributes({
+ hidden: false
+ }, true);
+ sprites.push(sprite);
+ }
+
+ store.each(function(rec, i) {
+ sprite = surface.add({
+ type: 'path',
+ path: ['M', centerX, centerY, 'L', centerX + rho * cos(i / l * pi2), centerY + rho * sin(i / l * pi2), 'Z'],
+ stroke: '#ccc'
+ });
+ sprite.setAttributes({
+ hidden: false
+ }, true);
+ sprites.push(sprite);
+ });
+ } else {
+ sprites = this.sprites;
+
+ for (i = 0; i < steps; i++) {
+ sprites[i].setAttributes({
+ x: centerX,
+ y: centerY,
+ radius: Math.max(rho * (i + 1) / steps, 0),
+ stroke: '#ccc'
+ }, true);
+ }
+
+ store.each(function(rec, j) {
+ sprites[i + j].setAttributes({
+ path: ['M', centerX, centerY, 'L', centerX + rho * cos(j / l * pi2), centerY + rho * sin(j / l * pi2), 'Z'],
+ stroke: '#ccc'
+ }, true);
+ });
+ }
+ this.sprites = sprites;
+
+ this.drawLabel();
+ },
+
+ drawLabel: function() {
+ var chart = this.chart,
+ surface = chart.surface,
+ bbox = chart.chartBBox,
+ store = chart.store,
+ centerX = bbox.x + (bbox.width / 2),
+ centerY = bbox.y + (bbox.height / 2),
+ rho = Math.min(bbox.width, bbox.height) /2,
+ max = Math.max, round = Math.round,
+ labelArray = [], label,
+ fields = [], nfields,
+ categories = [], xField,
+ aggregate = !this.maximum,
+ maxValue = this.maximum || 0,
+ steps = this.steps, i = 0, j, dx, dy,
+ pi2 = Math.PI * 2,
+ cos = Math.cos, sin = Math.sin,
+ display = this.label.display,
+ draw = display !== 'none',
+ margin = 10;
+
+ if (!draw) {
+ return;
+ }
+
+
+ chart.series.each(function(series) {
+ fields.push(series.yField);
+ xField = series.xField;
+ });
+
+
+ store.each(function(record, i) {
+ if (aggregate) {
+ for (i = 0, nfields = fields.length; i < nfields; i++) {
+ maxValue = max(+record.get(fields[i]), maxValue);
+ }
+ }
+ categories.push(record.get(xField));
+ });
+ if (!this.labelArray) {
+ if (display != 'categories') {
+
+ for (i = 1; i <= steps; i++) {
+ label = surface.add({
+ type: 'text',
+ text: round(i / steps * maxValue),
+ x: centerX,
+ y: centerY - rho * i / steps,
+ 'text-anchor': 'middle',
+ 'stroke-width': 0.1,
+ stroke: '#333'
+ });
+ label.setAttributes({
+ hidden: false
+ }, true);
+ labelArray.push(label);
+ }
+ }
+ if (display != 'scale') {
+
+ for (j = 0, steps = categories.length; j < steps; j++) {
+ dx = cos(j / steps * pi2) * (rho + margin);
+ dy = sin(j / steps * pi2) * (rho + margin);
+ label = surface.add({
+ type: 'text',
+ text: categories[j],
+ x: centerX + dx,
+ y: centerY + dy,
+ 'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
+ });
+ label.setAttributes({
+ hidden: false
+ }, true);
+ labelArray.push(label);
+ }
+ }
+ }
+ else {
+ labelArray = this.labelArray;
+ if (display != 'categories') {
+
+ for (i = 0; i < steps; i++) {
+ labelArray[i].setAttributes({
+ text: round((i + 1) / steps * maxValue),
+ x: centerX,
+ y: centerY - rho * (i + 1) / steps,
+ 'text-anchor': 'middle',
+ 'stroke-width': 0.1,
+ stroke: '#333'
+ }, true);
+ }
+ }
+ if (display != 'scale') {
+
+ for (j = 0, steps = categories.length; j < steps; j++) {
+ dx = cos(j / steps * pi2) * (rho + margin);
+ dy = sin(j / steps * pi2) * (rho + margin);
+ if (labelArray[i + j]) {
+ labelArray[i + j].setAttributes({
+ type: 'text',
+ text: categories[j],
+ x: centerX + dx,
+ y: centerY + dy,
+ 'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
+ }, true);
+ }
+ }
+ }
+ }
+ this.labelArray = labelArray;
+ }
+});
+
+Ext.define('Ext.data.AbstractStore', {
+ requires: ['Ext.util.MixedCollection', 'Ext.data.Operation', 'Ext.util.Filter'],
+
+ mixins: {
+ observable: 'Ext.util.Observable',
+ sortable: 'Ext.util.Sortable'
+ },
+
+ statics: {
+ create: function(store){
+ if (!store.isStore) {
+ if (!store.type) {
+ store.type = 'store';
+ }
+ store = Ext.createByAlias('store.' + store.type, store);
+ }
+ return store;
+ }
+ },
+
+ remoteSort : false,
+ remoteFilter: false,
+
+
+
+
+ autoLoad: false,
+
+
+ autoSync: false,
+
+
+ batchUpdateMode: 'operation',
+
+
+ filterOnLoad: true,
+
+
+ sortOnLoad: true,
+
+
+ implicitModel: false,
+
+
+ defaultProxyType: 'memory',
+
+
+ isDestroyed: false,
+
+ isStore: true,
+
+
+
+
+
+ sortRoot: 'data',
+
+
+ constructor: function(config) {
+ var me = this;
+
+ me.addEvents(
+
+ 'add',
+
+
+ 'remove',
+
+
+ 'update',
+
+
+ 'datachanged',
+
+
+ 'beforeload',
+
+
+ 'load',
+
+
+ 'beforesync',
+
+ 'clear'
+ );
+
+ Ext.apply(me, config);
+
+
+ me.removed = [];
+
+ me.mixins.observable.constructor.apply(me, arguments);
+ me.model = Ext.ModelManager.getModel(config.model || me.model);
+
+
+ Ext.applyIf(me, {
+ modelDefaults: {}
+ });
+
+
+ if (!me.model && me.fields) {
+ me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), {
+ extend: 'Ext.data.Model',
+ fields: me.fields,
+ proxy: me.proxy || me.defaultProxyType
+ });
+
+ delete me.fields;
+
+ me.implicitModel = true;
+ }
+
+
+ me.setProxy(config.proxy || me.proxy || me.model.getProxy());
+
+ if (me.id && !me.storeId) {
+ me.storeId = me.id;
+ delete me.id;
+ }
+
+ if (me.storeId) {
+ Ext.data.StoreManager.register(me);
+ }
+
+ me.mixins.sortable.initSortable.call(me);
+
+
+ me.filters = Ext.create('Ext.util.MixedCollection');
+ me.filters.addAll(me.decodeFilters(config.filters));
+ },
+
+
+ setProxy: function(proxy) {
+ var me = this;
+
+ if (proxy instanceof Ext.data.proxy.Proxy) {
+ proxy.setModel(me.model);
+ } else {
+ if (Ext.isString(proxy)) {
+ proxy = {
+ type: proxy
+ };
+ }
+ Ext.applyIf(proxy, {
+ model: me.model
+ });
+
+ proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
+ }
+
+ me.proxy = proxy;
+
+ return me.proxy;
+ },
+
+
+ getProxy: function() {
+ return this.proxy;
+ },
+
+
+ create: function(data, options) {
+ var me = this,
+ instance = Ext.ModelManager.create(Ext.applyIf(data, me.modelDefaults), me.model.modelName),
+ operation;
+
+ options = options || {};
+
+ Ext.applyIf(options, {
+ action : 'create',
+ records: [instance]
+ });
+
+ operation = Ext.create('Ext.data.Operation', options);
+
+ me.proxy.create(operation, me.onProxyWrite, me);
+
+ return instance;
+ },
+
+ read: function() {
+ return this.load.apply(this, arguments);
+ },
+
+ onProxyRead: Ext.emptyFn,
+
+ update: function(options) {
+ var me = this,
+ operation;
+ options = options || {};
+
+ Ext.applyIf(options, {
+ action : 'update',
+ records: me.getUpdatedRecords()
+ });
+
+ operation = Ext.create('Ext.data.Operation', options);
+
+ return me.proxy.update(operation, me.onProxyWrite, me);
+ },
+
+
+ onProxyWrite: function(operation) {
+ var me = this,
+ success = operation.wasSuccessful(),
+ records = operation.getRecords();
+
+ switch (operation.action) {
+ case 'create':
+ me.onCreateRecords(records, operation, success);
+ break;
+ case 'update':
+ me.onUpdateRecords(records, operation, success);
+ break;
+ case 'destroy':
+ me.onDestroyRecords(records, operation, success);
+ break;
+ }
+
+ if (success) {
+ me.fireEvent('write', me, operation);
+ me.fireEvent('datachanged', me);
+ }
+
+ Ext.callback(operation.callback, operation.scope || me, [records, operation, success]);
+ },
+
+
+
+ destroy: function(options) {
+ var me = this,
+ operation;
+
+ options = options || {};
+
+ Ext.applyIf(options, {
+ action : 'destroy',
+ records: me.getRemovedRecords()
+ });
+
+ operation = Ext.create('Ext.data.Operation', options);
+
+ return me.proxy.destroy(operation, me.onProxyWrite, me);
+ },
+
+
+ onBatchOperationComplete: function(batch, operation) {
+ return this.onProxyWrite(operation);
+ },
+
+
+ onBatchComplete: function(batch, operation) {
+ var me = this,
+ operations = batch.operations,
+ length = operations.length,
+ i;
+
+ me.suspendEvents();
+
+ for (i = 0; i < length; i++) {
+ me.onProxyWrite(operations[i]);
+ }
+
+ me.resumeEvents();
+
+ me.fireEvent('datachanged', me);
+ },
+
+ onBatchException: function(batch, operation) {
+
+
+
+
+
+ },
+
+
+ filterNew: function(item) {
+
+ return item.phantom === true && item.isValid();
+ },
+
+
+ getNewRecords: function() {
+ return [];
+ },
+
+
+ getUpdatedRecords: function() {
+ return [];
+ },
+
+
+ filterUpdated: function(item) {
+
+ return item.dirty === true && item.phantom !== true && item.isValid();
+ },
+
+
+ getRemovedRecords: function() {
+ return this.removed;
+ },
+
+ filter: function(filters, value) {
+
+ },
+
+
+ decodeFilters: function(filters) {
+ if (!Ext.isArray(filters)) {
+ if (filters === undefined) {
+ filters = [];
+ } else {
+ filters = [filters];
+ }
+ }
+
+ var length = filters.length,
+ Filter = Ext.util.Filter,
+ config, i;
+
+ for (i = 0; i < length; i++) {
+ config = filters[i];
+
+ if (!(config instanceof Filter)) {
+ Ext.apply(config, {
+ root: 'data'
+ });
+
+
+ if (config.fn) {
+ config.filterFn = config.fn;
+ }
+
+
+ if (typeof config == 'function') {
+ config = {
+ filterFn: config
+ };
+ }
+
+ filters[i] = new Filter(config);
+ }
+ }
+
+ return filters;
+ },
+
+ clearFilter: function(supressEvent) {
+
+ },
+
+ isFiltered: function() {
+
+ },
+
+ filterBy: function(fn, scope) {
+
+ },
+
+
+ sync: function() {
+ var me = this,
+ options = {},
+ toCreate = me.getNewRecords(),
+ toUpdate = me.getUpdatedRecords(),
+ toDestroy = me.getRemovedRecords(),
+ needsSync = false;
+
+ if (toCreate.length > 0) {
+ options.create = toCreate;
+ needsSync = true;
+ }
+
+ if (toUpdate.length > 0) {
+ options.update = toUpdate;
+ needsSync = true;
+ }
+
+ if (toDestroy.length > 0) {
+ options.destroy = toDestroy;
+ needsSync = true;
+ }
+
+ if (needsSync && me.fireEvent('beforesync', options) !== false) {
+ me.proxy.batch(options, me.getBatchListeners());
+ }
+ },
+
+
+
+ getBatchListeners: function() {
+ var me = this,
+ listeners = {
+ scope: me,
+ exception: me.onBatchException
+ };
+
+ if (me.batchUpdateMode == 'operation') {
+ listeners.operationcomplete = me.onBatchOperationComplete;
+ } else {
+ listeners.complete = me.onBatchComplete;
+ }
+
+ return listeners;
+ },
+
+
+ save: function() {
+ return this.sync.apply(this, arguments);
+ },
+
+
+ load: function(options) {
+ var me = this,
+ operation;
+
+ options = options || {};
+
+ Ext.applyIf(options, {
+ action : 'read',
+ filters: me.filters.items,
+ sorters: me.getSorters()
+ });
+
+ operation = Ext.create('Ext.data.Operation', options);
+
+ if (me.fireEvent('beforeload', me, operation) !== false) {
+ me.loading = true;
+ me.proxy.read(operation, me.onProxyLoad, me);
+ }
+
+ return me;
+ },
+
+
+ afterEdit : function(record) {
+ var me = this;
+
+ if (me.autoSync) {
+ me.sync();
+ }
+
+ me.fireEvent('update', me, record, Ext.data.Model.EDIT);
+ },
+
+
+ afterReject : function(record) {
+ this.fireEvent('update', this, record, Ext.data.Model.REJECT);
+ },
+
+
+ afterCommit : function(record) {
+ this.fireEvent('update', this, record, Ext.data.Model.COMMIT);
+ },
+
+ clearData: Ext.emptyFn,
+
+ destroyStore: function() {
+ var me = this;
+
+ if (!me.isDestroyed) {
+ if (me.storeId) {
+ Ext.data.StoreManager.unregister(me);
+ }
+ me.clearData();
+ me.data = null;
+ me.tree = null;
+
+ me.reader = me.writer = null;
+ me.clearListeners();
+ me.isDestroyed = true;
+
+ if (me.implicitModel) {
+ Ext.destroy(me.model);
+ }
+ }
+ },
+
+ doSort: function(sorterFn) {
+ var me = this;
+ if (me.remoteSort) {
+
+ me.load();
+ } else {
+ me.data.sortBy(sorterFn);
+ me.fireEvent('datachanged', me);
+ }
+ },
+
+ getCount: Ext.emptyFn,
+
+ getById: Ext.emptyFn,
+
+
+ removeAll: Ext.emptyFn,
+
+
+
+
+ isLoading: function() {
+ return this.loading;
+ }
+});
+
+
+
+Ext.define('Ext.util.Grouper', {
+
+
+
+ extend: 'Ext.util.Sorter',
+
+
+
+
+ getGroupString: function(instance) {
+ return instance.get(this.property);
+ }
+});
+
+Ext.define('Ext.data.Store', {
+ extend: 'Ext.data.AbstractStore',
+
+ alias: 'store.store',
+
+ requires: ['Ext.ModelManager', 'Ext.data.Model', 'Ext.util.Grouper'],
+ uses: ['Ext.data.proxy.Memory'],
+
+
+ remoteSort: false,
+
+
+ remoteFilter: false,
+
+
+ remoteGroup : false,
+
+
+
+
+
+
+
+
+ groupField: undefined,
+
+
+ groupDir: "ASC",
+
+
+ pageSize: 25,
+
+
+ currentPage: 1,
+
+
+ clearOnPageLoad: true,
+
+
+ loading: false,
+
+
+ sortOnFilter: true,
+
+
+ buffered: false,
+
+
+ purgePageCount: 5,
+
+ isStore: true,
+
+
+ constructor: function(config) {
+ config = config || {};
+
+ var me = this,
+ groupers = config.groupers,
+ proxy,
+ data;
+
+ if (config.buffered || me.buffered) {
+ me.prefetchData = Ext.create('Ext.util.MixedCollection', false, function(record) {
+ return record.index;
+ });
+ me.pendingRequests = [];
+ me.pagesRequested = [];
+
+ me.sortOnLoad = false;
+ me.filterOnLoad = false;
+ }
+
+ me.addEvents(
+
+ 'beforeprefetch',
+
+ 'groupchange',
+
+ 'prefetch'
+ );
+ data = config.data || me.data;
+
+
+ me.data = Ext.create('Ext.util.MixedCollection', false, function(record) {
+ return record.internalId;
+ });
+
+ if (data) {
+ me.inlineData = data;
+ delete config.data;
+ }
+
+ if (!groupers && config.groupField) {
+ groupers = [{
+ property : config.groupField,
+ direction: config.groupDir
+ }];
+ }
+ delete config.groupers;
+
+
+ me.groupers = Ext.create('Ext.util.MixedCollection');
+ me.groupers.addAll(me.decodeGroupers(groupers));
+
+ this.callParent([config]);
+
+ if (me.groupers.items.length) {
+ me.sort(me.groupers.items, 'prepend', false);
+ }
+
+ proxy = me.proxy;
+ data = me.inlineData;
+
+ if (data) {
+ if (proxy instanceof Ext.data.proxy.Memory) {
+ proxy.data = data;
+ me.read();
+ } else {
+ me.add.apply(me, data);
+ }
+
+ me.sort();
+ delete me.inlineData;
+ } else if (me.autoLoad) {
+ Ext.defer(me.load, 10, me, [typeof me.autoLoad === 'object' ? me.autoLoad: undefined]);
+
+
+ }
+ },
+
+ onBeforeSort: function() {
+ this.sort(this.groupers.items, 'prepend', false);
+ },
+
+
+ decodeGroupers: function(groupers) {
+ if (!Ext.isArray(groupers)) {
+ if (groupers === undefined) {
+ groupers = [];
+ } else {
+ groupers = [groupers];
+ }
+ }
+
+ var length = groupers.length,
+ Grouper = Ext.util.Grouper,
+ config, i;
+
+ for (i = 0; i < length; i++) {
+ config = groupers[i];
+
+ if (!(config instanceof Grouper)) {
+ if (Ext.isString(config)) {
+ config = {
+ property: config
+ };
+ }
+
+ Ext.applyIf(config, {
+ root : 'data',
+ direction: "ASC"
+ });
+
+
+ if (config.fn) {
+ config.sorterFn = config.fn;
+ }
+
+
+ if (typeof config == 'function') {
+ config = {
+ sorterFn: config
+ };
+ }
+
+ groupers[i] = new Grouper(config);
+ }
+ }
+
+ return groupers;
+ },
+
+
+ group: function(groupers, direction) {
+ var me = this,
+ grouper,
+ newGroupers;
+
+ if (Ext.isArray(groupers)) {
+ newGroupers = groupers;
+ } else if (Ext.isObject(groupers)) {
+ newGroupers = [groupers];
+ } else if (Ext.isString(groupers)) {
+ grouper = me.groupers.get(groupers);
+
+ if (!grouper) {
+ grouper = {
+ property : groupers,
+ direction: direction
+ };
+ newGroupers = [grouper];
+ } else if (direction === undefined) {
+ grouper.toggle();
+ } else {
+ grouper.setDirection(direction);
+ }
+ }
+
+ if (newGroupers && newGroupers.length) {
+ newGroupers = me.decodeGroupers(newGroupers);
+ me.groupers.clear();
+ me.groupers.addAll(newGroupers);
+ }
+
+ if (me.remoteGroup) {
+ me.load({
+ scope: me,
+ callback: me.fireGroupChange
+ });
+ } else {
+ me.sort();
+ me.fireEvent('groupchange', me, me.groupers);
+ }
+ },
+
+
+ clearGrouping: function(){
+ var me = this;
+
+ me.groupers.each(function(grouper){
+ me.sorters.remove(grouper);
+ });
+ me.groupers.clear();
+ if (me.remoteGroup) {
+ me.load({
+ scope: me,
+ callback: me.fireGroupChange
+ });
+ } else {
+ me.sort();
+ me.fireEvent('groupchange', me, me.groupers);
+ }
+ },
+
+
+ isGrouped: function() {
+ return this.groupers.getCount() > 0;
+ },
+
+
+ fireGroupChange: function(){
+ this.fireEvent('groupchange', this, this.groupers);
+ },
+
+
+ getGroups: function(requestGroupString) {
+ var records = this.data.items,
+ length = records.length,
+ groups = [],
+ pointers = {},
+ record,
+ groupStr,
+ group,
+ i;
+
+ for (i = 0; i < length; i++) {
+ record = records[i];
+ groupStr = this.getGroupString(record);
+ group = pointers[groupStr];
+
+ if (group === undefined) {
+ group = {
+ name: groupStr,
+ children: []
+ };
+
+ groups.push(group);
+ pointers[groupStr] = group;
+ }
+
+ group.children.push(record);
+ }
+
+ return requestGroupString ? pointers[requestGroupString] : groups;
+ },
+
+
+ getGroupsForGrouper: function(records, grouper) {
+ var length = records.length,
+ groups = [],
+ oldValue,
+ newValue,
+ record,
+ group,
+ i;
+
+ for (i = 0; i < length; i++) {
+ record = records[i];
+ newValue = grouper.getGroupString(record);
+
+ if (newValue !== oldValue) {
+ group = {
+ name: newValue,
+ grouper: grouper,
+ records: []
+ };
+ groups.push(group);
+ }
+
+ group.records.push(record);
+
+ oldValue = newValue;
+ }
+
+ return groups;
+ },
+
+
+ getGroupsForGrouperIndex: function(records, grouperIndex) {
+ var me = this,
+ groupers = me.groupers,
+ grouper = groupers.getAt(grouperIndex),
+ groups = me.getGroupsForGrouper(records, grouper),
+ length = groups.length,
+ i;
+
+ if (grouperIndex + 1 < groupers.length) {
+ for (i = 0; i < length; i++) {
+ groups[i].children = me.getGroupsForGrouperIndex(groups[i].records, grouperIndex + 1);
+ }
+ }
+
+ for (i = 0; i < length; i++) {
+ groups[i].depth = grouperIndex;
+ }
+
+ return groups;
+ },
+
+
+ getGroupData: function(sort) {
+ var me = this;
+ if (sort !== false) {
+ me.sort();
+ }
+
+ return me.getGroupsForGrouperIndex(me.data.items, 0);
+ },
+
+
+ getGroupString: function(instance) {
+ var group = this.groupers.first();
+ if (group) {
+ return instance.get(group.property);
+ }
+ return '';
+ },
+
+ insert: function(index, records) {
+ var me = this,
+ sync = false,
+ i,
+ record,
+ len;
+
+ records = [].concat(records);
+ for (i = 0, len = records.length; i < len; i++) {
+ record = me.createModel(records[i]);
+ record.set(me.modelDefaults);
+
+ records[i] = record;
+
+ me.data.insert(index + i, record);
+ record.join(me);
+
+ sync = sync || record.phantom === true;
+ }
+
+ if (me.snapshot) {
+ me.snapshot.addAll(records);
+ }
+
+ me.fireEvent('add', me, records, index);
+ me.fireEvent('datachanged', me);
+ if (me.autoSync && sync) {
+ me.sync();
+ }
+ },
+
+
+ add: function(records) {
+
+ if (!Ext.isArray(records)) {
+ records = Array.prototype.slice.apply(arguments);
+ }
+
+ var me = this,
+ i = 0,
+ length = records.length,
+ record;
+
+ for (; i < length; i++) {
+ record = me.createModel(records[i]);
+
+ records[i] = record;
+ }
+
+ me.insert(me.data.length, records);
+
+ return records;
+ },
+
+
+ createModel: function(record) {
+ if (!record.isModel) {
+ record = Ext.ModelManager.create(record, this.model);
+ }
+
+ return record;
+ },
+
+
+ each: function(fn, scope) {
+ this.data.each(fn, scope);
+ },
+
+
+ remove: function(records, isMove) {
+ if (!Ext.isArray(records)) {
+ records = [records];
+ }
+
+
+ isMove = isMove === true;
+ var me = this,
+ sync = false,
+ i = 0,
+ length = records.length,
+ isPhantom,
+ index,
+ record;
+
+ for (; i < length; i++) {
+ record = records[i];
+ index = me.data.indexOf(record);
+
+ if (me.snapshot) {
+ me.snapshot.remove(record);
+ }
+
+ if (index > -1) {
+ isPhantom = record.phantom === true;
+ if (!isMove && !isPhantom) {
+
+ me.removed.push(record);
+ }
+
+ record.unjoin(me);
+ me.data.remove(record);
+ sync = sync || !isPhantom;
+
+ me.fireEvent('remove', me, record, index);
+ }
+ }
+
+ me.fireEvent('datachanged', me);
+ if (!isMove && me.autoSync && sync) {
+ me.sync();
+ }
+ },
+
+
+ removeAt: function(index) {
+ var record = this.getAt(index);
+
+ if (record) {
+ this.remove(record);
+ }
+ },
+
+
+ load: function(options) {
+ var me = this;
+
+ options = options || {};
+
+ if (Ext.isFunction(options)) {
+ options = {
+ callback: options
+ };
+ }
+
+ Ext.applyIf(options, {
+ groupers: me.groupers.items,
+ page: me.currentPage,
+ start: (me.currentPage - 1) * me.pageSize,
+ limit: me.pageSize,
+ addRecords: false
+ });
+
+ return me.callParent([options]);
+ },
+
+
+ onProxyLoad: function(operation) {
+ var me = this,
+ resultSet = operation.getResultSet(),
+ records = operation.getRecords(),
+ successful = operation.wasSuccessful();
+
+ if (resultSet) {
+ me.totalCount = resultSet.total;
+ }
+
+ if (successful) {
+ me.loadRecords(records, operation);
+ }
+
+ me.loading = false;
+ me.fireEvent('load', me, records, successful);
+
+
+
+ me.fireEvent('read', me, records, operation.wasSuccessful());
+
+
+ Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
+ },
+
+
+ onCreateRecords: function(records, operation, success) {
+ if (success) {
+ var i = 0,
+ data = this.data,
+ snapshot = this.snapshot,
+ length = records.length,
+ originalRecords = operation.records,
+ record,
+ original,
+ index;
+
+
+ for (; i < length; ++i) {
+ record = records[i];
+ original = originalRecords[i];
+ if (original) {
+ index = data.indexOf(original);
+ if (index > -1) {
+ data.removeAt(index);
+ data.insert(index, record);
+ }
+ if (snapshot) {
+ index = snapshot.indexOf(original);
+ if (index > -1) {
+ snapshot.removeAt(index);
+ snapshot.insert(index, record);
+ }
+ }
+ record.phantom = false;
+ record.join(this);
+ }
+ }
+ }
+ },
+
+
+ onUpdateRecords: function(records, operation, success){
+ if (success) {
+ var i = 0,
+ length = records.length,
+ data = this.data,
+ snapshot = this.snapshot,
+ record;
+
+ for (; i < length; ++i) {
+ record = records[i];
+ data.replace(record);
+ if (snapshot) {
+ snapshot.replace(record);
+ }
+ record.join(this);
+ }
+ }
+ },
+
+
+ onDestroyRecords: function(records, operation, success){
+ if (success) {
+ var me = this,
+ i = 0,
+ length = records.length,
+ data = me.data,
+ snapshot = me.snapshot,
+ record;
+
+ for (; i < length; ++i) {
+ record = records[i];
+ record.unjoin(me);
+ data.remove(record);
+ if (snapshot) {
+ snapshot.remove(record);
+ }
+ }
+ me.removed = [];
+ }
+ },
+
+
+ getNewRecords: function() {
+ return this.data.filterBy(this.filterNew).items;
+ },
+
+
+ getUpdatedRecords: function() {
+ return this.data.filterBy(this.filterUpdated).items;
+ },
+
+
+ filter: function(filters, value) {
+ if (Ext.isString(filters)) {
+ filters = {
+ property: filters,
+ value: value
+ };
+ }
+
+ var me = this,
+ decoded = me.decodeFilters(filters),
+ i = 0,
+ doLocalSort = me.sortOnFilter && !me.remoteSort,
+ length = decoded.length;
+
+ for (; i < length; i++) {
+ me.filters.replace(decoded[i]);
+ }
+
+ if (me.remoteFilter) {
+
+ me.load();
+ } else {
+
+ if (me.filters.getCount()) {
+ me.snapshot = me.snapshot || me.data.clone();
+ me.data = me.data.filter(me.filters.items);
+
+ if (doLocalSort) {
+ me.sort();
+ }
+
+ if (!doLocalSort || me.sorters.length < 1) {
+ me.fireEvent('datachanged', me);
+ }
+ }
+ }
+ },
+
+
+ clearFilter: function(suppressEvent) {
+ var me = this;
+
+ me.filters.clear();
+
+ if (me.remoteFilter) {
+ me.load();
+ } else if (me.isFiltered()) {
+ me.data = me.snapshot.clone();
+ delete me.snapshot;
+
+ if (suppressEvent !== true) {
+ me.fireEvent('datachanged', me);
+ }
+ }
+ },
+
+
+ isFiltered: function() {
+ var snapshot = this.snapshot;
+ return !! snapshot && snapshot !== this.data;
+ },
+
+
+ filterBy: function(fn, scope) {
+ var me = this;
+
+ me.snapshot = me.snapshot || me.data.clone();
+ me.data = me.queryBy(fn, scope || me);
+ me.fireEvent('datachanged', me);
+ },
+
+
+ queryBy: function(fn, scope) {
+ var me = this,
+ data = me.snapshot || me.data;
+ return data.filterBy(fn, scope || me);
+ },
+
+
+ loadData: function(data, append) {
+ var model = this.model,
+ length = data.length,
+ i,
+ record;
+
+
+ for (i = 0; i < length; i++) {
+ record = data[i];
+
+ if (! (record instanceof Ext.data.Model)) {
+ data[i] = Ext.ModelManager.create(record, model);
+ }
+ }
+
+ this.loadRecords(data, {addRecords: append});
+ },
+
+
+ loadRecords: function(records, options) {
+ var me = this,
+ i = 0,
+ length = records.length;
+
+ options = options || {};
+
+
+ if (!options.addRecords) {
+ delete me.snapshot;
+ me.data.clear();
+ }
+
+ me.data.addAll(records);
+
+
+ for (; i < length; i++) {
+ if (options.start !== undefined) {
+ records[i].index = options.start + i;
+
+ }
+ records[i].join(me);
+ }
+
+
+ me.suspendEvents();
+
+ if (me.filterOnLoad && !me.remoteFilter) {
+ me.filter();
+ }
+
+ if (me.sortOnLoad && !me.remoteSort) {
+ me.sort();
+ }
+
+ me.resumeEvents();
+ me.fireEvent('datachanged', me, records);
+ },
+
+
+
+ loadPage: function(page) {
+ var me = this;
+
+ me.currentPage = page;
+
+ me.read({
+ page: page,
+ start: (page - 1) * me.pageSize,
+ limit: me.pageSize,
+ addRecords: !me.clearOnPageLoad
+ });
+ },
+
+
+ nextPage: function() {
+ this.loadPage(this.currentPage + 1);
+ },
+
+
+ previousPage: function() {
+ this.loadPage(this.currentPage - 1);
+ },
+
+
+ clearData: function() {
+ this.data.each(function(record) {
+ record.unjoin();
+ });
+
+ this.data.clear();
+ },
+
+
+
+ prefetch: function(options) {
+ var me = this,
+ operation,
+ requestId = me.getRequestId();
+
+ options = options || {};
+
+ Ext.applyIf(options, {
+ action : 'read',
+ filters: me.filters.items,
+ sorters: me.sorters.items,
+ requestId: requestId
+ });
+ me.pendingRequests.push(requestId);
+
+ operation = Ext.create('Ext.data.Operation', options);
+
+
+
+
+
+ if (me.fireEvent('beforeprefetch', me, operation) !== false) {
+ me.loading = true;
+ me.proxy.read(operation, me.onProxyPrefetch, me);
+ }
+
+ return me;
+ },
+
+
+ prefetchPage: function(page, options) {
+ var me = this,
+ pageSize = me.pageSize,
+ start = (page - 1) * me.pageSize,
+ end = start + pageSize;
+
+
+ if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) {
+ options = options || {};
+ me.pagesRequested.push(page);
+ Ext.applyIf(options, {
+ page : page,
+ start: start,
+ limit: pageSize,
+ callback: me.onWaitForGuarantee,
+ scope: me
+ });
+
+ me.prefetch(options);
+ }
+
+ },
+
+
+ getRequestId: function() {
+ this.requestSeed = this.requestSeed || 1;
+ return this.requestSeed++;
+ },
+
+
+ onProxyPrefetch: function(operation) {
+ var me = this,
+ resultSet = operation.getResultSet(),
+ records = operation.getRecords(),
+
+ successful = operation.wasSuccessful();
+
+ if (resultSet) {
+ me.totalCount = resultSet.total;
+ me.fireEvent('totalcountchange', me.totalCount);
+ }
+
+ if (successful) {
+ me.cacheRecords(records, operation);
+ }
+ Ext.Array.remove(me.pendingRequests, operation.requestId);
+ if (operation.page) {
+ Ext.Array.remove(me.pagesRequested, operation.page);
+ }
+
+ me.loading = false;
+ me.fireEvent('prefetch', me, records, successful, operation);
+
+
+ if (operation.blocking) {
+ me.fireEvent('load', me, records, successful);
+ }
+
+
+ Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
+ },
+
+
+ cacheRecords: function(records, operation) {
+ var me = this,
+ i = 0,
+ length = records.length,
+ start = operation ? operation.start : 0;
+
+ if (!Ext.isDefined(me.totalCount)) {
+ me.totalCount = records.length;
+ me.fireEvent('totalcountchange', me.totalCount);
+ }
+
+ for (; i < length; i++) {
+
+ records[i].index = start + i;
+ }
+
+ me.prefetchData.addAll(records);
+ if (me.purgePageCount) {
+ me.purgeRecords();
+ }
+
+ },
+
+
+
+ purgeRecords: function() {
+ var me = this,
+ prefetchCount = me.prefetchData.getCount(),
+ purgeCount = me.purgePageCount * me.pageSize,
+ numRecordsToPurge = prefetchCount - purgeCount - 1,
+ i = 0;
+
+ for (; i <= numRecordsToPurge; i++) {
+ me.prefetchData.removeAt(0);
+ }
+ },
+
+
+ rangeSatisfied: function(start, end) {
+ var me = this,
+ i = start,
+ satisfied = true;
+
+ for (; i < end; i++) {
+ if (!me.prefetchData.getByKey(i)) {
+ satisfied = false;
+ if (end - i > me.pageSize) {
+ Ext.Error.raise("A single page prefetch could never satisfy this request.");
+ }
+ break;
+ }
+ }
+ return satisfied;
+ },
+
+
+ getPageFromRecordIndex: function(index) {
+ return Math.floor(index / this.pageSize) + 1;
+ },
+
+
+ onGuaranteedRange: function() {
+ var me = this,
+ totalCount = me.getTotalCount(),
+ start = me.requestStart,
+ end = ((totalCount - 1) < me.requestEnd) ? totalCount - 1 : me.requestEnd,
+ range = [],
+ record,
+ i = start;
+
+ if (start > end) {
+ Ext.Error.raise("Start (" + start + ") was greater than end (" + end + ")");
+ }
+
+ if (start !== me.guaranteedStart && end !== me.guaranteedEnd) {
+ me.guaranteedStart = start;
+ me.guaranteedEnd = end;
+
+ for (; i <= end; i++) {
+ record = me.prefetchData.getByKey(i);
+ if (!record) {
+ Ext.Error.raise("Record was not found and store said it was guaranteed");
+ }
+ range.push(record);
+ }
+ me.fireEvent('guaranteedrange', range, start, end);
+ if (me.cb) {
+ me.cb.call(me.scope || me, range);
+ }
+ }
+
+ me.unmask();
+ },
+
+
+ mask: function() {
+ this.masked = true;
+ this.fireEvent('beforeload');
+ },
+
+
+ unmask: function() {
+ if (this.masked) {
+ this.fireEvent('load');
+ }
+ },
+
+
+ hasPendingRequests: function() {
+ return this.pendingRequests.length;
+ },
+
+
+
+ onWaitForGuarantee: function() {
+ if (!this.hasPendingRequests()) {
+ this.onGuaranteedRange();
+ }
+ },
+
+
+ guaranteeRange: function(start, end, cb, scope) {
+ if (start && end) {
+ if (end - start > this.pageSize) {
+ Ext.Error.raise({
+ start: start,
+ end: end,
+ pageSize: this.pageSize,
+ msg: "Requested a bigger range than the specified pageSize"
+ });
+ }
+ }
+
+ end = (end > this.totalCount) ? this.totalCount - 1 : end;
+
+ var me = this,
+ i = start,
+ prefetchData = me.prefetchData,
+ range = [],
+ startLoaded = !!prefetchData.getByKey(start),
+ endLoaded = !!prefetchData.getByKey(end),
+ startPage = me.getPageFromRecordIndex(start),
+ endPage = me.getPageFromRecordIndex(end);
+
+ me.cb = cb;
+ me.scope = scope;
+
+ me.requestStart = start;
+ me.requestEnd = end;
+
+ if (!startLoaded || !endLoaded) {
+
+ if (startPage === endPage) {
+ me.mask();
+ me.prefetchPage(startPage, {
+
+ callback: me.onWaitForGuarantee,
+ scope: me
+ });
+
+ } else {
+ me.mask();
+ me.prefetchPage(startPage, {
+
+ callback: me.onWaitForGuarantee,
+ scope: me
+ });
+ me.prefetchPage(endPage, {
+
+ callback: me.onWaitForGuarantee,
+ scope: me
+ });
+ }
+
+ } else {
+ me.onGuaranteedRange();
+ }
+ },
+
+
+
+ sort: function() {
+ var me = this,
+ prefetchData = me.prefetchData,
+ sorters,
+ start,
+ end,
+ range;
+
+ if (me.buffered) {
+ if (me.remoteSort) {
+ prefetchData.clear();
+ me.callParent(arguments);
+ } else {
+ sorters = me.getSorters();
+ start = me.guaranteedStart;
+ end = me.guaranteedEnd;
+ range;
+
+ if (sorters.length) {
+ prefetchData.sort(sorters);
+ range = prefetchData.getRange();
+ prefetchData.clear();
+ me.cacheRecords(range);
+ delete me.guaranteedStart;
+ delete me.guaranteedEnd;
+ me.guaranteeRange(start, end);
+ }
+ me.callParent(arguments);
+ }
+ } else {
+ me.callParent(arguments);
+ }
+ },
+
+
+
+
+ doSort: function(sorterFn) {
+ var me = this;
+ if (me.remoteSort) {
+
+ me.load();
+ } else {
+ me.data.sortBy(sorterFn);
+ if (!me.buffered) {
+ var range = me.getRange(),
+ ln = range.length,
+ i = 0;
+ for (; i < ln; i++) {
+ range[i].index = i;
+ }
+ }
+ me.fireEvent('datachanged', me);
+ }
+ },
+
+
+ find: function(property, value, start, anyMatch, caseSensitive, exactMatch) {
+ var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
+ return fn ? this.data.findIndexBy(fn, null, start) : -1;
+ },
+
+
+ findRecord: function() {
+ var me = this,
+ index = me.find.apply(me, arguments);
+ return index !== -1 ? me.getAt(index) : null;
+ },
+
+
+ createFilterFn: function(property, value, anyMatch, caseSensitive, exactMatch) {
+ if (Ext.isEmpty(value)) {
+ return false;
+ }
+ value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
+ return function(r) {
+ return value.test(r.data[property]);
+ };
+ },
+
+
+ findExact: function(property, value, start) {
+ return this.data.findIndexBy(function(rec) {
+ return rec.get(property) === value;
+ },
+ this, start);
+ },
+
+
+ findBy: function(fn, scope, start) {
+ return this.data.findIndexBy(fn, scope, start);
+ },
+
+
+ collect: function(dataIndex, allowNull, bypassFilter) {
+ var me = this,
+ data = (bypassFilter === true && me.snapshot) ? me.snapshot: me.data;
+
+ return data.collect(dataIndex, 'data', allowNull);
+ },
+
+
+ getCount: function() {
+ return this.data.length || 0;
+ },
+
+
+ getTotalCount: function() {
+ return this.totalCount;
+ },
+
+
+ getAt: function(index) {
+ return this.data.getAt(index);
+ },
+
+
+ getRange: function(start, end) {
+ return this.data.getRange(start, end);
+ },
+
+
+ getById: function(id) {
+ return (this.snapshot || this.data).findBy(function(record) {
+ return record.getId() === id;
+ });
+ },
+
+
+ indexOf: function(record) {
+ return this.data.indexOf(record);
+ },
+
+
+
+ indexOfTotal: function(record) {
+ return record.index || this.indexOf(record);
+ },
+
+
+ indexOfId: function(id) {
+ return this.data.indexOfKey(id);
+ },
+
+
+ removeAll: function(silent) {
+ var me = this;
+
+ me.clearData();
+ if (me.snapshot) {
+ me.snapshot.clear();
+ }
+ if (silent !== true) {
+ me.fireEvent('clear', me);
+ }
+ },
+
+
+
+
+ first: function(grouped) {
+ var me = this;
+
+ if (grouped && me.isGrouped()) {
+ return me.aggregate(function(records) {
+ return records.length ? records[0] : undefined;
+ }, me, true);
+ } else {
+ return me.data.first();
+ }
+ },
+
+
+ last: function(grouped) {
+ var me = this;
+
+ if (grouped && me.isGrouped()) {
+ return me.aggregate(function(records) {
+ var len = records.length;
+ return len ? records[len - 1] : undefined;
+ }, me, true);
+ } else {
+ return me.data.last();
+ }
+ },
+
+
+ sum: function(field, grouped) {
+ var me = this;
+
+ if (grouped && me.isGrouped()) {
+ return me.aggregate(me.getSum, me, true, [field]);
+ } else {
+ return me.getSum(me.data.items, field);
+ }
+ },
+
+
+ getSum: function(records, field) {
+ var total = 0,
+ i = 0,
+ len = records.length;
+
+ for (; i < len; ++i) {
+ total += records[i].get(field);
+ }
+
+ return total;
+ },
+
+
+ count: function(grouped) {
+ var me = this;
+
+ if (grouped && me.isGrouped()) {
+ return me.aggregate(function(records) {
+ return records.length;
+ }, me, true);
+ } else {
+ return me.getCount();
+ }
+ },
+
+
+ min: function(field, grouped) {
+ var me = this;
+
+ if (grouped && me.isGrouped()) {
+ return me.aggregate(me.getMin, me, true, [field]);
+ } else {
+ return me.getMin(me.data.items, field);
+ }
+ },
+
+
+ getMin: function(records, field){
+ var i = 1,
+ len = records.length,
+ value, min;
+
+ if (len > 0) {
+ min = records[0].get(field);
+ }
+
+ for (; i < len; ++i) {
+ value = records[i].get(field);
+ if (value < min) {
+ min = value;
+ }
+ }
+ return min;
+ },
+
+
+ max: function(field, grouped) {
+ var me = this;
+
+ if (grouped && me.isGrouped()) {
+ return me.aggregate(me.getMax, me, true, [field]);
+ } else {
+ return me.getMax(me.data.items, field);
+ }
+ },
+
+
+ getMax: function(records, field) {
+ var i = 1,
+ len = records.length,
+ value,
+ max;
+
+ if (len > 0) {
+ max = records[0].get(field);
+ }
+
+ for (; i < len; ++i) {
+ value = records[i].get(field);
+ if (value > max) {
+ max = value;
+ }
+ }
+ return max;
+ },
+
+
+ average: function(field, grouped) {
+ var me = this;
+ if (grouped && me.isGrouped()) {
+ return me.aggregate(me.getAverage, me, true, [field]);
+ } else {
+ return me.getAverage(me.data.items, field);
+ }
+ },
+
+
+ getAverage: function(records, field) {
+ var i = 0,
+ len = records.length,
+ sum = 0;
+
+ if (records.length > 0) {
+ for (; i < len; ++i) {
+ sum += records[i].get(field);
+ }
+ return sum / len;
+ }
+ return 0;
+ },
+
+
+ aggregate: function(fn, scope, grouped, args) {
+ args = args || [];
+ if (grouped && this.isGrouped()) {
+ var groups = this.getGroups(),
+ i = 0,
+ len = groups.length,
+ out = {},
+ group;
+
+ for (; i < len; ++i) {
+ group = groups[i];
+ out[group.name] = fn.apply(scope || this, [group.children].concat(args));
+ }
+ return out;
+ } else {
+ return fn.apply(scope || this, [this.data.items].concat(args));
+ }
+ }
+});
+
+
+Ext.define('Ext.data.JsonStore', {
+ extend: 'Ext.data.Store',
+ alias: 'store.json',
+
+
+ constructor: function(config) {
+ config = config || {};
+
+ Ext.applyIf(config, {
+ proxy: {
+ type : 'ajax',
+ reader: 'json',
+ writer: 'json'
+ }
+ });
+
+ this.callParent([config]);
+ }
+});
+
+
+Ext.define('Ext.chart.axis.Time', {
+
+
+
+ extend: 'Ext.chart.axis.Category',
+
+ alternateClassName: 'Ext.chart.TimeAxis',
+
+ alias: 'axis.time',
+
+ requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
+
+
+
+
+ calculateByLabelSize: true,
+
+
+ dateFormat: false,
+
+
+ groupBy: 'year,month,day',
+
+
+ aggregateOp: 'sum',
+
+
+ fromDate: false,
+
+
+ toDate: false,
+
+
+ step: [Ext.Date.DAY, 1],
+
+
+ constrain: false,
+
+
+ dateMethods: {
+ 'year': function(date) {
+ return date.getFullYear();
+ },
+ 'month': function(date) {
+ return date.getMonth() + 1;
+ },
+ 'day': function(date) {
+ return date.getDate();
+ },
+ 'hour': function(date) {
+ return date.getHours();
+ },
+ 'minute': function(date) {
+ return date.getMinutes();
+ },
+ 'second': function(date) {
+ return date.getSeconds();
+ },
+ 'millisecond': function(date) {
+ return date.getMilliseconds();
+ }
+ },
+
+
+ aggregateFn: (function() {
+ var etype = (function() {
+ var rgxp = /^\[object\s(.*)\]$/,
+ toString = Object.prototype.toString;
+ return function(e) {
+ return toString.call(e).match(rgxp)[1];
+ };
+ })();
+ return {
+ 'sum': function(list) {
+ var i = 0, l = list.length, acum = 0;
+ if (!list.length || etype(list[0]) != 'Number') {
+ return list[0];
+ }
+ for (; i < l; i++) {
+ acum += list[i];
+ }
+ return acum;
+ },
+ 'max': function(list) {
+ if (!list.length || etype(list[0]) != 'Number') {
+ return list[0];
+ }
+ return Math.max.apply(Math, list);
+ },
+ 'min': function(list) {
+ if (!list.length || etype(list[0]) != 'Number') {
+ return list[0];
+ }
+ return Math.min.apply(Math, list);
+ },
+ 'avg': function(list) {
+ var i = 0, l = list.length, acum = 0;
+ if (!list.length || etype(list[0]) != 'Number') {
+ return list[0];
+ }
+ for (; i < l; i++) {
+ acum += list[i];
+ }
+ return acum / l;
+ }
+ };
+ })(),
+
+
+ constrainDates: function() {
+ var fromDate = Ext.Date.clone(this.fromDate),
+ toDate = Ext.Date.clone(this.toDate),
+ step = this.step,
+ field = this.fields,
+ store = this.chart.store,
+ record, recObj, fieldNames = [],
+ newStore = Ext.create('Ext.data.Store', {
+ model: store.model
+ });
+
+ var getRecordByDate = (function() {
+ var index = 0, l = store.getCount();
+ return function(date) {
+ var rec, recDate;
+ for (; index < l; index++) {
+ rec = store.getAt(index);
+ recDate = rec.get(field);
+ if (+recDate > +date) {
+ return false;
+ } else if (+recDate == +date) {
+ return rec;
+ }
+ }
+ return false;
+ };
+ })();
+
+ if (!this.constrain) {
+ this.chart.filteredStore = this.chart.store;
+ return;
+ }
+
+ while(+fromDate <= +toDate) {
+ record = getRecordByDate(fromDate);
+ recObj = {};
+ if (record) {
+ newStore.add(record.data);
+ } else {
+ newStore.model.prototype.fields.each(function(f) {
+ recObj[f.name] = false;
+ });
+ recObj.date = fromDate;
+ newStore.add(recObj);
+ }
+ fromDate = Ext.Date.add(fromDate, step[0], step[1]);
+ }
+
+ this.chart.filteredStore = newStore;
+ },
+
+
+ aggregate: function() {
+ var aggStore = {},
+ aggKeys = [], key, value,
+ op = this.aggregateOp,
+ field = this.fields, i,
+ fields = this.groupBy.split(','),
+ curField,
+ recFields = [],
+ recFieldsLen = 0,
+ obj,
+ dates = [],
+ json = [],
+ l = fields.length,
+ dateMethods = this.dateMethods,
+ aggregateFn = this.aggregateFn,
+ store = this.chart.filteredStore || this.chart.store;
+
+ store.each(function(rec) {
+
+ if (!recFields.length) {
+ rec.fields.each(function(f) {
+ recFields.push(f.name);
+ });
+ recFieldsLen = recFields.length;
+ }
+
+ value = rec.get(field);
+
+ for (i = 0; i < l; i++) {
+ if (i == 0) {
+ key = String(dateMethods[fields[i]](value));
+ } else {
+ key += '||' + dateMethods[fields[i]](value);
+ }
+ }
+
+ if (key in aggStore) {
+ obj = aggStore[key];
+ } else {
+ obj = aggStore[key] = {};
+ aggKeys.push(key);
+ dates.push(value);
+ }
+
+ for (i = 0; i < recFieldsLen; i++) {
+ curField = recFields[i];
+ if (!obj[curField]) {
+ obj[curField] = [];
+ }
+ if (rec.get(curField) !== undefined) {
+ obj[curField].push(rec.get(curField));
+ }
+ }
+ });
+
+ for (key in aggStore) {
+ obj = aggStore[key];
+ for (i = 0; i < recFieldsLen; i++) {
+ curField = recFields[i];
+ obj[curField] = aggregateFn[op](obj[curField]);
+ }
+ json.push(obj);
+ }
+ this.chart.substore = Ext.create('Ext.data.JsonStore', {
+ fields: recFields,
+ data: json
+ });
+
+ this.dates = dates;
+ },
+
+
+ setLabels: function() {
+ var store = this.chart.substore,
+ fields = this.fields,
+ format = this.dateFormat,
+ labels, i, dates = this.dates,
+ formatFn = Ext.Date.format;
+ this.labels = labels = [];
+ store.each(function(record, i) {
+ if (!format) {
+ labels.push(record.get(fields));
+ } else {
+ labels.push(formatFn(dates[i], format));
+ }
+ }, this);
+ },
+
+ processView: function() {
+
+ if (this.constrain) {
+ this.constrainDates();
+ this.aggregate();
+ this.chart.substore = this.chart.filteredStore;
+ } else {
+ this.aggregate();
+ }
+ },
+
+
+ applyData: function() {
+ this.setLabels();
+ var count = this.chart.substore.getCount();
+ return {
+ from: 0,
+ to: count,
+ steps: count - 1,
+ step: 1
+ };
+ }
+ });
+
+
+
+Ext.define('Ext.chart.series.Series', {
+
+
+
+ mixins: {
+ observable: 'Ext.util.Observable',
+ labels: 'Ext.chart.Label',
+ highlights: 'Ext.chart.Highlight',
+ tips: 'Ext.chart.Tip',
+ callouts: 'Ext.chart.Callout'
+ },
+
+
+
+
+
+
+
+
+ type: null,
+
+
+ title: null,
+
+
+ showInLegend: true,
+
+
+ renderer: function(sprite, record, attributes, index, store) {
+ return attributes;
+ },
+
+
+ shadowAttributes: null,
+
+ //@private triggerdrawlistener flag
+
+ triggerAfterDraw: false,
+
+
+
+ constructor: function(config) {
+ var me = this;
+ if (config) {
+ Ext.apply(me, config);
+ }
+
+ me.shadowGroups = [];
+
+ me.mixins.labels.constructor.call(me, config);
+ me.mixins.highlights.constructor.call(me, config);
+ me.mixins.tips.constructor.call(me, config);
+ me.mixins.callouts.constructor.call(me, config);
+
+ me.addEvents({
+ scope: me,
+ itemmouseover: true,
+ itemmouseout: true,
+ itemmousedown: true,
+ itemmouseup: true,
+ mouseleave: true,
+ afterdraw: true,
+
+
+ titlechange: true
+ });
+
+ me.mixins.observable.constructor.call(me, config);
+
+ me.on({
+ scope: me,
+ itemmouseover: me.onItemMouseOver,
+ itemmouseout: me.onItemMouseOut,
+ mouseleave: me.onMouseLeave
+ });
+ },
+
+
+ setBBox: function(noGutter) {
+ var me = this,
+ chart = me.chart,
+ chartBBox = chart.chartBBox,
+ gutterX = noGutter ? 0 : chart.maxGutter[0],
+ gutterY = noGutter ? 0 : chart.maxGutter[1],
+ clipBox, bbox;
+
+ clipBox = {
+ x: chartBBox.x,
+ y: chartBBox.y,
+ width: chartBBox.width,
+ height: chartBBox.height
+ };
+ me.clipBox = clipBox;
+
+ bbox = {
+ x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
+ y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
+ width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
+ height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
+ };
+ me.bbox = bbox;
+ },
+
+
+ onAnimate: function(sprite, attr) {
+ var me = this;
+ sprite.stopAnimation();
+ if (me.triggerAfterDraw) {
+ return sprite.animate(Ext.applyIf(attr, me.chart.animate));
+ } else {
+ me.triggerAfterDraw = true;
+ return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
+ listeners: {
+ 'afteranimate': function() {
+ me.triggerAfterDraw = false;
+ me.fireEvent('afterrender');
+ }
+ }
+ }));
+ }
+ },
+
+
+ getGutters: function() {
+ return [0, 0];
+ },
+
+
+ onItemMouseOver: function(item) {
+ var me = this;
+ if (item.series === me) {
+ if (me.highlight) {
+ me.highlightItem(item);
+ }
+ if (me.tooltip) {
+ me.showTip(item);
+ }
+ }
+ },
+
+
+ onItemMouseOut: function(item) {
+ var me = this;
+ if (item.series === me) {
+ me.unHighlightItem();
+ if (me.tooltip) {
+ me.hideTip(item);
+ }
+ }
+ },
+
+
+ onMouseLeave: function() {
+ var me = this;
+ me.unHighlightItem();
+ if (me.tooltip) {
+ me.hideTip();
+ }
+ },
+
+
+ getItemForPoint: function(x, y) {
+
+ if (!this.items || !this.items.length || this.seriesIsHidden) {
+ return null;
+ }
+ var me = this,
+ items = me.items,
+ bbox = me.bbox,
+ item, i, ln;
+
+ if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
+ return null;
+ }
+ for (i = 0, ln = items.length; i < ln; i++) {
+ if (items[i] && this.isItemInPoint(x, y, items[i], i)) {
+ return items[i];
+ }
+ }
+
+ return null;
+ },
+
+ isItemInPoint: function(x, y, item, i) {
+ return false;
+ },
+
+
+ hideAll: function() {
+ var me = this,
+ items = me.items,
+ item, len, i, sprite;
+
+ me.seriesIsHidden = true;
+ me._prevShowMarkers = me.showMarkers;
+
+ me.showMarkers = false;
+
+ me.hideLabels(0);
+
+ for (i = 0, len = items.length; i < len; i++) {
+ item = items[i];
+ sprite = item.sprite;
+ if (sprite) {
+ sprite.setAttributes({
+ hidden: true
+ }, true);
+ }
+ }
+ },
+
+
+ showAll: function() {
+ var me = this,
+ prevAnimate = me.chart.animate;
+ me.chart.animate = false;
+ me.seriesIsHidden = false;
+ me.showMarkers = me._prevShowMarkers;
+ me.drawSeries();
+ me.chart.animate = prevAnimate;
+ },
+
+
+ getLegendColor: function(index) {
+ var me = this, fill, stroke;
+ if (me.seriesStyle) {
+ fill = me.seriesStyle.fill;
+ stroke = me.seriesStyle.stroke;
+ if (fill && fill != 'none') {
+ return fill;
+ }
+ return stroke;
+ }
+ return '#000';
+ },
+
+
+ visibleInLegend: function(index){
+ var excludes = this.__excludes;
+ if (excludes) {
+ return !excludes[index];
+ }
+ return !this.seriesIsHidden;
+ },
+
+
+ setTitle: function(index, title) {
+ var me = this,
+ oldTitle = me.title;
+
+ if (Ext.isString(index)) {
+ title = index;
+ index = 0;
+ }
+
+ if (Ext.isArray(oldTitle)) {
+ oldTitle[index] = title;
+ } else {
+ me.title = title;
+ }
+
+ me.fireEvent('titlechange', title, index);
+ }
+});
+
+
+Ext.define('Ext.chart.series.Cartesian', {
+
+
+
+ extend: 'Ext.chart.series.Series',
+
+ alternateClassName: ['Ext.chart.CartesianSeries', 'Ext.chart.CartesianChart'],
+
+
+
+
+ xField: null,
+
+
+ yField: null,
+
+
+ axis: 'left'
+});
+
+
+Ext.define('Ext.chart.series.Area', {
+
+
+
+ extend: 'Ext.chart.series.Cartesian',
+
+ alias: 'series.area',
+
+ requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
+
+
+
+ type: 'area',
+
+
+ stacked: true,
+
+
+ style: {},
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ var me = this,
+ surface = me.chart.surface,
+ i, l;
+ Ext.apply(me, config, {
+ __excludes: [],
+ highlightCfg: {
+ lineWidth: 3,
+ stroke: '#55c',
+ opacity: 0.8,
+ color: '#f00'
+ }
+ });
+ if (me.highlight) {
+ me.highlightSprite = surface.add({
+ type: 'path',
+ path: ['M', 0, 0],
+ zIndex: 1000,
+ opacity: 0.3,
+ lineWidth: 5,
+ hidden: true,
+ stroke: '#444'
+ });
+ }
+ me.group = surface.getGroup(me.seriesId);
+ },
+
+
+ shrink: function(xValues, yValues, size) {
+ var len = xValues.length,
+ ratio = Math.floor(len / size),
+ i, j,
+ xSum = 0,
+ yCompLen = this.areas.length,
+ ySum = [],
+ xRes = [],
+ yRes = [];
+
+ for (j = 0; j < yCompLen; ++j) {
+ ySum[j] = 0;
+ }
+ for (i = 0; i < len; ++i) {
+ xSum += xValues[i];
+ for (j = 0; j < yCompLen; ++j) {
+ ySum[j] += yValues[i][j];
+ }
+ if (i % ratio == 0) {
+
+ xRes.push(xSum/ratio);
+ for (j = 0; j < yCompLen; ++j) {
+ ySum[j] /= ratio;
+ }
+ yRes.push(ySum);
+
+ xSum = 0;
+ for (j = 0, ySum = []; j < yCompLen; ++j) {
+ ySum[j] = 0;
+ }
+ }
+ }
+ return {
+ x: xRes,
+ y: yRes
+ };
+ },
+
+
+ getBounds: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ areas = [].concat(me.yField),
+ areasLen = areas.length,
+ xValues = [],
+ yValues = [],
+ infinity = Infinity,
+ minX = infinity,
+ minY = infinity,
+ maxX = -infinity,
+ maxY = -infinity,
+ math = Math,
+ mmin = math.min,
+ mmax = math.max,
+ bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
+
+ me.setBBox();
+ bbox = me.bbox;
+
+
+ if (me.axis) {
+ axis = chart.axes.get(me.axis);
+ if (axis) {
+ out = axis.calcEnds();
+ minY = out.from || axis.prevMin;
+ maxY = mmax(out.to || axis.prevMax, 0);
+ }
+ }
+
+ if (me.yField && !Ext.isNumber(minY)) {
+ axis = Ext.create('Ext.chart.axis.Axis', {
+ chart: chart,
+ fields: [].concat(me.yField)
+ });
+ out = axis.calcEnds();
+ minY = out.from || axis.prevMin;
+ maxY = mmax(out.to || axis.prevMax, 0);
+ }
+
+ if (!Ext.isNumber(minY)) {
+ minY = 0;
+ }
+ if (!Ext.isNumber(maxY)) {
+ maxY = 0;
+ }
+
+ store.each(function(record, i) {
+ xValue = record.get(me.xField);
+ yValue = [];
+ if (typeof xValue != 'number') {
+ xValue = i;
+ }
+ xValues.push(xValue);
+ acumY = 0;
+ for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
+ areaElem = record.get(areas[areaIndex]);
+ if (typeof areaElem == 'number') {
+ minY = mmin(minY, areaElem);
+ yValue.push(areaElem);
+ acumY += areaElem;
+ }
+ }
+ minX = mmin(minX, xValue);
+ maxX = mmax(maxX, xValue);
+ maxY = mmax(maxY, acumY);
+ yValues.push(yValue);
+ }, me);
+
+ xScale = bbox.width / (maxX - minX);
+ yScale = bbox.height / (maxY - minY);
+
+ ln = xValues.length;
+ if ((ln > bbox.width) && me.areas) {
+ sumValues = me.shrink(xValues, yValues, bbox.width);
+ xValues = sumValues.x;
+ yValues = sumValues.y;
+ }
+
+ return {
+ bbox: bbox,
+ minX: minX,
+ minY: minY,
+ xValues: xValues,
+ yValues: yValues,
+ xScale: xScale,
+ yScale: yScale,
+ areasLen: areasLen
+ };
+ },
+
+
+ getPaths: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ first = true,
+ bounds = me.getBounds(),
+ bbox = bounds.bbox,
+ items = me.items = [],
+ componentPaths = [],
+ componentPath,
+ paths = [],
+ i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
+
+ ln = bounds.xValues.length;
+
+ for (i = 0; i < ln; i++) {
+ xValue = bounds.xValues[i];
+ yValue = bounds.yValues[i];
+ x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
+ acumY = 0;
+ for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
+
+ if (me.__excludes[areaIndex]) {
+ continue;
+ }
+ if (!componentPaths[areaIndex]) {
+ componentPaths[areaIndex] = [];
+ }
+ areaElem = yValue[areaIndex];
+ acumY += areaElem;
+ y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
+ if (!paths[areaIndex]) {
+ paths[areaIndex] = ['M', x, y];
+ componentPaths[areaIndex].push(['L', x, y]);
+ } else {
+ paths[areaIndex].push('L', x, y);
+ componentPaths[areaIndex].push(['L', x, y]);
+ }
+ if (!items[areaIndex]) {
+ items[areaIndex] = {
+ pointsUp: [],
+ pointsDown: [],
+ series: me
+ };
+ }
+ items[areaIndex].pointsUp.push([x, y]);
+ }
+ }
+
+
+ for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
+
+ if (me.__excludes[areaIndex]) {
+ continue;
+ }
+ path = paths[areaIndex];
+
+ if (areaIndex == 0 || first) {
+ first = false;
+ path.push('L', x, bbox.y + bbox.height,
+ 'L', bbox.x, bbox.y + bbox.height,
+ 'Z');
+ }
+
+ else {
+ componentPath = componentPaths[prevAreaIndex];
+ componentPath.reverse();
+ path.push('L', x, componentPath[0][2]);
+ for (i = 0; i < ln; i++) {
+ path.push(componentPath[i][0],
+ componentPath[i][1],
+ componentPath[i][2]);
+ items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
+ }
+ path.push('L', bbox.x, path[2], 'Z');
+ }
+ prevAreaIndex = areaIndex;
+ }
+ return {
+ paths: paths,
+ areasLen: bounds.areasLen
+ };
+ },
+
+
+ drawSeries: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ surface = chart.surface,
+ animate = chart.animate,
+ group = me.group,
+ endLineStyle = Ext.apply(me.seriesStyle, me.style),
+ colorArrayStyle = me.colorArrayStyle,
+ colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+ areaIndex, areaElem, paths, path, rendererAttributes;
+
+ me.unHighlightItem();
+ me.cleanHighlights();
+
+ if (!store || !store.getCount()) {
+ return;
+ }
+
+ paths = me.getPaths();
+
+ if (!me.areas) {
+ me.areas = [];
+ }
+
+ for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
+
+ if (me.__excludes[areaIndex]) {
+ continue;
+ }
+ if (!me.areas[areaIndex]) {
+ me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
+ type: 'path',
+ group: group,
+
+ path: paths.paths[areaIndex],
+ stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
+ fill: colorArrayStyle[areaIndex % colorArrayLength]
+ }, endLineStyle || {}));
+ }
+ areaElem = me.areas[areaIndex];
+ path = paths.paths[areaIndex];
+ if (animate) {
+
+ rendererAttributes = me.renderer(areaElem, false, {
+ path: path,
+
+ fill: colorArrayStyle[areaIndex % colorArrayLength],
+ stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
+ }, areaIndex, store);
+
+ me.animation = me.onAnimate(areaElem, {
+ to: rendererAttributes
+ });
+ } else {
+ rendererAttributes = me.renderer(areaElem, false, {
+ path: path,
+
+ hidden: false,
+ fill: colorArrayStyle[areaIndex % colorArrayLength],
+ stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
+ }, areaIndex, store);
+ me.areas[areaIndex].setAttributes(rendererAttributes, true);
+ }
+ }
+ me.renderLabels();
+ me.renderCallouts();
+ },
+
+
+ onAnimate: function(sprite, attr) {
+ sprite.show();
+ return this.callParent(arguments);
+ },
+
+
+ onCreateLabel: function(storeItem, item, i, display) {
+ var me = this,
+ group = me.labelsGroup,
+ config = me.label,
+ bbox = me.bbox,
+ endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
+
+ return me.chart.surface.add(Ext.apply({
+ 'type': 'text',
+ 'text-anchor': 'middle',
+ 'group': group,
+ 'x': item.point[0],
+ 'y': bbox.y + bbox.height / 2
+ }, endLabelStyle || {}));
+ },
+
+
+ onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
+ var me = this,
+ chart = me.chart,
+ resizing = chart.resizing,
+ config = me.label,
+ format = config.renderer,
+ field = config.field,
+ bbox = me.bbox,
+ x = item.point[0],
+ y = item.point[1],
+ bb, width, height;
+
+ label.setAttributes({
+ text: format(storeItem.get(field[index])),
+ hidden: true
+ }, true);
+
+ bb = label.getBBox();
+ width = bb.width / 2;
+ height = bb.height / 2;
+
+ x = x - width < bbox.x? bbox.x + width : x;
+ x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
+ y = y - height < bbox.y? bbox.y + height : y;
+ y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
+
+ if (me.chart.animate && !me.chart.resizing) {
+ label.show(true);
+ me.onAnimate(label, {
+ to: {
+ x: x,
+ y: y
+ }
+ });
+ } else {
+ label.setAttributes({
+ x: x,
+ y: y
+ }, true);
+ if (resizing) {
+ me.animation.on('afteranimate', function() {
+ label.show(true);
+ });
+ } else {
+ label.show(true);
+ }
+ }
+ },
+
+
+ onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ resizing = chart.resizing,
+ config = me.callouts,
+ items = me.items,
+ prev = (i == 0) ? false : items[i -1].point,
+ next = (i == items.length -1) ? false : items[i +1].point,
+ cur = item.point,
+ dir, norm, normal, a, aprev, anext,
+ bbox = callout.label.getBBox(),
+ offsetFromViz = 30,
+ offsetToSide = 10,
+ offsetBox = 3,
+ boxx, boxy, boxw, boxh,
+ p, clipRect = me.clipRect,
+ x, y;
+
+
+ if (!prev) {
+ prev = cur;
+ }
+ if (!next) {
+ next = cur;
+ }
+ a = (next[1] - prev[1]) / (next[0] - prev[0]);
+ aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
+ anext = (next[1] - cur[1]) / (next[0] - cur[0]);
+
+ norm = Math.sqrt(1 + a * a);
+ dir = [1 / norm, a / norm];
+ normal = [-dir[1], dir[0]];
+
+
+ if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) {
+ normal[0] *= -1;
+ normal[1] *= -1;
+ } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
+ normal[0] *= -1;
+ normal[1] *= -1;
+ }
+
+
+ x = cur[0] + normal[0] * offsetFromViz;
+ y = cur[1] + normal[1] * offsetFromViz;
+
+
+ boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+ boxy = y - bbox.height /2 - offsetBox;
+ boxw = bbox.width + 2 * offsetBox;
+ boxh = bbox.height + 2 * offsetBox;
+
+
+
+ if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
+ normal[0] *= -1;
+ }
+ if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
+ normal[1] *= -1;
+ }
+
+
+ x = cur[0] + normal[0] * offsetFromViz;
+ y = cur[1] + normal[1] * offsetFromViz;
+
+
+ boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+ boxy = y - bbox.height /2 - offsetBox;
+ boxw = bbox.width + 2 * offsetBox;
+ boxh = bbox.height + 2 * offsetBox;
+
+
+ callout.lines.setAttributes({
+ path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+ }, true);
+
+ callout.box.setAttributes({
+ x: boxx,
+ y: boxy,
+ width: boxw,
+ height: boxh
+ }, true);
+
+ callout.label.setAttributes({
+ x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
+ y: y
+ }, true);
+ for (p in callout) {
+ callout[p].show(true);
+ }
+ },
+
+ isItemInPoint: function(x, y, item, i) {
+ var me = this,
+ pointsUp = item.pointsUp,
+ pointsDown = item.pointsDown,
+ abs = Math.abs,
+ dist = Infinity, p, pln, point;
+
+ for (p = 0, pln = pointsUp.length; p < pln; p++) {
+ point = [pointsUp[p][0], pointsUp[p][1]];
+ if (dist > abs(x - point[0])) {
+ dist = abs(x - point[0]);
+ } else {
+ point = pointsUp[p -1];
+ if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
+ item.storeIndex = p -1;
+ item.storeField = me.yField[i];
+ item.storeItem = me.chart.store.getAt(p -1);
+ item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
+ return true;
+ } else {
+ break;
+ }
+ }
+ }
+ return false;
+ },
+
+
+ highlightSeries: function() {
+ var area, to, fillColor;
+ if (this._index !== undefined) {
+ area = this.areas[this._index];
+ if (area.__highlightAnim) {
+ area.__highlightAnim.paused = true;
+ }
+ area.__highlighted = true;
+ area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
+ area.__prevFill = area.__prevFill || area.attr.fill;
+ area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
+ fillColor = Ext.draw.Color.fromString(area.__prevFill);
+ to = {
+ lineWidth: (area.__prevLineWidth || 0) + 2
+ };
+ if (fillColor) {
+ to.fill = fillColor.getLighter(0.2).toString();
+ }
+ else {
+ to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
+ }
+ if (this.chart.animate) {
+ area.__highlightAnim = Ext.create('Ext.fx.Anim', Ext.apply({
+ target: area,
+ to: to
+ }, this.chart.animate));
+ }
+ else {
+ area.setAttributes(to, true);
+ }
+ }
+ },
+
+
+ unHighlightSeries: function() {
+ var area;
+ if (this._index !== undefined) {
+ area = this.areas[this._index];
+ if (area.__highlightAnim) {
+ area.__highlightAnim.paused = true;
+ }
+ if (area.__highlighted) {
+ area.__highlighted = false;
+ area.__highlightAnim = Ext.create('Ext.fx.Anim', {
+ target: area,
+ to: {
+ fill: area.__prevFill,
+ opacity: area.__prevOpacity,
+ lineWidth: area.__prevLineWidth
+ }
+ });
+ }
+ }
+ },
+
+
+ highlightItem: function(item) {
+ var me = this,
+ points, path;
+ if (!item) {
+ this.highlightSeries();
+ return;
+ }
+ points = item._points;
+ path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
+ : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
+ me.highlightSprite.setAttributes({
+ path: path,
+ hidden: false
+ }, true);
+ },
+
+
+ unHighlightItem: function(item) {
+ if (!item) {
+ this.unHighlightSeries();
+ }
+
+ if (this.highlightSprite) {
+ this.highlightSprite.hide(true);
+ }
+ },
+
+
+ hideAll: function() {
+ if (!isNaN(this._index)) {
+ this.__excludes[this._index] = true;
+ this.areas[this._index].hide(true);
+ this.drawSeries();
+ }
+ },
+
+
+ showAll: function() {
+ if (!isNaN(this._index)) {
+ this.__excludes[this._index] = false;
+ this.areas[this._index].show(true);
+ this.drawSeries();
+ }
+ },
+
+
+ getLegendColor: function(index) {
+ var me = this;
+ return me.colorArrayStyle[index % me.colorArrayStyle.length];
+ }
+});
+
+
+Ext.define('Ext.chart.series.Bar', {
+
+
+
+ extend: 'Ext.chart.series.Cartesian',
+
+ alternateClassName: ['Ext.chart.BarSeries', 'Ext.chart.BarChart', 'Ext.chart.StackedBarChart'],
+
+ requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
+
+
+
+ type: 'bar',
+
+ alias: 'series.bar',
+
+ column: false,
+
+
+ style: {},
+
+
+ gutter: 38.2,
+
+
+ groupGutter: 38.2,
+
+
+ xPadding: 0,
+
+
+ yPadding: 10,
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ var me = this,
+ surface = me.chart.surface,
+ shadow = me.chart.shadow,
+ i, l;
+ Ext.apply(me, config, {
+ highlightCfg: {
+ lineWidth: 3,
+ stroke: '#55c',
+ opacity: 0.8,
+ color: '#f00'
+ },
+
+ shadowAttributes: [{
+ "stroke-width": 6,
+ "stroke-opacity": 0.05,
+ stroke: 'rgb(200, 200, 200)',
+ translate: {
+ x: 1.2,
+ y: 1.2
+ }
+ }, {
+ "stroke-width": 4,
+ "stroke-opacity": 0.1,
+ stroke: 'rgb(150, 150, 150)',
+ translate: {
+ x: 0.9,
+ y: 0.9
+ }
+ }, {
+ "stroke-width": 2,
+ "stroke-opacity": 0.15,
+ stroke: 'rgb(100, 100, 100)',
+ translate: {
+ x: 0.6,
+ y: 0.6
+ }
+ }]
+ });
+ me.group = surface.getGroup(me.seriesId + '-bars');
+ if (shadow) {
+ for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+ me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+ }
+ }
+ },
+
+
+ getBarGirth: function() {
+ var me = this,
+ store = me.chart.store,
+ column = me.column,
+ ln = store.getCount(),
+ gutter = me.gutter / 100;
+
+ return (me.chart.chartBBox[column ? 'width' : 'height'] - me[column ? 'xPadding' : 'yPadding'] * 2) / (ln * (gutter + 1) - gutter);
+ },
+
+
+ getGutters: function() {
+ var me = this,
+ column = me.column,
+ gutter = Math.ceil(me[column ? 'xPadding' : 'yPadding'] + me.getBarGirth() / 2);
+ return me.column ? [gutter, 0] : [0, gutter];
+ },
+
+
+ getBounds: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ bars = [].concat(me.yField),
+ barsLen = bars.length,
+ groupBarsLen = barsLen,
+ groupGutter = me.groupGutter / 100,
+ column = me.column,
+ xPadding = me.xPadding,
+ yPadding = me.yPadding,
+ stacked = me.stacked,
+ barWidth = me.getBarGirth(),
+ math = Math,
+ mmax = math.max,
+ mabs = math.abs,
+ groupBarWidth, bbox, minY, maxY, axis, out,
+ scale, zero, total, rec, j, plus, minus;
+
+ me.setBBox(true);
+ bbox = me.bbox;
+
+
+ if (me.__excludes) {
+ for (j = 0, total = me.__excludes.length; j < total; j++) {
+ if (me.__excludes[j]) {
+ groupBarsLen--;
+ }
+ }
+ }
+
+ if (me.axis) {
+ axis = chart.axes.get(me.axis);
+ if (axis) {
+ out = axis.calcEnds();
+ minY = out.from || axis.prevMin;
+ maxY = mmax(out.to || axis.prevMax, 0);
+ }
+ }
+
+ if (me.yField && !Ext.isNumber(minY)) {
+ axis = Ext.create('Ext.chart.axis.Axis', {
+ chart: chart,
+ fields: [].concat(me.yField)
+ });
+ out = axis.calcEnds();
+ minY = out.from || axis.prevMin;
+ maxY = mmax(out.to || axis.prevMax, 0);
+ }
+
+ if (!Ext.isNumber(minY)) {
+ minY = 0;
+ }
+ if (!Ext.isNumber(maxY)) {
+ maxY = 0;
+ }
+ scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (maxY - minY);
+ groupBarWidth = barWidth / ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter);
+ zero = (column) ? bbox.y + bbox.height - yPadding : bbox.x + xPadding;
+
+ if (stacked) {
+ total = [[], []];
+ store.each(function(record, i) {
+ total[0][i] = total[0][i] || 0;
+ total[1][i] = total[1][i] || 0;
+ for (j = 0; j < barsLen; j++) {
+ if (me.__excludes && me.__excludes[j]) {
+ continue;
+ }
+ rec = record.get(bars[j]);
+ total[+(rec > 0)][i] += mabs(rec);
+ }
+ });
+ total[+(maxY > 0)].push(mabs(maxY));
+ total[+(minY > 0)].push(mabs(minY));
+ minus = mmax.apply(math, total[0]);
+ plus = mmax.apply(math, total[1]);
+ scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (plus + minus);
+ zero = zero + minus * scale * (column ? -1 : 1);
+ }
+ else if (minY / maxY < 0) {
+ zero = zero - minY * scale * (column ? -1 : 1);
+ }
+ return {
+ bars: bars,
+ bbox: bbox,
+ barsLen: barsLen,
+ groupBarsLen: groupBarsLen,
+ barWidth: barWidth,
+ groupBarWidth: groupBarWidth,
+ scale: scale,
+ zero: zero,
+ xPadding: xPadding,
+ yPadding: yPadding,
+ signed: minY / maxY < 0,
+ minY: minY,
+ maxY: maxY
+ };
+ },
+
+
+ getPaths: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ bounds = me.bounds = me.getBounds(),
+ items = me.items = [],
+ gutter = me.gutter / 100,
+ groupGutter = me.groupGutter / 100,
+ animate = chart.animate,
+ column = me.column,
+ group = me.group,
+ enableShadows = chart.shadow,
+ shadowGroups = me.shadowGroups,
+ shadowAttributes = me.shadowAttributes,
+ shadowGroupsLn = shadowGroups.length,
+ bbox = bounds.bbox,
+ xPadding = me.xPadding,
+ yPadding = me.yPadding,
+ stacked = me.stacked,
+ barsLen = bounds.barsLen,
+ colors = me.colorArrayStyle,
+ colorLength = colors && colors.length || 0,
+ math = Math,
+ mmax = math.max,
+ mmin = math.min,
+ mabs = math.abs,
+ j, yValue, height, totalDim, totalNegDim, bottom, top, hasShadow, barAttr, attrs, counter,
+ shadowIndex, shadow, sprite, offset, floorY;
+
+ store.each(function(record, i, total) {
+ bottom = bounds.zero;
+ top = bounds.zero;
+ totalDim = 0;
+ totalNegDim = 0;
+ hasShadow = false;
+ for (j = 0, counter = 0; j < barsLen; j++) {
+
+ if (me.__excludes && me.__excludes[j]) {
+ continue;
+ }
+ yValue = record.get(bounds.bars[j]);
+ height = Math.round((yValue - ((bounds.minY < 0) ? 0 : bounds.minY)) * bounds.scale);
+ barAttr = {
+ fill: colors[(barsLen > 1 ? j : 0) % colorLength]
+ };
+ if (column) {
+ Ext.apply(barAttr, {
+ height: height,
+ width: mmax(bounds.groupBarWidth, 0),
+ x: (bbox.x + xPadding + i * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked),
+ y: bottom - height
+ });
+ }
+ else {
+
+ offset = (total - 1) - i;
+ Ext.apply(barAttr, {
+ height: mmax(bounds.groupBarWidth, 0),
+ width: height + (bottom == bounds.zero),
+ x: bottom + (bottom != bounds.zero),
+ y: (bbox.y + yPadding + offset * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked + 1)
+ });
+ }
+ if (height < 0) {
+ if (column) {
+ barAttr.y = top;
+ barAttr.height = mabs(height);
+ } else {
+ barAttr.x = top + height;
+ barAttr.width = mabs(height);
+ }
+ }
+ if (stacked) {
+ if (height < 0) {
+ top += height * (column ? -1 : 1);
+ } else {
+ bottom += height * (column ? -1 : 1);
+ }
+ totalDim += mabs(height);
+ if (height < 0) {
+ totalNegDim += mabs(height);
+ }
+ }
+ barAttr.x = Math.floor(barAttr.x) + 1;
+ floorY = Math.floor(barAttr.y);
+ if (!Ext.isIE9 && barAttr.y > floorY) {
+ floorY--;
+ }
+ barAttr.y = floorY;
+ barAttr.width = Math.floor(barAttr.width);
+ barAttr.height = Math.floor(barAttr.height);
+ items.push({
+ series: me,
+ storeItem: record,
+ value: [record.get(me.xField), yValue],
+ attr: barAttr,
+ point: column ? [barAttr.x + barAttr.width / 2, yValue >= 0 ? barAttr.y : barAttr.y + barAttr.height] :
+ [yValue >= 0 ? barAttr.x + barAttr.width : barAttr.x, barAttr.y + barAttr.height / 2]
+ });
+
+ if (animate && chart.resizing) {
+ attrs = column ? {
+ x: barAttr.x,
+ y: bounds.zero,
+ width: barAttr.width,
+ height: 0
+ } : {
+ x: bounds.zero,
+ y: barAttr.y,
+ width: 0,
+ height: barAttr.height
+ };
+ if (enableShadows && (stacked && !hasShadow || !stacked)) {
+ hasShadow = true;
+
+ for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+ shadow = shadowGroups[shadowIndex].getAt(stacked ? i : (i * barsLen + j));
+ if (shadow) {
+ shadow.setAttributes(attrs, true);
+ }
+ }
+ }
+
+ sprite = group.getAt(i * barsLen + j);
+ if (sprite) {
+ sprite.setAttributes(attrs, true);
+ }
+ }
+ counter++;
+ }
+ if (stacked && items.length) {
+ items[i * counter].totalDim = totalDim;
+ items[i * counter].totalNegDim = totalNegDim;
+ }
+ }, me);
+ },
+
+
+ renderShadows: function(i, barAttr, baseAttrs, bounds) {
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ animate = chart.animate,
+ stacked = me.stacked,
+ shadowGroups = me.shadowGroups,
+ shadowAttributes = me.shadowAttributes,
+ shadowGroupsLn = shadowGroups.length,
+ store = chart.substore || chart.store,
+ column = me.column,
+ items = me.items,
+ shadows = [],
+ zero = bounds.zero,
+ shadowIndex, shadowBarAttr, shadow, totalDim, totalNegDim, j, rendererAttributes;
+
+ if ((stacked && (i % bounds.groupBarsLen === 0)) || !stacked) {
+ j = i / bounds.groupBarsLen;
+
+ for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+ shadowBarAttr = Ext.apply({}, shadowAttributes[shadowIndex]);
+ shadow = shadowGroups[shadowIndex].getAt(stacked ? j : i);
+ Ext.copyTo(shadowBarAttr, barAttr, 'x,y,width,height');
+ if (!shadow) {
+ shadow = surface.add(Ext.apply({
+ type: 'rect',
+ group: shadowGroups[shadowIndex]
+ }, Ext.apply({}, baseAttrs, shadowBarAttr)));
+ }
+ if (stacked) {
+ totalDim = items[i].totalDim;
+ totalNegDim = items[i].totalNegDim;
+ if (column) {
+ shadowBarAttr.y = zero - totalNegDim;
+ shadowBarAttr.height = totalDim;
+ }
+ else {
+ shadowBarAttr.x = zero - totalNegDim;
+ shadowBarAttr.width = totalDim;
+ }
+ }
+ if (animate) {
+ if (!stacked) {
+ rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store);
+ me.onAnimate(shadow, { to: rendererAttributes });
+ }
+ else {
+ rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: true }), i, store);
+ shadow.setAttributes(rendererAttributes, true);
+ }
+ }
+ else {
+ rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: false }), i, store);
+ shadow.setAttributes(rendererAttributes, true);
+ }
+ shadows.push(shadow);
+ }
+ }
+ return shadows;
+ },
+
+
+ drawSeries: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ surface = chart.surface,
+ animate = chart.animate,
+ stacked = me.stacked,
+ column = me.column,
+ enableShadows = chart.shadow,
+ shadowGroups = me.shadowGroups,
+ shadowGroupsLn = shadowGroups.length,
+ group = me.group,
+ seriesStyle = me.seriesStyle,
+ items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup,
+ bounds, endSeriesStyle, barAttr, attrs, anim;
+
+ if (!store || !store.getCount()) {
+ return;
+ }
+
+
+ delete seriesStyle.fill;
+ endSeriesStyle = Ext.apply(seriesStyle, this.style);
+ me.unHighlightItem();
+ me.cleanHighlights();
+
+ me.getPaths();
+ bounds = me.bounds;
+ items = me.items;
+
+ baseAttrs = column ? {
+ y: bounds.zero,
+ height: 0
+ } : {
+ x: bounds.zero,
+ width: 0
+ };
+ ln = items.length;
+
+ for (i = 0; i < ln; i++) {
+ sprite = group.getAt(i);
+ barAttr = items[i].attr;
+
+ if (enableShadows) {
+ items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds);
+ }
+
+
+ if (!sprite) {
+ attrs = Ext.apply({}, baseAttrs, barAttr);
+ attrs = Ext.apply(attrs, endSeriesStyle || {});
+ sprite = surface.add(Ext.apply({}, {
+ type: 'rect',
+ group: group
+ }, attrs));
+ }
+ if (animate) {
+ rendererAttributes = me.renderer(sprite, store.getAt(i), barAttr, i, store);
+ sprite._to = rendererAttributes;
+ anim = me.onAnimate(sprite, { to: Ext.apply(rendererAttributes, endSeriesStyle) });
+ if (enableShadows && stacked && (i % bounds.barsLen === 0)) {
+ j = i / bounds.barsLen;
+ for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+ anim.on('afteranimate', function() {
+ this.show(true);
+ }, shadowGroups[shadowIndex].getAt(j));
+ }
+ }
+ }
+ else {
+ rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(barAttr, { hidden: false }), i, store);
+ sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true);
+ }
+ items[i].sprite = sprite;
+ }
+
+
+ ln = group.getCount();
+ for (j = i; j < ln; j++) {
+ group.getAt(j).hide(true);
+ }
+
+ if (enableShadows) {
+ for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+ shadowGroup = shadowGroups[shadowIndex];
+ ln = shadowGroup.getCount();
+ for (j = i; j < ln; j++) {
+ shadowGroup.getAt(j).hide(true);
+ }
+ }
+ }
+ me.renderLabels();
+ },
+
+
+ onCreateLabel: function(storeItem, item, i, display) {
+ var me = this,
+ surface = me.chart.surface,
+ group = me.labelsGroup,
+ config = me.label,
+ endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}),
+ sprite;
+ return surface.add(Ext.apply({
+ type: 'text',
+ group: group
+ }, endLabelStyle || {}));
+ },
+
+
+ onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
+
+
+ var me = this,
+ opt = me.bounds,
+ groupBarWidth = opt.groupBarWidth,
+ column = me.column,
+ chart = me.chart,
+ chartBBox = chart.chartBBox,
+ resizing = chart.resizing,
+ xValue = item.value[0],
+ yValue = item.value[1],
+ attr = item.attr,
+ config = me.label,
+ rotate = config.orientation == 'vertical',
+ field = [].concat(config.field),
+ format = config.renderer,
+ text = format(storeItem.get(field[index])),
+ size = me.getLabelSize(text),
+ width = size.width,
+ height = size.height,
+ zero = opt.zero,
+ outside = 'outside',
+ insideStart = 'insideStart',
+ insideEnd = 'insideEnd',
+ offsetX = 10,
+ offsetY = 6,
+ signed = opt.signed,
+ x, y, finalAttr;
+
+ label.setAttributes({
+ text: text
+ });
+
+ if (column) {
+ if (display == outside) {
+ if (height + offsetY + attr.height > (yValue >= 0 ? zero - chartBBox.y : chartBBox.y + chartBBox.height - zero)) {
+ display = insideEnd;
+ }
+ } else {
+ if (height + offsetY > attr.height) {
+ display = outside;
+ }
+ }
+ x = attr.x + groupBarWidth / 2;
+ y = display == insideStart ?
+ (zero + ((height / 2 + 3) * (yValue >= 0 ? -1 : 1))) :
+ (yValue >= 0 ? (attr.y + ((height / 2 + 3) * (display == outside ? -1 : 1))) :
+ (attr.y + attr.height + ((height / 2 + 3) * (display === outside ? 1 : -1))));
+ }
+ else {
+ if (display == outside) {
+ if (width + offsetX + attr.width > (yValue >= 0 ? chartBBox.x + chartBBox.width - zero : zero - chartBBox.x)) {
+ display = insideEnd;
+ }
+ }
+ else {
+ if (width + offsetX > attr.width) {
+ display = outside;
+ }
+ }
+ x = display == insideStart ?
+ (zero + ((width / 2 + 5) * (yValue >= 0 ? 1 : -1))) :
+ (yValue >= 0 ? (attr.x + attr.width + ((width / 2 + 5) * (display === outside ? 1 : -1))) :
+ (attr.x + ((width / 2 + 5) * (display === outside ? -1 : 1))));
+ y = attr.y + groupBarWidth / 2;
+ }
+
+ finalAttr = {
+ x: x,
+ y: y
+ };
+
+ if (rotate) {
+ finalAttr.rotate = {
+ x: x,
+ y: y,
+ degrees: 270
+ };
+ }
+
+ if (animate && resizing) {
+ if (column) {
+ x = attr.x + attr.width / 2;
+ y = zero;
+ } else {
+ x = zero;
+ y = attr.y + attr.height / 2;
+ }
+ label.setAttributes({
+ x: x,
+ y: y
+ }, true);
+ if (rotate) {
+ label.setAttributes({
+ rotate: {
+ x: x,
+ y: y,
+ degrees: 270
+ }
+ }, true);
+ }
+ }
+
+ if (animate) {
+ me.onAnimate(label, { to: finalAttr });
+ }
+ else {
+ label.setAttributes(Ext.apply(finalAttr, {
+ hidden: false
+ }), true);
+ }
+ },
+
+
+ getLabelSize: function(value) {
+ var tester = this.testerLabel,
+ config = this.label,
+ endLabelStyle = Ext.apply({}, config, this.seriesLabelStyle || {}),
+ rotated = config.orientation === 'vertical',
+ bbox, w, h,
+ undef;
+ if (!tester) {
+ tester = this.testerLabel = this.chart.surface.add(Ext.apply({
+ type: 'text',
+ opacity: 0
+ }, endLabelStyle));
+ }
+ tester.setAttributes({
+ text: value
+ }, true);
+
+
+ bbox = tester.getBBox();
+ w = bbox.width;
+ h = bbox.height;
+ return {
+ width: rotated ? h : w,
+ height: rotated ? w : h
+ };
+ },
+
+
+ onAnimate: function(sprite, attr) {
+ sprite.show();
+ return this.callParent(arguments);
+ },
+
+ isItemInPoint: function(x, y, item) {
+ var bbox = item.sprite.getBBox();
+ return bbox.x <= x && bbox.y <= y
+ && (bbox.x + bbox.width) >= x
+ && (bbox.y + bbox.height) >= y;
+ },
+
+
+ hideAll: function() {
+ var axes = this.chart.axes;
+ if (!isNaN(this._index)) {
+ if (!this.__excludes) {
+ this.__excludes = [];
+ }
+ this.__excludes[this._index] = true;
+ this.drawSeries();
+ axes.each(function(axis) {
+ axis.drawAxis();
+ });
+ }
+ },
+
+
+ showAll: function() {
+ var axes = this.chart.axes;
+ if (!isNaN(this._index)) {
+ if (!this.__excludes) {
+ this.__excludes = [];
+ }
+ this.__excludes[this._index] = false;
+ this.drawSeries();
+ axes.each(function(axis) {
+ axis.drawAxis();
+ });
+ }
+ },
+
+
+ getLegendColor: function(index) {
+ var me = this;
+ return me.colorArrayStyle[index % me.colorArrayStyle.length];
+ }
+});
+
+
+Ext.define('Ext.chart.series.Column', {
+
+
+
+ alternateClassName: ['Ext.chart.ColumnSeries', 'Ext.chart.ColumnChart', 'Ext.chart.StackedColumnChart'],
+
+ extend: 'Ext.chart.series.Bar',
+
+
+
+ type: 'column',
+ alias: 'series.column',
+
+ column: true,
+
+
+ xPadding: 10,
+
+
+ yPadding: 0
+});
+
+Ext.define('Ext.chart.series.Gauge', {
+
+
+
+ extend: 'Ext.chart.series.Series',
+
+
+
+ type: "gauge",
+ alias: 'series.gauge',
+
+ rad: Math.PI / 180,
+
+
+ highlightDuration: 150,
+
+
+ angleField: false,
+
+
+ needle: false,
+
+
+ donut: false,
+
+
+ showInLegend: false,
+
+
+ style: {},
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ store = chart.store,
+ shadow = chart.shadow, i, l, cfg;
+ Ext.apply(me, config, {
+ shadowAttributes: [{
+ "stroke-width": 6,
+ "stroke-opacity": 1,
+ stroke: 'rgb(200, 200, 200)',
+ translate: {
+ x: 1.2,
+ y: 2
+ }
+ },
+ {
+ "stroke-width": 4,
+ "stroke-opacity": 1,
+ stroke: 'rgb(150, 150, 150)',
+ translate: {
+ x: 0.9,
+ y: 1.5
+ }
+ },
+ {
+ "stroke-width": 2,
+ "stroke-opacity": 1,
+ stroke: 'rgb(100, 100, 100)',
+ translate: {
+ x: 0.6,
+ y: 1
+ }
+ }]
+ });
+ me.group = surface.getGroup(me.seriesId);
+ if (shadow) {
+ for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+ me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+ }
+ }
+ surface.customAttributes.segment = function(opt) {
+ return me.getSegment(opt);
+ };
+ },
+
+ //@private updates some onbefore render parameters.
+
+ initialize: function() {
+ var me = this,
+ store = me.chart.substore || me.chart.store;
+
+ me.yField = [];
+ if (me.label.field) {
+ store.each(function(rec) {
+ me.yField.push(rec.get(me.label.field));
+ });
+ }
+ },
+
+
+ getSegment: function(opt) {
+ var me = this,
+ rad = me.rad,
+ cos = Math.cos,
+ sin = Math.sin,
+ abs = Math.abs,
+ x = me.centerX,
+ y = me.centerY,
+ x1 = 0, x2 = 0, x3 = 0, x4 = 0,
+ y1 = 0, y2 = 0, y3 = 0, y4 = 0,
+ delta = 1e-2,
+ r = opt.endRho - opt.startRho,
+ startAngle = opt.startAngle,
+ endAngle = opt.endAngle,
+ midAngle = (startAngle + endAngle) / 2 * rad,
+ margin = opt.margin || 0,
+ flag = abs(endAngle - startAngle) > 180,
+ a1 = Math.min(startAngle, endAngle) * rad,
+ a2 = Math.max(startAngle, endAngle) * rad,
+ singleSlice = false;
+
+ x += margin * cos(midAngle);
+ y += margin * sin(midAngle);
+
+ x1 = x + opt.startRho * cos(a1);
+ y1 = y + opt.startRho * sin(a1);
+
+ x2 = x + opt.endRho * cos(a1);
+ y2 = y + opt.endRho * sin(a1);
+
+ x3 = x + opt.startRho * cos(a2);
+ y3 = y + opt.startRho * sin(a2);
+
+ x4 = x + opt.endRho * cos(a2);
+ y4 = y + opt.endRho * sin(a2);
+
+ if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
+ singleSlice = true;
+ }
+
+ if (singleSlice) {
+ return {
+ path: [
+ ["M", x1, y1],
+ ["L", x2, y2],
+ ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
+ ["Z"]]
+ };
+ } else {
+ return {
+ path: [
+ ["M", x1, y1],
+ ["L", x2, y2],
+ ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
+ ["L", x3, y3],
+ ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
+ ["Z"]]
+ };
+ }
+ },
+
+
+ calcMiddle: function(item) {
+ var me = this,
+ rad = me.rad,
+ slice = item.slice,
+ x = me.centerX,
+ y = me.centerY,
+ startAngle = slice.startAngle,
+ endAngle = slice.endAngle,
+ radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin),
+ donut = +me.donut,
+ a1 = Math.min(startAngle, endAngle) * rad,
+ a2 = Math.max(startAngle, endAngle) * rad,
+ midAngle = -(a1 + (a2 - a1) / 2),
+ xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
+ ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
+
+ item.middle = {
+ x: xm,
+ y: ym
+ };
+ },
+
+
+ drawSeries: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ group = me.group,
+ animate = me.chart.animate,
+ axis = me.chart.axes.get(0),
+ minimum = axis && axis.minimum || me.minimum || 0,
+ maximum = axis && axis.maximum || me.maximum || 0,
+ field = me.angleField || me.field || me.xField,
+ surface = chart.surface,
+ chartBBox = chart.chartBBox,
+ rad = me.rad,
+ donut = +me.donut,
+ values = {},
+ items = [],
+ seriesStyle = me.seriesStyle,
+ seriesLabelStyle = me.seriesLabelStyle,
+ colorArrayStyle = me.colorArrayStyle,
+ colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+ gutterX = chart.maxGutter[0],
+ gutterY = chart.maxGutter[1],
+ cos = Math.cos,
+ sin = Math.sin,
+ rendererAttributes, centerX, centerY, slice, slices, sprite, value,
+ item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path,
+ p, spriteOptions, bbox, splitAngle, sliceA, sliceB;
+
+ Ext.apply(seriesStyle, me.style || {});
+
+ me.setBBox();
+ bbox = me.bbox;
+
+
+ if (me.colorSet) {
+ colorArrayStyle = me.colorSet;
+ colorArrayLength = colorArrayStyle.length;
+ }
+
+
+ if (!store || !store.getCount()) {
+ return;
+ }
+
+ centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
+ centerY = me.centerY = chartBBox.y + chartBBox.height;
+ me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
+ me.slices = slices = [];
+ me.items = items = [];
+
+ if (!me.value) {
+ record = store.getAt(0);
+ me.value = record.get(field);
+ }
+
+ value = me.value;
+ if (me.needle) {
+ sliceA = {
+ series: me,
+ value: value,
+ startAngle: -180,
+ endAngle: 0,
+ rho: me.radius
+ };
+ splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
+ slices.push(sliceA);
+ } else {
+ splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
+ sliceA = {
+ series: me,
+ value: value,
+ startAngle: -180,
+ endAngle: splitAngle,
+ rho: me.radius
+ };
+ sliceB = {
+ series: me,
+ value: me.maximum - value,
+ startAngle: splitAngle,
+ endAngle: 0,
+ rho: me.radius
+ };
+ slices.push(sliceA, sliceB);
+ }
+
+
+ for (i = 0, ln = slices.length; i < ln; i++) {
+ slice = slices[i];
+ sprite = group.getAt(i);
+
+ rendererAttributes = Ext.apply({
+ segment: {
+ startAngle: slice.startAngle,
+ endAngle: slice.endAngle,
+ margin: 0,
+ rho: slice.rho,
+ startRho: slice.rho * +donut / 100,
+ endRho: slice.rho
+ }
+ }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
+
+ item = Ext.apply({},
+ rendererAttributes.segment, {
+ slice: slice,
+ series: me,
+ storeItem: record,
+ index: i
+ });
+ items[i] = item;
+
+ if (!sprite) {
+ spriteOptions = Ext.apply({
+ type: "path",
+ group: group
+ }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
+ sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
+ }
+ slice.sprite = slice.sprite || [];
+ item.sprite = sprite;
+ slice.sprite.push(sprite);
+ if (animate) {
+ rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store);
+ sprite._to = rendererAttributes;
+ me.onAnimate(sprite, {
+ to: rendererAttributes
+ });
+ } else {
+ rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {
+ hidden: false
+ }), i, store);
+ sprite.setAttributes(rendererAttributes, true);
+ }
+ }
+
+ if (me.needle) {
+ splitAngle = splitAngle * Math.PI / 180;
+
+ if (!me.needleSprite) {
+ me.needleSprite = me.chart.surface.add({
+ type: 'path',
+ path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
+ centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
+ 'L', centerX + me.radius * cos(splitAngle),
+ centerY + -Math.abs(me.radius * sin(splitAngle))],
+ 'stroke-width': 4,
+ 'stroke': '#222'
+ });
+ } else {
+ if (animate) {
+ me.onAnimate(me.needleSprite, {
+ to: {
+ path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
+ centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
+ 'L', centerX + me.radius * cos(splitAngle),
+ centerY + -Math.abs(me.radius * sin(splitAngle))]
+ }
+ });
+ } else {
+ me.needleSprite.setAttributes({
+ type: 'path',
+ path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
+ centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
+ 'L', centerX + me.radius * cos(splitAngle),
+ centerY + -Math.abs(me.radius * sin(splitAngle))]
+ });
+ }
+ }
+ me.needleSprite.setAttributes({
+ hidden: false
+ }, true);
+ }
+
+ delete me.value;
+ },
+
+
+ setValue: function (value) {
+ this.value = value;
+ this.drawSeries();
+ },
+
+
+ onCreateLabel: function(storeItem, item, i, display) {},
+
+
+ onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {},
+
+
+ onPlaceCallout: function() {},
+
+
+ onAnimate: function(sprite, attr) {
+ sprite.show();
+ return this.callParent(arguments);
+ },
+
+ isItemInPoint: function(x, y, item, i) {
+ return false;
+ },
+
+
+ showAll: function() {
+ if (!isNaN(this._index)) {
+ this.__excludes[this._index] = false;
+ this.drawSeries();
+ }
+ },
+
+
+ getLegendColor: function(index) {
+ var me = this;
+ return me.colorArrayStyle[index % me.colorArrayStyle.length];
+ }
+});
+
+
+
+
+Ext.define('Ext.chart.series.Line', {
+
+
+
+ extend: 'Ext.chart.series.Cartesian',
+
+ alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'],
+
+ requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.draw.Draw', 'Ext.fx.Anim'],
+
+
+
+ type: 'line',
+
+ alias: 'series.line',
+
+
+ selectionTolerance: 20,
+
+
+ showMarkers: true,
+
+
+ markerConfig: {},
+
+
+ style: {},
+
+
+ smooth: false,
+
+
+ fill: false,
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ var me = this,
+ surface = me.chart.surface,
+ shadow = me.chart.shadow,
+ i, l;
+ Ext.apply(me, config, {
+ highlightCfg: {
+ 'stroke-width': 3
+ },
+ shadowAttributes: [{
+ "stroke-width": 6,
+ "stroke-opacity": 0.05,
+ stroke: 'rgb(0, 0, 0)',
+ translate: {
+ x: 1,
+ y: 1
+ }
+ }, {
+ "stroke-width": 4,
+ "stroke-opacity": 0.1,
+ stroke: 'rgb(0, 0, 0)',
+ translate: {
+ x: 1,
+ y: 1
+ }
+ }, {
+ "stroke-width": 2,
+ "stroke-opacity": 0.15,
+ stroke: 'rgb(0, 0, 0)',
+ translate: {
+ x: 1,
+ y: 1
+ }
+ }]
+ });
+ me.group = surface.getGroup(me.seriesId);
+ if (me.showMarkers) {
+ me.markerGroup = surface.getGroup(me.seriesId + '-markers');
+ }
+ if (shadow) {
+ for (i = 0, l = this.shadowAttributes.length; i < l; i++) {
+ me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+ }
+ }
+ },
+
+
+ shrink: function(xValues, yValues, size) {
+
+ var len = xValues.length,
+ ratio = Math.floor(len / size),
+ i = 1,
+ xSum = 0,
+ ySum = 0,
+ xRes = [xValues[0]],
+ yRes = [yValues[0]];
+
+ for (; i < len; ++i) {
+ xSum += xValues[i] || 0;
+ ySum += yValues[i] || 0;
+ if (i % ratio == 0) {
+ xRes.push(xSum/ratio);
+ yRes.push(ySum/ratio);
+ xSum = 0;
+ ySum = 0;
+ }
+ }
+ return {
+ x: xRes,
+ y: yRes
+ };
+ },
+
+
+ drawSeries: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ surface = chart.surface,
+ chartBBox = chart.chartBBox,
+ bbox = {},
+ group = me.group,
+ gutterX = chart.maxGutter[0],
+ gutterY = chart.maxGutter[1],
+ showMarkers = me.showMarkers,
+ markerGroup = me.markerGroup,
+ enableShadows = chart.shadow,
+ shadowGroups = me.shadowGroups,
+ shadowAttributes = this.shadowAttributes,
+ lnsh = shadowGroups.length,
+ dummyPath = ["M"],
+ path = ["M"],
+ markerIndex = chart.markerIndex,
+ axes = [].concat(me.axis),
+ shadowGroup,
+ shadowBarAttr,
+ xValues = [],
+ yValues = [],
+ onbreak = false,
+ markerStyle = me.markerStyle,
+ seriesStyle = me.seriesStyle,
+ seriesLabelStyle = me.seriesLabelStyle,
+ colorArrayStyle = me.colorArrayStyle,
+ colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+ seriesIdx = me.seriesIdx, shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes,
+ x, y, prevX, prevY, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue,
+ yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle,
+ endLineStyle, type, props, firstMarker;
+
+
+ if (!store || !store.getCount()) {
+ return;
+ }
+
+
+ endMarkerStyle = Ext.apply(markerStyle, me.markerConfig);
+ type = endMarkerStyle.type;
+ delete endMarkerStyle.type;
+ endLineStyle = Ext.apply(seriesStyle, me.style);
+
+
+ if (!endLineStyle['stroke-width']) {
+ endLineStyle['stroke-width'] = 0.5;
+ }
+
+
+ if (markerIndex && markerGroup && markerGroup.getCount()) {
+ for (i = 0; i < markerIndex; i++) {
+ marker = markerGroup.getAt(i);
+ markerGroup.remove(marker);
+ markerGroup.add(marker);
+ markerAux = markerGroup.getAt(markerGroup.getCount() - 2);
+ marker.setAttributes({
+ x: 0,
+ y: 0,
+ translate: {
+ x: markerAux.attr.translation.x,
+ y: markerAux.attr.translation.y
+ }
+ }, true);
+ }
+ }
+
+ me.unHighlightItem();
+ me.cleanHighlights();
+
+ me.setBBox();
+ bbox = me.bbox;
+
+ me.clipRect = [bbox.x, bbox.y, bbox.width, bbox.height];
+
+ for (i = 0, ln = axes.length; i < ln; i++) {
+ axis = chart.axes.get(axes[i]);
+ if (axis) {
+ ends = axis.calcEnds();
+ if (axis.position == 'top' || axis.position == 'bottom') {
+ minX = ends.from;
+ maxX = ends.to;
+ }
+ else {
+ minY = ends.from;
+ maxY = ends.to;
+ }
+ }
+ }
+
+
+
+ if (me.xField && !Ext.isNumber(minX)
+ && (me.axis == 'bottom' || me.axis == 'top')) {
+ axis = Ext.create('Ext.chart.axis.Axis', {
+ chart: chart,
+ fields: [].concat(me.xField)
+ }).calcEnds();
+ minX = axis.from;
+ maxX = axis.to;
+ }
+ if (me.yField && !Ext.isNumber(minY)
+ && (me.axis == 'right' || me.axis == 'left')) {
+ axis = Ext.create('Ext.chart.axis.Axis', {
+ chart: chart,
+ fields: [].concat(me.yField)
+ }).calcEnds();
+ minY = axis.from;
+ maxY = axis.to;
+ }
+
+ if (isNaN(minX)) {
+ minX = 0;
+ xScale = bbox.width / (store.getCount() - 1);
+ }
+ else {
+ xScale = bbox.width / (maxX - minX);
+ }
+
+ if (isNaN(minY)) {
+ minY = 0;
+ yScale = bbox.height / (store.getCount() - 1);
+ }
+ else {
+ yScale = bbox.height / (maxY - minY);
+ }
+
+ store.each(function(record, i) {
+ xValue = record.get(me.xField);
+ yValue = record.get(me.yField);
+
+ if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
+ if (Ext.isDefined(Ext.global.console)) {
+ Ext.global.console.warn("[Ext.chart.series.Line] Skipping a store element with an undefined value at ", record, xValue, yValue);
+ }
+ return;
+ }
+
+ if (typeof xValue == 'string' || typeof xValue == 'object'
+
+ || (me.axis != 'top' && me.axis != 'bottom')) {
+ xValue = i;
+ }
+ if (typeof yValue == 'string' || typeof yValue == 'object'
+
+ || (me.axis != 'left' && me.axis != 'right')) {
+ yValue = i;
+ }
+ xValues.push(xValue);
+ yValues.push(yValue);
+ }, me);
+
+ ln = xValues.length;
+ if (ln > bbox.width) {
+ coords = me.shrink(xValues, yValues, bbox.width);
+ xValues = coords.x;
+ yValues = coords.y;
+ }
+
+ me.items = [];
+
+ ln = xValues.length;
+ for (i = 0; i < ln; i++) {
+ xValue = xValues[i];
+ yValue = yValues[i];
+ if (yValue === false) {
+ if (path.length == 1) {
+ path = [];
+ }
+ onbreak = true;
+ me.items.push(false);
+ continue;
+ } else {
+ x = (bbox.x + (xValue - minX) * xScale).toFixed(2);
+ y = ((bbox.y + bbox.height) - (yValue - minY) * yScale).toFixed(2);
+ if (onbreak) {
+ onbreak = false;
+ path.push('M');
+ }
+ path = path.concat([x, y]);
+ }
+ if ((typeof firstY == 'undefined') && (typeof y != 'undefined')) {
+ firstY = y;
+ }
+
+ if (!me.line || chart.resizing) {
+ dummyPath = dummyPath.concat([x, bbox.y + bbox.height / 2]);
+ }
+
+
+ if (chart.animate && chart.resizing && me.line) {
+ me.line.setAttributes({
+ path: dummyPath
+ }, true);
+ if (me.fillPath) {
+ me.fillPath.setAttributes({
+ path: dummyPath,
+ opacity: 0.2
+ }, true);
+ }
+ if (me.line.shadows) {
+ shadows = me.line.shadows;
+ for (j = 0, lnsh = shadows.length; j < lnsh; j++) {
+ shadow = shadows[j];
+ shadow.setAttributes({
+ path: dummyPath
+ }, true);
+ }
+ }
+ }
+ if (showMarkers) {
+ marker = markerGroup.getAt(i);
+ if (!marker) {
+ marker = Ext.chart.Shape[type](surface, Ext.apply({
+ group: [group, markerGroup],
+ x: 0, y: 0,
+ translate: {
+ x: prevX || x,
+ y: prevY || (bbox.y + bbox.height / 2)
+ },
+ value: '"' + xValue + ', ' + yValue + '"'
+ }, endMarkerStyle));
+ marker._to = {
+ translate: {
+ x: x,
+ y: y
+ }
+ };
+ } else {
+ marker.setAttributes({
+ value: '"' + xValue + ', ' + yValue + '"',
+ x: 0, y: 0,
+ hidden: false
+ }, true);
+ marker._to = {
+ translate: {
+ x: x, y: y
+ }
+ };
+ }
+ }
+ me.items.push({
+ series: me,
+ value: [xValue, yValue],
+ point: [x, y],
+ sprite: marker,
+ storeItem: store.getAt(i)
+ });
+ prevX = x;
+ prevY = y;
+ }
+
+ if (path.length <= 1) {
+
+ return;
+ }
+
+ if (me.smooth) {
+ path = Ext.draw.Draw.smooth(path, 6);
+ }
+
+
+ if (chart.markerIndex && me.previousPath) {
+ fromPath = me.previousPath;
+ fromPath.splice(1, 2);
+ } else {
+ fromPath = path;
+ }
+
+
+ if (!me.line) {
+ me.line = surface.add(Ext.apply({
+ type: 'path',
+ group: group,
+ path: dummyPath,
+ stroke: endLineStyle.stroke || endLineStyle.fill
+ }, endLineStyle || {}));
+
+ me.line.setAttributes({
+ fill: 'none'
+ });
+ if (!endLineStyle.stroke && colorArrayLength) {
+ me.line.setAttributes({
+ stroke: colorArrayStyle[seriesIdx % colorArrayLength]
+ }, true);
+ }
+ if (enableShadows) {
+
+ shadows = me.line.shadows = [];
+ for (shindex = 0; shindex < lnsh; shindex++) {
+ shadowBarAttr = shadowAttributes[shindex];
+ shadowBarAttr = Ext.apply({}, shadowBarAttr, { path: dummyPath });
+ shadow = chart.surface.add(Ext.apply({}, {
+ type: 'path',
+ group: shadowGroups[shindex]
+ }, shadowBarAttr));
+ shadows.push(shadow);
+ }
+ }
+ }
+ if (me.fill) {
+ fillPath = path.concat([
+ ["L", x, bbox.y + bbox.height],
+ ["L", bbox.x, bbox.y + bbox.height],
+ ["L", bbox.x, firstY]
+ ]);
+ if (!me.fillPath) {
+ me.fillPath = surface.add({
+ group: group,
+ type: 'path',
+ opacity: endLineStyle.opacity || 0.3,
+ fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill,
+ path: dummyPath
+ });
+ }
+ }
+ markerCount = showMarkers && markerGroup.getCount();
+ if (chart.animate) {
+ fill = me.fill;
+ line = me.line;
+
+ rendererAttributes = me.renderer(line, false, { path: path }, i, store);
+ Ext.apply(rendererAttributes, endLineStyle || {}, {
+ stroke: endLineStyle.stroke || endLineStyle.fill
+ });
+
+ delete rendererAttributes.fill;
+ if (chart.markerIndex && me.previousPath) {
+ me.animation = animation = me.onAnimate(line, {
+ to: rendererAttributes,
+ from: {
+ path: fromPath
+ }
+ });
+ } else {
+ me.animation = animation = me.onAnimate(line, {
+ to: rendererAttributes
+ });
+ }
+
+ if (enableShadows) {
+ shadows = line.shadows;
+ for(j = 0; j < lnsh; j++) {
+ if (chart.markerIndex && me.previousPath) {
+ me.onAnimate(shadows[j], {
+ to: { path: path },
+ from: { path: fromPath }
+ });
+ } else {
+ me.onAnimate(shadows[j], {
+ to: { path: path }
+ });
+ }
+ }
+ }
+
+ if (fill) {
+ me.onAnimate(me.fillPath, {
+ to: Ext.apply({}, {
+ path: fillPath,
+ fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill
+ }, endLineStyle || {})
+ });
+ }
+
+ if (showMarkers) {
+ for(i = 0; i < ln; i++) {
+ item = markerGroup.getAt(i);
+ if (item) {
+ if (me.items[i]) {
+ rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
+ me.onAnimate(item, {
+ to: Ext.apply(rendererAttributes, endMarkerStyle || {})
+ });
+ } else {
+ item.setAttributes(Ext.apply({
+ hidden: true
+ }, item._to), true);
+ }
+ }
+ }
+ for(; i < markerCount; i++) {
+ item = markerGroup.getAt(i);
+ item.hide(true);
+ }
+
+
+
+
+ }
+ } else {
+ rendererAttributes = me.renderer(me.line, false, { path: path, hidden: false }, i, store);
+ Ext.apply(rendererAttributes, endLineStyle || {}, {
+ stroke: endLineStyle.stroke || endLineStyle.fill
+ });
+
+ delete rendererAttributes.fill;
+ me.line.setAttributes(rendererAttributes, true);
+
+ if (enableShadows) {
+ shadows = me.line.shadows;
+ for(j = 0; j < lnsh; j++) {
+ shadows[j].setAttributes({
+ path: path
+ }, true);
+ }
+ }
+ if (me.fill) {
+ me.fillPath.setAttributes({
+ path: fillPath
+ }, true);
+ }
+ if (showMarkers) {
+ for(i = 0; i < ln; i++) {
+ item = markerGroup.getAt(i);
+ if (item) {
+ if (me.items[i]) {
+ rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
+ item.setAttributes(Ext.apply(endMarkerStyle || {}, rendererAttributes || {}), true);
+ } else {
+ item.hide(true);
+ }
+ }
+ }
+ for(; i < markerCount; i++) {
+ item = markerGroup.getAt(i);
+ item.hide(true);
+ }
+ }
+ }
+
+ if (chart.markerIndex) {
+ path.splice(1, 0, path[1], path[2]);
+ me.previousPath = path;
+ }
+ me.renderLabels();
+ me.renderCallouts();
+ },
+
+
+ onCreateLabel: function(storeItem, item, i, display) {
+ var me = this,
+ group = me.labelsGroup,
+ config = me.label,
+ bbox = me.bbox,
+ endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
+
+ return me.chart.surface.add(Ext.apply({
+ 'type': 'text',
+ 'text-anchor': 'middle',
+ 'group': group,
+ 'x': item.point[0],
+ 'y': bbox.y + bbox.height / 2
+ }, endLabelStyle || {}));
+ },
+
+
+ onPlaceLabel: function(label, storeItem, item, i, display, animate) {
+ var me = this,
+ chart = me.chart,
+ resizing = chart.resizing,
+ config = me.label,
+ format = config.renderer,
+ field = config.field,
+ bbox = me.bbox,
+ x = item.point[0],
+ y = item.point[1],
+ radius = item.sprite.attr.radius,
+ bb, width, height;
+
+ label.setAttributes({
+ text: format(storeItem.get(field)),
+ hidden: true
+ }, true);
+
+ if (display == 'rotate') {
+ label.setAttributes({
+ 'text-anchor': 'start',
+ 'rotation': {
+ x: x,
+ y: y,
+ degrees: -45
+ }
+ }, true);
+
+ bb = label.getBBox();
+ width = bb.width;
+ height = bb.height;
+ x = x < bbox.x? bbox.x : x;
+ x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
+ y = (y - height < bbox.y)? bbox.y + height : y;
+
+ } else if (display == 'under' || display == 'over') {
+
+ bb = item.sprite.getBBox();
+ bb.width = bb.width || (radius * 2);
+ bb.height = bb.height || (radius * 2);
+ y = y + (display == 'over'? -bb.height : bb.height);
+
+ bb = label.getBBox();
+ width = bb.width/2;
+ height = bb.height/2;
+ x = x - width < bbox.x? bbox.x + width : x;
+ x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
+ y = y - height < bbox.y? bbox.y + height : y;
+ y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
+ }
+
+ if (me.chart.animate && !me.chart.resizing) {
+ label.show(true);
+ me.onAnimate(label, {
+ to: {
+ x: x,
+ y: y
+ }
+ });
+ } else {
+ label.setAttributes({
+ x: x,
+ y: y
+ }, true);
+ if (resizing) {
+ me.animation.on('afteranimate', function() {
+ label.show(true);
+ });
+ } else {
+ label.show(true);
+ }
+ }
+ },
+
+ //@private Overriding highlights.js highlightItem method.
+
+ highlightItem: function() {
+ var me = this;
+ me.callParent(arguments);
+ if (this.line && !this.highlighted) {
+ if (!('__strokeWidth' in this.line)) {
+ this.line.__strokeWidth = this.line.attr['stroke-width'] || 0;
+ }
+ if (this.line.__anim) {
+ this.line.__anim.paused = true;
+ }
+ this.line.__anim = Ext.create('Ext.fx.Anim', {
+ target: this.line,
+ to: {
+ 'stroke-width': this.line.__strokeWidth + 3
+ }
+ });
+ this.highlighted = true;
+ }
+ },
+
+ //@private Overriding highlights.js unHighlightItem method.
+
+ unHighlightItem: function() {
+ var me = this;
+ me.callParent(arguments);
+ if (this.line && this.highlighted) {
+ this.line.__anim = Ext.create('Ext.fx.Anim', {
+ target: this.line,
+ to: {
+ 'stroke-width': this.line.__strokeWidth
+ }
+ });
+ this.highlighted = false;
+ }
+ },
+
+ //@private called when a callout needs to be placed.
+
+ onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
+ if (!display) {
+ return;
+ }
+
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ resizing = chart.resizing,
+ config = me.callouts,
+ items = me.items,
+ prev = i == 0? false : items[i -1].point,
+ next = (i == items.length -1)? false : items[i +1].point,
+ cur = [+item.point[0], +item.point[1]],
+ dir, norm, normal, a, aprev, anext,
+ offsetFromViz = config.offsetFromViz || 30,
+ offsetToSide = config.offsetToSide || 10,
+ offsetBox = config.offsetBox || 3,
+ boxx, boxy, boxw, boxh,
+ p, clipRect = me.clipRect,
+ bbox = {
+ width: config.styles.width || 10,
+ height: config.styles.height || 10
+ },
+ x, y;
+
+
+ if (!prev) {
+ prev = cur;
+ }
+ if (!next) {
+ next = cur;
+ }
+ a = (next[1] - prev[1]) / (next[0] - prev[0]);
+ aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
+ anext = (next[1] - cur[1]) / (next[0] - cur[0]);
+
+ norm = Math.sqrt(1 + a * a);
+ dir = [1 / norm, a / norm];
+ normal = [-dir[1], dir[0]];
+
+
+ if (aprev > 0 && anext < 0 && normal[1] < 0
+ || aprev < 0 && anext > 0 && normal[1] > 0) {
+ normal[0] *= -1;
+ normal[1] *= -1;
+ } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0
+ || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
+ normal[0] *= -1;
+ normal[1] *= -1;
+ }
+
+ x = cur[0] + normal[0] * offsetFromViz;
+ y = cur[1] + normal[1] * offsetFromViz;
+
+
+ boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+ boxy = y - bbox.height /2 - offsetBox;
+ boxw = bbox.width + 2 * offsetBox;
+ boxh = bbox.height + 2 * offsetBox;
+
+
+
+ if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
+ normal[0] *= -1;
+ }
+ if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
+ normal[1] *= -1;
+ }
+
+
+ x = cur[0] + normal[0] * offsetFromViz;
+ y = cur[1] + normal[1] * offsetFromViz;
+
+
+ boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+ boxy = y - bbox.height /2 - offsetBox;
+ boxw = bbox.width + 2 * offsetBox;
+ boxh = bbox.height + 2 * offsetBox;
+
+ if (chart.animate) {
+
+ me.onAnimate(callout.lines, {
+ to: {
+ path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+ }
+ });
+
+ if (callout.panel) {
+ callout.panel.setPosition(boxx, boxy, true);
+ }
+ }
+ else {
+
+ callout.lines.setAttributes({
+ path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+ }, true);
+
+ if (callout.panel) {
+ callout.panel.setPosition(boxx, boxy);
+ }
+ }
+ for (p in callout) {
+ callout[p].show(true);
+ }
+ },
+
+ isItemInPoint: function(x, y, item, i) {
+ var me = this,
+ items = me.items,
+ tolerance = me.selectionTolerance,
+ result = null,
+ prevItem,
+ nextItem,
+ prevPoint,
+ nextPoint,
+ ln,
+ x1,
+ y1,
+ x2,
+ y2,
+ xIntersect,
+ yIntersect,
+ dist1, dist2, dist, midx, midy,
+ sqrt = Math.sqrt, abs = Math.abs;
+
+ nextItem = items[i];
+ prevItem = i && items[i - 1];
+
+ if (i >= ln) {
+ prevItem = items[ln - 1];
+ }
+ prevPoint = prevItem && prevItem.point;
+ nextPoint = nextItem && nextItem.point;
+ x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance;
+ y1 = prevItem ? prevPoint[1] : nextPoint[1];
+ x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance;
+ y2 = nextItem ? nextPoint[1] : prevPoint[1];
+ dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
+ dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
+ dist = Math.min(dist1, dist2);
+
+ if (dist <= tolerance) {
+ return dist == dist1? prevItem : nextItem;
+ }
+ return false;
+ },
+
+
+ toggleAll: function(show) {
+ var me = this,
+ i, ln, shadow, shadows;
+ if (!show) {
+ Ext.chart.series.Line.superclass.hideAll.call(me);
+ }
+ else {
+ Ext.chart.series.Line.superclass.showAll.call(me);
+ }
+ if (me.line) {
+ me.line.setAttributes({
+ hidden: !show
+ }, true);
+
+ if (me.line.shadows) {
+ for (i = 0, shadows = me.line.shadows, ln = shadows.length; i < ln; i++) {
+ shadow = shadows[i];
+ shadow.setAttributes({
+ hidden: !show
+ }, true);
+ }
+ }
+ }
+ if (me.fillPath) {
+ me.fillPath.setAttributes({
+ hidden: !show
+ }, true);
+ }
+ },
+
+
+ hideAll: function() {
+ this.toggleAll(false);
+ },
+
+
+ showAll: function() {
+ this.toggleAll(true);
+ }
+});
+
+Ext.define('Ext.chart.series.Pie', {
+
+
+
+ alternateClassName: ['Ext.chart.PieSeries', 'Ext.chart.PieChart'],
+
+ extend: 'Ext.chart.series.Series',
+
+
+
+ type: "pie",
+
+ alias: 'series.pie',
+
+ rad: Math.PI / 180,
+
+
+ highlightDuration: 150,
+
+
+ angleField: false,
+
+
+ lengthField: false,
+
+
+ donut: false,
+
+
+ showInLegend: false,
+
+
+
+
+ style: {},
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ store = chart.store,
+ shadow = chart.shadow, i, l, cfg;
+ Ext.applyIf(me, {
+ highlightCfg: {
+ segment: {
+ margin: 20
+ }
+ }
+ });
+ Ext.apply(me, config, {
+ shadowAttributes: [{
+ "stroke-width": 6,
+ "stroke-opacity": 1,
+ stroke: 'rgb(200, 200, 200)',
+ translate: {
+ x: 1.2,
+ y: 2
+ }
+ },
+ {
+ "stroke-width": 4,
+ "stroke-opacity": 1,
+ stroke: 'rgb(150, 150, 150)',
+ translate: {
+ x: 0.9,
+ y: 1.5
+ }
+ },
+ {
+ "stroke-width": 2,
+ "stroke-opacity": 1,
+ stroke: 'rgb(100, 100, 100)',
+ translate: {
+ x: 0.6,
+ y: 1
+ }
+ }]
+ });
+ me.group = surface.getGroup(me.seriesId);
+ if (shadow) {
+ for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+ me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+ }
+ }
+ surface.customAttributes.segment = function(opt) {
+ return me.getSegment(opt);
+ };
+ },
+
+ //@private updates some onbefore render parameters.
+
+ initialize: function() {
+ var me = this,
+ store = me.chart.substore || me.chart.store;
+
+ me.yField = [];
+ if (me.label.field) {
+ store.each(function(rec) {
+ me.yField.push(rec.get(me.label.field));
+ });
+ }
+ },
+
+
+ getSegment: function(opt) {
+ var me = this,
+ rad = me.rad,
+ cos = Math.cos,
+ sin = Math.sin,
+ abs = Math.abs,
+ x = me.centerX,
+ y = me.centerY,
+ x1 = 0, x2 = 0, x3 = 0, x4 = 0,
+ y1 = 0, y2 = 0, y3 = 0, y4 = 0,
+ delta = 1e-2,
+ r = opt.endRho - opt.startRho,
+ startAngle = opt.startAngle,
+ endAngle = opt.endAngle,
+ midAngle = (startAngle + endAngle) / 2 * rad,
+ margin = opt.margin || 0,
+ flag = abs(endAngle - startAngle) > 180,
+ a1 = Math.min(startAngle, endAngle) * rad,
+ a2 = Math.max(startAngle, endAngle) * rad,
+ singleSlice = false;
+
+ x += margin * cos(midAngle);
+ y += margin * sin(midAngle);
+
+ x1 = x + opt.startRho * cos(a1);
+ y1 = y + opt.startRho * sin(a1);
+
+ x2 = x + opt.endRho * cos(a1);
+ y2 = y + opt.endRho * sin(a1);
+
+ x3 = x + opt.startRho * cos(a2);
+ y3 = y + opt.startRho * sin(a2);
+
+ x4 = x + opt.endRho * cos(a2);
+ y4 = y + opt.endRho * sin(a2);
+
+ if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
+ singleSlice = true;
+ }
+
+ if (singleSlice) {
+ return {
+ path: [
+ ["M", x1, y1],
+ ["L", x2, y2],
+ ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
+ ["Z"]]
+ };
+ } else {
+ return {
+ path: [
+ ["M", x1, y1],
+ ["L", x2, y2],
+ ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
+ ["L", x3, y3],
+ ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
+ ["Z"]]
+ };
+ }
+ },
+
+
+ calcMiddle: function(item) {
+ var me = this,
+ rad = me.rad,
+ slice = item.slice,
+ x = me.centerX,
+ y = me.centerY,
+ startAngle = slice.startAngle,
+ endAngle = slice.endAngle,
+ donut = +me.donut,
+ a1 = Math.min(startAngle, endAngle) * rad,
+ a2 = Math.max(startAngle, endAngle) * rad,
+ midAngle = -(a1 + (a2 - a1) / 2),
+ xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
+ ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
+
+ item.middle = {
+ x: xm,
+ y: ym
+ };
+ },
+
+
+ drawSeries: function() {
+ var me = this,
+ store = me.chart.substore || me.chart.store,
+ group = me.group,
+ animate = me.chart.animate,
+ field = me.angleField || me.field || me.xField,
+ lenField = [].concat(me.lengthField),
+ totalLenField = 0,
+ colors = me.colorSet,
+ chart = me.chart,
+ surface = chart.surface,
+ chartBBox = chart.chartBBox,
+ enableShadows = chart.shadow,
+ shadowGroups = me.shadowGroups,
+ shadowAttributes = me.shadowAttributes,
+ lnsh = shadowGroups.length,
+ rad = me.rad,
+ layers = lenField.length,
+ rhoAcum = 0,
+ donut = +me.donut,
+ layerTotals = [],
+ values = {},
+ fieldLength,
+ items = [],
+ passed = false,
+ totalField = 0,
+ maxLenField = 0,
+ cut = 9,
+ defcut = true,
+ angle = 0,
+ seriesStyle = me.seriesStyle,
+ seriesLabelStyle = me.seriesLabelStyle,
+ colorArrayStyle = me.colorArrayStyle,
+ colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+ gutterX = chart.maxGutter[0],
+ gutterY = chart.maxGutter[1],
+ rendererAttributes,
+ shadowGroup,
+ shadowAttr,
+ shadows,
+ shadow,
+ shindex,
+ centerX,
+ centerY,
+ deltaRho,
+ first = 0,
+ slice,
+ slices,
+ sprite,
+ value,
+ item,
+ lenValue,
+ ln,
+ record,
+ i,
+ j,
+ startAngle,
+ endAngle,
+ middleAngle,
+ sliceLength,
+ path,
+ p,
+ spriteOptions, bbox;
+
+ Ext.apply(seriesStyle, me.style || {});
+
+ me.setBBox();
+ bbox = me.bbox;
+
+
+ if (me.colorSet) {
+ colorArrayStyle = me.colorSet;
+ colorArrayLength = colorArrayStyle.length;
+ }
+
+
+ if (!store || !store.getCount()) {
+ return;
+ }
+
+ me.unHighlightItem();
+ me.cleanHighlights();
+
+ centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
+ centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
+ me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
+ me.slices = slices = [];
+ me.items = items = [];
+
+ store.each(function(record, i) {
+ if (this.__excludes && this.__excludes[i]) {
+
+ return;
+ }
+ totalField += +record.get(field);
+ if (lenField[0]) {
+ for (j = 0, totalLenField = 0; j < layers; j++) {
+ totalLenField += +record.get(lenField[j]);
+ }
+ layerTotals[i] = totalLenField;
+ maxLenField = Math.max(maxLenField, totalLenField);
+ }
+ }, this);
+
+ store.each(function(record, i) {
+ if (this.__excludes && this.__excludes[i]) {
+
+ return;
+ }
+ value = record.get(field);
+ middleAngle = angle - 360 * value / totalField / 2;
+
+ if (isNaN(middleAngle)) {
+ middleAngle = 360;
+ value = 1;
+ totalField = 1;
+ }
+
+ if (!i || first == 0) {
+ angle = 360 - middleAngle;
+ me.firstAngle = angle;
+ middleAngle = angle - 360 * value / totalField / 2;
+ }
+ endAngle = angle - 360 * value / totalField;
+ slice = {
+ series: me,
+ value: value,
+ startAngle: angle,
+ endAngle: endAngle,
+ storeItem: record
+ };
+ if (lenField[0]) {
+ lenValue = layerTotals[i];
+ slice.rho = me.radius * (lenValue / maxLenField);
+ } else {
+ slice.rho = me.radius;
+ }
+ slices[i] = slice;
+ if((slice.startAngle % 360) == (slice.endAngle % 360)) {
+ slice.startAngle -= 0.0001;
+ }
+ angle = endAngle;
+ first++;
+ }, me);
+
+
+ if (enableShadows) {
+ for (i = 0, ln = slices.length; i < ln; i++) {
+ if (this.__excludes && this.__excludes[i]) {
+
+ continue;
+ }
+ slice = slices[i];
+ slice.shadowAttrs = [];
+ for (j = 0, rhoAcum = 0, shadows = []; j < layers; j++) {
+ sprite = group.getAt(i * layers + j);
+ deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
+
+ rendererAttributes = {
+ segment: {
+ startAngle: slice.startAngle,
+ endAngle: slice.endAngle,
+ margin: 0,
+ rho: slice.rho,
+ startRho: rhoAcum + (deltaRho * donut / 100),
+ endRho: rhoAcum + deltaRho
+ }
+ };
+
+ for (shindex = 0, shadows = []; shindex < lnsh; shindex++) {
+ shadowAttr = shadowAttributes[shindex];
+ shadow = shadowGroups[shindex].getAt(i);
+ if (!shadow) {
+ shadow = chart.surface.add(Ext.apply({},
+ {
+ type: 'path',
+ group: shadowGroups[shindex],
+ strokeLinejoin: "round"
+ },
+ rendererAttributes, shadowAttr));
+ }
+ if (animate) {
+ rendererAttributes = me.renderer(shadow, store.getAt(i), Ext.apply({},
+ rendererAttributes, shadowAttr), i, store);
+ me.onAnimate(shadow, {
+ to: rendererAttributes
+ });
+ } else {
+ rendererAttributes = me.renderer(shadow, store.getAt(i), Ext.apply(shadowAttr, {
+ hidden: false
+ }), i, store);
+ shadow.setAttributes(rendererAttributes, true);
+ }
+ shadows.push(shadow);
+ }
+ slice.shadowAttrs[j] = shadows;
+ }
+ }
+ }
+
+ for (i = 0, ln = slices.length; i < ln; i++) {
+ if (this.__excludes && this.__excludes[i]) {
+
+ continue;
+ }
+ slice = slices[i];
+ for (j = 0, rhoAcum = 0; j < layers; j++) {
+ sprite = group.getAt(i * layers + j);
+ deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
+
+ rendererAttributes = Ext.apply({
+ segment: {
+ startAngle: slice.startAngle,
+ endAngle: slice.endAngle,
+ margin: 0,
+ rho: slice.rho,
+ startRho: rhoAcum + (deltaRho * donut / 100),
+ endRho: rhoAcum + deltaRho
+ }
+ }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
+ item = Ext.apply({},
+ rendererAttributes.segment, {
+ slice: slice,
+ series: me,
+ storeItem: slice.storeItem,
+ index: i
+ });
+ me.calcMiddle(item);
+ if (enableShadows) {
+ item.shadows = slice.shadowAttrs[j];
+ }
+ items[i] = item;
+
+ if (!sprite) {
+ spriteOptions = Ext.apply({
+ type: "path",
+ group: group,
+ middle: item.middle
+ }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
+ sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
+ }
+ slice.sprite = slice.sprite || [];
+ item.sprite = sprite;
+ slice.sprite.push(sprite);
+ slice.point = [item.middle.x, item.middle.y];
+ if (animate) {
+ rendererAttributes = me.renderer(sprite, store.getAt(i), rendererAttributes, i, store);
+ sprite._to = rendererAttributes;
+ sprite._animating = true;
+ me.onAnimate(sprite, {
+ to: rendererAttributes,
+ listeners: {
+ afteranimate: {
+ fn: function() {
+ this._animating = false;
+ },
+ scope: sprite
+ }
+ }
+ });
+ } else {
+ rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(rendererAttributes, {
+ hidden: false
+ }), i, store);
+ sprite.setAttributes(rendererAttributes, true);
+ }
+ rhoAcum += deltaRho;
+ }
+ }
+
+
+ ln = group.getCount();
+ for (i = 0; i < ln; i++) {
+ if (!slices[(i / layers) >> 0] && group.getAt(i)) {
+ group.getAt(i).hide(true);
+ }
+ }
+ if (enableShadows) {
+ lnsh = shadowGroups.length;
+ for (shindex = 0; shindex < ln; shindex++) {
+ if (!slices[(shindex / layers) >> 0]) {
+ for (j = 0; j < lnsh; j++) {
+ if (shadowGroups[j].getAt(shindex)) {
+ shadowGroups[j].getAt(shindex).hide(true);
+ }
+ }
+ }
+ }
+ }
+ me.renderLabels();
+ me.renderCallouts();
+ },
+
+
+ onCreateLabel: function(storeItem, item, i, display) {
+ var me = this,
+ group = me.labelsGroup,
+ config = me.label,
+ centerX = me.centerX,
+ centerY = me.centerY,
+ middle = item.middle,
+ endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config || {});
+
+ return me.chart.surface.add(Ext.apply({
+ 'type': 'text',
+ 'text-anchor': 'middle',
+ 'group': group,
+ 'x': middle.x,
+ 'y': middle.y
+ }, endLabelStyle));
+ },
+
+
+ onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
+ var me = this,
+ chart = me.chart,
+ resizing = chart.resizing,
+ config = me.label,
+ format = config.renderer,
+ field = [].concat(config.field),
+ centerX = me.centerX,
+ centerY = me.centerY,
+ middle = item.middle,
+ opt = {
+ x: middle.x,
+ y: middle.y
+ },
+ x = middle.x - centerX,
+ y = middle.y - centerY,
+ from = {},
+ rho = 1,
+ theta = Math.atan2(y, x || 1),
+ dg = theta * 180 / Math.PI,
+ prevDg;
+
+ function fixAngle(a) {
+ if (a < 0) a += 360;
+ return a % 360;
+ }
+
+ label.setAttributes({
+ text: format(storeItem.get(field[index]))
+ }, true);
+
+ switch (display) {
+ case 'outside':
+ rho = Math.sqrt(x * x + y * y) * 2;
+
+ opt.x = rho * Math.cos(theta) + centerX;
+ opt.y = rho * Math.sin(theta) + centerY;
+ break;
+
+ case 'rotate':
+ dg = fixAngle(dg);
+ dg = (dg > 90 && dg < 270) ? dg + 180: dg;
+
+ prevDg = label.attr.rotation.degrees;
+ if (prevDg != null && Math.abs(prevDg - dg) > 180) {
+ if (dg > prevDg) {
+ dg -= 360;
+ } else {
+ dg += 360;
+ }
+ dg = dg % 360;
+ } else {
+ dg = fixAngle(dg);
+ }
+
+ opt.rotate = {
+ degrees: dg,
+ x: opt.x,
+ y: opt.y
+ };
+ break;
+
+ default:
+ break;
+ }
+
+ opt.translate = {
+ x: 0, y: 0
+ };
+ if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
+ me.onAnimate(label, {
+ to: opt
+ });
+ } else {
+ label.setAttributes(opt, true);
+ }
+ label._from = from;
+ },
+
+
+ onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
+ var me = this,
+ chart = me.chart,
+ resizing = chart.resizing,
+ config = me.callouts,
+ centerX = me.centerX,
+ centerY = me.centerY,
+ middle = item.middle,
+ opt = {
+ x: middle.x,
+ y: middle.y
+ },
+ x = middle.x - centerX,
+ y = middle.y - centerY,
+ rho = 1,
+ rhoCenter,
+ theta = Math.atan2(y, x || 1),
+ bbox = callout.label.getBBox(),
+ offsetFromViz = 20,
+ offsetToSide = 10,
+ offsetBox = 10,
+ p;
+
+
+ rho = item.endRho + offsetFromViz;
+ rhoCenter = (item.endRho + item.startRho) / 2 + (item.endRho - item.startRho) / 3;
+
+ opt.x = rho * Math.cos(theta) + centerX;
+ opt.y = rho * Math.sin(theta) + centerY;
+
+ x = rhoCenter * Math.cos(theta);
+ y = rhoCenter * Math.sin(theta);
+
+ if (chart.animate) {
+
+ me.onAnimate(callout.lines, {
+ to: {
+ path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
+ }
+ });
+
+ me.onAnimate(callout.box, {
+ to: {
+ x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
+ y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
+ width: bbox.width + 2 * offsetBox,
+ height: bbox.height + 2 * offsetBox
+ }
+ });
+
+ me.onAnimate(callout.label, {
+ to: {
+ x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
+ y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
+ }
+ });
+ } else {
+
+ callout.lines.setAttributes({
+ path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
+ },
+ true);
+
+ callout.box.setAttributes({
+ x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
+ y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
+ width: bbox.width + 2 * offsetBox,
+ height: bbox.height + 2 * offsetBox
+ },
+ true);
+
+ callout.label.setAttributes({
+ x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
+ y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
+ },
+ true);
+ }
+ for (p in callout) {
+ callout[p].show(true);
+ }
+ },
+
+
+ onAnimate: function(sprite, attr) {
+ sprite.show();
+ return this.callParent(arguments);
+ },
+
+ isItemInPoint: function(x, y, item, i) {
+ var me = this,
+ cx = me.centerX,
+ cy = me.centerY,
+ abs = Math.abs,
+ dx = abs(x - cx),
+ dy = abs(y - cy),
+ startAngle = item.startAngle,
+ endAngle = item.endAngle,
+ rho = Math.sqrt(dx * dx + dy * dy),
+ angle = Math.atan2(y - cy, x - cx) / me.rad + 360;
+
+
+ if (angle > me.firstAngle) {
+ angle -= 360;
+ }
+ return (angle <= startAngle && angle > endAngle
+ && rho >= item.startRho && rho <= item.endRho);
+ },
+
+
+ hideAll: function() {
+ var i, l, shadow, shadows, sh, lsh, sprite;
+ if (!isNaN(this._index)) {
+ this.__excludes = this.__excludes || [];
+ this.__excludes[this._index] = true;
+ sprite = this.slices[this._index].sprite;
+ for (sh = 0, lsh = sprite.length; sh < lsh; sh++) {
+ sprite[sh].setAttributes({
+ hidden: true
+ }, true);
+ }
+ if (this.slices[this._index].shadowAttrs) {
+ for (i = 0, shadows = this.slices[this._index].shadowAttrs, l = shadows.length; i < l; i++) {
+ shadow = shadows[i];
+ for (sh = 0, lsh = shadow.length; sh < lsh; sh++) {
+ shadow[sh].setAttributes({
+ hidden: true
+ }, true);
+ }
+ }
+ }
+ this.drawSeries();
+ }
+ },
+
+
+ showAll: function() {
+ if (!isNaN(this._index)) {
+ this.__excludes[this._index] = false;
+ this.drawSeries();
+ }
+ },
+
+
+ highlightItem: function(item) {
+ var me = this,
+ rad = me.rad;
+ item = item || this.items[this._index];
+
+
+
+
+
+ this.unHighlightItem();
+
+ if (!item || item.sprite && item.sprite._animating) {
+ return;
+ }
+ me.callParent([item]);
+ if (!me.highlight) {
+ return;
+ }
+ if ('segment' in me.highlightCfg) {
+ var highlightSegment = me.highlightCfg.segment,
+ animate = me.chart.animate,
+ attrs, i, shadows, shadow, ln, to, itemHighlightSegment, prop;
+
+ if (me.labelsGroup) {
+ var group = me.labelsGroup,
+ display = me.label.display,
+ label = group.getAt(item.index),
+ middle = (item.startAngle + item.endAngle) / 2 * rad,
+ r = highlightSegment.margin || 0,
+ x = r * Math.cos(middle),
+ y = r * Math.sin(middle);
+
+
+
+
+
+
+ if (Math.abs(x) < 1e-10) {
+ x = 0;
+ }
+ if (Math.abs(y) < 1e-10) {
+ y = 0;
+ }
+
+ if (animate) {
+ label.stopAnimation();
+ label.animate({
+ to: {
+ translate: {
+ x: x,
+ y: y
+ }
+ },
+ duration: me.highlightDuration
+ });
+ }
+ else {
+ label.setAttributes({
+ translate: {
+ x: x,
+ y: y
+ }
+ }, true);
+ }
+ }
+
+ if (me.chart.shadow && item.shadows) {
+ i = 0;
+ shadows = item.shadows;
+ ln = shadows.length;
+ for (; i < ln; i++) {
+ shadow = shadows[i];
+ to = {};
+ itemHighlightSegment = item.sprite._from.segment;
+ for (prop in itemHighlightSegment) {
+ if (! (prop in highlightSegment)) {
+ to[prop] = itemHighlightSegment[prop];
+ }
+ }
+ attrs = {
+ segment: Ext.applyIf(to, me.highlightCfg.segment)
+ };
+ if (animate) {
+ shadow.stopAnimation();
+ shadow.animate({
+ to: attrs,
+ duration: me.highlightDuration
+ });
+ }
+ else {
+ shadow.setAttributes(attrs, true);
+ }
+ }
+ }
+ }
+ },
+
+
+ unHighlightItem: function() {
+ var me = this;
+ if (!me.highlight) {
+ return;
+ }
+
+ if (('segment' in me.highlightCfg) && me.items) {
+ var items = me.items,
+ animate = me.chart.animate,
+ shadowsEnabled = !!me.chart.shadow,
+ group = me.labelsGroup,
+ len = items.length,
+ i = 0,
+ j = 0,
+ display = me.label.display,
+ shadowLen, p, to, ihs, hs, sprite, shadows, shadow, item, label, attrs;
+
+ for (; i < len; i++) {
+ item = items[i];
+ if (!item) {
+ continue;
+ }
+ sprite = item.sprite;
+ if (sprite && sprite._highlighted) {
+
+ if (group) {
+ label = group.getAt(item.index);
+ attrs = Ext.apply({
+ translate: {
+ x: 0,
+ y: 0
+ }
+ },
+ display == 'rotate' ? {
+ rotate: {
+ x: label.attr.x,
+ y: label.attr.y,
+ degrees: label.attr.rotation.degrees
+ }
+ }: {});
+ if (animate) {
+ label.stopAnimation();
+ label.animate({
+ to: attrs,
+ duration: me.highlightDuration
+ });
+ }
+ else {
+ label.setAttributes(attrs, true);
+ }
+ }
+ if (shadowsEnabled) {
+ shadows = item.shadows;
+ shadowLen = shadows.length;
+ for (; j < shadowLen; j++) {
+ to = {};
+ ihs = item.sprite._to.segment;
+ hs = item.sprite._from.segment;
+ Ext.apply(to, hs);
+ for (p in ihs) {
+ if (! (p in hs)) {
+ to[p] = ihs[p];
+ }
+ }
+ shadow = shadows[j];
+ if (animate) {
+ shadow.stopAnimation();
+ shadow.animate({
+ to: {
+ segment: to
+ },
+ duration: me.highlightDuration
+ });
+ }
+ else {
+ shadow.setAttributes({ segment: to }, true);
+ }
+ }
+ }
+ }
+ }
+ }
+ me.callParent(arguments);
+ },
+
+
+ getLegendColor: function(index) {
+ var me = this;
+ return me.colorArrayStyle[index % me.colorArrayStyle.length];
+ }
+});
+
+
+
+Ext.define('Ext.chart.series.Radar', {
+
+
+
+ extend: 'Ext.chart.series.Series',
+
+ requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],
+
+
+
+ type: "radar",
+ alias: 'series.radar',
+
+
+ rad: Math.PI / 180,
+
+ showInLegend: false,
+
+
+ style: {},
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ var me = this,
+ surface = me.chart.surface, i, l;
+ me.group = surface.getGroup(me.seriesId);
+ if (me.showMarkers) {
+ me.markerGroup = surface.getGroup(me.seriesId + '-markers');
+ }
+ },
+
+
+ drawSeries: function() {
+ var me = this,
+ store = me.chart.substore || me.chart.store,
+ group = me.group,
+ sprite,
+ chart = me.chart,
+ animate = chart.animate,
+ field = me.field || me.yField,
+ surface = chart.surface,
+ chartBBox = chart.chartBBox,
+ rendererAttributes,
+ centerX, centerY,
+ items,
+ radius,
+ maxValue = 0,
+ fields = [],
+ max = Math.max,
+ cos = Math.cos,
+ sin = Math.sin,
+ pi2 = Math.PI * 2,
+ l = store.getCount(),
+ startPath, path, x, y, rho,
+ i, nfields,
+ seriesStyle = me.seriesStyle,
+ seriesLabelStyle = me.seriesLabelStyle,
+ first = chart.resizing || !me.radar,
+ axis = chart.axes && chart.axes.get(0),
+ aggregate = !(axis && axis.maximum);
+
+ me.setBBox();
+
+ maxValue = aggregate? 0 : (axis.maximum || 0);
+
+ Ext.apply(seriesStyle, me.style || {});
+
+
+ if (!store || !store.getCount()) {
+ return;
+ }
+
+ me.unHighlightItem();
+ me.cleanHighlights();
+
+ centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
+ centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
+ me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2;
+ me.items = items = [];
+
+ if (aggregate) {
+
+ chart.series.each(function(series) {
+ fields.push(series.yField);
+ });
+
+ store.each(function(record, i) {
+ for (i = 0, nfields = fields.length; i < nfields; i++) {
+ maxValue = max(+record.get(fields[i]), maxValue);
+ }
+ });
+ }
+
+ maxValue = maxValue || 1;
+
+ startPath = []; path = [];
+ store.each(function(record, i) {
+ rho = radius * record.get(field) / maxValue;
+ x = rho * cos(i / l * pi2);
+ y = rho * sin(i / l * pi2);
+ if (i == 0) {
+ path.push('M', x + centerX, y + centerY);
+ startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY);
+ } else {
+ path.push('L', x + centerX, y + centerY);
+ startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY);
+ }
+ items.push({
+ sprite: false,
+ point: [centerX + x, centerY + y],
+ series: me
+ });
+ });
+ path.push('Z');
+
+ if (!me.radar) {
+ me.radar = surface.add(Ext.apply({
+ type: 'path',
+ group: group,
+ path: startPath
+ }, seriesStyle || {}));
+ }
+
+ if (chart.resizing) {
+ me.radar.setAttributes({
+ path: startPath
+ }, true);
+ }
+
+ if (chart.animate) {
+ me.onAnimate(me.radar, {
+ to: Ext.apply({
+ path: path
+ }, seriesStyle || {})
+ });
+ } else {
+ me.radar.setAttributes(Ext.apply({
+ path: path
+ }, seriesStyle || {}), true);
+ }
+
+ if (me.showMarkers) {
+ me.drawMarkers();
+ }
+ me.renderLabels();
+ me.renderCallouts();
+ },
+
+
+ drawMarkers: function() {
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ markerStyle = Ext.apply({}, me.markerStyle || {}),
+ endMarkerStyle = Ext.apply(markerStyle, me.markerConfig),
+ items = me.items,
+ type = endMarkerStyle.type,
+ markerGroup = me.markerGroup,
+ centerX = me.centerX,
+ centerY = me.centerY,
+ item, i, l, marker;
+
+ delete endMarkerStyle.type;
+
+ for (i = 0, l = items.length; i < l; i++) {
+ item = items[i];
+ marker = markerGroup.getAt(i);
+ if (!marker) {
+ marker = Ext.chart.Shape[type](surface, Ext.apply({
+ group: markerGroup,
+ x: 0,
+ y: 0,
+ translate: {
+ x: centerX,
+ y: centerY
+ }
+ }, endMarkerStyle));
+ }
+ else {
+ marker.show();
+ }
+ if (chart.resizing) {
+ marker.setAttributes({
+ x: 0,
+ y: 0,
+ translate: {
+ x: centerX,
+ y: centerY
+ }
+ }, true);
+ }
+ marker._to = {
+ translate: {
+ x: item.point[0],
+ y: item.point[1]
+ }
+ };
+
+ if (chart.animate) {
+ me.onAnimate(marker, {
+ to: marker._to
+ });
+ }
+ else {
+ marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), true);
+ }
+ }
+ },
+
+ isItemInPoint: function(x, y, item) {
+ var point,
+ tolerance = 10,
+ abs = Math.abs;
+ point = item.point;
+ return (abs(point[0] - x) <= tolerance &&
+ abs(point[1] - y) <= tolerance);
+ },
+
+
+ onCreateLabel: function(storeItem, item, i, display) {
+ var me = this,
+ group = me.labelsGroup,
+ config = me.label,
+ centerX = me.centerX,
+ centerY = me.centerY,
+ point = item.point,
+ endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);
+
+ return me.chart.surface.add(Ext.apply({
+ 'type': 'text',
+ 'text-anchor': 'middle',
+ 'group': group,
+ 'x': centerX,
+ 'y': centerY
+ }, config || {}));
+ },
+
+
+ onPlaceLabel: function(label, storeItem, item, i, display, animate) {
+ var me = this,
+ chart = me.chart,
+ resizing = chart.resizing,
+ config = me.label,
+ format = config.renderer,
+ field = config.field,
+ centerX = me.centerX,
+ centerY = me.centerY,
+ opt = {
+ x: item.point[0],
+ y: item.point[1]
+ },
+ x = opt.x - centerX,
+ y = opt.y - centerY;
+
+ label.setAttributes({
+ text: format(storeItem.get(field)),
+ hidden: true
+ },
+ true);
+
+ if (resizing) {
+ label.setAttributes({
+ x: centerX,
+ y: centerY
+ }, true);
+ }
+
+ if (animate) {
+ label.show(true);
+ me.onAnimate(label, {
+ to: opt
+ });
+ } else {
+ label.setAttributes(opt, true);
+ label.show(true);
+ }
+ },
+
+
+ toggleAll: function(show) {
+ var me = this,
+ i, ln, shadow, shadows;
+ if (!show) {
+ Ext.chart.series.Radar.superclass.hideAll.call(me);
+ }
+ else {
+ Ext.chart.series.Radar.superclass.showAll.call(me);
+ }
+ if (me.radar) {
+ me.radar.setAttributes({
+ hidden: !show
+ }, true);
+
+ if (me.radar.shadows) {
+ for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) {
+ shadow = shadows[i];
+ shadow.setAttributes({
+ hidden: !show
+ }, true);
+ }
+ }
+ }
+ },
+
+
+ hideAll: function() {
+ this.toggleAll(false);
+ this.hideMarkers(0);
+ },
+
+
+ showAll: function() {
+ this.toggleAll(true);
+ },
+
+
+ hideMarkers: function(index) {
+ var me = this,
+ count = me.markerGroup && me.markerGroup.getCount() || 0,
+ i = index || 0;
+ for (; i < count; i++) {
+ me.markerGroup.getAt(i).hide(true);
+ }
+ }
+});
+
+
+
+Ext.define('Ext.chart.series.Scatter', {
+
+
+
+ extend: 'Ext.chart.series.Cartesian',
+
+ requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.fx.Anim'],
+
+
+
+ type: 'scatter',
+ alias: 'series.scatter',
+
+
+
+
+
+ constructor: function(config) {
+ this.callParent(arguments);
+ var me = this,
+ shadow = me.chart.shadow,
+ surface = me.chart.surface, i, l;
+ Ext.apply(me, config, {
+ style: {},
+ markerConfig: {},
+ shadowAttributes: [{
+ "stroke-width": 6,
+ "stroke-opacity": 0.05,
+ stroke: 'rgb(0, 0, 0)'
+ }, {
+ "stroke-width": 4,
+ "stroke-opacity": 0.1,
+ stroke: 'rgb(0, 0, 0)'
+ }, {
+ "stroke-width": 2,
+ "stroke-opacity": 0.15,
+ stroke: 'rgb(0, 0, 0)'
+ }]
+ });
+ me.group = surface.getGroup(me.seriesId);
+ if (shadow) {
+ for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+ me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+ }
+ }
+ },
+
+
+ getBounds: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ axes = [].concat(me.axis),
+ bbox, xScale, yScale, ln, minX, minY, maxX, maxY, i, axis, ends;
+
+ me.setBBox();
+ bbox = me.bbox;
+
+ for (i = 0, ln = axes.length; i < ln; i++) {
+ axis = chart.axes.get(axes[i]);
+ if (axis) {
+ ends = axis.calcEnds();
+ if (axis.position == 'top' || axis.position == 'bottom') {
+ minX = ends.from;
+ maxX = ends.to;
+ }
+ else {
+ minY = ends.from;
+ maxY = ends.to;
+ }
+ }
+ }
+
+ if (me.xField && !Ext.isNumber(minX)) {
+ axis = Ext.create('Ext.chart.axis.Axis', {
+ chart: chart,
+ fields: [].concat(me.xField)
+ }).calcEnds();
+ minX = axis.from;
+ maxX = axis.to;
+ }
+ if (me.yField && !Ext.isNumber(minY)) {
+ axis = Ext.create('Ext.chart.axis.Axis', {
+ chart: chart,
+ fields: [].concat(me.yField)
+ }).calcEnds();
+ minY = axis.from;
+ maxY = axis.to;
+ }
+
+ if (isNaN(minX)) {
+ minX = 0;
+ maxX = store.getCount() - 1;
+ xScale = bbox.width / (store.getCount() - 1);
+ }
+ else {
+ xScale = bbox.width / (maxX - minX);
+ }
+
+ if (isNaN(minY)) {
+ minY = 0;
+ maxY = store.getCount() - 1;
+ yScale = bbox.height / (store.getCount() - 1);
+ }
+ else {
+ yScale = bbox.height / (maxY - minY);
+ }
+
+ return {
+ bbox: bbox,
+ minX: minX,
+ minY: minY,
+ xScale: xScale,
+ yScale: yScale
+ };
+ },
+
+
+ getPaths: function() {
+ var me = this,
+ chart = me.chart,
+ enableShadows = chart.shadow,
+ store = chart.substore || chart.store,
+ group = me.group,
+ bounds = me.bounds = me.getBounds(),
+ bbox = me.bbox,
+ xScale = bounds.xScale,
+ yScale = bounds.yScale,
+ minX = bounds.minX,
+ minY = bounds.minY,
+ boxX = bbox.x,
+ boxY = bbox.y,
+ boxHeight = bbox.height,
+ items = me.items = [],
+ attrs = [],
+ x, y, xValue, yValue, sprite;
+
+ store.each(function(record, i) {
+ xValue = record.get(me.xField);
+ yValue = record.get(me.yField);
+
+ if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
+ if (Ext.isDefined(Ext.global.console)) {
+ Ext.global.console.warn("[Ext.chart.series.Scatter] Skipping a store element with an undefined value at ", record, xValue, yValue);
+ }
+ return;
+ }
+
+ if (typeof xValue == 'string' || typeof xValue == 'object') {
+ xValue = i;
+ }
+ if (typeof yValue == 'string' || typeof yValue == 'object') {
+ yValue = i;
+ }
+ x = boxX + (xValue - minX) * xScale;
+ y = boxY + boxHeight - (yValue - minY) * yScale;
+ attrs.push({
+ x: x,
+ y: y
+ });
+
+ me.items.push({
+ series: me,
+ value: [xValue, yValue],
+ point: [x, y],
+ storeItem: record
+ });
+
+
+ if (chart.animate && chart.resizing) {
+ sprite = group.getAt(i);
+ if (sprite) {
+ me.resetPoint(sprite);
+ if (enableShadows) {
+ me.resetShadow(sprite);
+ }
+ }
+ }
+ });
+ return attrs;
+ },
+
+
+ resetPoint: function(sprite) {
+ var bbox = this.bbox;
+ sprite.setAttributes({
+ translate: {
+ x: (bbox.x + bbox.width) / 2,
+ y: (bbox.y + bbox.height) / 2
+ }
+ }, true);
+ },
+
+
+ resetShadow: function(sprite) {
+ var me = this,
+ shadows = sprite.shadows,
+ shadowAttributes = me.shadowAttributes,
+ ln = me.shadowGroups.length,
+ bbox = me.bbox,
+ i, attr;
+ for (i = 0; i < ln; i++) {
+ attr = Ext.apply({}, shadowAttributes[i]);
+ if (attr.translate) {
+ attr.translate.x += (bbox.x + bbox.width) / 2;
+ attr.translate.y += (bbox.y + bbox.height) / 2;
+ }
+ else {
+ attr.translate = {
+ x: (bbox.x + bbox.width) / 2,
+ y: (bbox.y + bbox.height) / 2
+ };
+ }
+ shadows[i].setAttributes(attr, true);
+ }
+ },
+
+
+ createPoint: function(attr, type) {
+ var me = this,
+ chart = me.chart,
+ group = me.group,
+ bbox = me.bbox;
+
+ return Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
+ x: 0,
+ y: 0,
+ group: group,
+ translate: {
+ x: (bbox.x + bbox.width) / 2,
+ y: (bbox.y + bbox.height) / 2
+ }
+ }, attr));
+ },
+
+
+ createShadow: function(sprite, endMarkerStyle, type) {
+ var me = this,
+ chart = me.chart,
+ shadowGroups = me.shadowGroups,
+ shadowAttributes = me.shadowAttributes,
+ lnsh = shadowGroups.length,
+ bbox = me.bbox,
+ i, shadow, shadows, attr;
+
+ sprite.shadows = shadows = [];
+
+ for (i = 0; i < lnsh; i++) {
+ attr = Ext.apply({}, shadowAttributes[i]);
+ if (attr.translate) {
+ attr.translate.x += (bbox.x + bbox.width) / 2;
+ attr.translate.y += (bbox.y + bbox.height) / 2;
+ }
+ else {
+ Ext.apply(attr, {
+ translate: {
+ x: (bbox.x + bbox.width) / 2,
+ y: (bbox.y + bbox.height) / 2
+ }
+ });
+ }
+ Ext.apply(attr, endMarkerStyle);
+ shadow = Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
+ x: 0,
+ y: 0,
+ group: shadowGroups[i]
+ }, attr));
+ shadows.push(shadow);
+ }
+ },
+
+
+ drawSeries: function() {
+ var me = this,
+ chart = me.chart,
+ store = chart.substore || chart.store,
+ group = me.group,
+ enableShadows = chart.shadow,
+ shadowGroups = me.shadowGroups,
+ shadowAttributes = me.shadowAttributes,
+ lnsh = shadowGroups.length,
+ sprite, attrs, attr, ln, i, endMarkerStyle, shindex, type, shadows,
+ rendererAttributes, shadowAttribute;
+
+ endMarkerStyle = Ext.apply(me.markerStyle, me.markerConfig);
+ type = endMarkerStyle.type;
+ delete endMarkerStyle.type;
+
+
+ if (!store || !store.getCount()) {
+ return;
+ }
+
+ me.unHighlightItem();
+ me.cleanHighlights();
+
+ attrs = me.getPaths();
+ ln = attrs.length;
+ for (i = 0; i < ln; i++) {
+ attr = attrs[i];
+ sprite = group.getAt(i);
+ Ext.apply(attr, endMarkerStyle);
+
+
+ if (!sprite) {
+ sprite = me.createPoint(attr, type);
+ if (enableShadows) {
+ me.createShadow(sprite, endMarkerStyle, type);
+ }
+ }
+
+ shadows = sprite.shadows;
+ if (chart.animate) {
+ rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store);
+ sprite._to = rendererAttributes;
+ me.onAnimate(sprite, {
+ to: rendererAttributes
+ });
+
+ for (shindex = 0; shindex < lnsh; shindex++) {
+ shadowAttribute = Ext.apply({}, shadowAttributes[shindex]);
+ rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, {
+ translate: {
+ x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0),
+ y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0)
+ }
+ }, shadowAttribute), i, store);
+ me.onAnimate(shadows[shindex], { to: rendererAttributes });
+ }
+ }
+ else {
+ rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply({ translate: attr }, { hidden: false }), i, store);
+ sprite.setAttributes(rendererAttributes, true);
+
+ for (shindex = 0; shindex < lnsh; shindex++) {
+ shadowAttribute = shadowAttributes[shindex];
+ rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({
+ x: attr.x,
+ y: attr.y
+ }, shadowAttribute), i, store);
+ shadows[shindex].setAttributes(rendererAttributes, true);
+ }
+ }
+ me.items[i].sprite = sprite;
+ }
+
+
+ ln = group.getCount();
+ for (i = attrs.length; i < ln; i++) {
+ group.getAt(i).hide(true);
+ }
+ me.renderLabels();
+ me.renderCallouts();
+ },
+
+
+ onCreateLabel: function(storeItem, item, i, display) {
+ var me = this,
+ group = me.labelsGroup,
+ config = me.label,
+ endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle),
+ bbox = me.bbox;
+
+ return me.chart.surface.add(Ext.apply({
+ type: 'text',
+ group: group,
+ x: item.point[0],
+ y: bbox.y + bbox.height / 2
+ }, endLabelStyle));
+ },
+
+
+ onPlaceLabel: function(label, storeItem, item, i, display, animate) {
+ var me = this,
+ chart = me.chart,
+ resizing = chart.resizing,
+ config = me.label,
+ format = config.renderer,
+ field = config.field,
+ bbox = me.bbox,
+ x = item.point[0],
+ y = item.point[1],
+ radius = item.sprite.attr.radius,
+ bb, width, height, anim;
+
+ label.setAttributes({
+ text: format(storeItem.get(field)),
+ hidden: true
+ }, true);
+
+ if (display == 'rotate') {
+ label.setAttributes({
+ 'text-anchor': 'start',
+ 'rotation': {
+ x: x,
+ y: y,
+ degrees: -45
+ }
+ }, true);
+
+ bb = label.getBBox();
+ width = bb.width;
+ height = bb.height;
+ x = x < bbox.x? bbox.x : x;
+ x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
+ y = (y - height < bbox.y)? bbox.y + height : y;
+
+ } else if (display == 'under' || display == 'over') {
+
+ bb = item.sprite.getBBox();
+ bb.width = bb.width || (radius * 2);
+ bb.height = bb.height || (radius * 2);
+ y = y + (display == 'over'? -bb.height : bb.height);
+
+ bb = label.getBBox();
+ width = bb.width/2;
+ height = bb.height/2;
+ x = x - width < bbox.x ? bbox.x + width : x;
+ x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
+ y = y - height < bbox.y? bbox.y + height : y;
+ y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
+ }
+
+ if (!chart.animate) {
+ label.setAttributes({
+ x: x,
+ y: y
+ }, true);
+ label.show(true);
+ }
+ else {
+ if (resizing) {
+ anim = item.sprite.getActiveAnimation();
+ if (anim) {
+ anim.on('afteranimate', function() {
+ label.setAttributes({
+ x: x,
+ y: y
+ }, true);
+ label.show(true);
+ });
+ }
+ else {
+ label.show(true);
+ }
+ }
+ else {
+ me.onAnimate(label, {
+ to: {
+ x: x,
+ y: y
+ }
+ });
+ }
+ }
+ },
+
+
+ onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
+ var me = this,
+ chart = me.chart,
+ surface = chart.surface,
+ resizing = chart.resizing,
+ config = me.callouts,
+ items = me.items,
+ cur = item.point,
+ normal,
+ bbox = callout.label.getBBox(),
+ offsetFromViz = 30,
+ offsetToSide = 10,
+ offsetBox = 3,
+ boxx, boxy, boxw, boxh,
+ p, clipRect = me.bbox,
+ x, y;
+
+
+ normal = [Math.cos(Math.PI /4), -Math.sin(Math.PI /4)];
+ x = cur[0] + normal[0] * offsetFromViz;
+ y = cur[1] + normal[1] * offsetFromViz;
+
+
+ boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+ boxy = y - bbox.height /2 - offsetBox;
+ boxw = bbox.width + 2 * offsetBox;
+ boxh = bbox.height + 2 * offsetBox;
+
+
+
+ if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
+ normal[0] *= -1;
+ }
+ if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
+ normal[1] *= -1;
+ }
+
+
+ x = cur[0] + normal[0] * offsetFromViz;
+ y = cur[1] + normal[1] * offsetFromViz;
+
+
+ boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+ boxy = y - bbox.height /2 - offsetBox;
+ boxw = bbox.width + 2 * offsetBox;
+ boxh = bbox.height + 2 * offsetBox;
+
+ if (chart.animate) {
+
+ me.onAnimate(callout.lines, {
+ to: {
+ path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+ }
+ }, true);
+
+ me.onAnimate(callout.box, {
+ to: {
+ x: boxx,
+ y: boxy,
+ width: boxw,
+ height: boxh
+ }
+ }, true);
+
+ me.onAnimate(callout.label, {
+ to: {
+ x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
+ y: y
+ }
+ }, true);
+ } else {
+
+ callout.lines.setAttributes({
+ path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+ }, true);
+
+ callout.box.setAttributes({
+ x: boxx,
+ y: boxy,
+ width: boxw,
+ height: boxh
+ }, true);
+
+ callout.label.setAttributes({
+ x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
+ y: y
+ }, true);
+ }
+ for (p in callout) {
+ callout[p].show(true);
+ }
+ },
+
+
+ onAnimate: function(sprite, attr) {
+ sprite.show();
+ return this.callParent(arguments);
+ },
+
+ isItemInPoint: function(x, y, item) {
+ var point,
+ tolerance = 10,
+ abs = Math.abs;
+
+ function dist(point) {
+ var dx = abs(point[0] - x),
+ dy = abs(point[1] - y);
+ return Math.sqrt(dx * dx + dy * dy);
+ }
+ point = item.point;
+ return (point[0] - tolerance <= x && point[0] + tolerance >= x &&
+ point[1] - tolerance <= y && point[1] + tolerance >= y);
+ }
+});
+
+
+
+Ext.define('Ext.chart.theme.Base', {
+
+
+
+ requires: ['Ext.chart.theme.Theme'],
+
+
+
+ constructor: function(config) {
+ Ext.chart.theme.call(this, config, {
+ background: false,
+ axis: {
+ stroke: '#444',
+ 'stroke-width': 1
+ },
+ axisLabelTop: {
+ fill: '#444',
+ font: '12px Arial, Helvetica, sans-serif',
+ spacing: 2,
+ padding: 5,
+ renderer: function(v) { return v; }
+ },
+ axisLabelRight: {
+ fill: '#444',
+ font: '12px Arial, Helvetica, sans-serif',
+ spacing: 2,
+ padding: 5,
+ renderer: function(v) { return v; }
+ },
+ axisLabelBottom: {
+ fill: '#444',
+ font: '12px Arial, Helvetica, sans-serif',
+ spacing: 2,
+ padding: 5,
+ renderer: function(v) { return v; }
+ },
+ axisLabelLeft: {
+ fill: '#444',
+ font: '12px Arial, Helvetica, sans-serif',
+ spacing: 2,
+ padding: 5,
+ renderer: function(v) { return v; }
+ },
+ axisTitleTop: {
+ font: 'bold 18px Arial',
+ fill: '#444'
+ },
+ axisTitleRight: {
+ font: 'bold 18px Arial',
+ fill: '#444',
+ rotate: {
+ x:0, y:0,
+ degrees: 270
+ }
+ },
+ axisTitleBottom: {
+ font: 'bold 18px Arial',
+ fill: '#444'
+ },
+ axisTitleLeft: {
+ font: 'bold 18px Arial',
+ fill: '#444',
+ rotate: {
+ x:0, y:0,
+ degrees: 270
+ }
+ },
+ series: {
+ 'stroke-width': 0
+ },
+ seriesLabel: {
+ font: '12px Arial',
+ fill: '#333'
+ },
+ marker: {
+ stroke: '#555',
+ fill: '#000',
+ radius: 3,
+ size: 3
+ },
+ colors: [ "#94ae0a", "#115fa6","#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
+ seriesThemes: [{
+ fill: "#115fa6"
+ }, {
+ fill: "#94ae0a"
+ }, {
+ fill: "#a61120"
+ }, {
+ fill: "#ff8809"
+ }, {
+ fill: "#ffd13e"
+ }, {
+ fill: "#a61187"
+ }, {
+ fill: "#24ad9a"
+ }, {
+ fill: "#7c7474"
+ }, {
+ fill: "#a66111"
+ }],
+ markerThemes: [{
+ fill: "#115fa6",
+ type: 'circle'
+ }, {
+ fill: "#94ae0a",
+ type: 'cross'
+ }, {
+ fill: "#a61120",
+ type: 'plus'
+ }]
+ });
+ }
+}, function() {
+ var palette = ['#b1da5a', '#4ce0e7', '#e84b67', '#da5abd', '#4d7fe6', '#fec935'],
+ names = ['Green', 'Sky', 'Red', 'Purple', 'Blue', 'Yellow'],
+ i = 0, j = 0, l = palette.length, themes = Ext.chart.theme,
+ categories = [['#f0a50a', '#c20024', '#2044ba', '#810065', '#7eae29'],
+ ['#6d9824', '#87146e', '#2a9196', '#d39006', '#1e40ac'],
+ ['#fbbc29', '#ce2e4e', '#7e0062', '#158b90', '#57880e'],
+ ['#ef5773', '#fcbd2a', '#4f770d', '#1d3eaa', '#9b001f'],
+ ['#7eae29', '#fdbe2a', '#910019', '#27b4bc', '#d74dbc'],
+ ['#44dce1', '#0b2592', '#996e05', '#7fb325', '#b821a1']],
+ cats = categories.length;
+
+
+ for (; i < l; i++) {
+ themes[names[i]] = (function(color) {
+ return Ext.extend(themes.Base, {
+ constructor: function(config) {
+ themes.Base.prototype.constructor.call(this, Ext.apply({
+ baseColor: color
+ }, config));
+ }
+ });
+ })(palette[i]);
+ }
+
+
+ for (i = 0; i < cats; i++) {
+ themes['Category' + (i + 1)] = (function(category) {
+ return Ext.extend(themes.Base, {
+ constructor: function(config) {
+ themes.Base.prototype.constructor.call(this, Ext.apply({
+ colors: category
+ }, config));
+ }
+ });
+ })(categories[i]);
+ }
+});
+
+
+Ext.define('Ext.data.ArrayStore', {
+ extend: 'Ext.data.Store',
+ alias: 'store.array',
+ uses: ['Ext.data.reader.Array'],
+
+
+ constructor: function(config) {
+ config = config || {};
+
+ Ext.applyIf(config, {
+ proxy: {
+ type: 'memory',
+ reader: 'array'
+ }
+ });
+
+ this.callParent([config]);
+ },
+
+ loadData: function(data, append) {
+ if (this.expandData === true) {
+ var r = [],
+ i = 0,
+ ln = data.length;
+
+ for (; i < ln; i++) {
+ r[r.length] = [data[i]];
+ }
+
+ data = r;
+ }
+
+ this.callParent([data, append]);
+ }
+}, function() {
+
+ Ext.data.SimpleStore = Ext.data.ArrayStore;
+
+});
+
+
+Ext.define('Ext.data.Batch', {
+ mixins: {
+ observable: 'Ext.util.Observable'
+ },
+
+
+ autoStart: false,
+
+
+ current: -1,
+
+
+ total: 0,
+
+
+ isRunning: false,
+
+
+ isComplete: false,
+
+
+ hasException: false,
+
+
+ pauseOnException: true,
+
+ constructor: function(config) {
+ var me = this;
+
+ me.addEvents(
+
+ 'complete',
+
+
+ 'exception',
+
+
+ 'operationcomplete'
+ );
+
+ me.mixins.observable.constructor.call(me, config);
+
+
+ me.operations = [];
+ },
+
+
+ add: function(operation) {
+ this.total++;
+
+ operation.setBatch(this);
+
+ this.operations.push(operation);
+ },
+
+
+ start: function() {
+ this.hasException = false;
+ this.isRunning = true;
+
+ this.runNextOperation();
+ },
+
+
+ runNextOperation: function() {
+ this.runOperation(this.current + 1);
+ },
+
+
+ pause: function() {
+ this.isRunning = false;
+ },
+
+
+ runOperation: function(index) {
+ var me = this,
+ operations = me.operations,
+ operation = operations[index],
+ onProxyReturn;
+
+ if (operation === undefined) {
+ me.isRunning = false;
+ me.isComplete = true;
+ me.fireEvent('complete', me, operations[operations.length - 1]);
+ } else {
+ me.current = index;
+
+ onProxyReturn = function(operation) {
+ var hasException = operation.hasException();
+
+ if (hasException) {
+ me.hasException = true;
+ me.fireEvent('exception', me, operation);
+ } else {
+ me.fireEvent('operationcomplete', me, operation);
+ }
+
+ if (hasException && me.pauseOnException) {
+ me.pause();
+ } else {
+ operation.setCompleted();
+ me.runNextOperation();
+ }
+ };
+
+ operation.setStarted();
+
+ me.proxy[operation.action](operation, onProxyReturn, me);
+ }
+ }
+});
+
+Ext.define('Ext.data.BelongsToAssociation', {
+ extend: 'Ext.data.Association',
+
+ alias: 'association.belongsto',
+
+
+
+
+
+
+
+
+
+ constructor: function(config) {
+ this.callParent(arguments);
+
+ var me = this,
+ ownerProto = me.ownerModel.prototype,
+ associatedName = me.associatedName,
+ getterName = me.getterName || 'get' + associatedName,
+ setterName = me.setterName || 'set' + associatedName;
+
+ Ext.applyIf(me, {
+ name : associatedName,
+ foreignKey : associatedName.toLowerCase() + "_id",
+ instanceName: associatedName + 'BelongsToInstance',
+ associationKey: associatedName.toLowerCase()
+ });
+
+ ownerProto[getterName] = me.createGetter();
+ ownerProto[setterName] = me.createSetter();
+ },
+
+
+ createSetter: function() {
+ var me = this,
+ ownerModel = me.ownerModel,
+ associatedModel = me.associatedModel,
+ foreignKey = me.foreignKey,
+ primaryKey = me.primaryKey;
+
+
+ return function(value, options, scope) {
+ this.set(foreignKey, value);
+
+ if (typeof options == 'function') {
+ options = {
+ callback: options,
+ scope: scope || this
+ };
+ }
+
+ if (Ext.isObject(options)) {
+ return this.save(options);
+ }
+ };
+ },
+
+
+ createGetter: function() {
+ var me = this,
+ ownerModel = me.ownerModel,
+ associatedName = me.associatedName,
+ associatedModel = me.associatedModel,
+ foreignKey = me.foreignKey,
+ primaryKey = me.primaryKey,
+ instanceName = me.instanceName;
+
+
+ return function(options, scope) {
+ options = options || {};
+
+ var foreignKeyId = this.get(foreignKey),
+ instance, callbackFn;
+
+ if (this[instanceName] === undefined) {
+ instance = Ext.ModelManager.create({}, associatedName);
+ instance.set(primaryKey, foreignKeyId);
+
+ if (typeof options == 'function') {
+ options = {
+ callback: options,
+ scope: scope || this
+ };
+ }
+
+ associatedModel.load(foreignKeyId, options);
+ } else {
+ instance = this[instanceName];
+
+
+
+
+ if (typeof options == 'function') {
+ options.call(scope || this, instance);
+ }
+
+ if (options.success) {
+ options.success.call(scope || this, instance);
+ }
+
+ if (options.callback) {
+ options.callback.call(scope || this, instance);
+ }
+
+ return instance;
+ }
+ };
+ },
+
+
+ read: function(record, reader, associationData){
+ record[this.instanceName] = reader.read([associationData]).records[0];
+ }
+});
+
+
+Ext.define('Ext.data.BufferStore', {
+ extend: 'Ext.data.Store',
+ alias: 'store.buffer',
+ sortOnLoad: false,
+ filterOnLoad: false,
+
+ constructor: function() {
+ Ext.Error.raise('The BufferStore class has been deprecated. Instead, specify the buffered config option on Ext.data.Store');
+ }
+});
+
+
+Ext.define('Ext.direct.Manager', {
+
+
+ singleton: true,
+
+ mixins: {
+ observable: 'Ext.util.Observable'
+ },
+
+ requires: ['Ext.util.MixedCollection'],
+
+ statics: {
+ exceptions: {
+ TRANSPORT: 'xhr',
+ PARSE: 'parse',
+ LOGIN: 'login',
+ SERVER: 'exception'
+ }
+ },
+
+
+
+ constructor: function(){
+ var me = this;
+
+ me.addEvents(
+
+ 'event',
+
+ 'exception'
+ );
+ me.transactions = Ext.create('Ext.util.MixedCollection');
+ me.providers = Ext.create('Ext.util.MixedCollection');
+
+ me.mixins.observable.constructor.call(me);
+ },
+
+
+ addProvider : function(provider){
+ var me = this,
+ args = arguments,
+ i = 0,
+ len;
+
+ if (args.length > 1) {
+ for (len = args.length; i < len; ++i) {
+ me.addProvider(args[i]);
+ }
+ return;
+ }
+
+
+ if (!provider.isProvider) {
+ provider = Ext.create('direct.' + provider.type + 'provider', provider);
+ }
+ me.providers.add(provider);
+ provider.on('data', me.onProviderData, me);
+
+
+ if (!provider.isConnected()) {
+ provider.connect();
+ }
+
+ return provider;
+ },
+
+
+ getProvider : function(id){
+ return id.isProvider ? id : this.providers.get(id);
+ },
+
+
+ removeProvider : function(provider){
+ var me = this,
+ providers = me.providers,
+ provider = provider.isProvider ? provider : providers.get(provider);
+
+ if (provider) {
+ provider.un('data', me.onProviderData, me);
+ providers.remove(provider);
+ return provider;
+ }
+ return null;
+ },
+
+
+ addTransaction: function(transaction){
+ this.transactions.add(transaction);
+ return transaction;
+ },
+
+
+ removeTransaction: function(transaction){
+ transaction = this.getTransaction(transaction);
+ this.transactions.remove(transaction);
+ return transaction;
+ },
+
+
+ getTransaction: function(transaction){
+ return transaction.isTransaction ? transaction : this.transactions.get(transaction);
+ },
+
+ onProviderData : function(provider, event){
+ var me = this,
+ i = 0,
+ len;
+
+ if (Ext.isArray(event)) {
+ for (len = event.length; i < len; ++i) {
+ me.onProviderData(provider, event[i]);
+ }
+ return;
+ }
+ if (event.name && event.name != 'event' && event.name != 'exception') {
+ me.fireEvent(event.name, event);
+ } else if (event.type == 'exception') {
+ me.fireEvent('exception', event);
+ }
+ me.fireEvent('event', event, provider);
+ }
+}, function(){
+
+ Ext.Direct = Ext.direct.Manager;
+});
+
+
+Ext.define('Ext.data.proxy.Direct', {
+
+
+ extend: 'Ext.data.proxy.Server',
+ alternateClassName: 'Ext.data.DirectProxy',
+
+ alias: 'proxy.direct',
+
+ requires: ['Ext.direct.Manager'],
+
+
+
+
+ paramOrder: undefined,
+
+
+ paramsAsHash: true,
+
+
+ directFn : undefined,
+
+
+
+
+
+
+ paramOrderRe: /[\s,|]/,
+
+ constructor: function(config){
+ var me = this;
+
+ Ext.apply(me, config);
+ if (Ext.isString(me.paramOrder)) {
+ me.paramOrder = me.paramOrder.split(me.paramOrderRe);
+ }
+ me.callParent(arguments);
+ },
+
+ doRequest: function(operation, callback, scope) {
+ var me = this,
+ writer = me.getWriter(),
+ request = me.buildRequest(operation, callback, scope),
+ fn = me.api[request.action] || me.directFn,
+ args = [],
+ params = request.params,
+ paramOrder = me.paramOrder,
+ method,
+ i = 0,
+ len;
+
+ if (!fn) {
+ Ext.Error.raise('No direct function specified for this proxy');
+ }
+
+ if (operation.allowWrite()) {
+ request = writer.write(request);
+ }
+
+ if (operation.action == 'read') {
+
+ method = fn.directCfg.method;
+
+ if (method.ordered) {
+ if (method.len > 0) {
+ if (paramOrder) {
+ for (len = paramOrder.length; i < len; ++i) {
+ args.push(params[paramOrder[i]]);
+ }
+ } else if (me.paramsAsHash) {
+ args.push(params);
+ }
+ }
+ } else {
+ args.push(params);
+ }
+ } else {
+ args.push(request.jsonData);
+ }
+
+ Ext.apply(request, {
+ args: args,
+ directFn: fn
+ });
+ args.push(me.createRequestCallback(request, operation, callback, scope), me);
+ fn.apply(window, args);
+ },
+
+
+ applyEncoding: function(value){
+ return value;
+ },
+
+ createRequestCallback: function(request, operation, callback, scope){
+ var me = this;
+
+ return function(data, event){
+ me.processResponse(event.status, operation, request, event, callback, scope);
+ };
+ },
+
+
+ extractResponseData: function(response){
+ return Ext.isDefined(response.result) ? response.result : response.data;
+ },
+
+
+ setException: function(operation, response) {
+ operation.setException(response.message);
+ },
+
+
+ buildUrl: function(){
+ return '';
+ }
+});
+
+
+
+Ext.define('Ext.data.DirectStore', {
+
+
+ extend: 'Ext.data.Store',
+
+ alias: 'store.direct',
+
+ requires: ['Ext.data.proxy.Direct'],
+
+
+
+ constructor : function(config){
+ config = Ext.apply({}, config);
+ if (!config.proxy) {
+ var proxy = {
+ type: 'direct',
+ reader: {
+ type: 'json'
+ }
+ };
+ Ext.copyTo(proxy, config, 'paramOrder,paramsAsHash,directFn,api,simpleSortMode');
+ Ext.copyTo(proxy.reader, config, 'totalProperty,root,idProperty');
+ config.proxy = proxy;
+ }
+ this.callParent([config]);
+ }
+});
+
+
+
+Ext.define('Ext.util.Inflector', {
+
+
+
+ singleton: true,
+
+
+
+
+ plurals: [
+ [(/(quiz)$/i), "$1zes" ],
+ [(/^(ox)$/i), "$1en" ],
+ [(/([m|l])ouse$/i), "$1ice" ],
+ [(/(matr|vert|ind)ix|ex$/i), "$1ices" ],
+ [(/(x|ch|ss|sh)$/i), "$1es" ],
+ [(/([^aeiouy]|qu)y$/i), "$1ies" ],
+ [(/(hive)$/i), "$1s" ],
+ [(/(?:([^f])fe|([lr])f)$/i), "$1$2ves"],
+ [(/sis$/i), "ses" ],
+ [(/([ti])um$/i), "$1a" ],
+ [(/(buffal|tomat|potat)o$/i), "$1oes" ],
+ [(/(bu)s$/i), "$1ses" ],
+ [(/(alias|status|sex)$/i), "$1es" ],
+ [(/(octop|vir)us$/i), "$1i" ],
+ [(/(ax|test)is$/i), "$1es" ],
+ [(/^person$/), "people" ],
+ [(/^man$/), "men" ],
+ [(/^(child)$/), "$1ren" ],
+ [(/s$/i), "s" ],
+ [(/$/), "s" ]
+ ],
+
+
+ singulars: [
+ [(/(quiz)zes$/i), "$1" ],
+ [(/(matr)ices$/i), "$1ix" ],
+ [(/(vert|ind)ices$/i), "$1ex" ],
+ [(/^(ox)en/i), "$1" ],
+ [(/(alias|status)es$/i), "$1" ],
+ [(/(octop|vir)i$/i), "$1us" ],
+ [(/(cris|ax|test)es$/i), "$1is" ],
+ [(/(shoe)s$/i), "$1" ],
+ [(/(o)es$/i), "$1" ],
+ [(/(bus)es$/i), "$1" ],
+ [(/([m|l])ice$/i), "$1ouse" ],
+ [(/(x|ch|ss|sh)es$/i), "$1" ],
+ [(/(m)ovies$/i), "$1ovie" ],
+ [(/(s)eries$/i), "$1eries"],
+ [(/([^aeiouy]|qu)ies$/i), "$1y" ],
+ [(/([lr])ves$/i), "$1f" ],
+ [(/(tive)s$/i), "$1" ],
+ [(/(hive)s$/i), "$1" ],
+ [(/([^f])ves$/i), "$1fe" ],
+ [(/(^analy)ses$/i), "$1sis" ],
+ [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"],
+ [(/([ti])a$/i), "$1um" ],
+ [(/(n)ews$/i), "$1ews" ],
+ [(/people$/i), "person" ],
+ [(/s$/i), "" ]
+ ],
+
+
+ uncountable: [
+ "sheep",
+ "fish",
+ "series",
+ "species",
+ "money",
+ "rice",
+ "information",
+ "equipment",
+ "grass",
+ "mud",
+ "offspring",
+ "deer",
+ "means"
+ ],
+
+
+ singular: function(matcher, replacer) {
+ this.singulars.unshift([matcher, replacer]);
+ },
+
+
+ plural: function(matcher, replacer) {
+ this.plurals.unshift([matcher, replacer]);
+ },
+
+
+ clearSingulars: function() {
+ this.singulars = [];
+ },
+
+
+ clearPlurals: function() {
+ this.plurals = [];
+ },
+
+
+ isTransnumeral: function(word) {
+ return Ext.Array.indexOf(this.uncountable, word) != -1;
+ },
+
+
+ pluralize: function(word) {
+ if (this.isTransnumeral(word)) {
+ return word;
+ }
+
+ var plurals = this.plurals,
+ length = plurals.length,
+ tuple, regex, i;
+
+ for (i = 0; i < length; i++) {
+ tuple = plurals[i];
+ regex = tuple[0];
+
+ if (regex == word || (regex.test && regex.test(word))) {
+ return word.replace(regex, tuple[1]);
+ }
+ }
+
+ return word;
+ },
+
+
+ singularize: function(word) {
+ if (this.isTransnumeral(word)) {
+ return word;
+ }
+
+ var singulars = this.singulars,
+ length = singulars.length,
+ tuple, regex, i;
+
+ for (i = 0; i < length; i++) {
+ tuple = singulars[i];
+ regex = tuple[0];
+
+ if (regex == word || (regex.test && regex.test(word))) {
+ return word.replace(regex, tuple[1]);
+ }
+ }
+
+ return word;
+ },
+
+
+ classify: function(word) {
+ return Ext.String.capitalize(this.singularize(word));
+ },
+
+
+ ordinalize: function(number) {
+ var parsed = parseInt(number, 10),
+ mod10 = parsed % 10,
+ mod100 = parsed % 100;
+
+
+ if (11 <= mod100 && mod100 <= 13) {
+ return number + "th";
+ } else {
+ switch(mod10) {
+ case 1 : return number + "st";
+ case 2 : return number + "nd";
+ case 3 : return number + "rd";
+ default: return number + "th";
+ }
+ }
+ }
+}, function() {
+
+ var irregulars = {
+ alumnus: 'alumni',
+ cactus : 'cacti',
+ focus : 'foci',
+ nucleus: 'nuclei',
+ radius: 'radii',
+ stimulus: 'stimuli',
+ ellipsis: 'ellipses',
+ paralysis: 'paralyses',
+ oasis: 'oases',
+ appendix: 'appendices',
+ index: 'indexes',
+ beau: 'beaux',
+ bureau: 'bureaux',
+ tableau: 'tableaux',
+ woman: 'women',
+ child: 'children',
+ man: 'men',
+ corpus: 'corpora',
+ criterion: 'criteria',
+ curriculum: 'curricula',
+ genus: 'genera',
+ memorandum: 'memoranda',
+ phenomenon: 'phenomena',
+ foot: 'feet',
+ goose: 'geese',
+ tooth: 'teeth',
+ antenna: 'antennae',
+ formula: 'formulae',
+ nebula: 'nebulae',
+ vertebra: 'vertebrae',
+ vita: 'vitae'
+ },
+ singular;
+
+ for (singular in irregulars) {
+ this.plural(singular, irregulars[singular]);
+ this.singular(irregulars[singular], singular);
+ }
+});
+
+Ext.define('Ext.data.HasManyAssociation', {
+ extend: 'Ext.data.Association',
+ requires: ['Ext.util.Inflector'],
+
+ alias: 'association.hasmany',
+
+
+
+
+
+
+
+
+
+
+
+
+
+ constructor: function(config) {
+ var me = this,
+ ownerProto,
+ name;
+
+ me.callParent(arguments);
+
+ me.name = me.name || Ext.util.Inflector.pluralize(me.associatedName.toLowerCase());
+
+ ownerProto = me.ownerModel.prototype;
+ name = me.name;
+
+ Ext.applyIf(me, {
+ storeName : name + "Store",
+ foreignKey: me.ownerName.toLowerCase() + "_id"
+ });
+
+ ownerProto[name] = me.createStore();
+ },
+
+
+ createStore: function() {
+ var that = this,
+ associatedModel = that.associatedModel,
+ storeName = that.storeName,
+ foreignKey = that.foreignKey,
+ primaryKey = that.primaryKey,
+ filterProperty = that.filterProperty,
+ autoLoad = that.autoLoad,
+ storeConfig = that.storeConfig || {};
+
+ return function() {
+ var me = this,
+ config, filter,
+ modelDefaults = {};
+
+ if (me[storeName] === undefined) {
+ if (filterProperty) {
+ filter = {
+ property : filterProperty,
+ value : me.get(filterProperty),
+ exactMatch: true
+ };
+ } else {
+ filter = {
+ property : foreignKey,
+ value : me.get(primaryKey),
+ exactMatch: true
+ };
+ }
+
+ modelDefaults[foreignKey] = me.get(primaryKey);
+
+ config = Ext.apply({}, storeConfig, {
+ model : associatedModel,
+ filters : [filter],
+ remoteFilter : false,
+ modelDefaults: modelDefaults
+ });
+
+ me[storeName] = Ext.create('Ext.data.Store', config);
+ if (autoLoad) {
+ me[storeName].load();
+ }
+ }
+
+ return me[storeName];
+ };
+ },
+
+
+ read: function(record, reader, associationData){
+ var store = record[this.name](),
+ inverse;
+
+ store.add(reader.read(associationData).records);
+
+
+
+ inverse = this.associatedModel.prototype.associations.findBy(function(assoc){
+ return assoc.type === 'belongsTo' && assoc.associatedName === record.$className;
+ });
+
+
+ if (inverse) {
+ store.data.each(function(associatedRecord){
+ associatedRecord[inverse.instanceName] = record;
+ });
+ }
+ }
+});
+
+Ext.define('Ext.data.JsonP', {
+
+
+
+ singleton: true,
+
+ statics: {
+ requestCount: 0,
+ requests: {}
+ },
+
+
+
+
+ timeout: 30000,
+
+
+ disableCaching: true,
+
+
+ disableCachingParam: '_dc',
+
+
+ callbackKey: 'callback',
+
+
+ request: function(options){
+ options = Ext.apply({}, options);
+
+ if (!options.url) {
+ Ext.Error.raise('A url must be specified for a JSONP request.');
+ }
+
+ var me = this,
+ disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching,
+ cacheParam = options.disableCachingParam || me.disableCachingParam,
+ id = ++me.statics().requestCount,
+ callbackName = 'callback' + id,
+ callbackKey = options.callbackKey || me.callbackKey,
+ timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout,
+ params = Ext.apply({}, options.params),
+ url = options.url,
+ request,
+ script;
+
+ params[callbackKey] = 'Ext.data.JsonP.' + callbackName;
+ if (disableCaching) {
+ params[cacheParam] = new Date().getTime();
+ }
+
+ script = me.createScript(url, params);
+
+ me.statics().requests[id] = request = {
+ url: url,
+ params: params,
+ script: script,
+ id: id,
+ scope: options.scope,
+ success: options.success,
+ failure: options.failure,
+ callback: options.callback,
+ callbackName: callbackName
+ };
+
+ if (timeout > 0) {
+ request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout);
+ }
+
+ me.setupErrorHandling(request);
+ me[callbackName] = Ext.bind(me.handleResponse, me, [request], true);
+ Ext.getHead().appendChild(script);
+ return request;
+ },
+
+
+ abort: function(request){
+ var requests = this.statics().requests,
+ key;
+
+ if (request) {
+ if (!request.id) {
+ request = requests[request];
+ }
+ this.abort(request);
+ } else {
+ for (key in requests) {
+ if (requests.hasOwnProperty(key)) {
+ this.abort(requests[key]);
+ }
+ }
+ }
+ },
+
+
+ setupErrorHandling: function(request){
+ request.script.onerror = Ext.bind(this.handleError, this, [request]);
+ },
+
+
+ handleAbort: function(request){
+ request.errorType = 'abort';
+ this.handleResponse(null, request);
+ },
+
+
+ handleError: function(request){
+ request.errorType = 'error';
+ this.handleResponse(null, request);
+ },
+
+
+ cleanupErrorHandling: function(request){
+ request.script.onerror = null;
+ },
+
+
+ handleTimeout: function(request){
+ request.errorType = 'timeout';
+ this.handleResponse(null, request);
+ },
+
+
+ handleResponse: function(result, request){
+
+ var success = true;
+
+ if (request.timeout) {
+ clearTimeout(request.timeout);
+ }
+ delete this[request.callbackName];
+ delete this.statics()[request.id];
+ this.cleanupErrorHandling(request);
+ Ext.fly(request.script).remove();
+
+ if (request.errorType) {
+ success = false;
+ Ext.callback(request.failure, request.scope, [request.errorType]);
+ } else {
+ Ext.callback(request.success, request.scope, [result]);
+ }
+ Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
+ },
+
+
+ createScript: function(url, params) {
+ var script = document.createElement('script');
+ script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));
+ script.setAttribute("async", true);
+ script.setAttribute("type", "text/javascript");
+ return script;
+ }
+});
+
+
+Ext.define('Ext.data.JsonPStore', {
+ extend: 'Ext.data.Store',
+ alias : 'store.jsonp',
+
+
+ constructor: function(config) {
+ this.callParent(Ext.apply(config, {
+ reader: Ext.create('Ext.data.reader.Json', config),
+ proxy : Ext.create('Ext.data.proxy.JsonP', config)
+ }));
+ }
+});
+
+
+Ext.define('Ext.data.NodeInterface', {
+ requires: ['Ext.data.Field'],
+
+ statics: {
+
+ decorate: function(record) {
+ if (!record.isNode) {
+
+
+ var mgr = Ext.ModelManager,
+ modelName = record.modelName,
+ modelClass = mgr.getModel(modelName),
+ idName = modelClass.prototype.idProperty,
+ instances = Ext.Array.filter(mgr.all.getArray(), function(item) {
+ return item.modelName == modelName;
+ }),
+ iln = instances.length,
+ newFields = [],
+ i, instance, jln, j, newField;
+
+
+ modelClass.override(this.getPrototypeBody());
+ newFields = this.applyFields(modelClass, [
+ {name: idName, type: 'string', defaultValue: null},
+ {name: 'parentId', type: 'string', defaultValue: null},
+ {name: 'index', type: 'int', defaultValue: null},
+ {name: 'depth', type: 'int', defaultValue: 0},
+ {name: 'expanded', type: 'bool', defaultValue: false, persist: false},
+ {name: 'checked', type: 'auto', defaultValue: null},
+ {name: 'leaf', type: 'bool', defaultValue: false, persist: false},
+ {name: 'cls', type: 'string', defaultValue: null, persist: false},
+ {name: 'iconCls', type: 'string', defaultValue: null, persist: false},
+ {name: 'root', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'isLast', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'isFirst', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'allowDrop', type: 'boolean', defaultValue: true, persist: false},
+ {name: 'allowDrag', type: 'boolean', defaultValue: true, persist: false},
+ {name: 'loaded', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'loading', type: 'boolean', defaultValue: false, persist: false},
+ {name: 'href', type: 'string', defaultValue: null, persist: false},
+ {name: 'hrefTarget',type: 'string', defaultValue: null, persist: false},
+ {name: 'qtip', type: 'string', defaultValue: null, persist: false},
+ {name: 'qtitle', type: 'string', defaultValue: null, persist: false}
+ ]);
+
+ jln = newFields.length;
+
+ for (i = 0; i < iln; i++) {
+ instance = instances[i];
+ for (j = 0; j < jln; j++) {
+ newField = newFields[j];
+ if (instance.get(newField.name) === undefined) {
+ instance.data[newField.name] = newField.defaultValue;
+ }
+ }
+ }
+ }
+
+ Ext.applyIf(record, {
+ firstChild: null,
+ lastChild: null,
+ parentNode: null,
+ previousSibling: null,
+ nextSibling: null,
+ childNodes: []
+ });
+
+ record.commit(true);
+
+ record.enableBubble([
+
+ "append",
+
+
+ "remove",
+
+
+ "move",
+
+
+ "insert",
+
+
+ "beforeappend",
+
+
+ "beforeremove",
+
+
+ "beforemove",
+
+
+ "beforeinsert",
+
+
+ "expand",
+
+
+ "collapse",
+
+
+ "beforeexpand",
+
+
+ "beforecollapse",
+
+
+ "sort"
+ ]);
+
+ return record;
+ },
+
+ applyFields: function(modelClass, addFields) {
+ var modelPrototype = modelClass.prototype,
+ fields = modelPrototype.fields,
+ keys = fields.keys,
+ ln = addFields.length,
+ addField, i, name,
+ newFields = [];
+
+ for (i = 0; i < ln; i++) {
+ addField = addFields[i];
+ if (!Ext.Array.contains(keys, addField.name)) {
+ addField = Ext.create('data.field', addField);
+
+ newFields.push(addField);
+ fields.add(addField);
+ }
+ }
+
+ return newFields;
+ },
+
+ getPrototypeBody: function() {
+ return {
+ isNode: true,
+
+
+ createNode: function(node) {
+ if (Ext.isObject(node) && !node.isModel) {
+ node = Ext.ModelManager.create(node, this.modelName);
+ }
+
+ return Ext.data.NodeInterface.decorate(node);
+ },
+
+
+ isLeaf : function() {
+ return this.get('leaf') === true;
+ },
+
+
+ setFirstChild : function(node) {
+ this.firstChild = node;
+ },
+
+
+ setLastChild : function(node) {
+ this.lastChild = node;
+ },
+
+
+ updateInfo: function(silent) {
+ var me = this,
+ isRoot = me.isRoot(),
+ parentNode = me.parentNode,
+ isFirst = (!parentNode ? true : parentNode.firstChild == me),
+ isLast = (!parentNode ? true : parentNode.lastChild == me),
+ depth = 0,
+ parent = me,
+ children = me.childNodes,
+ len = children.length,
+ i = 0;
+
+ while (parent.parentNode) {
+ ++depth;
+ parent = parent.parentNode;
+ }
+
+ me.beginEdit();
+ me.set({
+ isFirst: isFirst,
+ isLast: isLast,
+ depth: depth,
+ index: parentNode ? parentNode.indexOf(me) : 0,
+ parentId: parentNode ? parentNode.getId() : null
+ });
+ me.endEdit(silent);
+ if (silent) {
+ me.commit();
+ }
+
+ for (i = 0; i < len; i++) {
+ children[i].updateInfo(silent);
+ }
+ },
+
+
+ isLast : function() {
+ return this.get('isLast');
+ },
+
+
+ isFirst : function() {
+ return this.get('isFirst');
+ },
+
+
+ hasChildNodes : function() {
+ return !this.isLeaf() && this.childNodes.length > 0;
+ },
+
+
+ isExpandable : function() {
+ return this.get('expandable') || this.hasChildNodes();
+ },
+
+
+ appendChild : function(node, suppressEvents, suppressNodeUpdate) {
+ var me = this,
+ i, ln,
+ index,
+ oldParent,
+ ps;
+
+
+ if (Ext.isArray(node)) {
+ for (i = 0, ln = node.length; i < ln; i++) {
+ me.appendChild(node[i]);
+ }
+ } else {
+
+ node = me.createNode(node);
+
+ if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
+ return false;
+ }
+
+ index = me.childNodes.length;
+ oldParent = node.parentNode;
+
+
+ if (oldParent) {
+ if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
+ return false;
+ }
+ oldParent.removeChild(node, null, false, true);
+ }
+
+ index = me.childNodes.length;
+ if (index === 0) {
+ me.setFirstChild(node);
+ }
+
+ me.childNodes.push(node);
+ node.parentNode = me;
+ node.nextSibling = null;
+
+ me.setLastChild(node);
+
+ ps = me.childNodes[index - 1];
+ if (ps) {
+ node.previousSibling = ps;
+ ps.nextSibling = node;
+ ps.updateInfo(suppressNodeUpdate);
+ } else {
+ node.previousSibling = null;
+ }
+
+ node.updateInfo(suppressNodeUpdate);
+
+
+ if (!me.isLoaded()) {
+ me.set('loaded', true);
+ }
+
+ else if (me.childNodes.length === 1) {
+ me.set('loaded', me.isLoaded());
+ }
+
+ if (suppressEvents !== true) {
+ me.fireEvent("append", me, node, index);
+
+ if (oldParent) {
+ node.fireEvent("move", node, oldParent, me, index);
+ }
+ }
+
+ return node;
+ }
+ },
+
+
+ getBubbleTarget: function() {
+ return this.parentNode;
+ },
+
+
+ removeChild : function(node, destroy, suppressEvents, suppressNodeUpdate) {
+ var me = this,
+ index = me.indexOf(node);
+
+ if (index == -1 || (suppressEvents !== true && me.fireEvent("beforeremove", me, node) === false)) {
+ return false;
+ }
+
+
+ me.childNodes.splice(index, 1);
+
+
+ if (me.firstChild == node) {
+ me.setFirstChild(node.nextSibling);
+ }
+ if (me.lastChild == node) {
+ me.setLastChild(node.previousSibling);
+ }
+
+
+ if (node.previousSibling) {
+ node.previousSibling.nextSibling = node.nextSibling;
+ node.previousSibling.updateInfo(suppressNodeUpdate);
+ }
+ if (node.nextSibling) {
+ node.nextSibling.previousSibling = node.previousSibling;
+ node.nextSibling.updateInfo(suppressNodeUpdate);
+ }
+
+ if (suppressEvents !== true) {
+ me.fireEvent("remove", me, node);
+ }
+
+
+
+ if (!me.childNodes.length) {
+ me.set('loaded', me.isLoaded());
+ }
+
+ if (destroy) {
+ node.destroy(true);
+ } else {
+ node.clear();
+ }
+
+ return node;
+ },
+
+
+ copy: function(newId, deep) {
+ var me = this,
+ result = me.callOverridden(arguments),
+ len = me.childNodes ? me.childNodes.length : 0,
+ i;
+
+
+ if (deep) {
+ for (i = 0; i < len; i++) {
+ result.appendChild(me.childNodes[i].copy(true));
+ }
+ }
+ return result;
+ },
+
+
+ clear : function(destroy) {
+ var me = this;
+
+
+ me.parentNode = me.previousSibling = me.nextSibling = null;
+ if (destroy) {
+ me.firstChild = me.lastChild = null;
+ }
+ },
+
+
+ destroy : function(silent) {
+
+ var me = this;
+
+ if (silent === true) {
+ me.clear(true);
+ Ext.each(me.childNodes, function(n) {
+ n.destroy(true);
+ });
+ me.childNodes = null;
+ } else {
+ me.remove(true);
+ }
+
+ me.callOverridden();
+ },
+
+
+ insertBefore : function(node, refNode, suppressEvents) {
+ var me = this,
+ index = me.indexOf(refNode),
+ oldParent = node.parentNode,
+ refIndex = index,
+ ps;
+
+ if (!refNode) {
+ return me.appendChild(node);
+ }
+
+
+ if (node == refNode) {
+ return false;
+ }
+
+
+ node = me.createNode(node);
+
+ if (suppressEvents !== true && me.fireEvent("beforeinsert", me, node, refNode) === false) {
+ return false;
+ }
+
+
+ if (oldParent == me && me.indexOf(node) < index) {
+ refIndex--;
+ }
+
+
+ if (oldParent) {
+ if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index, refNode) === false) {
+ return false;
+ }
+ oldParent.removeChild(node);
+ }
+
+ if (refIndex === 0) {
+ me.setFirstChild(node);
+ }
+
+ me.childNodes.splice(refIndex, 0, node);
+ node.parentNode = me;
+
+ node.nextSibling = refNode;
+ refNode.previousSibling = node;
+
+ ps = me.childNodes[refIndex - 1];
+ if (ps) {
+ node.previousSibling = ps;
+ ps.nextSibling = node;
+ ps.updateInfo();
+ } else {
+ node.previousSibling = null;
+ }
+
+ node.updateInfo();
+
+ if (!me.isLoaded()) {
+ me.set('loaded', true);
+ }
+
+ else if (me.childNodes.length === 1) {
+ me.set('loaded', me.isLoaded());
+ }
+
+ if (suppressEvents !== true) {
+ me.fireEvent("insert", me, node, refNode);
+
+ if (oldParent) {
+ node.fireEvent("move", node, oldParent, me, refIndex, refNode);
+ }
+ }
+
+ return node;
+ },
+
+
+ insertChild: function(index, node) {
+ var sibling = this.childNodes[index];
+ if (sibling) {
+ return this.insertBefore(node, sibling);
+ }
+ else {
+ return this.appendChild(node);
+ }
+ },
+
+
+ remove : function(destroy, suppressEvents) {
+ var parentNode = this.parentNode;
+
+ if (parentNode) {
+ parentNode.removeChild(this, destroy, suppressEvents, true);
+ }
+ return this;
+ },
+
+
+ removeAll : function(destroy, suppressEvents) {
+ var cn = this.childNodes,
+ n;
+
+ while ((n = cn[0])) {
+ this.removeChild(n, destroy, suppressEvents);
+ }
+ return this;
+ },
+
+
+ getChildAt : function(index) {
+ return this.childNodes[index];
+ },
+
+
+ replaceChild : function(newChild, oldChild, suppressEvents) {
+ var s = oldChild ? oldChild.nextSibling : null;
+
+ this.removeChild(oldChild, suppressEvents);
+ this.insertBefore(newChild, s, suppressEvents);
+ return oldChild;
+ },
+
+
+ indexOf : function(child) {
+ return Ext.Array.indexOf(this.childNodes, child);
+ },
+
+
+ getDepth : function() {
+ return this.get('depth');
+ },
+
+
+ bubble : function(fn, scope, args) {
+ var p = this;
+ while (p) {
+ if (fn.apply(scope || p, args || [p]) === false) {
+ break;
+ }
+ p = p.parentNode;
+ }
+ },
+
+ cascade: function() {
+ if (Ext.isDefined(Ext.global.console)) {
+ Ext.global.console.warn('Ext.data.Node: cascade has been deprecated. Please use cascadeBy instead.');
+ }
+ return this.cascadeBy.apply(this, arguments);
+ },
+
+
+ cascadeBy : function(fn, scope, args) {
+ if (fn.apply(scope || this, args || [this]) !== false) {
+ var childNodes = this.childNodes,
+ length = childNodes.length,
+ i;
+
+ for (i = 0; i < length; i++) {
+ childNodes[i].cascadeBy(fn, scope, args);
+ }
+ }
+ },
+
+
+ eachChild : function(fn, scope, args) {
+ var childNodes = this.childNodes,
+ length = childNodes.length,
+ i;
+
+ for (i = 0; i < length; i++) {
+ if (fn.apply(scope || this, args || [childNodes[i]]) === false) {
+ break;
+ }
+ }
+ },
+
+
+ findChild : function(attribute, value, deep) {
+ return this.findChildBy(function() {
+ return this.get(attribute) == value;
+ }, null, deep);
+ },
+
+
+ findChildBy : function(fn, scope, deep) {
+ var cs = this.childNodes,
+ len = cs.length,
+ i = 0, n, res;
+
+ for (; i < len; i++) {
+ n = cs[i];
+ if (fn.call(scope || n, n) === true) {
+ return n;
+ }
+ else if (deep) {
+ res = n.findChildBy(fn, scope, deep);
+ if (res !== null) {
+ return res;
+ }
+ }
+ }
+
+ return null;
+ },
+
+
+ contains : function(node) {
+ return node.isAncestor(this);
+ },
+
+
+ isAncestor : function(node) {
+ var p = this.parentNode;
+ while (p) {
+ if (p == node) {
+ return true;
+ }
+ p = p.parentNode;
+ }
+ return false;
+ },
+
+
+ sort : function(sortFn, recursive, suppressEvent) {
+ var cs = this.childNodes,
+ ln = cs.length,
+ i, n;
+
+ if (ln > 0) {
+ Ext.Array.sort(cs, sortFn);
+ for (i = 0; i < ln; i++) {
+ n = cs[i];
+ n.previousSibling = cs[i-1];
+ n.nextSibling = cs[i+1];
+
+ if (i === 0) {
+ this.setFirstChild(n);
+ n.updateInfo();
+ }
+ if (i == ln - 1) {
+ this.setLastChild(n);
+ n.updateInfo();
+ }
+ if (recursive && !n.isLeaf()) {
+ n.sort(sortFn, true, true);
+ }
+ }
+
+ if (suppressEvent !== true) {
+ this.fireEvent('sort', this, cs);
+ }
+ }
+ },
+
+
+ isExpanded: function() {
+ return this.get('expanded');
+ },
+
+
+ isLoaded: function() {
+ return this.get('loaded');
+ },
+
+
+ isLoading: function() {
+ return this.get('loading');
+ },
+
+
+ isRoot: function() {
+ return !this.parentNode;
+ },
+
+
+ isVisible: function() {
+ var parent = this.parentNode;
+ while (parent) {
+ if (!parent.isExpanded()) {
+ return false;
+ }
+ parent = parent.parentNode;
+ }
+ return true;
+ },
+
+
+ expand: function(recursive, callback, scope) {
+ var me = this;
+
+
+
+
+
+ if (!me.isLeaf()) {
+
+ if (!me.isLoading() && !me.isExpanded()) {
+
+
+
+
+ me.fireEvent('beforeexpand', me, function(records) {
+ me.set('expanded', true);
+ me.fireEvent('expand', me, me.childNodes, false);
+
+
+ if (recursive) {
+ me.expandChildren(true, callback, scope);
+ }
+ else {
+ Ext.callback(callback, scope || me, [me.childNodes]);
+ }
+ }, me);
+ }
+
+ else if (recursive) {
+ me.expandChildren(true, callback, scope);
+ }
+ else {
+ Ext.callback(callback, scope || me, [me.childNodes]);
+ }
+
+
+
+
+ }
+
+ else {
+ Ext.callback(callback, scope || me);
+ }
+ },
+
+
+ expandChildren: function(recursive, callback, scope) {
+ var me = this,
+ i = 0,
+ nodes = me.childNodes,
+ ln = nodes.length,
+ node,
+ expanding = 0;
+
+ for (; i < ln; ++i) {
+ node = nodes[i];
+ if (!node.isLeaf() && !node.isExpanded()) {
+ expanding++;
+ nodes[i].expand(recursive, function () {
+ expanding--;
+ if (callback && !expanding) {
+ Ext.callback(callback, scope || me, me.childNodes);
+ }
+ });
+ }
+ }
+
+ if (!expanding && callback) {
+ Ext.callback(callback, scope || me, me.childNodes);
+ }
+ },
+
+
+ collapse: function(recursive, callback, scope) {
+ var me = this;
+
+
+ if (!me.isLeaf()) {
+
+ if (!me.collapsing && me.isExpanded()) {
+ me.fireEvent('beforecollapse', me, function(records) {
+ me.set('expanded', false);
+ me.fireEvent('collapse', me, me.childNodes, false);
+
+
+ if (recursive) {
+ me.collapseChildren(true, callback, scope);
+ }
+ else {
+ Ext.callback(callback, scope || me, [me.childNodes]);
+ }
+ }, me);
+ }
+
+ else if (recursive) {
+ me.collapseChildren(true, callback, scope);
+ }
+ }
+
+ else {
+ Ext.callback(callback, scope || me, me.childNodes);
+ }
+ },
+
+
+ collapseChildren: function(recursive, callback, scope) {
+ var me = this,
+ i = 0,
+ nodes = me.childNodes,
+ ln = nodes.length,
+ node,
+ collapsing = 0;
+
+ for (; i < ln; ++i) {
+ node = nodes[i];
+ if (!node.isLeaf() && node.isExpanded()) {
+ collapsing++;
+ nodes[i].collapse(recursive, function () {
+ collapsing--;
+ if (callback && !collapsing) {
+ Ext.callback(callback, scope || me, me.childNodes);
+ }
+ });
+ }
+ }
+
+ if (!collapsing && callback) {
+ Ext.callback(callback, scope || me, me.childNodes);
+ }
+ }
+ };
+ }
+ }
+});
+
+Ext.define('Ext.data.NodeStore', {
+ extend: 'Ext.data.Store',
+ alias: 'store.node',
+ requires: ['Ext.data.NodeInterface'],
+
+
+ node: null,
+
+
+ recursive: false,
+
+
+ rootVisible: false,
+
+ constructor: function(config) {
+ var me = this,
+ node;
+
+ config = config || {};
+ Ext.apply(me, config);
+
+ if (Ext.isDefined(me.proxy)) {
+ Ext.Error.raise("A NodeStore cannot be bound to a proxy. Instead bind it to a record " +
+ "decorated with the NodeInterface by setting the node config.");
+ }
+
+ config.proxy = {type: 'proxy'};
+ me.callParent([config]);
+
+ me.addEvents('expand', 'collapse', 'beforeexpand', 'beforecollapse');
+
+ node = me.node;
+ if (node) {
+ me.node = null;
+ me.setNode(node);
+ }
+ },
+
+ setNode: function(node) {
+ var me = this;
+
+ if (me.node && me.node != node) {
+
+ me.mun(me.node, {
+ expand: me.onNodeExpand,
+ collapse: me.onNodeCollapse,
+ append: me.onNodeAppend,
+ insert: me.onNodeInsert,
+ remove: me.onNodeRemove,
+ sort: me.onNodeSort,
+ scope: me
+ });
+ me.node = null;
+ }
+
+ if (node) {
+ Ext.data.NodeInterface.decorate(node);
+ me.removeAll();
+ if (me.rootVisible) {
+ me.add(node);
+ }
+ me.mon(node, {
+ expand: me.onNodeExpand,
+ collapse: me.onNodeCollapse,
+ append: me.onNodeAppend,
+ insert: me.onNodeInsert,
+ remove: me.onNodeRemove,
+ sort: me.onNodeSort,
+ scope: me
+ });
+ me.node = node;
+ if (node.isExpanded() && node.isLoaded()) {
+ me.onNodeExpand(node, node.childNodes, true);
+ }
+ }
+ },
+
+ onNodeSort: function(node, childNodes) {
+ var me = this;
+
+ if ((me.indexOf(node) !== -1 || (node === me.node && !me.rootVisible) && node.isExpanded())) {
+ me.onNodeCollapse(node, childNodes, true);
+ me.onNodeExpand(node, childNodes, true);
+ }
+ },
+
+ onNodeExpand: function(parent, records, suppressEvent) {
+ var me = this,
+ insertIndex = me.indexOf(parent) + 1,
+ ln = records ? records.length : 0,
+ i, record;
+
+ if (!me.recursive && parent !== me.node) {
+ return;
+ }
+
+ if (!me.isVisible(parent)) {
+ return;
+ }
+
+ if (!suppressEvent && me.fireEvent('beforeexpand', parent, records, insertIndex) === false) {
+ return;
+ }
+
+ if (ln) {
+ me.insert(insertIndex, records);
+ for (i = 0; i < ln; i++) {
+ record = records[i];
+ if (record.isExpanded()) {
+ if (record.isLoaded()) {
+
+ me.onNodeExpand(record, record.childNodes, true);
+ }
+ else {
+ record.set('expanded', false);
+ record.expand();
+ }
+ }
+ }
+ }
+
+ if (!suppressEvent) {
+ me.fireEvent('expand', parent, records);
+ }
+ },
+
+ onNodeCollapse: function(parent, records, suppressEvent) {
+ var me = this,
+ ln = records.length,
+ collapseIndex = me.indexOf(parent) + 1,
+ i, record;
+
+ if (!me.recursive && parent !== me.node) {
+ return;
+ }
+
+ if (!suppressEvent && me.fireEvent('beforecollapse', parent, records, collapseIndex) === false) {
+ return;
+ }
+
+ for (i = 0; i < ln; i++) {
+ record = records[i];
+ me.remove(record);
+ if (record.isExpanded()) {
+ me.onNodeCollapse(record, record.childNodes, true);
+ }
+ }
+
+ if (!suppressEvent) {
+ me.fireEvent('collapse', parent, records, collapseIndex);
+ }
+ },
+
+ onNodeAppend: function(parent, node, index) {
+ var me = this,
+ refNode, sibling;
+
+ if (me.isVisible(node)) {
+ if (index === 0) {
+ refNode = parent;
+ } else {
+ sibling = node.previousSibling;
+ while (sibling.isExpanded() && sibling.lastChild) {
+ sibling = sibling.lastChild;
+ }
+ refNode = sibling;
+ }
+ me.insert(me.indexOf(refNode) + 1, node);
+ if (!node.isLeaf() && node.isExpanded()) {
+ if (node.isLoaded()) {
+
+ me.onNodeExpand(node, node.childNodes, true);
+ }
+ else {
+ node.set('expanded', false);
+ node.expand();
+ }
+ }
+ }
+ },
+
+ onNodeInsert: function(parent, node, refNode) {
+ var me = this,
+ index = this.indexOf(refNode);
+
+ if (index != -1 && me.isVisible(node)) {
+ me.insert(index, node);
+ if (!node.isLeaf() && node.isExpanded()) {
+ if (node.isLoaded()) {
+
+ me.onNodeExpand(node, node.childNodes, true);
+ }
+ else {
+ node.set('expanded', false);
+ node.expand();
+ }
+ }
+ }
+ },
+
+ onNodeRemove: function(parent, node, index) {
+ var me = this;
+ if (me.indexOf(node) != -1) {
+ if (!node.isLeaf() && node.isExpanded()) {
+ me.onNodeCollapse(node, node.childNodes, true);
+ }
+ me.remove(node);
+ }
+ },
+
+ isVisible: function(node) {
+ var parent = node.parentNode;
+ while (parent) {
+ if (parent === this.node && !this.rootVisible && parent.isExpanded()) {
+ return true;
+ }
+
+ if (this.indexOf(parent) === -1 || !parent.isExpanded()) {
+ return false;
+ }
+
+ parent = parent.parentNode;
+ }
+ return true;
+ }
+});
+
+Ext.define('Ext.data.Request', {
+
+ action: undefined,
+
+
+ params: undefined,
+
+
+ method: 'GET',
+
+
+ url: undefined,
+
+ constructor: function(config) {
+ Ext.apply(this, config);
+ }
+});
+
+Ext.define('Ext.data.Tree', {
+ alias: 'data.tree',
+
+ mixins: {
+ observable: "Ext.util.Observable"
+ },
+
+
+ root: null,
+
+ constructor: function(root) {
+ var me = this;
+
+ me.nodeHash = {};
+
+ me.mixins.observable.constructor.call(me);
+
+ if (root) {
+ me.setRootNode(root);
+ }
+ },
+
+
+ getRootNode : function() {
+ return this.root;
+ },
+
+
+ setRootNode : function(node) {
+ var me = this;
+
+ me.root = node;
+ Ext.data.NodeInterface.decorate(node);
+
+ if (me.fireEvent('beforeappend', null, node) !== false) {
+ node.set('root', true);
+ node.updateInfo();
+
+ me.relayEvents(node, [
+
+ "append",
+
+
+ "remove",
+
+
+ "move",
+
+
+ "insert",
+
+
+ "beforeappend",
+
+
+ "beforeremove",
+
+
+ "beforemove",
+
+
+ "beforeinsert",
+
+
+ "expand",
+
+
+ "collapse",
+
+
+ "beforeexpand",
+
+
+ "beforecollapse" ,
+
+
+ "rootchange"
+ ]);
+
+ node.on({
+ scope: me,
+ insert: me.onNodeInsert,
+ append: me.onNodeAppend,
+ remove: me.onNodeRemove
+ });
+
+ me.registerNode(node);
+ me.fireEvent('append', null, node);
+ me.fireEvent('rootchange', node);
+ }
+
+ return node;
+ },
+
+
+ flatten: function(){
+ var nodes = [],
+ hash = this.nodeHash,
+ key;
+
+ for (key in hash) {
+ if (hash.hasOwnProperty(key)) {
+ nodes.push(hash[key]);
+ }
+ }
+ return nodes;
+ },
+
+
+ onNodeInsert: function(parent, node) {
+ this.registerNode(node);
+ },
+
+
+ onNodeAppend: function(parent, node) {
+ this.registerNode(node);
+ },
+
+
+ onNodeRemove: function(parent, node) {
+ this.unregisterNode(node);
+ },
+
+
+ getNodeById : function(id) {
+ return this.nodeHash[id];
+ },
+
+
+ registerNode : function(node) {
+ this.nodeHash[node.getId() || node.internalId] = node;
+ },
+
+
+ unregisterNode : function(node) {
+ delete this.nodeHash[node.getId() || node.internalId];
+ },
+
+
+ sort: function(sorterFn, recursive) {
+ this.getRootNode().sort(sorterFn, recursive);
+ },
+
+
+ filter: function(filters, recursive) {
+ this.getRootNode().filter(filters, recursive);
+ }
+});
+
+Ext.define('Ext.data.TreeStore', {
+ extend: 'Ext.data.AbstractStore',
+ alias: 'store.tree',
+ requires: ['Ext.data.Tree', 'Ext.data.NodeInterface', 'Ext.data.NodeStore'],
+
+
+ clearOnLoad : true,
+
+
+ nodeParam: 'node',
+
+
+ defaultRootId: 'root',
+
+
+ defaultRootProperty: 'children',
+
+
+ folderSort: false,
+
+ constructor: function(config) {
+ var me = this,
+ root,
+ fields;
+
+
+ config = Ext.apply({}, config);
+
+
+ fields = config.fields || me.fields;
+ if (!fields) {
+ config.fields = [{name: 'text', type: 'string'}];
+ }
+
+ me.callParent([config]);
+
+
+ me.tree = Ext.create('Ext.data.Tree');
+
+ me.tree.on({
+ scope: me,
+ remove: me.onNodeRemove,
+ beforeexpand: me.onBeforeNodeExpand,
+ beforecollapse: me.onBeforeNodeCollapse,
+ append: me.onNodeAdded,
+ insert: me.onNodeAdded
+ });
+
+ me.onBeforeSort();
+
+ root = me.root;
+ if (root) {
+ delete me.root;
+ me.setRootNode(root);
+ }
+
+ me.relayEvents(me.tree, [
+
+ "append",
+
+
+ "remove",
+
+
+ "move",
+
+
+ "insert",
+
+
+ "beforeappend",
+
+
+ "beforeremove",
+
+
+ "beforemove",
+
+
+ "beforeinsert",
+
+
+ "expand",
+
+
+ "collapse",
+
+
+ "beforeexpand",
+
+
+ "beforecollapse",
+
+
+ "sort",
+
+
+ "rootchange"
+ ]);
+
+ me.addEvents(
+
+ 'rootchange'
+ );
+
+ if (Ext.isDefined(me.nodeParameter)) {
+ if (Ext.isDefined(Ext.global.console)) {
+ Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. Please use nodeParam instead.');
+ }
+ me.nodeParam = me.nodeParameter;
+ delete me.nodeParameter;
+ }
+ },
+
+
+ setProxy: function(proxy) {
+ var reader,
+ needsRoot;
+
+ if (proxy instanceof Ext.data.proxy.Proxy) {
+
+ needsRoot = Ext.isEmpty(proxy.getReader().root);
+ } else if (Ext.isString(proxy)) {
+
+ needsRoot = true;
+ } else {
+
+ reader = proxy.reader;
+ needsRoot = !(reader && !Ext.isEmpty(reader.root));
+ }
+ proxy = this.callParent(arguments);
+ if (needsRoot) {
+ reader = proxy.getReader();
+ reader.root = this.defaultRootProperty;
+
+ reader.buildExtractors(true);
+ }
+ },
+
+
+ onBeforeSort: function() {
+ if (this.folderSort) {
+ this.sort({
+ property: 'leaf',
+ direction: 'ASC'
+ }, 'prepend', false);
+ }
+ },
+
+
+ onBeforeNodeExpand: function(node, callback, scope) {
+ if (node.isLoaded()) {
+ Ext.callback(callback, scope || node, [node.childNodes]);
+ }
+ else if (node.isLoading()) {
+ this.on('load', function() {
+ Ext.callback(callback, scope || node, [node.childNodes]);
+ }, this, {single: true});
+ }
+ else {
+ this.read({
+ node: node,
+ callback: function() {
+ Ext.callback(callback, scope || node, [node.childNodes]);
+ }
+ });
+ }
+ },
+
+
+ getNewRecords: function() {
+ return Ext.Array.filter(this.tree.flatten(), this.filterNew);
+ },
+
+
+ getUpdatedRecords: function() {
+ return Ext.Array.filter(this.tree.flatten(), this.filterUpdated);
+ },
+
+
+ onBeforeNodeCollapse: function(node, callback, scope) {
+ callback.call(scope || node, node.childNodes);
+ },
+
+ onNodeRemove: function(parent, node) {
+ var removed = this.removed;
+
+ if (!node.isReplace && Ext.Array.indexOf(removed, node) == -1) {
+ removed.push(node);
+ }
+ },
+
+ onNodeAdded: function(parent, node) {
+ var proxy = this.getProxy(),
+ reader = proxy.getReader(),
+ data = node.raw || node.data,
+ dataRoot, children;
+
+ Ext.Array.remove(this.removed, node);
+
+ if (!node.isLeaf() && !node.isLoaded()) {
+ dataRoot = reader.getRoot(data);
+ if (dataRoot) {
+ this.fillNode(node, reader.extractData(dataRoot));
+ delete data[reader.root];
+ }
+ }
+ },
+
+
+ setRootNode: function(root) {
+ var me = this;
+
+ root = root || {};
+ if (!root.isNode) {
+
+ Ext.applyIf(root, {
+ id: me.defaultRootId,
+ text: 'Root',
+ allowDrag: false
+ });
+ root = Ext.ModelManager.create(root, me.model);
+ }
+ Ext.data.NodeInterface.decorate(root);
+
+
+
+ me.getProxy().getReader().buildExtractors(true);
+
+
+ me.tree.setRootNode(root);
+
+
+ if (!root.isLoaded() && root.isExpanded()) {
+ me.load({
+ node: root
+ });
+ }
+
+ return root;
+ },
+
+
+ getRootNode: function() {
+ return this.tree.getRootNode();
+ },
+
+
+ getNodeById: function(id) {
+ return this.tree.getNodeById(id);
+ },
+
+
+ load: function(options) {
+ options = options || {};
+ options.params = options.params || {};
+
+ var me = this,
+ node = options.node || me.tree.getRootNode(),
+ root;
+
+
+
+ if (!node) {
+ node = me.setRootNode({
+ expanded: true
+ });
+ }
+
+ if (me.clearOnLoad) {
+ node.removeAll();
+ }
+
+ Ext.applyIf(options, {
+ node: node
+ });
+ options.params[me.nodeParam] = node ? node.getId() : 'root';
+
+ if (node) {
+ node.set('loading', true);
+ }
+
+ return me.callParent([options]);
+ },
+
+
+
+ fillNode: function(node, records) {
+ var me = this,
+ ln = records ? records.length : 0,
+ i = 0, sortCollection;
+
+ if (ln && me.sortOnLoad && !me.remoteSort && me.sorters && me.sorters.items) {
+ sortCollection = Ext.create('Ext.util.MixedCollection');
+ sortCollection.addAll(records);
+ sortCollection.sort(me.sorters.items);
+ records = sortCollection.items;
+ }
+
+ node.set('loaded', true);
+ for (; i < ln; i++) {
+ node.appendChild(records[i], undefined, true);
+ }
+
+ return records;
+ },
+
+
+ onProxyLoad: function(operation) {
+ var me = this,
+ successful = operation.wasSuccessful(),
+ records = operation.getRecords(),
+ node = operation.node;
+
+ node.set('loading', false);
+ if (successful) {
+ records = me.fillNode(node, records);
+ }
+
+ me.fireEvent('read', me, operation.node, records, successful);
+ me.fireEvent('load', me, operation.node, records, successful);
+
+ Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
+ },
+
+
+ onCreateRecords: function(records, operation, success) {
+ if (success) {
+ var i = 0,
+ length = records.length,
+ originalRecords = operation.records,
+ parentNode,
+ record,
+ original,
+ index;
+
+
+ for (; i < length; ++i) {
+ record = records[i];
+ original = originalRecords[i];
+ if (original) {
+ parentNode = original.parentNode;
+ if (parentNode) {
+
+ original.isReplace = true;
+ parentNode.replaceChild(record, original);
+ delete original.isReplace;
+ }
+ record.phantom = false;
+ }
+ }
+ }
+ },
+
+
+ onUpdateRecords: function(records, operation, success){
+ if (success) {
+ var me = this,
+ i = 0,
+ length = records.length,
+ data = me.data,
+ original,
+ parentNode,
+ record;
+
+ for (; i < length; ++i) {
+ record = records[i];
+ original = me.tree.getNodeById(record.getId());
+ parentNode = original.parentNode;
+ if (parentNode) {
+
+ original.isReplace = true;
+ parentNode.replaceChild(record, original);
+ original.isReplace = false;
+ }
+ }
+ }
+ },
+
+
+ onDestroyRecords: function(records, operation, success){
+ if (success) {
+ this.removed = [];
+ }
+ },
+
+
+ removeAll: function() {
+ this.getRootNode().destroy();
+ this.fireEvent('clear', this);
+ },
+
+
+ doSort: function(sorterFn) {
+ var me = this;
+ if (me.remoteSort) {
+
+ me.load();
+ } else {
+ me.tree.sort(sorterFn, true);
+ me.fireEvent('datachanged', me);
+ }
+ me.fireEvent('sort', me);
+ }
+});
+
+Ext.define('Ext.data.XmlStore', {
+ extend: 'Ext.data.Store',
+ alternateClassName: 'Ext.data.XmlStore',
+ alias: 'store.xml',
+
+
+ constructor: function(config){
+ config = config || {};
+ config = config || {};
+
+ Ext.applyIf(config, {
+ proxy: {
+ type: 'ajax',
+ reader: 'xml',
+ writer: 'xml'
+ }
+ });
+
+ this.callParent([config]);
+ }
+});
+
+
+Ext.define('Ext.data.proxy.Client', {
+ extend: 'Ext.data.proxy.Proxy',
+ alternateClassName: 'Ext.data.ClientProxy',
+
+
+ clear: function() {
+ Ext.Error.raise("The Ext.data.proxy.Client subclass that you are using has not defined a 'clear' function. See src/data/ClientProxy.js for details.");
+ }
+});
+
+Ext.define('Ext.data.proxy.JsonP', {
+ extend: 'Ext.data.proxy.Server',
+ alternateClassName: 'Ext.data.ScriptTagProxy',
+ alias: ['proxy.jsonp', 'proxy.scripttag'],
+ requires: ['Ext.data.JsonP'],
+
+ defaultWriterType: 'base',
+
+
+ callbackKey : 'callback',
+
+
+ recordParam: 'records',
+
+
+ autoAppendParams: true,
+
+ constructor: function(){
+ this.addEvents(
+
+ 'exception'
+ );
+ this.callParent(arguments);
+ },
+
+
+ doRequest: function(operation, callback, scope) {
+
+ var me = this,
+ writer = me.getWriter(),
+ request = me.buildRequest(operation),
+ params = request.params;
+
+ if (operation.allowWrite()) {
+ request = writer.write(request);
+ }
+
+
+ Ext.apply(request, {
+ callbackKey: me.callbackKey,
+ timeout: me.timeout,
+ scope: me,
+ disableCaching: false,
+ callback: me.createRequestCallback(request, operation, callback, scope)
+ });
+
+
+ if (me.autoAppendParams) {
+ request.params = {};
+ }
+
+ request.jsonp = Ext.data.JsonP.request(request);
+
+ request.params = params;
+ operation.setStarted();
+ me.lastRequest = request;
+
+ return request;
+ },
+
+
+ createRequestCallback: function(request, operation, callback, scope) {
+ var me = this;
+
+ return function(success, response, errorType) {
+ delete me.lastRequest;
+ me.processResponse(success, operation, request, response, callback, scope);
+ };
+ },
+
+
+ setException: function(operation, response) {
+ operation.setException(operation.request.jsonp.errorType);
+ },
+
+
+
+ buildUrl: function(request) {
+ var me = this,
+ url = me.callParent(arguments),
+ params = Ext.apply({}, request.params),
+ filters = params.filters,
+ records,
+ filter, i;
+
+ delete params.filters;
+
+ if (me.autoAppendParams) {
+ url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
+ }
+
+ if (filters && filters.length) {
+ for (i = 0; i < filters.length; i++) {
+ filter = filters[i];
+
+ if (filter.value) {
+ url = Ext.urlAppend(url, filter.property + "=" + filter.value);
+ }
+ }
+ }
+
+
+ records = request.records;
+
+ if (Ext.isArray(records) && records.length > 0) {
+ url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.recordParam, me.encodeRecords(records)));
+ }
+
+ return url;
+ },
+
+
+ destroy: function() {
+ this.abort();
+ this.callParent();
+ },
+
+
+ abort: function() {
+ var lastRequest = this.lastRequest;
+ if (lastRequest) {
+ Ext.data.JsonP.abort(lastRequest.jsonp);
+ }
+ },
+
+
+ encodeRecords: function(records) {
+ var encoded = "",
+ i = 0,
+ len = records.length;
+
+ for (; i < len; i++) {
+ encoded += Ext.Object.toQueryString(records[i].data);
+ }
+
+ return encoded;
+ }
+});
+
+
+Ext.define('Ext.data.proxy.WebStorage', {
+ extend: 'Ext.data.proxy.Client',
+ alternateClassName: 'Ext.data.WebStorageProxy',
+
+
+ id: undefined,
+
+
+ constructor: function(config) {
+ this.callParent(arguments);
+
+
+ this.cache = {};
+
+ if (this.getStorageObject() === undefined) {
+ Ext.Error.raise("Local Storage is not supported in this browser, please use another type of data proxy");
+ }
+
+
+ this.id = this.id || (this.store ? this.store.storeId : undefined);
+
+ if (this.id === undefined) {
+ Ext.Error.raise("No unique id was provided to the local storage proxy. See Ext.data.proxy.LocalStorage documentation for details");
+ }
+
+ this.initialize();
+ },
+
+
+ create: function(operation, callback, scope) {
+ var records = operation.records,
+ length = records.length,
+ ids = this.getIds(),
+ id, record, i;
+
+ operation.setStarted();
+
+ for (i = 0; i < length; i++) {
+ record = records[i];
+
+ if (record.phantom) {
+ record.phantom = false;
+ id = this.getNextId();
+ } else {
+ id = record.getId();
+ }
+
+ this.setRecord(record, id);
+ ids.push(id);
+ }
+
+ this.setIds(ids);
+
+ operation.setCompleted();
+ operation.setSuccessful();
+
+ if (typeof callback == 'function') {
+ callback.call(scope || this, operation);
+ }
+ },
+
+
+ read: function(operation, callback, scope) {
+
+
+ var records = [],
+ ids = this.getIds(),
+ length = ids.length,
+ i, recordData, record;
+
+
+ if (operation.id) {
+ record = this.getRecord(operation.id);
+
+ if (record) {
+ records.push(record);
+ operation.setSuccessful();
+ }
+ } else {
+ for (i = 0; i < length; i++) {
+ records.push(this.getRecord(ids[i]));
+ }
+ operation.setSuccessful();
+ }
+
+ operation.setCompleted();
+
+ operation.resultSet = Ext.create('Ext.data.ResultSet', {
+ records: records,
+ total : records.length,
+ loaded : true
+ });
+
+ if (typeof callback == 'function') {
+ callback.call(scope || this, operation);
+ }
+ },
+
+
+ update: function(operation, callback, scope) {
+ var records = operation.records,
+ length = records.length,
+ ids = this.getIds(),
+ record, id, i;
+
+ operation.setStarted();
+
+ for (i = 0; i < length; i++) {
+ record = records[i];
+ this.setRecord(record);
+
+
+
+ id = record.getId();
+ if (id !== undefined && Ext.Array.indexOf(ids, id) == -1) {
+ ids.push(id);
+ }
+ }
+ this.setIds(ids);
+
+ operation.setCompleted();
+ operation.setSuccessful();
+
+ if (typeof callback == 'function') {
+ callback.call(scope || this, operation);
+ }
+ },
+
+
+ destroy: function(operation, callback, scope) {
+ var records = operation.records,
+ length = records.length,
+ ids = this.getIds(),
+
+
+ newIds = [].concat(ids),
+ i;
+
+ for (i = 0; i < length; i++) {
+ Ext.Array.remove(newIds, records[i].getId());
+ this.removeRecord(records[i], false);
+ }
+
+ this.setIds(newIds);
+
+ operation.setCompleted();
+ operation.setSuccessful();
+
+ if (typeof callback == 'function') {
+ callback.call(scope || this, operation);
+ }
+ },
+
+
+ getRecord: function(id) {
+ if (this.cache[id] === undefined) {
+ var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))),
+ data = {},
+ Model = this.model,
+ fields = Model.prototype.fields.items,
+ length = fields.length,
+ i, field, name, record;
+
+ for (i = 0; i < length; i++) {
+ field = fields[i];
+ name = field.name;
+
+ if (typeof field.decode == 'function') {
+ data[name] = field.decode(rawData[name]);
+ } else {
+ data[name] = rawData[name];
+ }
+ }
+
+ record = new Model(data, id);
+ record.phantom = false;
+
+ this.cache[id] = record;
+ }
+
+ return this.cache[id];
+ },
+
+
+ setRecord: function(record, id) {
+ if (id) {
+ record.setId(id);
+ } else {
+ id = record.getId();
+ }
+
+ var me = this,
+ rawData = record.data,
+ data = {},
+ model = me.model,
+ fields = model.prototype.fields.items,
+ length = fields.length,
+ i = 0,
+ field, name, obj, key;
+
+ for (; i < length; i++) {
+ field = fields[i];
+ name = field.name;
+
+ if (typeof field.encode == 'function') {
+ data[name] = field.encode(rawData[name], record);
+ } else {
+ data[name] = rawData[name];
+ }
+ }
+
+ obj = me.getStorageObject();
+ key = me.getRecordKey(id);
+
+
+ me.cache[id] = record;
+
+
+ obj.removeItem(key);
+ obj.setItem(key, Ext.encode(data));
+ },
+
+
+ removeRecord: function(id, updateIds) {
+ var me = this,
+ ids;
+
+ if (id.isModel) {
+ id = id.getId();
+ }
+
+ if (updateIds !== false) {
+ ids = me.getIds();
+ Ext.Array.remove(ids, id);
+ me.setIds(ids);
+ }
+
+ me.getStorageObject().removeItem(me.getRecordKey(id));
+ },
+
+
+ getRecordKey: function(id) {
+ if (id.isModel) {
+ id = id.getId();
+ }
+
+ return Ext.String.format("{0}-{1}", this.id, id);
+ },
+
+
+ getRecordCounterKey: function() {
+ return Ext.String.format("{0}-counter", this.id);
+ },
+
+
+ getIds: function() {
+ var ids = (this.getStorageObject().getItem(this.id) || "").split(","),
+ length = ids.length,
+ i;
+
+ if (length == 1 && ids[0] === "") {
+ ids = [];
+ } else {
+ for (i = 0; i < length; i++) {
+ ids[i] = parseInt(ids[i], 10);
+ }
+ }
+
+ return ids;
+ },
+
+
+ setIds: function(ids) {
+ var obj = this.getStorageObject(),
+ str = ids.join(",");
+
+ obj.removeItem(this.id);
+
+ if (!Ext.isEmpty(str)) {
+ obj.setItem(this.id, str);
+ }
+ },
+
+
+ getNextId: function() {
+ var obj = this.getStorageObject(),
+ key = this.getRecordCounterKey(),
+ last = obj.getItem(key),
+ ids, id;
+
+ if (last === null) {
+ ids = this.getIds();
+ last = ids[ids.length - 1] || 0;
+ }
+
+ id = parseInt(last, 10) + 1;
+ obj.setItem(key, id);
+
+ return id;
+ },
+
+
+ initialize: function() {
+ var storageObject = this.getStorageObject();
+ storageObject.setItem(this.id, storageObject.getItem(this.id) || "");
+ },
+
+
+ clear: function() {
+ var obj = this.getStorageObject(),
+ ids = this.getIds(),
+ len = ids.length,
+ i;
+
+
+ for (i = 0; i < len; i++) {
+ this.removeRecord(ids[i]);
+ }
+
+
+ obj.removeItem(this.getRecordCounterKey());
+ obj.removeItem(this.id);
+ },
+
+
+ getStorageObject: function() {
+ Ext.Error.raise("The getStorageObject function has not been defined in your Ext.data.proxy.WebStorage subclass");
+ }
+});
+
+Ext.define('Ext.data.proxy.LocalStorage', {
+ extend: 'Ext.data.proxy.WebStorage',
+ alias: 'proxy.localstorage',
+ alternateClassName: 'Ext.data.LocalStorageProxy',
+
+
+ getStorageObject: function() {
+ return window.localStorage;
+ }
+});
+
+Ext.define('Ext.data.proxy.Memory', {
+ extend: 'Ext.data.proxy.Client',
+ alias: 'proxy.memory',
+ alternateClassName: 'Ext.data.MemoryProxy',
+
+
+
+ constructor: function(config) {
+ this.callParent([config]);
+
+
+ this.setReader(this.reader);
+ },
+
+
+ read: function(operation, callback, scope) {
+ var me = this,
+ reader = me.getReader(),
+ result = reader.read(me.data);
+
+ Ext.apply(operation, {
+ resultSet: result
+ });
+
+ operation.setCompleted();
+ operation.setSuccessful();
+ Ext.callback(callback, scope || me, [operation]);
+ },
+
+ clear: Ext.emptyFn
+});
+
+
+Ext.define('Ext.data.proxy.Rest', {
+ extend: 'Ext.data.proxy.Ajax',
+ alternateClassName: 'Ext.data.RestProxy',
+ alias : 'proxy.rest',
+
+
+ appendId: true,
+
+
+
+
+ batchActions: false,
+
+
+ buildUrl: function(request) {
+ var me = this,
+ operation = request.operation,
+ records = operation.records || [],
+ record = records[0],
+ format = me.format,
+ url = me.getUrl(request),
+ id = record ? record.getId() : operation.id;
+
+ if (me.appendId && id) {
+ if (!url.match(/\/$/)) {
+ url += '/';
+ }
+
+ url += id;
+ }
+
+ if (format) {
+ if (!url.match(/\.$/)) {
+ url += '.';
+ }
+
+ url += format;
+ }
+
+ request.url = url;
+
+ return me.callParent(arguments);
+ }
+}, function() {
+ Ext.apply(this.prototype, {
+
+ actionMethods: {
+ create : 'POST',
+ read : 'GET',
+ update : 'PUT',
+ destroy: 'DELETE'
+ }
+ });
+});
+
+
+Ext.define('Ext.data.proxy.SessionStorage', {
+ extend: 'Ext.data.proxy.WebStorage',
+ alias: 'proxy.sessionstorage',
+ alternateClassName: 'Ext.data.SessionStorageProxy',
+
+
+ getStorageObject: function() {
+ return window.sessionStorage;
+ }
+});
+
+
+Ext.define('Ext.data.reader.Array', {
+ extend: 'Ext.data.reader.Json',
+ alternateClassName: 'Ext.data.ArrayReader',
+ alias : 'reader.array',
+
+
+ buildExtractors: function() {
+ this.callParent(arguments);
+
+ var fields = this.model.prototype.fields.items,
+ length = fields.length,
+ extractorFunctions = [],
+ i;
+
+ for (i = 0; i < length; i++) {
+ extractorFunctions.push(function(index) {
+ return function(data) {
+ return data[index];
+ };
+ }(fields[i].mapping || i));
+ }
+
+ this.extractorFunctions = extractorFunctions;
+ }
+});
+
+
+Ext.define('Ext.data.reader.Xml', {
+ extend: 'Ext.data.reader.Reader',
+ alternateClassName: 'Ext.data.XmlReader',
+ alias : 'reader.xml',
+
+
+
+
+
+ createAccessor: function() {
+ var selectValue = function(expr, root){
+ var node = Ext.DomQuery.selectNode(expr, root),
+ val;
+
+
+
+ };
+
+ return function(expr) {
+ var me = this;
+
+ if (Ext.isEmpty(expr)) {
+ return Ext.emptyFn;
+ }
+
+ if (Ext.isFunction(expr)) {
+ return expr;
+ }
+
+ return function(root) {
+ var node = Ext.DomQuery.selectNode(expr, root),
+ val = me.getNodeValue(node);
+
+ return Ext.isEmpty(val) ? null : val;
+ };
+ };
+ }(),
+
+ getNodeValue: function(node) {
+ var val;
+ if (node && node.firstChild) {
+ val = node.firstChild.nodeValue;
+ }
+ return val || null;
+ },
+
+
+ getResponseData: function(response) {
+ var xml = response.responseXML;
+
+ if (!xml) {
+ Ext.Error.raise({
+ response: response,
+ msg: 'XML data not found in the response'
+ });
+ }
+
+ return xml;
+ },
+
+
+ getData: function(data) {
+ return data.documentElement || data;
+ },
+
+
+ getRoot: function(data) {
+ var nodeName = data.nodeName,
+ root = this.root;
+
+ if (!root || (nodeName && nodeName == root)) {
+ return data;
+ } else if (Ext.DomQuery.isXml(data)) {
+
+
+
+ return Ext.DomQuery.selectNode(root, data);
+ }
+ },
+
+
+ extractData: function(root) {
+ var recordName = this.record;
+
+ if (!recordName) {
+ Ext.Error.raise('Record is a required parameter');
+ }
+
+ if (recordName != root.nodeName) {
+ root = Ext.DomQuery.select(recordName, root);
+ } else {
+ root = [root];
+ }
+ return this.callParent([root]);
+ },
+
+
+ getAssociatedDataRoot: function(data, associationName) {
+ return Ext.DomQuery.select(associationName, data)[0];
+ },
+
+
+ readRecords: function(doc) {
+
+ if (Ext.isArray(doc)) {
+ doc = doc[0];
+ }
+
+
+ this.xmlData = doc;
+ return this.callParent([doc]);
+ }
+});
+
+
+Ext.define('Ext.data.writer.Xml', {
+
+
+
+ extend: 'Ext.data.writer.Writer',
+ alternateClassName: 'Ext.data.XmlWriter',
+
+ alias: 'writer.xml',
+
+
+
+
+ documentRoot: 'xmlData',
+
+
+ defaultDocumentRoot: 'xmlData',
+
+
+ header: '',
+
+
+ record: 'record',
+
+
+ writeRecords: function(request, data) {
+ var me = this,
+ xml = [],
+ i = 0,
+ len = data.length,
+ root = me.documentRoot,
+ record = me.record,
+ needsRoot = data.length !== 1,
+ item,
+ key;
+
+
+ xml.push(me.header || '');
+
+ if (!root && needsRoot) {
+ root = me.defaultDocumentRoot;
+ }
+
+ if (root) {
+ xml.push('<', root, '>');
+ }
+
+ for (; i < len; ++i) {
+ item = data[i];
+ xml.push('<', record, '>');
+ for (key in item) {
+ if (item.hasOwnProperty(key)) {
+ xml.push('<', key, '>', item[key], '</', key, '>');
+ }
+ }
+ xml.push('</', record, '>');
+ }
+
+ if (root) {
+ xml.push('</', root, '>');
+ }
+
+ request.xmlData = xml.join('');
+ return request;
+ }
+});
+
+
+Ext.define('Ext.direct.Event', {
+
+
+
+ alias: 'direct.event',
+
+ requires: ['Ext.direct.Manager'],
+
+
+
+ status: true,
+
+ constructor: function(config) {
+ Ext.apply(this, config);
+ },
+
+
+ getData: function(){
+ return this.data;
+ }
+});
+
+
+Ext.define('Ext.direct.RemotingEvent', {
+
+
+
+ extend: 'Ext.direct.Event',
+
+ alias: 'direct.rpc',
+
+
+
+
+ getTransaction: function(){
+ return this.transaction || Ext.direct.Manager.getTransaction(this.tid);
+ }
+});
+
+
+Ext.define('Ext.direct.ExceptionEvent', {
+
+
+
+ extend: 'Ext.direct.RemotingEvent',
+
+ alias: 'direct.exception',
+
+
+
+ status: false
+});
+
+
+Ext.define('Ext.direct.Provider', {
+
+
+
+ alias: 'direct.provider',
+
+ mixins: {
+ observable: 'Ext.util.Observable'
+ },
+
+
+
+
+
+ constructor : function(config){
+ var me = this;
+
+ Ext.apply(me, config);
+ me.addEvents(
+
+ 'connect',
+
+ 'disconnect',
+
+ 'data',
+
+ 'exception'
+ );
+ me.mixins.observable.constructor.call(me, config);
+ },
+
+
+ isConnected: function(){
+ return false;
+ },
+
+
+ connect: Ext.emptyFn,
+
+
+ disconnect: Ext.emptyFn
+});
+
+
+
+Ext.define('Ext.direct.JsonProvider', {
+
+
+
+ extend: 'Ext.direct.Provider',
+
+ alias: 'direct.jsonprovider',
+
+ uses: ['Ext.direct.ExceptionEvent'],
+
+
+
+
+ parseResponse: function(response){
+ if (!Ext.isEmpty(response.responseText)) {
+ if (Ext.isObject(response.responseText)) {
+ return response.responseText;
+ }
+ return Ext.decode(response.responseText);
+ }
+ return null;
+ },
+
+
+ createEvents: function(response){
+ var data = null,
+ events = [],
+ event,
+ i = 0,
+ len;
+
+ try{
+ data = this.parseResponse(response);
+ } catch(e) {
+ event = Ext.create('Ext.direct.ExceptionEvent', {
+ data: e,
+ xhr: response,
+ code: Ext.direct.Manager.self.exceptions.PARSE,
+ message: 'Error parsing json response: \n\n ' + data
+ });
+ return [event];
+ }
+
+ if (Ext.isArray(data)) {
+ for (len = data.length; i < len; ++i) {
+ events.push(this.createEvent(data[i]));
+ }
+ } else {
+ events.push(this.createEvent(data));
+ }
+ return events;
+ },
+
+
+ createEvent: function(response){
+ return Ext.create('direct.' + response.type, response);
+ }
+});
+
+Ext.define('Ext.direct.PollingProvider', {
+
+
+
+ extend: 'Ext.direct.JsonProvider',
+
+ alias: 'direct.pollingprovider',
+
+ uses: ['Ext.direct.ExceptionEvent'],
+
+ requires: ['Ext.Ajax', 'Ext.util.DelayedTask'],
+
+
+
+
+ interval: 3000,
+
+
+
+
+
+
+ constructor : function(config){
+ this.callParent(arguments);
+ this.addEvents(
+
+ 'beforepoll',
+
+ 'poll'
+ );
+ },
+
+
+ isConnected: function(){
+ return !!this.pollTask;
+ },
+
+
+ connect: function(){
+ var me = this, url = me.url;
+
+ if (url && !me.pollTask) {
+ me.pollTask = Ext.TaskManager.start({
+ run: function(){
+ if (me.fireEvent('beforepoll', me) !== false) {
+ if (Ext.isFunction(url)) {
+ url(me.baseParams);
+ } else {
+ Ext.Ajax.request({
+ url: url,
+ callback: me.onData,
+ scope: me,
+ params: me.baseParams
+ });
+ }
+ }
+ },
+ interval: me.interval,
+ scope: me
+ });
+ me.fireEvent('connect', me);
+ } else if (!url) {
+ Ext.Error.raise('Error initializing PollingProvider, no url configured.');
+ }
+ },
+
+
+ disconnect: function(){
+ var me = this;
+
+ if (me.pollTask) {
+ Ext.TaskManager.stop(me.pollTask);
+ delete me.pollTask;
+ me.fireEvent('disconnect', me);
+ }
+ },
+
+
+ onData: function(opt, success, response){
+ var me = this,
+ i = 0,
+ len,
+ events;
+
+ if (success) {
+ events = me.createEvents(response);
+ for (len = events.length; i < len; ++i) {
+ me.fireEvent('data', me, events[i]);
+ }
+ } else {
+ me.fireEvent('data', me, Ext.create('Ext.direct.ExceptionEvent', {
+ data: null,
+ code: Ext.direct.Manager.self.exceptions.TRANSPORT,
+ message: 'Unable to connect to the server.',
+ xhr: response
+ }));
+ }
+ }
+});
+
+Ext.define('Ext.direct.RemotingMethod', {
+
+ constructor: function(config){
+ var me = this,
+ params = Ext.isDefined(config.params) ? config.params : config.len,
+ name;
+
+ me.name = config.name;
+ me.formHandler = config.formHandler;
+ if (Ext.isNumber(params)) {
+
+ me.len = params;
+ me.ordered = true;
+ } else {
+
+ me.params = [];
+ Ext.each(params, function(param){
+ name = Ext.isObject(param) ? param.name : param;
+ me.params.push(name);
+ });
+ }
+ },
+
+
+ getCallData: function(args){
+ var me = this,
+ data = null,
+ len = me.len,
+ params = me.params,
+ callback,
+ scope,
+ name;
+
+ if (me.ordered) {
+ callback = args[len];
+ scope = args[len + 1];
+ if (len !== 0) {
+ data = args.slice(0, len);
+ }
+ } else {
+ data = Ext.apply({}, args[0]);
+ callback = args[1];
+ scope = args[2];
+
+
+ for (name in data) {
+ if (data.hasOwnProperty(name)) {
+ if (!Ext.Array.contains(params, name)) {
+ delete data[name];
+ }
+ }
+ }
+ }
+
+ return {
+ data: data,
+ callback: callback,
+ scope: scope
+ };
+ }
+});
+
+
+Ext.define('Ext.direct.Transaction', {
+
+
+
+ alias: 'direct.transaction',
+ alternateClassName: 'Ext.Direct.Transaction',
+
+ statics: {
+ TRANSACTION_ID: 0
+ },
+
+
+
+ constructor: function(config){
+ var me = this;
+
+ Ext.apply(me, config);
+ me.id = ++me.self.TRANSACTION_ID;
+ me.retryCount = 0;
+ },
+
+ send: function(){
+ this.provider.queueTransaction(this);
+ },
+
+ retry: function(){
+ this.retryCount++;
+ this.send();
+ },
+
+ getProvider: function(){
+ return this.provider;
+ }
+});
+
+
+Ext.define('Ext.direct.RemotingProvider', {
+
+
+
+ alias: 'direct.remotingprovider',
+
+ extend: 'Ext.direct.JsonProvider',
+
+ requires: [
+ 'Ext.util.MixedCollection',
+ 'Ext.util.DelayedTask',
+ 'Ext.direct.Transaction',
+ 'Ext.direct.RemotingMethod'
+ ],
+
+
+
+
+
+
+
+
+
+
+
+
+ enableBuffer: 10,
+
+
+ maxRetries: 1,
+
+
+ timeout: undefined,
+
+ constructor : function(config){
+ var me = this;
+ me.callParent(arguments);
+ me.addEvents(
+
+ 'beforecall',
+
+ 'call'
+ );
+ me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || window;
+ me.transactions = Ext.create('Ext.util.MixedCollection');
+ me.callBuffer = [];
+ },
+
+
+ initAPI : function(){
+ var actions = this.actions,
+ namespace = this.namespace,
+ action,
+ cls,
+ methods,
+ i,
+ len,
+ method;
+
+ for (action in actions) {
+ cls = namespace[action];
+ if (!cls) {
+ cls = namespace[action] = {};
+ }
+ methods = actions[action];
+
+ for (i = 0, len = methods.length; i < len; ++i) {
+ method = Ext.create('Ext.direct.RemotingMethod', methods[i]);
+ cls[method.name] = this.createHandler(action, method);
+ }
+ }
+ },
+
+
+ createHandler : function(action, method){
+ var me = this,
+ handler;
+
+ if (!method.formHandler) {
+ handler = function(){
+ me.configureRequest(action, method, Array.prototype.slice.call(arguments, 0));
+ };
+ } else {
+ handler = function(form, callback, scope){
+ me.configureFormRequest(action, method, form, callback, scope);
+ };
+ }
+ handler.directCfg = {
+ action: action,
+ method: method
+ };
+ return handler;
+ },
+
+
+ isConnected: function(){
+ return !!this.connected;
+ },
+
+
+ connect: function(){
+ var me = this;
+
+ if (me.url) {
+ me.initAPI();
+ me.connected = true;
+ me.fireEvent('connect', me);
+ } else if(!me.url) {
+ Ext.Error.raise('Error initializing RemotingProvider, no url configured.');
+ }
+ },
+
+
+ disconnect: function(){
+ var me = this;
+
+ if (me.connected) {
+ me.connected = false;
+ me.fireEvent('disconnect', me);
+ }
+ },
+
+
+ runCallback: function(transaction, event){
+ var funcName = event.status ? 'success' : 'failure',
+ callback,
+ result;
+
+ if (transaction && transaction.callback) {
+ callback = transaction.callback;
+ result = Ext.isDefined(event.result) ? event.result : event.data;
+
+ if (Ext.isFunction(callback)) {
+ callback(result, event);
+ } else {
+ Ext.callback(callback[funcName], callback.scope, [result, event]);
+ Ext.callback(callback.callback, callback.scope, [result, event]);
+ }
+ }
+ },
+
+
+ onData: function(options, success, response){
+ var me = this,
+ i = 0,
+ len,
+ events,
+ event,
+ transaction,
+ transactions;
+
+ if (success) {
+ events = me.createEvents(response);
+ for (len = events.length; i < len; ++i) {
+ event = events[i];
+ transaction = me.getTransaction(event);
+ me.fireEvent('data', me, event);
+ if (transaction) {
+ me.runCallback(transaction, event, true);
+ Ext.direct.Manager.removeTransaction(transaction);
+ }
+ }
+ } else {
+ transactions = [].concat(options.transaction);
+ for (len = transactions.length; i < len; ++i) {
+ transaction = me.getTransaction(transactions[i]);
+ if (transaction && transaction.retryCount < me.maxRetries) {
+ transaction.retry();
+ } else {
+ event = Ext.create('Ext.direct.ExceptionEvent', {
+ data: null,
+ transaction: transaction,
+ code: Ext.direct.Manager.self.exceptions.TRANSPORT,
+ message: 'Unable to connect to the server.',
+ xhr: response
+ });
+ me.fireEvent('data', me, event);
+ if (transaction) {
+ me.runCallback(transaction, event, false);
+ Ext.direct.Manager.removeTransaction(transaction);
+ }
+ }
+ }
+ }
+ },
+
+
+ getTransaction: function(options){
+ return options && options.tid ? Ext.direct.Manager.getTransaction(options.tid) : null;
+ },
+
+
+ configureRequest: function(action, method, args){
+ var me = this,
+ callData = method.getCallData(args),
+ data = callData.data,
+ callback = callData.callback,
+ scope = callData.scope,
+ transaction;
+
+ transaction = Ext.create('Ext.direct.Transaction', {
+ provider: me,
+ args: args,
+ action: action,
+ method: method.name,
+ data: data,
+ callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback
+ });
+
+ if (me.fireEvent('beforecall', me, transaction, method) !== false) {
+ Ext.direct.Manager.addTransaction(transaction);
+ me.queueTransaction(transaction);
+ me.fireEvent('call', me, transaction, method);
+ }
+ },
+
+
+ getCallData: function(transaction){
+ return {
+ action: transaction.action,
+ method: transaction.method,
+ data: transaction.data,
+ type: 'rpc',
+ tid: transaction.id
+ };
+ },
+
+
+ sendRequest : function(data){
+ var me = this,
+ request = {
+ url: me.url,
+ callback: me.onData,
+ scope: me,
+ transaction: data,
+ timeout: me.timeout
+ }, callData,
+ enableUrlEncode = me.enableUrlEncode,
+ i = 0,
+ len,
+ params;
+
+
+ if (Ext.isArray(data)) {
+ callData = [];
+ for (len = data.length; i < len; ++i) {
+ callData.push(me.getCallData(data[i]));
+ }
+ } else {
+ callData = me.getCallData(data);
+ }
+
+ if (enableUrlEncode) {
+ params = {};
+ params[Ext.isString(enableUrlEncode) ? enableUrlEncode : 'data'] = Ext.encode(callData);
+ request.params = params;
+ } else {
+ request.jsonData = callData;
+ }
+ Ext.Ajax.request(request);
+ },
+
+
+ queueTransaction: function(transaction){
+ var me = this,
+ enableBuffer = me.enableBuffer;
+
+ if (transaction.form) {
+ me.sendFormRequest(transaction);
+ return;
+ }
+
+ me.callBuffer.push(transaction);
+ if (enableBuffer) {
+ if (!me.callTask) {
+ me.callTask = Ext.create('Ext.util.DelayedTask', me.combineAndSend, me);
+ }
+ me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10);
+ } else {
+ me.combineAndSend();
+ }
+ },
+
+
+ combineAndSend : function(){
+ var buffer = this.callBuffer,
+ len = buffer.length;
+
+ if (len > 0) {
+ this.sendRequest(len == 1 ? buffer[0] : buffer);
+ this.callBuffer = [];
+ }
+ },
+
+
+ configureFormRequest : function(action, method, form, callback, scope){
+ var me = this,
+ transaction = Ext.create('Ext.direct.Transaction', {
+ provider: me,
+ action: action,
+ method: method.name,
+ args: [form, callback, scope],
+ callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback,
+ isForm: true
+ }),
+ isUpload,
+ params;
+
+ if (me.fireEvent('beforecall', me, transaction, method) !== false) {
+ Ext.direct.Manager.addTransaction(transaction);
+ isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data';
+
+ params = {
+ extTID: transaction.id,
+ extAction: action,
+ extMethod: method.name,
+ extType: 'rpc',
+ extUpload: String(isUpload)
+ };
+
+
+
+ Ext.apply(transaction, {
+ form: Ext.getDom(form),
+ isUpload: isUpload,
+ params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
+ });
+ me.fireEvent('call', me, transaction, method);
+ me.sendFormRequest(transaction);
+ }
+ },
+
+
+ sendFormRequest: function(transaction){
+ Ext.Ajax.request({
+ url: this.url,
+ params: transaction.params,
+ callback: this.onData,
+ scope: this,
+ form: transaction.form,
+ isUpload: transaction.isUpload,
+ transaction: transaction
+ });
+ }
+
+});
+
+
+Ext.define('Ext.draw.Matrix', {
+
+
+
+ requires: ['Ext.draw.Draw'],
+
+
+
+ constructor: function(a, b, c, d, e, f) {
+ if (a != null) {
+ this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]];
+ }
+ else {
+ this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
+ }
+ },
+
+ add: function(a, b, c, d, e, f) {
+ var me = this,
+ out = [[], [], []],
+ matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
+ x,
+ y,
+ z,
+ res;
+
+ for (x = 0; x < 3; x++) {
+ for (y = 0; y < 3; y++) {
+ res = 0;
+ for (z = 0; z < 3; z++) {
+ res += me.matrix[x][z] * matrix[z][y];
+ }
+ out[x][y] = res;
+ }
+ }
+ me.matrix = out;
+ },
+
+ prepend: function(a, b, c, d, e, f) {
+ var me = this,
+ out = [[], [], []],
+ matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
+ x,
+ y,
+ z,
+ res;
+
+ for (x = 0; x < 3; x++) {
+ for (y = 0; y < 3; y++) {
+ res = 0;
+ for (z = 0; z < 3; z++) {
+ res += matrix[x][z] * me.matrix[z][y];
+ }
+ out[x][y] = res;
+ }
+ }
+ me.matrix = out;
+ },
+
+ invert: function() {
+ var matrix = this.matrix,
+ a = matrix[0][0],
+ b = matrix[1][0],
+ c = matrix[0][1],
+ d = matrix[1][1],
+ e = matrix[0][2],
+ f = matrix[1][2],
+ x = a * d - b * c;
+ return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x);
+ },
+
+ clone: function() {
+ var matrix = this.matrix,
+ a = matrix[0][0],
+ b = matrix[1][0],
+ c = matrix[0][1],
+ d = matrix[1][1],
+ e = matrix[0][2],
+ f = matrix[1][2];
+ return new Ext.draw.Matrix(a, b, c, d, e, f);
+ },
+
+ translate: function(x, y) {
+ this.prepend(1, 0, 0, 1, x, y);
+ },
+
+ scale: function(x, y, cx, cy) {
+ var me = this;
+ if (y == null) {
+ y = x;
+ }
+ me.add(1, 0, 0, 1, cx, cy);
+ me.add(x, 0, 0, y, 0, 0);
+ me.add(1, 0, 0, 1, -cx, -cy);
+ },
+
+ rotate: function(a, x, y) {
+ a = Ext.draw.Draw.rad(a);
+ var me = this,
+ cos = +Math.cos(a).toFixed(9),
+ sin = +Math.sin(a).toFixed(9);
+ me.add(cos, sin, -sin, cos, x, y);
+ me.add(1, 0, 0, 1, -x, -y);
+ },
+
+ x: function(x, y) {
+ var matrix = this.matrix;
+ return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2];
+ },
+
+ y: function(x, y) {
+ var matrix = this.matrix;
+ return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2];
+ },
+
+ get: function(i, j) {
+ return + this.matrix[i][j].toFixed(4);
+ },
+
+ toString: function() {
+ var me = this;
+ return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join();
+ },
+
+ toSvg: function() {
+ var me = this;
+ return "matrix(" + [me.get(0, 0), me.get(1, 0), me.get(0, 1), me.get(1, 1), me.get(0, 2), me.get(1, 2)].join() + ")";
+ },
+
+ toFilter: function() {
+ var me = this;
+ return "progid:DXImageTransform.Microsoft.Matrix(M11=" + me.get(0, 0) +
+ ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) +
+ ", Dx=" + me.get(0, 2) + ", Dy=" + me.get(1, 2) + ")";
+ },
+
+ offset: function() {
+ var matrix = this.matrix;
+ return [matrix[0][2].toFixed(4), matrix[1][2].toFixed(4)];
+ },
+
+
+ split: function () {
+ function norm(a) {
+ return a[0] * a[0] + a[1] * a[1];
+ }
+ function normalize(a) {
+ var mag = Math.sqrt(norm(a));
+ a[0] /= mag;
+ a[1] /= mag;
+ }
+ var matrix = this.matrix,
+ out = {
+ translateX: matrix[0][2],
+ translateY: matrix[1][2]
+ },
+ row;
+
+
+ row = [[matrix[0][0], matrix[0][1]], [matrix[1][1], matrix[1][1]]];
+ out.scaleX = Math.sqrt(norm(row[0]));
+ normalize(row[0]);
+
+ out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
+ row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
+
+ out.scaleY = Math.sqrt(norm(row[1]));
+ normalize(row[1]);
+ out.shear /= out.scaleY;
+
+
+ out.rotate = Math.asin(-row[0][1]);
+
+ out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate);
+
+ return out;
+ }
+});
+
+Ext.define('Ext.draw.SpriteDD', {
+ extend: 'Ext.dd.DragSource',
+
+ constructor : function(sprite, cfg){
+ var me = this,
+ el = sprite.el;
+ me.sprite = sprite;
+ me.el = el;
+ me.dragData = {el: el, sprite: sprite};
+ me.callParent([el, cfg]);
+ me.sprite.setStyle('cursor', 'move');
+ },
+
+ showFrame: Ext.emptyFn,
+ createFrame : Ext.emptyFn,
+
+ getDragEl : function(e){
+ return this.el;
+ },
+
+ getRegion: function() {
+ var me = this,
+ el = me.el,
+ pos, x1, x2, y1, y2, t, r, b, l, bbox, sprite;
+
+ sprite = me.sprite;
+ bbox = sprite.getBBox();
+
+ try {
+ pos = Ext.core.Element.getXY(el);
+ } catch (e) { }
+
+ if (!pos) {
+ return null;
+ }
+
+ x1 = pos[0];
+ x2 = x1 + bbox.width;
+ y1 = pos[1];
+ y2 = y1 + bbox.height;
+
+ return Ext.create('Ext.util.Region', y1, x2, y2, x1);
+ },
+
+
+
+ startDrag: function(x, y) {
+ var me = this,
+ attr = me.sprite.attr,
+ trans = attr.translation;
+ if (me.sprite.vml) {
+ me.prevX = x + attr.x;
+ me.prevY = y + attr.y;
+ } else {
+ me.prevX = x - trans.x;
+ me.prevY = y - trans.y;
+ }
+ },
+
+ onDrag: function(e) {
+ var xy = e.getXY(),
+ me = this,
+ sprite = me.sprite,
+ attr = sprite.attr;
+ me.translateX = xy[0] - me.prevX;
+ me.translateY = xy[1] - me.prevY;
+ sprite.setAttributes({
+ translate: {
+ x: me.translateX,
+ y: me.translateY
+ }
+ }, true);
+ if (sprite.vml) {
+ me.prevX = xy[0] + attr.x || 0;
+ me.prevY = xy[1] + attr.y || 0;
+ }
+ }
+});
+
+Ext.define('Ext.draw.Sprite', {
+
+
+ mixins: {
+ observable: 'Ext.util.Observable',
+ animate: 'Ext.util.Animate'
+ },
+
+ requires: ['Ext.draw.SpriteDD'],
+
+
+
+ dirty: false,
+ dirtyHidden: false,
+ dirtyTransform: false,
+ dirtyPath: true,
+ dirtyFont: true,
+ zIndexDirty: true,
+ isSprite: true,
+ zIndex: 0,
+ fontProperties: [
+ 'font',
+ 'font-size',
+ 'font-weight',
+ 'font-style',
+ 'font-family',
+ 'text-anchor',
+ 'text'
+ ],
+ pathProperties: [
+ 'x',
+ 'y',
+ 'd',
+ 'path',
+ 'height',
+ 'width',
+ 'radius',
+ 'r',
+ 'rx',
+ 'ry',
+ 'cx',
+ 'cy'
+ ],
+ constructor: function(config) {
+ var me = this;
+ config = config || {};
+ me.id = Ext.id(null, 'ext-sprite-');
+ me.transformations = [];
+ Ext.copyTo(this, config, 'surface,group,type,draggable');
+
+ me.bbox = {};
+ me.attr = {
+ zIndex: 0,
+ translation: {
+ x: null,
+ y: null
+ },
+ rotation: {
+ degrees: null,
+ x: null,
+ y: null
+ },
+ scaling: {
+ x: null,
+ y: null,
+ cx: null,
+ cy: null
+ }
+ };
+
+ delete config.surface;
+ delete config.group;
+ delete config.type;
+ delete config.draggable;
+ me.setAttributes(config);
+ me.addEvents(
+ 'beforedestroy',
+ 'destroy',
+ 'render',
+ 'mousedown',
+ 'mouseup',
+ 'mouseover',
+ 'mouseout',
+ 'mousemove',
+ 'click'
+ );
+ me.mixins.observable.constructor.apply(this, arguments);
+ },
+
+
+ initDraggable: function() {
+ var me = this;
+ me.draggable = true;
+
+ if (!me.el) {
+ me.surface.createSprite(me);
+ }
+ me.dd = Ext.create('Ext.draw.SpriteDD', me, Ext.isBoolean(me.draggable) ? null : me.draggable);
+ me.on('beforedestroy', me.dd.destroy, me.dd);
+ },
+
+
+ setAttributes: function(attrs, redraw) {
+ var me = this,
+ fontProps = me.fontProperties,
+ fontPropsLength = fontProps.length,
+ pathProps = me.pathProperties,
+ pathPropsLength = pathProps.length,
+ hasSurface = !!me.surface,
+ custom = hasSurface && me.surface.customAttributes || {},
+ spriteAttrs = me.attr,
+ attr, i, translate, translation, rotate, rotation, scale, scaling;
+
+ for (attr in custom) {
+ if (attrs.hasOwnProperty(attr) && typeof custom[attr] == "function") {
+ Ext.apply(attrs, custom[attr].apply(me, [].concat(attrs[attr])));
+ }
+ }
+
+
+ if (!!attrs.hidden !== !!spriteAttrs.hidden) {
+ me.dirtyHidden = true;
+ }
+
+
+ for (i = 0; i < pathPropsLength; i++) {
+ attr = pathProps[i];
+ if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
+ me.dirtyPath = true;
+ break;
+ }
+ }
+
+
+ if ('zIndex' in attrs) {
+ me.zIndexDirty = true;
+ }
+
+
+ for (i = 0; i < fontPropsLength; i++) {
+ attr = fontProps[i];
+ if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
+ me.dirtyFont = true;
+ break;
+ }
+ }
+
+ translate = attrs.translate;
+ translation = spriteAttrs.translation;
+ if (translate) {
+ if ((translate.x && translate.x !== translation.x) ||
+ (translate.y && translate.y !== translation.y)) {
+ Ext.apply(translation, translate);
+ me.dirtyTransform = true;
+ }
+ delete attrs.translate;
+ }
+
+ rotate = attrs.rotate;
+ rotation = spriteAttrs.rotation;
+ if (rotate) {
+ if ((rotate.x && rotate.x !== rotation.x) ||
+ (rotate.y && rotate.y !== rotation.y) ||
+ (rotate.degrees && rotate.degrees !== rotation.degrees)) {
+ Ext.apply(rotation, rotate);
+ me.dirtyTransform = true;
+ }
+ delete attrs.rotate;
+ }
+
+ scale = attrs.scale;
+ scaling = spriteAttrs.scaling;
+ if (scale) {
+ if ((scale.x && scale.x !== scaling.x) ||
+ (scale.y && scale.y !== scaling.y) ||
+ (scale.cx && scale.cx !== scaling.cx) ||
+ (scale.cy && scale.cy !== scaling.cy)) {
+ Ext.apply(scaling, scale);
+ me.dirtyTransform = true;
+ }
+ delete attrs.scale;
+ }
+
+ Ext.apply(spriteAttrs, attrs);
+ me.dirty = true;
+
+ if (redraw === true && hasSurface) {
+ me.redraw();
+ }
+ return this;
+ },
+
+
+ getBBox: function() {
+ return this.surface.getBBox(this);
+ },
+
+ setText: function(text) {
+ return this.surface.setText(this, text);
+ },
+
+
+ hide: function(redraw) {
+ this.setAttributes({
+ hidden: true
+ }, redraw);
+ return this;
+ },
+
+
+ show: function(redraw) {
+ this.setAttributes({
+ hidden: false
+ }, redraw);
+ return this;
+ },
+
+
+ remove: function() {
+ if (this.surface) {
+ this.surface.remove(this);
+ return true;
+ }
+ return false;
+ },
+
+ onRemove: function() {
+ this.surface.onRemove(this);
+ },
+
+
+ destroy: function() {
+ var me = this;
+ if (me.fireEvent('beforedestroy', me) !== false) {
+ me.remove();
+ me.surface.onDestroy(me);
+ me.clearListeners();
+ me.fireEvent('destroy');
+ }
+ },
+
+
+ redraw: function() {
+ this.surface.renderItem(this);
+ return this;
+ },
+
+
+ setStyle: function() {
+ this.el.setStyle.apply(this.el, arguments);
+ return this;
+ },
+
+
+ addCls: function(obj) {
+ this.surface.addCls(this, obj);
+ return this;
+ },
+
+
+ removeCls: function(obj) {
+ this.surface.removeCls(this, obj);
+ return this;
+ }
+});
+
+
+Ext.define('Ext.draw.engine.Svg', {
+
+
+
+ extend: 'Ext.draw.Surface',
+
+ requires: ['Ext.draw.Draw', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.core.Element'],
+
+
+
+ engine: 'Svg',
+
+ trimRe: /^\s+|\s+$/g,
+ spacesRe: /\s+/,
+ xlink: "http:/" + "/www.w3.org/1999/xlink",
+
+ translateAttrs: {
+ radius: "r",
+ radiusX: "rx",
+ radiusY: "ry",
+ path: "d",
+ lineWidth: "stroke-width",
+ fillOpacity: "fill-opacity",
+ strokeOpacity: "stroke-opacity",
+ strokeLinejoin: "stroke-linejoin"
+ },
+
+ minDefaults: {
+ circle: {
+ cx: 0,
+ cy: 0,
+ r: 0,
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ ellipse: {
+ cx: 0,
+ cy: 0,
+ rx: 0,
+ ry: 0,
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ rect: {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ rx: 0,
+ ry: 0,
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ text: {
+ x: 0,
+ y: 0,
+ "text-anchor": "start",
+ "font-family": null,
+ "font-size": null,
+ "font-weight": null,
+ "font-style": null,
+ fill: "#000",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ path: {
+ d: "M0,0",
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ image: {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ preserveAspectRatio: "none",
+ opacity: null
+ }
+ },
+
+ createSvgElement: function(type, attrs) {
+ var el = this.domRef.createElementNS("http:/" + "/www.w3.org/2000/svg", type),
+ key;
+ if (attrs) {
+ for (key in attrs) {
+ el.setAttribute(key, String(attrs[key]));
+ }
+ }
+ return el;
+ },
+
+ createSpriteElement: function(sprite) {
+
+ var el = this.createSvgElement(sprite.type);
+ el.id = sprite.id;
+ if (el.style) {
+ el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
+ }
+ sprite.el = Ext.get(el);
+ this.applyZIndex(sprite);
+ sprite.matrix = Ext.create('Ext.draw.Matrix');
+ sprite.bbox = {
+ plain: 0,
+ transform: 0
+ };
+ sprite.fireEvent("render", sprite);
+ return el;
+ },
+
+ getBBox: function (sprite, isWithoutTransform) {
+ var realPath = this["getPath" + sprite.type](sprite);
+ if (isWithoutTransform) {
+ sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
+ return sprite.bbox.plain;
+ }
+ sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
+ return sprite.bbox.transform;
+ },
+
+ getBBoxText: function (sprite) {
+ var bbox = {},
+ bb, height, width, i, ln, el;
+
+ if (sprite && sprite.el) {
+ el = sprite.el.dom;
+ try {
+ bbox = el.getBBox();
+ return bbox;
+ } catch(e) {
+
+ }
+ bbox = {x: bbox.x, y: Infinity, width: 0, height: 0};
+ ln = el.getNumberOfChars();
+ for (i = 0; i < ln; i++) {
+ bb = el.getExtentOfChar(i);
+ bbox.y = Math.min(bb.y, bbox.y);
+ height = bb.y + bb.height - bbox.y;
+ bbox.height = Math.max(bbox.height, height);
+ width = bb.x + bb.width - bbox.x;
+ bbox.width = Math.max(bbox.width, width);
+ }
+ return bbox;
+ }
+ },
+
+ hide: function() {
+ Ext.get(this.el).hide();
+ },
+
+ show: function() {
+ Ext.get(this.el).show();
+ },
+
+ hidePrim: function(sprite) {
+ this.addCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
+ },
+
+ showPrim: function(sprite) {
+ this.removeCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
+ },
+
+ getDefs: function() {
+ return this._defs || (this._defs = this.createSvgElement("defs"));
+ },
+
+ transform: function(sprite) {
+ var me = this,
+ matrix = Ext.create('Ext.draw.Matrix'),
+ transforms = sprite.transformations,
+ transformsLength = transforms.length,
+ i = 0,
+ transform, type;
+
+ for (; i < transformsLength; i++) {
+ transform = transforms[i];
+ type = transform.type;
+ if (type == "translate") {
+ matrix.translate(transform.x, transform.y);
+ }
+ else if (type == "rotate") {
+ matrix.rotate(transform.degrees, transform.x, transform.y);
+ }
+ else if (type == "scale") {
+ matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
+ }
+ }
+ sprite.matrix = matrix;
+ sprite.el.set({transform: matrix.toSvg()});
+ },
+
+ setSize: function(w, h) {
+ var me = this,
+ el = me.el;
+
+ w = +w || me.width;
+ h = +h || me.height;
+ me.width = w;
+ me.height = h;
+
+ el.setSize(w, h);
+ el.set({
+ width: w,
+ height: h
+ });
+ me.callParent([w, h]);
+ },
+
+
+ getRegion: function() {
+
+
+ var svgXY = this.el.getXY(),
+ rectXY = this.bgRect.getXY(),
+ max = Math.max,
+ x = max(svgXY[0], rectXY[0]),
+ y = max(svgXY[1], rectXY[1]);
+ return {
+ left: x,
+ top: y,
+ right: x + this.width,
+ bottom: y + this.height
+ };
+ },
+
+ onRemove: function(sprite) {
+ if (sprite.el) {
+ sprite.el.remove();
+ delete sprite.el;
+ }
+ this.callParent(arguments);
+ },
+
+ setViewBox: function(x, y, width, height) {
+ if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) {
+ this.callParent(arguments);
+ this.el.dom.setAttribute("viewBox", [x, y, width, height].join(" "));
+ }
+ },
+
+ render: function (container) {
+ var me = this;
+ if (!me.el) {
+ var width = me.width || 10,
+ height = me.height || 10,
+ el = me.createSvgElement('svg', {
+ xmlns: "http:/" + "/www.w3.org/2000/svg",
+ version: 1.1,
+ width: width,
+ height: height
+ }),
+ defs = me.getDefs(),
+
+
+
+
+
+ bgRect = me.createSvgElement("rect", {
+ width: "100%",
+ height: "100%",
+ fill: "#000",
+ stroke: "none",
+ opacity: 0
+ }),
+ webkitRect;
+
+ if (Ext.isSafari3) {
+
+ webkitRect = me.createSvgElement("rect", {
+ x: -10,
+ y: -10,
+ width: "110%",
+ height: "110%",
+ fill: "none",
+ stroke: "#000"
+ });
+ }
+ el.appendChild(defs);
+ if (Ext.isSafari3) {
+ el.appendChild(webkitRect);
+ }
+ el.appendChild(bgRect);
+ container.appendChild(el);
+ me.el = Ext.get(el);
+ me.bgRect = Ext.get(bgRect);
+ if (Ext.isSafari3) {
+ me.webkitRect = Ext.get(webkitRect);
+ me.webkitRect.hide();
+ }
+ me.el.on({
+ scope: me,
+ mouseup: me.onMouseUp,
+ mousedown: me.onMouseDown,
+ mouseover: me.onMouseOver,
+ mouseout: me.onMouseOut,
+ mousemove: me.onMouseMove,
+ mouseenter: me.onMouseEnter,
+ mouseleave: me.onMouseLeave,
+ click: me.onClick
+ });
+ }
+ me.renderAll();
+ },
+
+
+ onMouseEnter: function(e) {
+ if (this.el.parent().getRegion().contains(e.getPoint())) {
+ this.fireEvent('mouseenter', e);
+ }
+ },
+
+
+ onMouseLeave: function(e) {
+ if (!this.el.parent().getRegion().contains(e.getPoint())) {
+ this.fireEvent('mouseleave', e);
+ }
+ },
+
+ processEvent: function(name, e) {
+ var target = e.getTarget(),
+ surface = this.surface,
+ sprite;
+
+ this.fireEvent(name, e);
+
+ if (target.nodeName == "tspan" && target.parentNode) {
+ target = target.parentNode;
+ }
+ sprite = this.items.get(target.id);
+ if (sprite) {
+ sprite.fireEvent(name, sprite, e);
+ }
+ },
+
+
+ tuneText: function (sprite, attrs) {
+ var el = sprite.el.dom,
+ tspans = [],
+ height, tspan, text, i, ln, texts, factor;
+
+ if (attrs.hasOwnProperty("text")) {
+ tspans = this.setText(sprite, attrs.text);
+ }
+
+ if (tspans.length) {
+ height = this.getBBoxText(sprite).height;
+ for (i = 0, ln = tspans.length; i < ln; i++) {
+
+
+ factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4;
+ tspans[i].setAttribute("dy", i ? height * 1.2 : height / factor);
+ }
+ sprite.dirty = true;
+ }
+ },
+
+ setText: function(sprite, textString) {
+ var me = this,
+ el = sprite.el.dom,
+ x = el.getAttribute("x"),
+ tspans = [],
+ height, tspan, text, i, ln, texts;
+
+ while (el.firstChild) {
+ el.removeChild(el.firstChild);
+ }
+
+ texts = String(textString).split("\n");
+ for (i = 0, ln = texts.length; i < ln; i++) {
+ text = texts[i];
+ if (text) {
+ tspan = me.createSvgElement("tspan");
+ tspan.appendChild(document.createTextNode(Ext.htmlDecode(text)));
+ tspan.setAttribute("x", x);
+ el.appendChild(tspan);
+ tspans[i] = tspan;
+ }
+ }
+ return tspans;
+ },
+
+ renderAll: function() {
+ this.items.each(this.renderItem, this);
+ },
+
+ renderItem: function (sprite) {
+ if (!this.el) {
+ return;
+ }
+ if (!sprite.el) {
+ this.createSpriteElement(sprite);
+ }
+ if (sprite.zIndexDirty) {
+ this.applyZIndex(sprite);
+ }
+ if (sprite.dirty) {
+ this.applyAttrs(sprite);
+ this.applyTransformations(sprite);
+ }
+ },
+
+ redraw: function(sprite) {
+ sprite.dirty = sprite.zIndexDirty = true;
+ this.renderItem(sprite);
+ },
+
+ applyAttrs: function (sprite) {
+ var me = this,
+ el = sprite.el,
+ group = sprite.group,
+ sattr = sprite.attr,
+ groups, i, ln, attrs, font, key, style, name, rect;
+
+ if (group) {
+ groups = [].concat(group);
+ ln = groups.length;
+ for (i = 0; i < ln; i++) {
+ group = groups[i];
+ me.getGroup(group).add(sprite);
+ }
+ delete sprite.group;
+ }
+ attrs = me.scrubAttrs(sprite) || {};
+
+
+ sprite.bbox.plain = 0;
+ sprite.bbox.transform = 0;
+ if (sprite.type == "circle" || sprite.type == "ellipse") {
+ attrs.cx = attrs.cx || attrs.x;
+ attrs.cy = attrs.cy || attrs.y;
+ }
+ else if (sprite.type == "rect") {
+ attrs.rx = attrs.ry = attrs.r;
+ }
+ else if (sprite.type == "path" && attrs.d) {
+ attrs.d = Ext.draw.Draw.pathToAbsolute(attrs.d);
+ }
+ sprite.dirtyPath = false;
+
+
+ if (attrs['clip-rect']) {
+ me.setClip(sprite, attrs);
+ delete attrs['clip-rect'];
+ }
+ if (sprite.type == 'text' && attrs.font && sprite.dirtyFont) {
+ el.set({ style: "font: " + attrs.font});
+ sprite.dirtyFont = false;
+ }
+ if (sprite.type == "image") {
+ el.dom.setAttributeNS(me.xlink, "href", attrs.src);
+ }
+ Ext.applyIf(attrs, me.minDefaults[sprite.type]);
+
+ if (sprite.dirtyHidden) {
+ (sattr.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
+ sprite.dirtyHidden = false;
+ }
+ for (key in attrs) {
+ if (attrs.hasOwnProperty(key) && attrs[key] != null) {
+ el.dom.setAttribute(key, String(attrs[key]));
+ }
+ }
+ if (sprite.type == 'text') {
+ me.tuneText(sprite, attrs);
+ }
+
+
+ style = sattr.style;
+ if (style) {
+ el.setStyle(style);
+ }
+
+ sprite.dirty = false;
+
+ if (Ext.isSafari3) {
+
+ me.webkitRect.show();
+ setTimeout(function () {
+ me.webkitRect.hide();
+ });
+ }
+ },
+
+ setClip: function(sprite, params) {
+ var me = this,
+ rect = params["clip-rect"],
+ clipEl, clipPath;
+ if (rect) {
+ if (sprite.clip) {
+ sprite.clip.parentNode.parentNode.removeChild(sprite.clip.parentNode);
+ }
+ clipEl = me.createSvgElement('clipPath');
+ clipPath = me.createSvgElement('rect');
+ clipEl.id = Ext.id(null, 'ext-clip-');
+ clipPath.setAttribute("x", rect.x);
+ clipPath.setAttribute("y", rect.y);
+ clipPath.setAttribute("width", rect.width);
+ clipPath.setAttribute("height", rect.height);
+ clipEl.appendChild(clipPath);
+ me.getDefs().appendChild(clipEl);
+ sprite.el.dom.setAttribute("clip-path", "url(#" + clipEl.id + ")");
+ sprite.clip = clipPath;
+ }
+
+
+
+
+
+
+ },
+
+
+ applyZIndex: function(sprite) {
+ var idx = this.normalizeSpriteCollection(sprite),
+ el = sprite.el,
+ prevEl;
+ if (this.el.dom.childNodes[idx + 2] !== el.dom) {
+ if (idx > 0) {
+
+ do {
+ prevEl = this.items.getAt(--idx).el;
+ } while (!prevEl && idx > 0);
+ }
+ el.insertAfter(prevEl || this.bgRect);
+ }
+ sprite.zIndexDirty = false;
+ },
+
+ createItem: function (config) {
+ var sprite = Ext.create('Ext.draw.Sprite', config);
+ sprite.surface = this;
+ return sprite;
+ },
+
+ addGradient: function(gradient) {
+ gradient = Ext.draw.Draw.parseGradient(gradient);
+ var ln = gradient.stops.length,
+ vector = gradient.vector,
+ gradientEl,
+ stop,
+ stopEl,
+ i;
+ if (gradient.type == "linear") {
+ gradientEl = this.createSvgElement("linearGradient");
+ gradientEl.setAttribute("x1", vector[0]);
+ gradientEl.setAttribute("y1", vector[1]);
+ gradientEl.setAttribute("x2", vector[2]);
+ gradientEl.setAttribute("y2", vector[3]);
+ }
+ else {
+ gradientEl = this.createSvgElement("radialGradient");
+ gradientEl.setAttribute("cx", gradient.centerX);
+ gradientEl.setAttribute("cy", gradient.centerY);
+ gradientEl.setAttribute("r", gradient.radius);
+ if (Ext.isNumber(gradient.focalX) && Ext.isNumber(gradient.focalY)) {
+ gradientEl.setAttribute("fx", gradient.focalX);
+ gradientEl.setAttribute("fy", gradient.focalY);
+ }
+ }
+ gradientEl.id = gradient.id;
+ this.getDefs().appendChild(gradientEl);
+
+ for (i = 0; i < ln; i++) {
+ stop = gradient.stops[i];
+ stopEl = this.createSvgElement("stop");
+ stopEl.setAttribute("offset", stop.offset + "%");
+ stopEl.setAttribute("stop-color", stop.color);
+ stopEl.setAttribute("stop-opacity",stop.opacity);
+ gradientEl.appendChild(stopEl);
+ }
+ },
+
+
+ hasCls: function(sprite, className) {
+ return className && (' ' + (sprite.el.dom.getAttribute('class') || '') + ' ').indexOf(' ' + className + ' ') != -1;
+ },
+
+ addCls: function(sprite, className) {
+ var el = sprite.el,
+ i,
+ len,
+ v,
+ cls = [],
+ curCls = el.getAttribute('class') || '';
+
+ if (!Ext.isArray(className)) {
+ if (typeof className == 'string' && !this.hasCls(sprite, className)) {
+ el.set({ 'class': curCls + ' ' + className });
+ }
+ }
+ else {
+ for (i = 0, len = className.length; i < len; i++) {
+ v = className[i];
+ if (typeof v == 'string' && (' ' + curCls + ' ').indexOf(' ' + v + ' ') == -1) {
+ cls.push(v);
+ }
+ }
+ if (cls.length) {
+ el.set({ 'class': ' ' + cls.join(' ') });
+ }
+ }
+ },
+
+ removeCls: function(sprite, className) {
+ var me = this,
+ el = sprite.el,
+ curCls = el.getAttribute('class') || '',
+ i, idx, len, cls, elClasses;
+ if (!Ext.isArray(className)){
+ className = [className];
+ }
+ if (curCls) {
+ elClasses = curCls.replace(me.trimRe, ' ').split(me.spacesRe);
+ for (i = 0, len = className.length; i < len; i++) {
+ cls = className[i];
+ if (typeof cls == 'string') {
+ cls = cls.replace(me.trimRe, '');
+ idx = Ext.Array.indexOf(elClasses, cls);
+ if (idx != -1) {
+ elClasses.splice(idx, 1);
+ }
+ }
+ }
+ el.set({ 'class': elClasses.join(' ') });
+ }
+ },
+
+ destroy: function() {
+ var me = this;
+
+ me.callParent();
+ if (me.el) {
+ me.el.remove();
+ }
+ delete me.el;
+ }
+});
+
+
+Ext.define('Ext.draw.engine.Vml', {
+
+
+
+ extend: 'Ext.draw.Surface',
+
+ requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.core.Element'],
+
+
+
+ engine: 'Vml',
+
+ map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
+ bitesRe: /([clmz]),?([^clmz]*)/gi,
+ valRe: /-?[^,\s-]+/g,
+ fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i,
+ pathlike: /^(path|rect)$/,
+ NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops
+ partialPathRe: /[clmz]/g,
+ fontFamilyRe: /^['"]+|['"]+$/g,
+ baseVmlCls: Ext.baseCSSPrefix + 'vml-base',
+ vmlGroupCls: Ext.baseCSSPrefix + 'vml-group',
+ spriteCls: Ext.baseCSSPrefix + 'vml-sprite',
+ measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span',
+ zoom: 21600,
+ coordsize: 1000,
+ coordorigin: '0 0',
+
+ // @private
+ // Convert an SVG standard path into a VML path
+ path2vml: function (path) {
+ var me = this,
+ nonVML = me.NonVmlPathRe,
+ map = me.map,
+ val = me.valRe,
+ zoom = me.zoom,
+ bites = me.bitesRe,
+ command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw),
+ res, pa, p, r, i, ii, j, jj;
+ if (String(path).match(nonVML)) {
+ command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw);
+ } else if (!String(path).match(me.partialPathRe)) {
+ res = String(path).replace(bites, function (all, command, args) {
+ var vals = [],
+ isMove = command.toLowerCase() == "m",
+ res = map[command];
+ args.replace(val, function (value) {
+ if (isMove && vals[length] == 2) {
+ res += vals + map[command == "m" ? "l" : "L"];
+ vals = [];
+ }
+ vals.push(Math.round(value * zoom));
+ });
+ return res + vals;
+ });
+ return res;
+ }
+ pa = command(path);
+ res = [];
+ for (i = 0, ii = pa.length; i < ii; i++) {
+ p = pa[i];
+ r = pa[i][0].toLowerCase();
+ if (r == "z") {
+ r = "x";
+ }
+ for (j = 1, jj = p.length; j < jj; j++) {
+ r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : "");
+ }
+ res.push(r);
+ }
+ return res.join(" ");
+ },
+
+ // @private - set of attributes which need to be translated from the sprite API to the native browser API
+ translateAttrs: {
+ radius: "r",
+ radiusX: "rx",
+ radiusY: "ry",
+ lineWidth: "stroke-width",
+ fillOpacity: "fill-opacity",
+ strokeOpacity: "stroke-opacity",
+ strokeLinejoin: "stroke-linejoin"
+ },
+
+ // @private - Minimun set of defaults for different types of sprites.
+ minDefaults: {
+ circle: {
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ ellipse: {
+ cx: 0,
+ cy: 0,
+ rx: 0,
+ ry: 0,
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ rect: {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ rx: 0,
+ ry: 0,
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ text: {
+ x: 0,
+ y: 0,
+ "text-anchor": "start",
+ font: '10px "Arial"',
+ fill: "#000",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ path: {
+ d: "M0,0",
+ fill: "none",
+ stroke: null,
+ "stroke-width": null,
+ opacity: null,
+ "fill-opacity": null,
+ "stroke-opacity": null
+ },
+ image: {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0,
+ preserveAspectRatio: "none",
+ opacity: null
+ }
+ },
+
+ // private
+ onMouseEnter: function(e) {
+ this.fireEvent("mouseenter", e);
+ },
+
+ // private
+ onMouseLeave: function(e) {
+ this.fireEvent("mouseleave", e);
+ },
+
+ // @private - Normalize a delegated single event from the main container to each sprite and sprite group
+ processEvent: function(name, e) {
+ var target = e.getTarget(),
+ surface = this.surface,
+ sprite;
+ this.fireEvent(name, e);
+ sprite = this.items.get(target.id);
+ if (sprite) {
+ sprite.fireEvent(name, sprite, e);
+ }
+ },
+
+ // Create the VML element/elements and append them to the DOM
+ createSpriteElement: function(sprite) {
+ var me = this,
+ attr = sprite.attr,
+ type = sprite.type,
+ zoom = me.zoom,
+ vml = sprite.vml || (sprite.vml = {}),
+ round = Math.round,
+ el = (type === 'image') ? me.createNode('image') : me.createNode('shape'),
+ path, skew, textPath;
+
+ el.coordsize = zoom + ' ' + zoom;
+ el.coordorigin = attr.coordorigin || "0 0";
+ Ext.get(el).addCls(me.spriteCls);
+ if (type == "text") {
+ vml.path = path = me.createNode("path");
+ path.textpathok = true;
+ vml.textpath = textPath = me.createNode("textpath");
+ textPath.on = true;
+ el.appendChild(textPath);
+ el.appendChild(path);
+ }
+ el.id = sprite.id;
+ sprite.el = Ext.get(el);
+ me.el.appendChild(el);
+ if (type !== 'image') {
+ skew = me.createNode("skew");
+ skew.on = true;
+ el.appendChild(skew);
+ sprite.skew = skew;
+ }
+ sprite.matrix = Ext.create('Ext.draw.Matrix');
+ sprite.bbox = {
+ plain: null,
+ transform: null
+ };
+ sprite.fireEvent("render", sprite);
+ return sprite.el;
+ },
+
+ // @private - Get bounding box for the sprite. The Sprite itself has the public method.
+ getBBox: function (sprite, isWithoutTransform) {
+ var realPath = this["getPath" + sprite.type](sprite);
+ if (isWithoutTransform) {
+ sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
+ return sprite.bbox.plain;
+ }
+ sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
+ return sprite.bbox.transform;
+ },
+
+ getBBoxText: function (sprite) {
+ var vml = sprite.vml;
+ return {
+ x: vml.X + (vml.bbx || 0) - vml.W / 2,
+ y: vml.Y - vml.H / 2,
+ width: vml.W,
+ height: vml.H
+ };
+ },
+
+ applyAttrs: function (sprite) {
+ var me = this,
+ vml = sprite.vml,
+ group = sprite.group,
+ spriteAttr = sprite.attr,
+ el = sprite.el,
+ dom = el.dom,
+ style, name, groups, i, ln, scrubbedAttrs, font, key, bbox;
+
+ if (group) {
+ groups = [].concat(group);
+ ln = groups.length;
+ for (i = 0; i < ln; i++) {
+ group = groups[i];
+ me.getGroup(group).add(sprite);
+ }
+ delete sprite.group;
+ }
+ scrubbedAttrs = me.scrubAttrs(sprite) || {};
+
+ if (sprite.zIndexDirty) {
+ me.setZIndex(sprite);
+ }
+
+ // Apply minimum default attributes
+ Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]);
+
+ if (sprite.type == 'image') {
+ Ext.apply(sprite.attr, {
+ x: scrubbedAttrs.x,
+ y: scrubbedAttrs.y,
+ width: scrubbedAttrs.width,
+ height: scrubbedAttrs.height
+ });
+ bbox = sprite.getBBox();
+ el.setStyle({
+ width: bbox.width + 'px',
+ height: bbox.height + 'px'
+ });
+ dom.src = scrubbedAttrs.src;
+ }
+
+ if (dom.href) {
+ dom.href = scrubbedAttrs.href;
+ }
+ if (dom.title) {
+ dom.title = scrubbedAttrs.title;
+ }
+ if (dom.target) {
+ dom.target = scrubbedAttrs.target;
+ }
+ if (dom.cursor) {
+ dom.cursor = scrubbedAttrs.cursor;
+ }
+
+ // Change visibility
+ if (sprite.dirtyHidden) {
+ (scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
+ sprite.dirtyHidden = false;
+ }
+
+ // Update path
+ if (sprite.dirtyPath) {
+ if (sprite.type == "circle" || sprite.type == "ellipse") {
+ var cx = scrubbedAttrs.x,
+ cy = scrubbedAttrs.y,
+ rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0,
+ ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0;
+ dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}",
+ Math.round((cx - rx) * me.zoom),
+ Math.round((cy - ry) * me.zoom),
+ Math.round((cx + rx) * me.zoom),
+ Math.round((cy + ry) * me.zoom),
+ Math.round(cx * me.zoom));
+ sprite.dirtyPath = false;
+ }
+ else if (sprite.type !== "text" && sprite.type !== 'image') {
+ sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path;
+ dom.path = me.path2vml(scrubbedAttrs.path);
+ sprite.dirtyPath = false;
+ }
+ }
+
+ // Apply clipping
+ if ("clip-rect" in scrubbedAttrs) {
+ me.setClip(sprite, scrubbedAttrs);
+ }
+
+ // Handle text (special handling required)
+ if (sprite.type == "text") {
+ me.setTextAttributes(sprite, scrubbedAttrs);
+ }
+
+ // Handle fill and opacity
+ if (scrubbedAttrs.opacity || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
+ me.setFill(sprite, scrubbedAttrs);
+ }
+
+ // Handle stroke (all fills require a stroke element)
+ if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
+ me.setStroke(sprite, scrubbedAttrs);
+ }
+
+ //set styles
+ style = spriteAttr.style;
+ if (style) {
+ el.setStyle(style);
+ }
+
+ sprite.dirty = false;
+ },
+
+ setZIndex: function(sprite) {
+ if (sprite.el) {
+ if (sprite.attr.zIndex != undefined) {
+ sprite.el.setStyle('zIndex', sprite.attr.zIndex);
+ }
+ sprite.zIndexDirty = false;
+ }
+ },
+
+ // Normalize all virtualized types into paths.
+ setPaths: function(sprite, params) {
+ var spriteAttr = sprite.attr;
+ // Clear bbox cache
+ sprite.bbox.plain = null;
+ sprite.bbox.transform = null;
+ if (sprite.type == 'circle') {
+ spriteAttr.rx = spriteAttr.ry = params.r;
+ return Ext.draw.Draw.ellipsePath(sprite);
+ }
+ else if (sprite.type == 'ellipse') {
+ spriteAttr.rx = params.rx;
+ spriteAttr.ry = params.ry;
+ return Ext.draw.Draw.ellipsePath(sprite);
+ }
+ else if (sprite.type == 'rect') {
+ spriteAttr.rx = spriteAttr.ry = params.r;
+ return Ext.draw.Draw.rectPath(sprite);
+ }
+ else if (sprite.type == 'path' && spriteAttr.path) {
+ return Ext.draw.Draw.pathToAbsolute(spriteAttr.path);
+ }
+ return false;
+ },
+
+ setFill: function(sprite, params) {
+ var me = this,
+ el = sprite.el.dom,
+ fillEl = el.fill,
+ newfill = false,
+ opacity, gradient, fillUrl, rotation, angle;
+
+ if (!fillEl) {
+ // NOT an expando (but it sure looks like one)...
+ fillEl = el.fill = me.createNode("fill");
+ newfill = true;
+ }
+ if (Ext.isArray(params.fill)) {
+ params.fill = params.fill[0];
+ }
+ if (params.fill == "none") {
+ fillEl.on = false;
+ }
+ else {
+ if (typeof params.opacity == "number") {
+ fillEl.opacity = params.opacity;
+ }
+ if (typeof params["fill-opacity"] == "number") {
+ fillEl.opacity = params["fill-opacity"];
+ }
+ fillEl.on = true;
+ if (typeof params.fill == "string") {
+ fillUrl = params.fill.match(me.fillUrlRe);
+ if (fillUrl) {
+ fillUrl = fillUrl[1];
+ // If the URL matches one of the registered gradients, render that gradient
+ if (fillUrl.charAt(0) == "#") {
+ gradient = me.gradientsColl.getByKey(fillUrl.substring(1));
+ }
+ if (gradient) {
+ // VML angle is offset and inverted from standard, and must be adjusted to match rotation transform
+ rotation = params.rotation;
+ angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360;
+ // IE will flip the angle at 0 degrees...
+ if (angle === 0) {
+ angle = 180;
+ }
+ fillEl.angle = angle;
+ fillEl.type = "gradient";
+ fillEl.method = "sigma";
+ fillEl.colors.value = gradient.colors;
+ }
+ // Otherwise treat it as an image
+ else {
+ fillEl.src = fillUrl;
+ fillEl.type = "tile";
+ }
+ }
+ else {
+ fillEl.color = Ext.draw.Color.toHex(params.fill);
+ fillEl.src = "";
+ fillEl.type = "solid";
+ }
+ }
+ }
+ if (newfill) {
+ el.appendChild(fillEl);
+ }
+ },
+
+ setStroke: function(sprite, params) {
+ var me = this,
+ el = sprite.el.dom,
+ strokeEl = sprite.strokeEl,
+ newStroke = false,
+ width, opacity;
+
+ if (!strokeEl) {
+ strokeEl = sprite.strokeEl = me.createNode("stroke");
+ newStroke = true;
+ }
+ if (Ext.isArray(params.stroke)) {
+ params.stroke = params.stroke[0];
+ }
+ if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) {
+ strokeEl.on = false;
+ }
+ else {
+ strokeEl.on = true;
+ if (params.stroke && !params.stroke.match(me.fillUrlRe)) {
+ // VML does NOT support a gradient stroke :(
+ strokeEl.color = Ext.draw.Color.toHex(params.stroke);
+ }
+ strokeEl.joinstyle = params["stroke-linejoin"];
+ strokeEl.endcap = params["stroke-linecap"] || "round";
+ strokeEl.miterlimit = params["stroke-miterlimit"] || 8;
+ width = parseFloat(params["stroke-width"] || 1) * 0.75;
+ opacity = params["stroke-opacity"] || 1;
+ // VML Does not support stroke widths under 1, so we're going to fiddle with stroke-opacity instead.
+ if (Ext.isNumber(width) && width < 1) {
+ strokeEl.weight = 1;
+ strokeEl.opacity = opacity * width;
+ }
+ else {
+ strokeEl.weight = width;
+ strokeEl.opacity = opacity;
+ }
+ }
+ if (newStroke) {
+ el.appendChild(strokeEl);
+ }
+ },
+
+ setClip: function(sprite, params) {
+ var me = this,
+ el = sprite.el,
+ clipEl = sprite.clipEl,
+ rect = String(params["clip-rect"]).split(me.separatorRe);
+ if (!clipEl) {
+ clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div"));
+ clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite');
+ }
+ if (rect.length == 4) {
+ rect[2] = +rect[2] + (+rect[0]);
+ rect[3] = +rect[3] + (+rect[1]);
+ clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3]));
+ clipEl.setSize(me.el.width, me.el.height);
+ }
+ else {
+ clipEl.setStyle("clip", "");
+ }
+ },
+
+ setTextAttributes: function(sprite, params) {
+ var me = this,
+ vml = sprite.vml,
+ textStyle = vml.textpath.style,
+ spanCacheStyle = me.span.style,
+ zoom = me.zoom,
+ round = Math.round,
+ fontObj = {
+ fontSize: "font-size",
+ fontWeight: "font-weight",
+ fontStyle: "font-style"
+ },
+ fontProp,
+ paramProp;
+ if (sprite.dirtyFont) {
+ if (params.font) {
+ textStyle.font = spanCacheStyle.font = params.font;
+ }
+ if (params["font-family"]) {
+ textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"';
+ spanCacheStyle.fontFamily = params["font-family"];
+ }
+
+ for (fontProp in fontObj) {
+ paramProp = params[fontObj[fontProp]];
+ if (paramProp) {
+ textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp;
+ }
+ }
+
+ me.setText(sprite, params.text);
+
+ if (vml.textpath.string) {
+ me.span.innerHTML = String(vml.textpath.string).replace(/</g, "<").replace(/&/g, "&").replace(/\n/g, "<br>");
+ }
+ vml.W = me.span.offsetWidth;
+ vml.H = me.span.offsetHeight + 2;
+
+
+ if (params["text-anchor"] == "middle") {
+ textStyle["v-text-align"] = "center";
+ }
+ else if (params["text-anchor"] == "end") {
+ textStyle["v-text-align"] = "right";
+ vml.bbx = -Math.round(vml.W / 2);
+ }
+ else {
+ textStyle["v-text-align"] = "left";
+ vml.bbx = Math.round(vml.W / 2);
+ }
+ }
+ vml.X = params.x;
+ vml.Y = params.y;
+ vml.path.v = Ext.String.format("m{0},{1}l{2},{1}", Math.round(vml.X * zoom), Math.round(vml.Y * zoom), Math.round(vml.X * zoom) + 1);
+
+ sprite.bbox.plain = null;
+ sprite.bbox.transform = null;
+ sprite.dirtyFont = false;
+ },
+
+ setText: function(sprite, text) {
+ sprite.vml.textpath.string = Ext.htmlDecode(text);
+ },
+
+ hide: function() {
+ this.el.hide();
+ },
+
+ show: function() {
+ this.el.show();
+ },
+
+ hidePrim: function(sprite) {
+ sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility');
+ },
+
+ showPrim: function(sprite) {
+ sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility');
+ },
+
+ setSize: function(width, height) {
+ var me = this,
+ viewBox = me.viewBox,
+ scaleX, scaleY, items, i, len;
+ width = width || me.width;
+ height = height || me.height;
+ me.width = width;
+ me.height = height;
+
+ if (!me.el) {
+ return;
+ }
+
+
+ if (width != undefined) {
+ me.el.setWidth(width);
+ }
+ if (height != undefined) {
+ me.el.setHeight(height);
+ }
+
+
+ if (viewBox && (width || height)) {
+ var viewBoxX = viewBox.x,
+ viewBoxY = viewBox.y,
+ viewBoxWidth = viewBox.width,
+ viewBoxHeight = viewBox.height,
+ relativeHeight = height / viewBoxHeight,
+ relativeWidth = width / viewBoxWidth,
+ size;
+ if (viewBoxWidth * relativeHeight < width) {
+ viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
+ }
+ if (viewBoxHeight * relativeWidth < height) {
+ viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
+ }
+ size = 1 / Math.max(viewBoxWidth / width, viewBoxHeight / height);
+
+ me.viewBoxShift = {
+ dx: -viewBoxX,
+ dy: -viewBoxY,
+ scale: size
+ };
+ items = me.items.items;
+ for (i = 0, len = items.length; i < len; i++) {
+ me.transform(items[i]);
+ }
+ }
+ this.callParent(arguments);
+ },
+
+ setViewBox: function(x, y, width, height) {
+ this.callParent(arguments);
+ this.viewBox = {
+ x: x,
+ y: y,
+ width: width,
+ height: height
+ };
+ },
+
+ onAdd: function(item) {
+ this.callParent(arguments);
+ if (this.el) {
+ this.renderItem(item);
+ }
+ },
+
+ onRemove: function(sprite) {
+ if (sprite.el) {
+ sprite.el.remove();
+ delete sprite.el;
+ }
+ this.callParent(arguments);
+ },
+
+ render: function (container) {
+ var me = this,
+ doc = Ext.getDoc().dom;
+
+ if (!me.createNode) {
+ try {
+ if (!doc.namespaces.rvml) {
+ doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
+ }
+ me.createNode = function (tagName) {
+ return doc.createElement("<rvml:" + tagName + ' class="rvml">');
+ };
+ } catch (e) {
+ me.createNode = function (tagName) {
+ return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
+ };
+ }
+ }
+
+ if (!me.el) {
+ var el = doc.createElement("div");
+ me.el = Ext.get(el);
+ me.el.addCls(me.baseVmlCls);
+
+
+ me.span = doc.createElement("span");
+ Ext.get(me.span).addCls(me.measureSpanCls);
+ el.appendChild(me.span);
+ me.el.setSize(me.width || 10, me.height || 10);
+ container.appendChild(el);
+ me.el.on({
+ scope: me,
+ mouseup: me.onMouseUp,
+ mousedown: me.onMouseDown,
+ mouseover: me.onMouseOver,
+ mouseout: me.onMouseOut,
+ mousemove: me.onMouseMove,
+ mouseenter: me.onMouseEnter,
+ mouseleave: me.onMouseLeave,
+ click: me.onClick
+ });
+ }
+ me.renderAll();
+ },
+
+ renderAll: function() {
+ this.items.each(this.renderItem, this);
+ },
+
+ redraw: function(sprite) {
+ sprite.dirty = true;
+ this.renderItem(sprite);
+ },
+
+ renderItem: function (sprite) {
+
+ if (!this.el) {
+ return;
+ }
+
+
+ if (!sprite.el) {
+ this.createSpriteElement(sprite);
+ }
+
+ if (sprite.dirty) {
+ this.applyAttrs(sprite);
+ if (sprite.dirtyTransform) {
+ this.applyTransformations(sprite);
+ }
+ }
+ },
+
+ rotationCompensation: function (deg, dx, dy) {
+ var matrix = Ext.create('Ext.draw.Matrix');
+ matrix.rotate(-deg, 0.5, 0.5);
+ return {
+ x: matrix.x(dx, dy),
+ y: matrix.y(dx, dy)
+ };
+ },
+
+ transform: function(sprite) {
+ var me = this,
+ matrix = Ext.create('Ext.draw.Matrix'),
+ transforms = sprite.transformations,
+ transformsLength = transforms.length,
+ i = 0,
+ deltaDegrees = 0,
+ deltaScaleX = 1,
+ deltaScaleY = 1,
+ flip = "",
+ el = sprite.el,
+ dom = el.dom,
+ domStyle = dom.style,
+ zoom = me.zoom,
+ skew = sprite.skew,
+ deltaX, deltaY, transform, type, compensate, y, fill, newAngle,zoomScaleX, zoomScaleY, newOrigin;
+
+ for (; i < transformsLength; i++) {
+ transform = transforms[i];
+ type = transform.type;
+ if (type == "translate") {
+ matrix.translate(transform.x, transform.y);
+ }
+ else if (type == "rotate") {
+ matrix.rotate(transform.degrees, transform.x, transform.y);
+ deltaDegrees += transform.degrees;
+ }
+ else if (type == "scale") {
+ matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
+ deltaScaleX *= transform.x;
+ deltaScaleY *= transform.y;
+ }
+ }
+
+ if (me.viewBoxShift) {
+ matrix.scale(me.viewBoxShift.scale, me.viewBoxShift.scale, -1, -1);
+ matrix.add(1, 0, 0, 1, me.viewBoxShift.dx, me.viewBoxShift.dy);
+ }
+
+ sprite.matrix = matrix;
+
+
+
+
+ if (sprite.type != "image" && skew) {
+
+ skew.matrix = matrix.toString();
+ skew.offset = matrix.offset();
+ }
+ else {
+ deltaX = matrix.matrix[0][2];
+ deltaY = matrix.matrix[1][2];
+
+ zoomScaleX = zoom / deltaScaleX;
+ zoomScaleY = zoom / deltaScaleY;
+
+ dom.coordsize = Math.abs(zoomScaleX) + " " + Math.abs(zoomScaleY);
+
+
+ newAngle = deltaDegrees * (deltaScaleX * ((deltaScaleY < 0) ? -1 : 1));
+ if (newAngle != domStyle.rotation && !(newAngle === 0 && !domStyle.rotation)) {
+ domStyle.rotation = newAngle;
+ }
+ if (deltaDegrees) {
+
+ compensate = me.rotationCompensation(deltaDegrees, deltaX, deltaY);
+ deltaX = compensate.x;
+ deltaY = compensate.y;
+ }
+
+
+ if (deltaScaleX < 0) {
+ flip += "x";
+ }
+ if (deltaScaleY < 0) {
+ flip += " y";
+ y = -1;
+ }
+ if (flip != "" && !dom.style.flip) {
+ domStyle.flip = flip;
+ }
+
+
+ newOrigin = (deltaX * -zoomScaleX) + " " + (deltaY * -zoomScaleY);
+ if (newOrigin != dom.coordorigin) {
+ dom.coordorigin = (deltaX * -zoomScaleX) + " " + (deltaY * -zoomScaleY);
+ }
+ }
+ },
+
+ createItem: function (config) {
+ return Ext.create('Ext.draw.Sprite', config);
+ },
+
+ getRegion: function() {
+ return this.el.getRegion();
+ },
+
+ addCls: function(sprite, className) {
+ if (sprite && sprite.el) {
+ sprite.el.addCls(className);
+ }
+ },
+
+ removeCls: function(sprite, className) {
+ if (sprite && sprite.el) {
+ sprite.el.removeCls(className);
+ }
+ },
+
+
+ addGradient: function(gradient) {
+ var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')),
+ colors = [],
+ stops = Ext.create('Ext.util.MixedCollection');
+
+
+ stops.addAll(gradient.stops);
+ stops.sortByKey("ASC", function(a, b) {
+ a = parseInt(a, 10);
+ b = parseInt(b, 10);
+ return a > b ? 1 : (a < b ? -1 : 0);
+ });
+ stops.eachKey(function(k, v) {
+ colors.push(k + "% " + v.color);
+ });
+
+ gradients.add(gradient.id, {
+ colors: colors.join(","),
+ angle: gradient.angle
+ });
+ },
+
+ destroy: function() {
+ var me = this;
+
+ me.callParent(arguments);
+ if (me.el) {
+ me.el.remove();
+ }
+ delete me.el;
+ }
+});
+
+
+Ext.define('Ext.fx.target.ElementCSS', {
+
+
+
+ extend: 'Ext.fx.target.Element',
+
+
+
+ setAttr: function(targetData, isFirstFrame) {
+ var cssArr = {
+ attrs: [],
+ duration: [],
+ easing: []
+ },
+ ln = targetData.length,
+ attributes,
+ attrs,
+ attr,
+ easing,
+ duration,
+ o,
+ i,
+ j,
+ ln2;
+ for (i = 0; i < ln; i++) {
+ attrs = targetData[i];
+ duration = attrs.duration;
+ easing = attrs.easing;
+ attrs = attrs.attrs;
+ for (attr in attrs) {
+ if (Ext.Array.indexOf(cssArr.attrs, attr) == -1) {
+ cssArr.attrs.push(attr.replace(/[A-Z]/g, function(v) {
+ return '-' + v.toLowerCase();
+ }));
+ cssArr.duration.push(duration + 'ms');
+ cssArr.easing.push(easing);
+ }
+ }
+ }
+ attributes = cssArr.attrs.join(',');
+ duration = cssArr.duration.join(',');
+ easing = cssArr.easing.join(', ');
+ for (i = 0; i < ln; i++) {
+ attrs = targetData[i].attrs;
+ for (attr in attrs) {
+ ln2 = attrs[attr].length;
+ for (j = 0; j < ln2; j++) {
+ o = attrs[attr][j];
+ o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', isFirstFrame ? '' : attributes);
+ o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', isFirstFrame ? '' : duration);
+ o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', isFirstFrame ? '' : easing);
+ o[0].setStyle(attr, o[1]);
+
+
+ if (isFirstFrame) {
+ o = o[0].dom.offsetWidth;
+ }
+ else {
+
+ o[0].on(Ext.supports.CSS3TransitionEnd, function() {
+ this.setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', null);
+ this.setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', null);
+ this.setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', null);
+ }, o[0], { single: true });
+ }
+ }
+ }
+ }
+ }
+});
+
+Ext.define('Ext.fx.target.CompositeElementCSS', {
+
+
+
+ extend: 'Ext.fx.target.CompositeElement',
+
+ requires: ['Ext.fx.target.ElementCSS'],
+
+
+ setAttr: function() {
+ return Ext.fx.target.ElementCSS.prototype.setAttr.apply(this, arguments);
+ }
+});
+
+Ext.define('Ext.layout.container.AbstractFit', {
+
+
+
+ extend: 'Ext.layout.container.Container',
+
+
+
+ itemCls: Ext.baseCSSPrefix + 'fit-item',
+ targetCls: Ext.baseCSSPrefix + 'layout-fit',
+ type: 'fit'
+});
+
+Ext.define('Ext.layout.container.Fit', {
+
+
+
+ extend: 'Ext.layout.container.AbstractFit',
+ alias: 'layout.fit',
+ alternateClassName: 'Ext.layout.FitLayout',
+
+
+
+
+ onLayout : function() {
+ var me = this;
+ me.callParent();
+
+ if (me.owner.items.length) {
+ me.setItemBox(me.owner.items.get(0), me.getLayoutTargetSize());
+ }
+ },
+
+ getTargetBox : function() {
+ return this.getLayoutTargetSize();
+ },
+
+ setItemBox : function(item, box) {
+ var me = this;
+ if (item && box.height > 0) {
+ if (me.isManaged('width') === true) {
+ box.width = undefined;
+ }
+ if (me.isManaged('height') === true) {
+ box.height = undefined;
+ }
+ me.setItemSize(item, box.width, box.height);
+ }
+ }
+});
+
+
+Ext.define('Ext.layout.container.AbstractCard', {
+
+
+
+ extend: 'Ext.layout.container.Fit',
+
+
+
+ type: 'card',
+
+ sizeAllCards: false,
+
+ hideInactive: true,
+
+
+ deferredRender : false,
+
+ beforeLayout: function() {
+ var me = this;
+ me.activeItem = me.getActiveItem();
+ if (me.activeItem && me.deferredRender) {
+ me.renderItems([me.activeItem], me.getRenderTarget());
+ return true;
+ }
+ else {
+ return this.callParent(arguments);
+ }
+ },
+
+ onLayout: function() {
+ var me = this,
+ activeItem = me.activeItem,
+ items = me.getVisibleItems(),
+ ln = items.length,
+ targetBox = me.getTargetBox(),
+ i, item;
+
+ for (i = 0; i < ln; i++) {
+ item = items[i];
+ me.setItemBox(item, targetBox);
+ }
+
+ if (!me.firstActivated && activeItem) {
+ if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
+ activeItem.fireEvent('activate', activeItem);
+ }
+ me.firstActivated = true;
+ }
+ },
+
+ isValidParent : function(item, target, position) {
+
+
+ var itemEl = item.el ? item.el.dom : Ext.getDom(item);
+ return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
+ },
+
+
+ getActiveItem: function() {
+ var me = this;
+ if (!me.activeItem && me.owner) {
+ me.activeItem = me.parseActiveItem(me.owner.activeItem);
+ }
+
+ if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
+ return me.activeItem;
+ }
+
+ return null;
+ },
+
+
+ parseActiveItem: function(item) {
+ if (item && item.isComponent) {
+ return item;
+ }
+ else if (typeof item == 'number' || item === undefined) {
+ return this.getLayoutItems()[item || 0];
+ }
+ else {
+ return this.owner.getComponent(item);
+ }
+ },
+
+
+ configureItem: function(item, position) {
+ this.callParent([item, position]);
+ if (this.hideInactive && this.activeItem !== item) {
+ item.hide();
+ }
+ else {
+ item.show();
+ }
+ },
+
+ onRemove: function(component) {
+ if (component === this.activeItem) {
+ this.activeItem = null;
+ if (this.owner.items.getCount() === 0) {
+ this.firstActivated = false;
+ }
+ }
+ },
+
+
+ getAnimation: function(newCard, owner) {
+ var newAnim = (newCard || {}).cardSwitchAnimation;
+ if (newAnim === false) {
+ return false;
+ }
+ return newAnim || owner.cardSwitchAnimation;
+ },
+
+
+ getNext: function(wrap) {
+
+
+
+ var items = this.getLayoutItems(),
+ index = Ext.Array.indexOf(items, this.activeItem);
+ return items[index + 1] || (wrap ? items[0] : false);
+ },
+
+
+ next: function(anim, wrap) {
+
+
+
+ return this.setActiveItem(this.getNext(wrap), anim);
+ },
+
+
+ getPrev: function(wrap) {
+
+
+
+ var items = this.getLayoutItems(),
+ index = Ext.Array.indexOf(items, this.activeItem);
+ return items[index - 1] || (wrap ? items[items.length - 1] : false);
+ },
+
+
+ prev: function(anim, wrap) {
+
+
+
+ return this.setActiveItem(this.getPrev(wrap), anim);
+ }
+});
+
+
+Ext.define('Ext.selection.Model', {
+ extend: 'Ext.util.Observable',
+ alternateClassName: 'Ext.AbstractStoreSelectionModel',
+ requires: ['Ext.data.StoreManager'],
+
+
+
+
+
+ allowDeselect: false,
+
+
+ selected: null,
+
+
+
+ pruneRemoved: true,
+
+ constructor: function(cfg) {
+ var me = this;
+
+ cfg = cfg || {};
+ Ext.apply(me, cfg);
+
+ me.addEvents(
+
+ 'selectionchange'
+ );
+
+ me.modes = {
+ SINGLE: true,
+ SIMPLE: true,
+ MULTI: true
+ };
+
+
+ me.setSelectionMode(cfg.mode || me.mode);
+
+
+ me.selected = Ext.create('Ext.util.MixedCollection');
+
+ me.callParent(arguments);
+ },
+
+
+ bind : function(store, initial){
+ var me = this;
+
+ if(!initial && me.store){
+ if(store !== me.store && me.store.autoDestroy){
+ me.store.destroy();
+ }else{
+ me.store.un("add", me.onStoreAdd, me);
+ me.store.un("clear", me.onStoreClear, me);
+ me.store.un("remove", me.onStoreRemove, me);
+ me.store.un("update", me.onStoreUpdate, me);
+ }
+ }
+ if(store){
+ store = Ext.data.StoreManager.lookup(store);
+ store.on({
+ add: me.onStoreAdd,
+ clear: me.onStoreClear,
+ remove: me.onStoreRemove,
+ update: me.onStoreUpdate,
+ scope: me
+ });
+ }
+ me.store = store;
+ if(store && !initial) {
+ me.refresh();
+ }
+ },
+
+ selectAll: function(silent) {
+ var selections = this.store.getRange(),
+ i = 0,
+ len = selections.length;
+
+ for (; i < len; i++) {
+ this.doSelect(selections[i], true, silent);
+ }
+ },
+
+ deselectAll: function() {
+ var selections = this.getSelection(),
+ i = 0,
+ len = selections.length;
+
+ for (; i < len; i++) {
+ this.doDeselect(selections[i]);
+ }
+ },
+
+
+
+
+ selectWithEvent: function(record, e) {
+ var me = this;
+
+ switch (me.selectionMode) {
+ case 'MULTI':
+ if (e.ctrlKey && me.isSelected(record)) {
+ me.doDeselect(record, false);
+ } else if (e.shiftKey && me.lastFocused) {
+ me.selectRange(me.lastFocused, record, e.ctrlKey);
+ } else if (e.ctrlKey) {
+ me.doSelect(record, true, false);
+ } else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
+ me.doSelect(record, false, false);
+ } else {
+ me.doSelect(record, false);
+ }
+ break;
+ case 'SIMPLE':
+ if (me.isSelected(record)) {
+ me.doDeselect(record);
+ } else {
+ me.doSelect(record, true);
+ }
+ break;
+ case 'SINGLE':
+
+ if (me.allowDeselect && me.isSelected(record)) {
+ me.doDeselect(record);
+
+ } else {
+ me.doSelect(record, false);
+ }
+ break;
+ }
+ },
+
+
+ selectRange : function(startRow, endRow, keepExisting, dir){
+ var me = this,
+ store = me.store,
+ selectedCount = 0,
+ i,
+ tmp,
+ dontDeselect,
+ records = [];
+
+ if (me.isLocked()){
+ return;
+ }
+
+ if (!keepExisting) {
+ me.clearSelections();
+ }
+
+ if (!Ext.isNumber(startRow)) {
+ startRow = store.indexOf(startRow);
+ }
+ if (!Ext.isNumber(endRow)) {
+ endRow = store.indexOf(endRow);
+ }
+
+
+ if (startRow > endRow){
+ tmp = endRow;
+ endRow = startRow;
+ startRow = tmp;
+ }
+
+ for (i = startRow; i <= endRow; i++) {
+ if (me.isSelected(store.getAt(i))) {
+ selectedCount++;
+ }
+ }
+
+ if (!dir) {
+ dontDeselect = -1;
+ } else {
+ dontDeselect = (dir == 'up') ? startRow : endRow;
+ }
+
+ for (i = startRow; i <= endRow; i++){
+ if (selectedCount == (endRow - startRow + 1)) {
+ if (i != dontDeselect) {
+ me.doDeselect(i, true);
+ }
+ } else {
+ records.push(store.getAt(i));
+ }
+ }
+ me.doMultiSelect(records, true);
+ },
+
+
+ select: function(records, keepExisting, suppressEvent) {
+ this.doSelect(records, keepExisting, suppressEvent);
+ },
+
+
+ deselect: function(records, suppressEvent) {
+ this.doDeselect(records, suppressEvent);
+ },
+
+ doSelect: function(records, keepExisting, suppressEvent) {
+ var me = this,
+ record;
+
+ if (me.locked) {
+ return;
+ }
+ if (typeof records === "number") {
+ records = [me.store.getAt(records)];
+ }
+ if (me.selectionMode == "SINGLE" && records) {
+ record = records.length ? records[0] : records;
+ me.doSingleSelect(record, suppressEvent);
+ } else {
+ me.doMultiSelect(records, keepExisting, suppressEvent);
+ }
+ },
+
+ doMultiSelect: function(records, keepExisting, suppressEvent) {
+ var me = this,
+ selected = me.selected,
+ change = false,
+ i = 0,
+ len, record;
+
+ if (me.locked) {
+ return;
+ }
+
+
+ records = !Ext.isArray(records) ? [records] : records;
+ len = records.length;
+ if (!keepExisting && selected.getCount() > 0) {
+ change = true;
+ me.doDeselect(me.getSelection(), true);
+ }
+
+ for (; i < len; i++) {
+ record = records[i];
+ if (keepExisting && me.isSelected(record)) {
+ continue;
+ }
+ change = true;
+ me.lastSelected = record;
+ selected.add(record);
+
+ me.onSelectChange(record, true, suppressEvent);
+ }
+ me.setLastFocused(record, suppressEvent);
+
+ me.maybeFireSelectionChange(change && !suppressEvent);
+ },
+
+
+ doDeselect: function(records, suppressEvent) {
+ var me = this,
+ selected = me.selected,
+ change = false,
+ i = 0,
+ len, record;
+
+ if (me.locked) {
+ return;
+ }
+
+ if (typeof records === "number") {
+ records = [me.store.getAt(records)];
+ }
+
+ records = !Ext.isArray(records) ? [records] : records;
+ len = records.length;
+ for (; i < len; i++) {
+ record = records[i];
+ if (selected.remove(record)) {
+ if (me.lastSelected == record) {
+ me.lastSelected = selected.last();
+ }
+ me.onSelectChange(record, false, suppressEvent);
+ change = true;
+ }
+ }
+
+ me.maybeFireSelectionChange(change && !suppressEvent);
+ },
+
+ doSingleSelect: function(record, suppressEvent) {
+ var me = this,
+ selected = me.selected;
+
+ if (me.locked) {
+ return;
+ }
+
+
+ if (me.isSelected(record)) {
+ return;
+ }
+ if (selected.getCount() > 0) {
+ me.doDeselect(me.lastSelected, suppressEvent);
+ }
+ selected.add(record);
+ me.lastSelected = record;
+ me.onSelectChange(record, true, suppressEvent);
+ if (!suppressEvent) {
+ me.setLastFocused(record);
+ }
+ me.maybeFireSelectionChange(!suppressEvent);
+ },
+
+
+ setLastFocused: function(record, supressFocus) {
+ var me = this,
+ recordBeforeLast = me.lastFocused;
+ me.lastFocused = record;
+ me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
+ },
+
+
+ isFocused: function(record) {
+ return record === this.getLastFocused();
+ },
+
+
+
+
+ maybeFireSelectionChange: function(fireEvent) {
+ if (fireEvent) {
+ var me = this;
+ me.fireEvent('selectionchange', me, me.getSelection());
+ }
+ },
+
+
+ getLastSelected: function() {
+ return this.lastSelected;
+ },
+
+ getLastFocused: function() {
+ return this.lastFocused;
+ },
+
+
+ getSelection: function() {
+ return this.selected.getRange();
+ },
+
+
+ getSelectionMode: function() {
+ return this.selectionMode;
+ },
+
+
+ setSelectionMode: function(selMode) {
+ selMode = selMode ? selMode.toUpperCase() : 'SINGLE';
+
+
+ this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE';
+ },
+
+
+ isLocked: function() {
+ return this.locked;
+ },
+
+
+ setLocked: function(locked) {
+ this.locked = !!locked;
+ },
+
+
+ isSelected: function(record) {
+ record = Ext.isNumber(record) ? this.store.getAt(record) : record;
+ return this.selected.indexOf(record) !== -1;
+ },
+
+
+ hasSelection: function() {
+ return this.selected.getCount() > 0;
+ },
+
+ refresh: function() {
+ var me = this,
+ toBeSelected = [],
+ oldSelections = me.getSelection(),
+ len = oldSelections.length,
+ selection,
+ change,
+ i = 0,
+ lastFocused = this.getLastFocused();
+
+
+
+
+ for (; i < len; i++) {
+ selection = oldSelections[i];
+ if (!this.pruneRemoved || me.store.indexOf(selection) !== -1) {
+ toBeSelected.push(selection);
+ }
+ }
+
+
+
+ if (me.selected.getCount() != toBeSelected.length) {
+ change = true;
+ }
+
+ me.clearSelections();
+
+ if (me.store.indexOf(lastFocused) !== -1) {
+
+ this.setLastFocused(lastFocused, true);
+ }
+
+ if (toBeSelected.length) {
+
+ me.doSelect(toBeSelected, false, true);
+ }
+
+ me.maybeFireSelectionChange(change);
+ },
+
+ clearSelections: function() {
+
+ var me = this;
+ me.selected.clear();
+ me.lastSelected = null;
+ me.setLastFocused(null);
+ },
+
+
+ onStoreAdd: function() {
+
+ },
+
+
+
+ onStoreClear: function() {
+ var me = this,
+ selected = this.selected;
+
+ if (selected.getCount > 0) {
+ selected.clear();
+ me.lastSelected = null;
+ me.setLastFocused(null);
+ me.maybeFireSelectionChange(true);
+ }
+ },
+
+
+
+
+ onStoreRemove: function(store, record) {
+ var me = this,
+ selected = me.selected;
+
+ if (me.locked || !me.pruneRemoved) {
+ return;
+ }
+
+ if (selected.remove(record)) {
+ if (me.lastSelected == record) {
+ me.lastSelected = null;
+ }
+ if (me.getLastFocused() == record) {
+ me.setLastFocused(null);
+ }
+ me.maybeFireSelectionChange(true);
+ }
+ },
+
+ getCount: function() {
+ return this.selected.getCount();
+ },
+
+
+ destroy: function() {
+
+ },
+
+
+ onStoreUpdate: function() {
+
+ },
+
+
+ onSelectChange: function(record, isSelected, suppressEvent) {
+
+ },
+
+
+ onLastFocusChanged: function(oldFocused, newFocused) {
+
+ },
+
+
+ onEditorKey: function(field, e) {
+
+ },
+
+
+ bindComponent: function(cmp) {
+
+ }
+});
+
+Ext.define('Ext.selection.DataViewModel', {
+ extend: 'Ext.selection.Model',
+
+ requires: ['Ext.util.KeyNav'],
+
+ deselectOnContainerClick: true,
+
+
+ enableKeyNav: true,
+
+ constructor: function(cfg){
+ this.addEvents(
+
+ 'deselect',
+
+
+ 'select'
+ );
+ this.callParent(arguments);
+ },
+
+ bindComponent: function(view) {
+ var me = this,
+ eventListeners = {
+ refresh: me.refresh,
+ scope: me
+ };
+
+ me.view = view;
+ me.bind(view.getStore());
+
+ view.on(view.triggerEvent, me.onItemClick, me);
+ view.on(view.triggerCtEvent, me.onContainerClick, me);
+
+ view.on(eventListeners);
+
+ if (me.enableKeyNav) {
+ me.initKeyNav(view);
+ }
+ },
+
+ onItemClick: function(view, record, item, index, e) {
+ this.selectWithEvent(record, e);
+ },
+
+ onContainerClick: function() {
+ if (this.deselectOnContainerClick) {
+ this.deselectAll();
+ }
+ },
+
+ initKeyNav: function(view) {
+ var me = this;
+
+ if (!view.rendered) {
+ view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
+ return;
+ }
+
+ view.el.set({
+ tabIndex: -1
+ });
+ me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
+ down: Ext.pass(me.onNavKey, [1], me),
+ right: Ext.pass(me.onNavKey, [1], me),
+ left: Ext.pass(me.onNavKey, [-1], me),
+ up: Ext.pass(me.onNavKey, [-1], me),
+ scope: me
+ });
+ },
+
+ onNavKey: function(step) {
+ step = step || 1;
+ var me = this,
+ view = me.view,
+ selected = me.getSelection()[0],
+ numRecords = me.view.store.getCount(),
+ idx;
+
+ if (selected) {
+ idx = view.indexOf(view.getNode(selected)) + step;
+ } else {
+ idx = 0;
+ }
+
+ if (idx < 0) {
+ idx = numRecords - 1;
+ } else if (idx >= numRecords) {
+ idx = 0;
+ }
+
+ me.select(idx);
+ },
+
+
+ onSelectChange: function(record, isSelected, suppressEvent) {
+ var me = this,
+ view = me.view,
+ allowSelect = true;
+
+ if (isSelected) {
+ if (!suppressEvent) {
+ allowSelect = me.fireEvent('beforeselect', me, record) !== false;
+ }
+ if (allowSelect) {
+ view.onItemSelect(record);
+ if (!suppressEvent) {
+ me.fireEvent('select', me, record);
+ }
+ }
+ } else {
+ view.onItemDeselect(record);
+ if (!suppressEvent) {
+ me.fireEvent('deselect', me, record);
+ }
+ }
+ }
+});
+
+
+Ext.define('Ext.state.CookieProvider', {
+ extend: 'Ext.state.Provider',
+
+ constructor : function(config){
+ var me = this;
+ me.path = "/";
+ me.expires = new Date(new Date().getTime()+(1000*60*60*24*7));
+ me.domain = null;
+ me.secure = false;
+ me.callParent(arguments);
+ me.state = me.readCookies();
+ },
+
+
+ set : function(name, value){
+ var me = this;
+
+ if(typeof value == "undefined" || value === null){
+ me.clear(name);
+ return;
+ }
+ me.setCookie(name, value);
+ me.callParent(arguments);
+ },
+
+
+ clear : function(name){
+ this.clearCookie(name);
+ this.callParent(arguments);
+ },
+
+
+ readCookies : function(){
+ var cookies = {},
+ c = document.cookie + ";",
+ re = /\s?(.*?)=(.*?);/g,
+ prefix = this.prefix,
+ len = prefix.length,
+ matches,
+ name,
+ value;
+
+ while((matches = re.exec(c)) != null){
+ name = matches[1];
+ value = matches[2];
+ if (name && name.substring(0, len) == prefix){
+ cookies[name.substr(len)] = this.decodeValue(value);
+ }
+ }
+ return cookies;
+ },
+
+
+ setCookie : function(name, value){
+ var me = this;
+
+ document.cookie = me.prefix + name + "=" + me.encodeValue(value) +
+ ((me.expires == null) ? "" : ("; expires=" + me.expires.toGMTString())) +
+ ((me.path == null) ? "" : ("; path=" + me.path)) +
+ ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
+ ((me.secure == true) ? "; secure" : "");
+ },
+
+
+ clearCookie : function(name){
+ var me = this;
+
+ document.cookie = me.prefix + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
+ ((me.path == null) ? "" : ("; path=" + me.path)) +
+ ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
+ ((me.secure == true) ? "; secure" : "");
+ }
+});
+
+Ext.define('Ext.state.LocalStorageProvider', {
+
+
+ extend: 'Ext.state.Provider',
+
+ alias: 'state.localstorage',
+
+
+
+ constructor: function(){
+ var me = this;
+ me.callParent(arguments);
+ me.store = me.getStorageObject();
+ me.state = me.readLocalStorage();
+ },
+
+ readLocalStorage: function(){
+ var store = this.store,
+ i = 0,
+ len = store.length,
+ prefix = this.prefix,
+ prefixLen = prefix.length,
+ data = {},
+ key;
+
+ for (; i < len; ++i) {
+ key = store.key(i);
+ if (key.substring(0, prefixLen) == prefix) {
+ data[key.substr(prefixLen)] = this.decodeValue(store.getItem(key));
+ }
+ }
+ return data;
+ },
+
+ set : function(name, value){
+ var me = this;
+
+ me.clear(name);
+ if (typeof value == "undefined" || value === null) {
+ return;
+ }
+ me.store.setItem(me.prefix + name, me.encodeValue(value));
+ me.callParent(arguments);
+ },
+
+
+ clear : function(name){
+ this.store.removeItem(this.prefix + name);
+ this.callParent(arguments);
+ },
+
+ getStorageObject: function(){
+ try {
+ var supports = 'localStorage' in window && window['localStorage'] !== null;
+ if (supports) {
+ return window.localStorage;
+ }
+ } catch (e) {
+ return false;
+ }
+ Ext.Error.raise('LocalStorage is not supported by the current browser');
+ }
+});
+
+
+
+Ext.define('Ext.util.Point', {
+
+
+ extend: 'Ext.util.Region',
+
+ statics: {
+
+
+ fromEvent: function(e) {
+ e = (e.changedTouches && e.changedTouches.length > 0) ? e.changedTouches[0] : e;
+ return new this(e.pageX, e.pageY);
+ }
+ },
+
+
+
+ constructor: function(x, y) {
+ this.callParent([y, x, y, x]);
+ },
+
+
+ toString: function() {
+ return "Point[" + this.x + "," + this.y + "]";
+ },
+
+
+ equals: function(p) {
+ return (this.x == p.x && this.y == p.y);
+ },
+
+
+ isWithin: function(p, threshold) {
+ if (!Ext.isObject(threshold)) {
+ threshold = {
+ x: threshold,
+ y: threshold
+ };
+ }
+
+ return (this.x <= p.x + threshold.x && this.x >= p.x - threshold.x &&
+ this.y <= p.y + threshold.y && this.y >= p.y - threshold.y);
+ },
+
+
+ roundedEquals: function(p) {
+ return (Math.round(this.x) == Math.round(p.x) && Math.round(this.y) == Math.round(p.y));
+ }
+}, function() {
+
+ this.prototype.translate = Ext.util.Region.prototype.translateBy;
+});
+
+
+Ext.define('Ext.view.AbstractView', {
+ extend: 'Ext.Component',
+ alternateClassName: 'Ext.view.AbstractView',
+ requires: [
+ 'Ext.LoadMask',
+ 'Ext.data.StoreManager',
+ 'Ext.CompositeElementLite',
+ 'Ext.DomQuery',
+ 'Ext.selection.DataViewModel'
+ ],
+
+ inheritableStatics: {
+ getRecord: function(node) {
+ return this.getBoundView(node).getRecord(node);
+ },
+
+ getBoundView: function(node) {
+ return Ext.getCmp(node.boundView);
+ }
+ },
+
+
+
+
+
+
+
+ itemCls: Ext.baseCSSPrefix + 'dataview-item',
+
+
+
+
+
+
+ loadingText: 'Loading...',
+
+
+
+
+ loadingUseMsg: true,
+
+
+
+
+
+ selectedItemCls: Ext.baseCSSPrefix + 'item-selected',
+
+
+ emptyText: "",
+
+
+ deferEmptyText: true,
+
+
+ trackOver: false,
+
+
+ blockRefresh: false,
+
+
+
+
+
+ last: false,
+
+ triggerEvent: 'itemclick',
+ triggerCtEvent: 'containerclick',
+
+ addCmpEvents: function() {
+
+ },
+
+
+ initComponent : function(){
+ var me = this,
+ isDef = Ext.isDefined,
+ itemTpl = me.itemTpl,
+ memberFn = {};
+
+ if (itemTpl) {
+ if (Ext.isArray(itemTpl)) {
+
+ itemTpl = itemTpl.join('');
+ } else if (Ext.isObject(itemTpl)) {
+
+ memberFn = Ext.apply(memberFn, itemTpl.initialConfig);
+ itemTpl = itemTpl.html;
+ }
+
+ if (!me.itemSelector) {
+ me.itemSelector = '.' + me.itemCls;
+ }
+
+ itemTpl = Ext.String.format('<tpl for="."><div class="{0}">{1}</div></tpl>', me.itemCls, itemTpl);
+ me.tpl = Ext.create('Ext.XTemplate', itemTpl, memberFn);
+ }
+
+ if (!isDef(me.tpl) || !isDef(me.itemSelector)) {
+ Ext.Error.raise({
+ sourceClass: 'Ext.view.View',
+ tpl: me.tpl,
+ itemSelector: me.itemSelector,
+ msg: "DataView requires both tpl and itemSelector configurations to be defined."
+ });
+ }
+
+ me.callParent();
+ if(Ext.isString(me.tpl) || Ext.isArray(me.tpl)){
+ me.tpl = Ext.create('Ext.XTemplate', me.tpl);
+ }
+
+
+
+ if (isDef(me.overCls) || isDef(me.overClass)) {
+ if (Ext.isDefined(Ext.global.console)) {
+ Ext.global.console.warn('Ext.view.View: Using the deprecated overCls or overClass configuration. Use overItemCls instead.');
+ }
+ me.overItemCls = me.overCls || me.overClass;
+ delete me.overCls;
+ delete me.overClass;
+ }
+
+ if (me.overItemCls) {
+ me.trackOver = true;
+ }
+
+ if (isDef(me.selectedCls) || isDef(me.selectedClass)) {
+ if (Ext.isDefined(Ext.global.console)) {
+ Ext.global.console.warn('Ext.view.View: Using the deprecated selectedCls or selectedClass configuration. Use selectedItemCls instead.');
+ }
+ me.selectedItemCls = me.selectedCls || me.selectedClass;
+ delete me.selectedCls;
+ delete me.selectedClass;
+ }
+
+ me.addEvents(
+
+ 'beforerefresh',
+
+ 'refresh',
+
+ 'itemupdate',
+
+ 'itemadd',
+
+ 'itemremove'
+ );
+
+ me.addCmpEvents();
+
+ if (me.store) {
+ me.store = Ext.data.StoreManager.lookup(me.store);
+ }
+ me.all = new Ext.CompositeElementLite();
+ me.getSelectionModel().bindComponent(me);
+ },
+
+ onRender: function() {
+ var me = this,
+ loadingText = me.loadingText,
+ loadingHeight = me.loadingHeight,
+ undef;
+
+ me.callParent(arguments);
+ if (loadingText) {
+
+
+
+
+
+ me.loadMask = Ext.create('Ext.LoadMask', me.floating ? me : me.ownerCt || me, {
+ msg: loadingText,
+ msgCls: me.loadingCls,
+ useMsg: me.loadingUseMsg,
+ listeners: {
+ beforeshow: function() {
+ me.getTargetEl().update('');
+ me.getSelectionModel().deselectAll();
+ me.all.clear();
+ if (loadingHeight) {
+ me.setCalculatedSize(undef, loadingHeight);
+ }
+ },
+ hide: function() {
+ if (loadingHeight) {
+ me.setHeight(me.height);
+ }
+ }
+ }
+ });
+ }
+ },
+
+ getSelectionModel: function(){
+ var me = this,
+ mode = 'SINGLE';
+
+ if (!me.selModel) {
+ me.selModel = {};
+ }
+
+ if (me.simpleSelect) {
+ mode = 'SIMPLE';
+ } else if (me.multiSelect) {
+ mode = 'MULTI';
+ }
+
+ Ext.applyIf(me.selModel, {
+ allowDeselect: me.allowDeselect,
+ mode: mode
+ });
+
+ if (!me.selModel.events) {
+ me.selModel = Ext.create('Ext.selection.DataViewModel', me.selModel);
+ }
+
+ if (!me.selModel.hasRelaySetup) {
+ me.relayEvents(me.selModel, ['selectionchange', 'beforeselect', 'select', 'deselect']);
+ me.selModel.hasRelaySetup = true;
+ }
+
+
+
+ if (me.disableSelection) {
+ me.selModel.locked = true;
+ }
+
+ return me.selModel;
+ },
+
+
+ refresh: function() {
+ var me = this,
+ el,
+ records;
+
+ if (!me.rendered) {
+ return;
+ }
+
+ me.fireEvent('beforerefresh', me);
+ el = me.getTargetEl();
+ records = me.store.getRange();
+
+ el.update('');
+ if (records.length < 1) {
+ if (!me.deferEmptyText || me.hasSkippedEmptyText) {
+ el.update(me.emptyText);
+ }
+ me.all.clear();
+ } else {
+ me.tpl.overwrite(el, me.collectData(records, 0));
+ me.all.fill(Ext.query(me.getItemSelector(), el.dom));
+ me.updateIndexes(0);
+ }
+
+ me.selModel.refresh();
+ me.hasSkippedEmptyText = true;
+ me.fireEvent('refresh', me);
+ },
+
+
+ prepareData: function(data, index, record) {
+ if (record) {
+ Ext.apply(data, record.getAssociatedData());
+ }
+ return data;
+ },
+
+
+ collectData : function(records, startIndex){
+ var r = [],
+ i = 0,
+ len = records.length;
+
+ for(; i < len; i++){
+ r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
+ }
+
+ return r;
+ },
+
+
+ bufferRender : function(records, index){
+ var div = document.createElement('div');
+ this.tpl.overwrite(div, this.collectData(records, index));
+ return Ext.query(this.getItemSelector(), div);
+ },
+
+
+ onUpdate : function(ds, record){
+ var me = this,
+ index = me.store.indexOf(record),
+ original,
+ node;
+
+ if (index > -1){
+ original = me.all.elements[index];
+ node = me.bufferRender([record], index)[0];
+
+ me.all.replaceElement(index, node, true);
+ me.updateIndexes(index, index);
+
+
+
+ me.selModel.refresh();
+ me.fireEvent('itemupdate', record, index, node);
+ }
+
+ },
+
+
+ onAdd : function(ds, records, index) {
+ var me = this,
+ nodes;
+
+ if (me.all.getCount() === 0) {
+ me.refresh();
+ return;
+ }
+
+ nodes = me.bufferRender(records, index);
+ me.doAdd(nodes, records, index);
+
+ me.selModel.refresh();
+ me.updateIndexes(index);
+ me.fireEvent('itemadd', records, index, nodes);
+ },
+
+ doAdd: function(nodes, records, index) {
+ var n, a = this.all.elements;
+ if (index < this.all.getCount()) {
+ n = this.all.item(index).insertSibling(nodes, 'before', true);
+ a.splice.apply(a, [index, 0].concat(nodes));
+ }
+ else {
+ n = this.all.last().insertSibling(nodes, 'after', true);
+ a.push.apply(a, nodes);
+ }
+ },
+
+
+ onRemove : function(ds, record, index) {
+ var me = this;
+
+ me.doRemove(record, index);
+ me.updateIndexes(index);
+ if (me.store.getCount() === 0){
+ me.refresh();
+ }
+ me.fireEvent('itemremove', record, index);
+ },
+
+ doRemove: function(record, index) {
+ this.all.removeElement(index, true);
+ },
+
+
+ refreshNode : function(index){
+ this.onUpdate(this.store, this.store.getAt(index));
+ },
+
+
+ updateIndexes : function(startIndex, endIndex) {
+ var ns = this.all.elements,
+ records = this.store.getRange();
+ startIndex = startIndex || 0;
+ endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
+ for(var i = startIndex; i <= endIndex; i++){
+ ns[i].viewIndex = i;
+ ns[i].viewRecordId = records[i].internalId;
+ if (!ns[i].boundView) {
+ ns[i].boundView = this.id;
+ }
+ }
+ },
+
+
+ getStore : function(){
+ return this.store;
+ },
+
+
+ bindStore : function(store, initial) {
+ var me = this;
+
+ if (!initial && me.store) {
+ if (store !== me.store && me.store.autoDestroy) {
+ me.store.destroy();
+ }
+ else {
+ me.mun(me.store, {
+ scope: me,
+ datachanged: me.onDataChanged,
+ add: me.onAdd,
+ remove: me.onRemove,
+ update: me.onUpdate,
+ clear: me.refresh
+ });
+ }
+ if (!store) {
+ if (me.loadMask) {
+ me.loadMask.bindStore(null);
+ }
+ me.store = null;
+ }
+ }
+ if (store) {
+ store = Ext.data.StoreManager.lookup(store);
+ me.mon(store, {
+ scope: me,
+ datachanged: me.onDataChanged,
+ add: me.onAdd,
+ remove: me.onRemove,
+ update: me.onUpdate,
+ clear: me.refresh
+ });
+ if (me.loadMask) {
+ me.loadMask.bindStore(store);
+ }
+ }
+
+ me.store = store;
+
+ me.getSelectionModel().bind(store);
+
+ if (store) {
+ me.refresh(true);
+ }
+ },
+
+
+ onDataChanged: function() {
+ if (this.blockRefresh !== true) {
+ this.refresh.apply(this, arguments);
+ }
+ },
+
+
+ findItemByChild: function(node){
+ return Ext.fly(node).findParent(this.getItemSelector(), this.getTargetEl());
+ },
+
+
+ findTargetByEvent: function(e) {
+ return e.getTarget(this.getItemSelector(), this.getTargetEl());
+ },
+
+
+
+ getSelectedNodes: function(){
+ var nodes = [],
+ records = this.selModel.getSelection(),
+ ln = records.length,
+ i = 0;
+
+ for (; i < ln; i++) {
+ nodes.push(this.getNode(records[i]));
+ }
+
+ return nodes;
+ },
+
+
+ getRecords: function(nodes) {
+ var records = [],
+ i = 0,
+ len = nodes.length,
+ data = this.store.data;
+
+ for (; i < len; i++) {
+ records[records.length] = data.getByKey(nodes[i].viewRecordId);
+ }
+
+ return records;
+ },
+
+
+ getRecord: function(node){
+ return this.store.data.getByKey(Ext.getDom(node).viewRecordId);
+ },
+
+
+
+ isSelected : function(node) {
+
+ var r = this.getRecord(node);
+ return this.selModel.isSelected(r);
+ },
+
+
+ select: function(records, keepExisting, suppressEvent) {
+ this.selModel.select(records, keepExisting, suppressEvent);
+ },
+
+
+ deselect: function(records, suppressEvent) {
+ this.selModel.deselect(records, suppressEvent);
+ },
+
+
+ getNode : function(nodeInfo) {
+ if (Ext.isString(nodeInfo)) {
+ return document.getElementById(nodeInfo);
+ } else if (Ext.isNumber(nodeInfo)) {
+ return this.all.elements[nodeInfo];
+ } else if (nodeInfo instanceof Ext.data.Model) {
+ return this.getNodeByRecord(nodeInfo);
+ }
+ return nodeInfo;
+ },
+
+
+ getNodeByRecord: function(record) {
+ var ns = this.all.elements,
+ ln = ns.length,
+ i = 0;
+
+ for (; i < ln; i++) {
+ if (ns[i].viewRecordId === record.internalId) {
+ return ns[i];
+ }
+ }
+
+ return null;
+ },
+
+
+ getNodes: function(start, end) {
+ var ns = this.all.elements,
+ nodes = [],
+ i;
+
+ start = start || 0;
+ end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
+ if (start <= end) {
+ for (i = start; i <= end && ns[i]; i++) {
+ nodes.push(ns[i]);
+ }
+ } else {
+ for (i = start; i >= end && ns[i]; i--) {
+ nodes.push(ns[i]);
+ }
+ }
+ return nodes;
+ },
+
+
+ indexOf: function(node) {
+ node = this.getNode(node);
+ if (Ext.isNumber(node.viewIndex)) {
+ return node.viewIndex;
+ }
+ return this.all.indexOf(node);
+ },
+
+ onDestroy : function() {
+ var me = this;
+
+ me.all.clear();
+ me.callParent();
+ me.bindStore(null);
+ me.selModel.destroy();
+ },
+
+
+ onItemSelect: function(record) {
+ var node = this.getNode(record);
+ Ext.fly(node).addCls(this.selectedItemCls);
+ },
+
+
+ onItemDeselect: function(record) {
+ var node = this.getNode(record);
+ Ext.fly(node).removeCls(this.selectedItemCls);
+ },
+
+ getItemSelector: function() {
+ return this.itemSelector;
+ }
+}, function() {
+
+
+
+
+ Ext.deprecate('extjs', '4.0', function() {
+ Ext.view.AbstractView.override({
+
+
+
+
+
+ getSelectionCount : function(){
+ console.warn("DataView: getSelectionCount will be removed, please interact with the Ext.selection.DataViewModel");
+ return this.selModel.getSelection().length;
+ },
+
+
+ getSelectedRecords : function(){
+ console.warn("DataView: getSelectedRecords will be removed, please interact with the Ext.selection.DataViewModel");
+ return this.selModel.getSelection();
+ },
+
+ select: function(records, keepExisting, supressEvents) {
+ console.warn("DataView: select will be removed, please access select through a DataView's SelectionModel, ie: view.getSelectionModel().select()");
+ var sm = this.getSelectionModel();
+ return sm.select.apply(sm, arguments);
+ },
+
+ clearSelections: function() {
+ console.warn("DataView: clearSelections will be removed, please access deselectAll through DataView's SelectionModel, ie: view.getSelectionModel().deselectAll()");
+ var sm = this.getSelectionModel();
+ return sm.deselectAll();
+ }
+ });
+ });
+});
+
+
+Ext.define('Ext.Action', {
+
+
+
+
+
+
+
+
+
+
+
+
+
+ constructor : function(config){
+ this.initialConfig = config;
+ this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
+ this.items = [];
+ },
+
+
+ isAction : true,
+
+
+ setText : function(text){
+ this.initialConfig.text = text;
+ this.callEach('setText', [text]);
+ },
+
+
+ getText : function(){
+ return this.initialConfig.text;
+ },
+
+
+ setIconCls : function(cls){
+ this.initialConfig.iconCls = cls;
+ this.callEach('setIconCls', [cls]);
+ },
+
+
+ getIconCls : function(){
+ return this.initialConfig.iconCls;
+ },
+
+
+ setDisabled : function(v){
+ this.initialConfig.disabled = v;
+ this.callEach('setDisabled', [v]);
+ },
+
+
+ enable : function(){
+ this.setDisabled(false);
+ },
+
+
+ disable : function(){
+ this.setDisabled(true);
+ },
+
+
+ isDisabled : function(){
+ return this.initialConfig.disabled;
+ },
+
+
+ setHidden : function(v){
+ this.initialConfig.hidden = v;
+ this.callEach('setVisible', [!v]);
+ },
+
+
+ show : function(){
+ this.setHidden(false);
+ },
+
+
+ hide : function(){
+ this.setHidden(true);
+ },
+
+
+ isHidden : function(){
+ return this.initialConfig.hidden;
+ },
+
+
+ setHandler : function(fn, scope){
+ this.initialConfig.handler = fn;
+ this.initialConfig.scope = scope;
+ this.callEach('setHandler', [fn, scope]);
+ },
+
+
+ each : function(fn, scope){
+ Ext.each(this.items, fn, scope);
+ },
+
+
+ callEach : function(fnName, args){
+ var cs = this.items;
+ for(var i = 0, len = cs.length; i < len; i++){
+ cs[i][fnName].apply(cs[i], args);
+ }
+ },
+
+
+ addComponent : function(comp){
+ this.items.push(comp);
+ comp.on('destroy', this.removeComponent, this);
+ },
+
+
+ removeComponent : function(comp){
+ this.items.remove(comp);
+ },
+
+
+ execute : function(){
+ this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments);
+ }
+});
+
+
+Ext.define('Ext.layout.component.Editor', {
+
+
+
+ alias: ['layout.editor'],
+
+ extend: 'Ext.layout.component.Component',
+
+
+
+ onLayout: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ autoSize = owner.autoSize;
+
+ if (autoSize === true) {
+ autoSize = {
+ width: 'field',
+ height: 'field'
+ };
+ }
+
+ if (autoSize) {
+ width = me.getDimension(owner, autoSize.width, 'Width', width);
+ height = me.getDimension(owner, autoSize.height, 'Height', height);
+ }
+ me.setTargetSize(width, height);
+ owner.field.setSize(width, height);
+ },
+
+ getDimension: function(owner, type, dimension, actual){
+ var method = 'get' + dimension;
+ switch (type) {
+ case 'boundEl':
+ return owner.boundEl[method]();
+ case 'field':
+ return owner.field[method]();
+ default:
+ return actual;
+ }
+ }
+});
+
+Ext.define('Ext.Editor', {
+
+
+
+ extend: 'Ext.Component',
+
+ alias: 'widget.editor',
+
+ requires: ['Ext.layout.component.Editor'],
+
+
+
+ componentLayout: 'editor',
+
+
+
+
+ allowBlur: true,
+
+
+
+
+ revertInvalid: true,
+
+
+
+
+
+
+ value : '',
+
+
+ alignment: 'c-c?',
+
+
+ offsets: [0, 0],
+
+
+ shadow : 'frame',
+
+
+ constrain : false,
+
+
+ swallowKeys : true,
+
+
+ completeOnEnter : true,
+
+
+ cancelOnEsc : true,
+
+
+ updateEl : false,
+
+
+
+
+ hidden: true,
+ baseCls: Ext.baseCSSPrefix + 'editor',
+
+ initComponent : function() {
+ var me = this,
+ field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
+
+ Ext.apply(field, {
+ inEditor: true,
+ msgTarget: field.msgTarget == 'title' ? 'title' : 'qtip'
+ });
+ me.mon(field, {
+ scope: me,
+ blur: {
+ fn: me.onBlur,
+
+ delay: 1
+ },
+ specialkey: me.onSpecialKey
+ });
+
+ if (field.grow) {
+ me.mon(field, 'autosize', me.onAutoSize, me, {delay: 1});
+ }
+ me.floating = {
+ constrain: me.constrain
+ };
+
+ me.callParent(arguments);
+
+ me.addEvents(
+
+ 'beforestartedit',
+
+ 'startedit',
+
+ 'beforecomplete',
+
+ 'complete',
+
+ 'canceledit',
+
+ 'specialkey'
+ );
+ },
+
+
+ onAutoSize: function(){
+ this.doComponentLayout();
+ },
+
+
+ onRender : function(ct, position) {
+ var me = this,
+ field = me.field;
+
+ me.callParent(arguments);
+
+ field.render(me.el);
+
+
+ field.inputEl.dom.name = '';
+ if (me.swallowKeys) {
+ field.inputEl.swallowEvent([
+ 'keypress',
+ 'keydown'
+ ]);
+ }
+ },
+
+
+ onSpecialKey : function(field, event) {
+ var me = this,
+ key = event.getKey(),
+ complete = me.completeOnEnter && key == event.ENTER,
+ cancel = me.cancelOnEsc && key == event.ESC;
+
+ if (complete || cancel) {
+ event.stopEvent();
+
+
+ Ext.defer(function() {
+ if (complete) {
+ me.completeEdit();
+ } else {
+ me.cancelEdit();
+ }
+ if (field.triggerBlur) {
+ field.triggerBlur();
+ }
+ }, 10);
+ }
+
+ this.fireEvent('specialkey', this, field, event);
+ },
+
+
+ startEdit : function(el, value) {
+ var me = this,
+ field = me.field;
+
+ me.completeEdit();
+ me.boundEl = Ext.get(el);
+ value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
+
+ if (!me.rendered) {
+ me.render(me.parentEl || document.body);
+ }
+
+ if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
+ me.startValue = value;
+ me.show();
+ field.reset();
+ field.setValue(value);
+ me.realign(true);
+ field.focus(false, 10);
+ if (field.autoSize) {
+ field.autoSize();
+ }
+ me.editing = true;
+ }
+ },
+
+
+ realign : function(autoSize) {
+ var me = this;
+ if (autoSize === true) {
+ me.doComponentLayout();
+ }
+ me.alignTo(me.boundEl, me.alignment, me.offsets);
+ },
+
+
+ completeEdit : function(remainVisible) {
+ var me = this,
+ field = me.field,
+ value;
+
+ if (!me.editing) {
+ return;
+ }
+
+
+ if (field.assertValue) {
+ field.assertValue();
+ }
+
+ value = me.getValue();
+ if (!field.isValid()) {
+ if (me.revertInvalid !== false) {
+ me.cancelEdit(remainVisible);
+ }
+ return;
+ }
+
+ if (String(value) === String(me.startValue) && me.ignoreNoChange) {
+ me.hideEdit(remainVisible);
+ return;
+ }
+
+ if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) {
+
+ value = me.getValue();
+ if (me.updateEl && me.boundEl) {
+ me.boundEl.update(value);
+ }
+ me.hideEdit(remainVisible);
+ me.fireEvent('complete', me, value, me.startValue);
+ }
+ },
+
+
+ onShow : function() {
+ var me = this;
+
+ me.callParent(arguments);
+ if (me.hideEl !== false) {
+ me.boundEl.hide();
+ }
+ me.fireEvent("startedit", me.boundEl, me.startValue);
+ },
+
+
+ cancelEdit : function(remainVisible) {
+ var me = this,
+ startValue = me.startValue,
+ value;
+
+ if (me.editing) {
+ value = me.getValue();
+ me.setValue(startValue);
+ me.hideEdit(remainVisible);
+ me.fireEvent('canceledit', me, value, startValue);
+ }
+ },
+
+
+ hideEdit: function(remainVisible) {
+ if (remainVisible !== true) {
+ this.editing = false;
+ this.hide();
+ }
+ },
+
+
+ onBlur : function() {
+ var me = this;
+
+
+ if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) {
+ me.completeEdit();
+ }
+ },
+
+
+ onHide : function() {
+ var me = this,
+ field = me.field;
+
+ if (me.editing) {
+ me.completeEdit();
+ return;
+ }
+ field.blur();
+ if (field.collapse) {
+ field.collapse();
+ }
+
+
+ if (me.hideEl !== false) {
+ me.boundEl.show();
+ }
+ me.callParent(arguments);
+ },
+
+
+ setValue : function(value) {
+ this.field.setValue(value);
+ },
+
+
+ getValue : function() {
+ return this.field.getValue();
+ },
+
+ beforeDestroy : function() {
+ var me = this;
+
+ Ext.destroy(me.field);
+ delete me.field;
+ delete me.parentEl;
+ delete me.boundEl;
+
+ me.callParent(arguments);
+ }
+});
+
+Ext.define('Ext.Img', {
+ extend: 'Ext.Component',
+ alias: ['widget.image', 'widget.imagecomponent'],
+
+ src: '',
+
+ getElConfig: function() {
+ return {
+ tag: 'img',
+ src: this.src
+ };
+ },
+
+
+ setSrc: function(src) {
+ var me = this,
+ img = me.el;
+ me.src = src;
+ if (img) {
+ img.dom.src = src;
+ }
+ }
+});
+
+
+Ext.define('Ext.Layer', {
+ uses: ['Ext.Shadow'],
+
+
+ statics: {
+ shims: []
+ },
+
+ extend: 'Ext.core.Element',
+
+ constructor: function(config, existingEl) {
+ config = config || {};
+ var me = this,
+ dh = Ext.core.DomHelper,
+ cp = config.parentEl,
+ pel = cp ? Ext.getDom(cp) : document.body,
+ hm = config.hideMode;
+
+ if (existingEl) {
+ me.dom = Ext.getDom(existingEl);
+ }
+ if (!me.dom) {
+ me.dom = dh.append(pel, config.dh || {
+ tag: 'div',
+ cls: Ext.baseCSSPrefix + 'layer'
+ });
+ } else {
+ me.addCls(Ext.baseCSSPrefix + 'layer');
+ if (!me.dom.parentNode) {
+ pel.appendChild(me.dom);
+ }
+ }
+
+ if (config.cls) {
+ me.addCls(config.cls);
+ }
+ me.constrain = config.constrain !== false;
+
+
+
+
+ if (hm) {
+ me.setVisibilityMode(Ext.core.Element[hm.toUpperCase()]);
+ if (me.visibilityMode == Ext.core.Element.ASCLASS) {
+ me.visibilityCls = config.visibilityCls;
+ }
+ } else if (config.useDisplay) {
+ me.setVisibilityMode(Ext.core.Element.DISPLAY);
+ } else {
+ me.setVisibilityMode(Ext.core.Element.VISIBILITY);
+ }
+
+ if (config.id) {
+ me.id = me.dom.id = config.id;
+ } else {
+ me.id = Ext.id(me.dom);
+ }
+ me.position('absolute');
+ if (config.shadow) {
+ me.shadowOffset = config.shadowOffset || 4;
+ me.shadow = Ext.create('Ext.Shadow', {
+ offset: me.shadowOffset,
+ mode: config.shadow
+ });
+ me.disableShadow();
+ } else {
+ me.shadowOffset = 0;
+ }
+ me.useShim = config.shim !== false && Ext.useShims;
+ if (config.hidden === true) {
+ me.hide();
+ } else {
+ this.show();
+ }
+ },
+
+ getZIndex: function() {
+ return parseInt((this.getShim() || this).getStyle('z-index'), 10);
+ },
+
+ getShim: function() {
+ var me = this,
+ shim, pn;
+
+ if (!me.useShim) {
+ return null;
+ }
+ if (!me.shim) {
+ shim = me.self.shims.shift();
+ if (!shim) {
+ shim = me.createShim();
+ shim.enableDisplayMode('block');
+ shim.hide();
+ }
+ pn = me.dom.parentNode;
+ if (shim.dom.parentNode != pn) {
+ pn.insertBefore(shim.dom, me.dom);
+ }
+ me.shim = shim;
+ }
+ return me.shim;
+ },
+
+ hideShim: function() {
+ if (this.shim) {
+ this.shim.setDisplayed(false);
+ this.self.shims.push(this.shim);
+ delete this.shim;
+ }
+ },
+
+ disableShadow: function() {
+ if (this.shadow) {
+ this.shadowDisabled = true;
+ this.shadow.hide();
+ this.lastShadowOffset = this.shadowOffset;
+ this.shadowOffset = 0;
+ }
+ },
+
+ enableShadow: function(show) {
+ if (this.shadow) {
+ this.shadowDisabled = false;
+ this.shadowOffset = this.lastShadowOffset;
+ delete this.lastShadowOffset;
+ if (show) {
+ this.sync(true);
+ }
+ }
+ },
+
+
+ sync: function(doShow) {
+ var me = this,
+ shadow = me.shadow,
+ shadowPos, shimStyle, shadowSize;
+
+ if (!this.updating && this.isVisible() && (shadow || this.useShim)) {
+ var shim = this.getShim(),
+ l = this.getLeft(true),
+ t = this.getTop(true),
+ w = this.getWidth(),
+ h = this.getHeight(),
+ shimIndex;
+
+ if (shadow && !this.shadowDisabled) {
+ if (doShow && !shadow.isVisible()) {
+ shadow.show(this);
+ } else {
+ shadow.realign(l, t, w, h);
+ }
+ if (shim) {
+
+ shimIndex = shim.getStyle('z-index');
+ if (shimIndex > me.zindex) {
+ me.shim.setStyle('z-index', me.zindex - 2);
+ }
+ shim.show();
+
+ if (shadow.isVisible()) {
+ shadowPos = shadow.el.getXY();
+ shimStyle = shim.dom.style;
+ shadowSize = shadow.el.getSize();
+ shimStyle.left = (shadowPos[0]) + 'px';
+ shimStyle.top = (shadowPos[1]) + 'px';
+ shimStyle.width = (shadowSize.width) + 'px';
+ shimStyle.height = (shadowSize.height) + 'px';
+ } else {
+ shim.setSize(w, h);
+ shim.setLeftTop(l, t);
+ }
+ }
+ } else if (shim) {
+
+ shimIndex = shim.getStyle('z-index');
+ if (shimIndex > me.zindex) {
+ me.shim.setStyle('z-index', me.zindex - 2);
+ }
+ shim.show();
+ shim.setSize(w, h);
+ shim.setLeftTop(l, t);
+ }
+ }
+ return this;
+ },
+
+ remove: function() {
+ this.hideUnders();
+ this.callParent();
+ },
+
+
+ beginUpdate: function() {
+ this.updating = true;
+ },
+
+
+ endUpdate: function() {
+ this.updating = false;
+ this.sync(true);
+ },
+
+
+ hideUnders: function() {
+ if (this.shadow) {
+ this.shadow.hide();
+ }
+ this.hideShim();
+ },
+
+
+ constrainXY: function() {
+ if (this.constrain) {
+ var vw = Ext.core.Element.getViewWidth(),
+ vh = Ext.core.Element.getViewHeight(),
+ s = Ext.getDoc().getScroll(),
+ xy = this.getXY(),
+ x = xy[0],
+ y = xy[1],
+ so = this.shadowOffset,
+ w = this.dom.offsetWidth + so,
+ h = this.dom.offsetHeight + so,
+ moved = false;
+
+ if ((x + w) > vw + s.left) {
+ x = vw - w - so;
+ moved = true;
+ }
+ if ((y + h) > vh + s.top) {
+ y = vh - h - so;
+ moved = true;
+ }
+
+ if (x < s.left) {
+ x = s.left;
+ moved = true;
+ }
+ if (y < s.top) {
+ y = s.top;
+ moved = true;
+ }
+ if (moved) {
+ Ext.Layer.superclass.setXY.call(this, [x, y]);
+ this.sync();
+ }
+ }
+ return this;
+ },
+
+ getConstrainOffset: function() {
+ return this.shadowOffset;
+ },
+
+
+ setVisible: function(visible, animate, duration, callback, easing) {
+ var me = this,
+ cb;
+
+
+ cb = function() {
+ if (visible) {
+ me.sync(true);
+ }
+ if (callback) {
+ callback();
+ }
+ };
+
+
+ if (!visible) {
+ this.hideUnders(true);
+ }
+ this.callParent([visible, animate, duration, callback, easing]);
+ if (!animate) {
+ cb();
+ }
+ return this;
+ },
+
+
+ beforeFx: function() {
+ this.beforeAction();
+ return this.callParent(arguments);
+ },
+
+
+ afterFx: function() {
+ this.callParent(arguments);
+ this.sync(this.isVisible());
+ },
+
+
+ beforeAction: function() {
+ if (!this.updating && this.shadow) {
+ this.shadow.hide();
+ }
+ },
+
+
+ setLeft: function(left) {
+ this.callParent(arguments);
+ return this.sync();
+ },
+
+ setTop: function(top) {
+ this.callParent(arguments);
+ return this.sync();
+ },
+
+ setLeftTop: function(left, top) {
+ this.callParent(arguments);
+ return this.sync();
+ },
+
+ setXY: function(xy, animate, duration, callback, easing) {
+
+
+ callback = this.createCB(callback);
+
+ this.fixDisplay();
+ this.beforeAction();
+ this.callParent([xy, animate, duration, callback, easing]);
+ if (!animate) {
+ callback();
+ }
+ return this;
+ },
+
+
+ createCB: function(callback) {
+ var me = this,
+ showShadow = me.shadow && me.shadow.isVisible();
+
+ return function() {
+ me.constrainXY();
+ me.sync(showShadow);
+ if (callback) {
+ callback();
+ }
+ };
+ },
+
+
+ setX: function(x, animate, duration, callback, easing) {
+ this.setXY([x, this.getY()], animate, duration, callback, easing);
+ return this;
+ },
+
+
+ setY: function(y, animate, duration, callback, easing) {
+ this.setXY([this.getX(), y], animate, duration, callback, easing);
+ return this;
+ },
+
+
+ setSize: function(w, h, animate, duration, callback, easing) {
+
+ callback = this.createCB(callback);
+
+ this.beforeAction();
+ this.callParent([w, h, animate, duration, callback, easing]);
+ if (!animate) {
+ callback();
+ }
+ return this;
+ },
+
+
+ setWidth: function(w, animate, duration, callback, easing) {
+
+ callback = this.createCB(callback);
+
+ this.beforeAction();
+ this.callParent([w, animate, duration, callback, easing]);
+ if (!animate) {
+ callback();
+ }
+ return this;
+ },
+
+
+ setHeight: function(h, animate, duration, callback, easing) {
+
+ callback = this.createCB(callback);
+
+ this.beforeAction();
+ this.callParent([h, animate, duration, callback, easing]);
+ if (!animate) {
+ callback();
+ }
+ return this;
+ },
+
+
+ setBounds: function(x, y, width, height, animate, duration, callback, easing) {
+
+ callback = this.createCB(callback);
+
+ this.beforeAction();
+ if (!animate) {
+ Ext.Layer.superclass.setXY.call(this, [x, y]);
+ Ext.Layer.superclass.setSize.call(this, width, height);
+ callback();
+ } else {
+ this.callParent([x, y, width, height, animate, duration, callback, easing]);
+ }
+ return this;
+ },
+
+
+ setZIndex: function(zindex) {
+ this.zindex = zindex;
+ if (this.getShim()) {
+ this.shim.setStyle('z-index', zindex++);
+ }
+ if (this.shadow) {
+ this.shadow.setZIndex(zindex++);
+ }
+ this.setStyle('z-index', zindex);
+ return this;
+ }
+});
+
+
+
+Ext.define('Ext.layout.component.ProgressBar', {
+
+
+
+ alias: ['layout.progressbar'],
+
+ extend: 'Ext.layout.component.Component',
+
+
+
+ type: 'progressbar',
+
+ onLayout: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ textEl = owner.textEl;
+
+ me.setElementSize(owner.el, width, height);
+ textEl.setWidth(owner.el.getWidth(true));
+
+ me.callParent([width, height]);
+
+ owner.updateProgress(owner.value);
+ }
+});
+
+Ext.define('Ext.ProgressBar', {
+ extend: 'Ext.Component',
+ alias: 'widget.progressbar',
+
+ requires: [
+ 'Ext.Template',
+ 'Ext.CompositeElement',
+ 'Ext.TaskManager',
+ 'Ext.layout.component.ProgressBar'
+ ],
+
+ uses: ['Ext.fx.Anim'],
+
+ baseCls: Ext.baseCSSPrefix + 'progress',
+
+ config: {
+
+ animate: false,
+
+
+ text: ''
+ },
+
+
+ waitTimer: null,
+
+ renderTpl: [
+ '<div class="{baseCls}-text {baseCls}-text-back">',
+ '<div> </div>',
+ '</div>',
+ '<div class="{baseCls}-bar">',
+ '<div class="{baseCls}-text">',
+ '<div> </div>',
+ '</div>',
+ '</div>'
+ ],
+
+ componentLayout: 'progressbar',
+
+
+ initComponent: function() {
+ this.callParent();
+
+ this.renderSelectors = Ext.apply(this.renderSelectors || {}, {
+ textTopEl: '.' + this.baseCls + '-text',
+ textBackEl: '.' + this.baseCls + '-text-back',
+ bar: '.' + this.baseCls + '-bar'
+ });
+
+ this.addEvents(
+
+ "update"
+ );
+ },
+
+ afterRender : function() {
+ var me = this;
+
+ me.textEl = me.textEl ? Ext.get(me.textEl) : me.el.select('.' + me.baseCls + '-text');
+
+ this.callParent(arguments);
+
+ if (me.value) {
+ me.updateProgress(me.value, me.text);
+ }
+ else {
+ me.updateText(me.text);
+ }
+ },
+
+
+ updateProgress: function(value, text, animate) {
+ var newWidth;
+ this.value = value || 0;
+ if (text) {
+ this.updateText(text);
+ }
+ if (this.rendered && !this.isDestroyed) {
+ newWidth = Math.floor(this.value * this.el.getWidth(true));
+ if (Ext.isForcedBorderBox) {
+ newWidth += this.bar.getBorderWidth("lr");
+ }
+ if (animate === true || (animate !== false && this.animate)) {
+ this.bar.stopAnimation();
+ this.bar.animate(Ext.apply({
+ to: {
+ width: newWidth + 'px'
+ }
+ }, this.animate));
+ } else {
+ this.bar.setWidth(newWidth);
+ }
+ }
+ this.fireEvent('update', this, this.value, text);
+ return this;
+ },
+
+
+ updateText: function(text) {
+ this.text = text;
+ if (this.rendered) {
+ this.textEl.update(this.text);
+ }
+ return this;
+ },
+
+ applyText : function(text) {
+ this.updateText(text);
+ },
+
+
+ wait: function(o) {
+ if (!this.waitTimer) {
+ var scope = this;
+ o = o || {};
+ this.updateText(o.text);
+ this.waitTimer = Ext.TaskManager.start({
+ run: function(i){
+ var inc = o.increment || 10;
+ i -= 1;
+ this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
+ },
+ interval: o.interval || 1000,
+ duration: o.duration,
+ onStop: function(){
+ if (o.fn) {
+ o.fn.apply(o.scope || this);
+ }
+ this.reset();
+ },
+ scope: scope
+ });
+ }
+ return this;
+ },
+
+
+ isWaiting: function(){
+ return this.waitTimer !== null;
+ },
+
+
+ reset: function(hide){
+ this.updateProgress(0);
+ this.clearTimer();
+ if (hide === true) {
+ this.hide();
+ }
+ return this;
+ },
+
+
+ clearTimer: function(){
+ if (this.waitTimer) {
+ this.waitTimer.onStop = null;
+ Ext.TaskManager.stop(this.waitTimer);
+ this.waitTimer = null;
+ }
+ },
+
+ onDestroy: function(){
+ this.clearTimer();
+ if (this.rendered) {
+ if (this.textEl.isComposite) {
+ this.textEl.clear();
+ }
+ Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
+ }
+ this.callParent();
+ }
+});
+
+
+Ext.define('Ext.ShadowPool', {
+ singleton: true,
+ requires: ['Ext.core.DomHelper'],
+
+ markup: function() {
+ if (Ext.supports.CSS3BoxShadow) {
+ return '<div class="' + Ext.baseCSSPrefix + 'css-shadow" role="presentation"></div>';
+ } else if (Ext.isIE) {
+ return '<div class="' + Ext.baseCSSPrefix + 'ie-shadow" role="presentation"></div>';
+ } else {
+ return '<div class="' + Ext.baseCSSPrefix + 'frame-shadow" role="presentation">' +
+ '<div class="xst" role="presentation">' +
+ '<div class="xstl" role="presentation"></div>' +
+ '<div class="xstc" role="presentation"></div>' +
+ '<div class="xstr" role="presentation"></div>' +
+ '</div>' +
+ '<div class="xsc" role="presentation">' +
+ '<div class="xsml" role="presentation"></div>' +
+ '<div class="xsmc" role="presentation"></div>' +
+ '<div class="xsmr" role="presentation"></div>' +
+ '</div>' +
+ '<div class="xsb" role="presentation">' +
+ '<div class="xsbl" role="presentation"></div>' +
+ '<div class="xsbc" role="presentation"></div>' +
+ '<div class="xsbr" role="presentation"></div>' +
+ '</div>' +
+ '</div>';
+ }
+ }(),
+
+ shadows: [],
+
+ pull: function() {
+ var sh = this.shadows.shift();
+ if (!sh) {
+ sh = Ext.get(Ext.core.DomHelper.insertHtml("beforeBegin", document.body.firstChild, this.markup));
+ sh.autoBoxAdjust = false;
+ }
+ return sh;
+ },
+
+ push: function(sh) {
+ this.shadows.push(sh);
+ },
+
+ reset: function() {
+ Ext.Array.each(this.shadows, function(shadow) {
+ shadow.remove();
+ });
+ this.shadows = [];
+ }
+});
+
+Ext.define('Ext.Shadow', {
+ requires: ['Ext.ShadowPool'],
+
+ constructor: function(config) {
+ Ext.apply(this, config);
+ if (typeof this.mode != "string") {
+ this.mode = this.defaultMode;
+ }
+ var offset = this.offset,
+ adjusts = {
+ h: 0
+ },
+ rad = Math.floor(this.offset / 2);
+
+ switch (this.mode.toLowerCase()) {
+
+ case "drop":
+ if (Ext.supports.CSS3BoxShadow) {
+ adjusts.w = adjusts.h = -offset;
+ adjusts.l = adjusts.t = offset;
+ } else {
+ adjusts.w = 0;
+ adjusts.l = adjusts.t = offset;
+ adjusts.t -= 1;
+ if (Ext.isIE) {
+ adjusts.l -= offset + rad;
+ adjusts.t -= offset + rad;
+ adjusts.w -= rad;
+ adjusts.h -= rad;
+ adjusts.t += 1;
+ }
+ }
+ break;
+ case "sides":
+ if (Ext.supports.CSS3BoxShadow) {
+ adjusts.h -= offset;
+ adjusts.t = offset;
+ adjusts.l = adjusts.w = 0;
+ } else {
+ adjusts.w = (offset * 2);
+ adjusts.l = -offset;
+ adjusts.t = offset - 1;
+ if (Ext.isIE) {
+ adjusts.l -= (offset - rad);
+ adjusts.t -= offset + rad;
+ adjusts.l += 1;
+ adjusts.w -= (offset - rad) * 2;
+ adjusts.w -= rad + 1;
+ adjusts.h -= 1;
+ }
+ }
+ break;
+ case "frame":
+ if (Ext.supports.CSS3BoxShadow) {
+ adjusts.l = adjusts.w = adjusts.t = 0;
+ } else {
+ adjusts.w = adjusts.h = (offset * 2);
+ adjusts.l = adjusts.t = -offset;
+ adjusts.t += 1;
+ adjusts.h -= 2;
+ if (Ext.isIE) {
+ adjusts.l -= (offset - rad);
+ adjusts.t -= (offset - rad);
+ adjusts.l += 1;
+ adjusts.w -= (offset + rad + 1);
+ adjusts.h -= (offset + rad);
+ adjusts.h += 1;
+ }
+ break;
+ }
+ }
+ this.adjusts = adjusts;
+ },
+
+
+
+ offset: 4,
+
+
+ defaultMode: "drop",
+
+
+ show: function(target) {
+ target = Ext.get(target);
+ if (!this.el) {
+ this.el = Ext.ShadowPool.pull();
+ if (this.el.dom.nextSibling != target.dom) {
+ this.el.insertBefore(target);
+ }
+ }
+ this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
+ if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
+ this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
+ }
+ this.realign(
+ target.getLeft(true),
+ target.getTop(true),
+ target.getWidth(),
+ target.getHeight()
+ );
+ this.el.dom.style.display = "block";
+ },
+
+
+ isVisible: function() {
+ return this.el ? true: false;
+ },
+
+
+ realign: function(l, t, targetWidth, targetHeight) {
+ if (!this.el) {
+ return;
+ }
+ var adjusts = this.adjusts,
+ d = this.el.dom,
+ targetStyle = d.style,
+ shadowWidth,
+ shadowHeight,
+ cn,
+ sww,
+ sws,
+ shs;
+
+ targetStyle.left = (l + adjusts.l) + "px";
+ targetStyle.top = (t + adjusts.t) + "px";
+ shadowWidth = Math.max(targetWidth + adjusts.w, 0);
+ shadowHeight = Math.max(targetHeight + adjusts.h, 0);
+ sws = shadowWidth + "px";
+ shs = shadowHeight + "px";
+ if (targetStyle.width != sws || targetStyle.height != shs) {
+ targetStyle.width = sws;
+ targetStyle.height = shs;
+ if (Ext.supports.CSS3BoxShadow) {
+ targetStyle.boxShadow = '0 0 ' + this.offset + 'px 0 #888';
+ } else {
+
+
+ if (!Ext.isIE) {
+ cn = d.childNodes;
+ sww = Math.max(0, (shadowWidth - 12)) + "px";
+ cn[0].childNodes[1].style.width = sww;
+ cn[1].childNodes[1].style.width = sww;
+ cn[2].childNodes[1].style.width = sww;
+ cn[1].style.height = Math.max(0, (shadowHeight - 12)) + "px";
+ }
+ }
+ }
+ },
+
+
+ hide: function() {
+ if (this.el) {
+ this.el.dom.style.display = "none";
+ Ext.ShadowPool.push(this.el);
+ delete this.el;
+ }
+ },
+
+
+ setZIndex: function(z) {
+ this.zIndex = z;
+ if (this.el) {
+ this.el.setStyle("z-index", z);
+ }
+ }
+});
+
+
+Ext.define('Ext.button.Split', {
+
+
+
+ alias: 'widget.splitbutton',
+
+ extend: 'Ext.button.Button',
+ alternateClassName: 'Ext.SplitButton',
+
+
+ arrowCls : 'split',
+ split : true,
+
+
+ initComponent : function(){
+ this.callParent();
+
+ this.addEvents("arrowclick");
+ },
+
+
+ setArrowHandler : function(handler, scope){
+ this.arrowHandler = handler;
+ this.scope = scope;
+ },
+
+
+ onClick : function(e, t) {
+ var me = this;
+
+ e.preventDefault();
+ if (!me.disabled) {
+ if (me.overMenuTrigger) {
+ if (me.menu && !me.menu.isVisible() && !me.ignoreNextClick) {
+ me.showMenu();
+ }
+ me.fireEvent("arrowclick", me, e);
+ if (me.arrowHandler) {
+ me.arrowHandler.call(me.scope || me, me, e);
+ }
+ } else {
+ if (me.enableToggle) {
+ me.toggle();
+ }
+ me.fireEvent("click", me, e);
+ if (me.handler) {
+ me.handler.call(me.scope || me, me, e);
+ }
+ me.onBlur();
+ }
+ }
+ }
+});
+
+
+Ext.define('Ext.button.Cycle', {
+
+
+
+ alias: 'widget.cycle',
+
+ extend: 'Ext.button.Split',
+ alternateClassName: 'Ext.CycleButton',
+
+
+
+
+
+
+
+
+
+
+
+ getButtonText: function(item) {
+ var me = this,
+ text = '';
+
+ if (item && me.showText === true) {
+ if (me.prependText) {
+ text += me.prependText;
+ }
+ text += item.text;
+ return text;
+ }
+ return me.text;
+ },
+
+
+ setActiveItem: function(item, suppressEvent) {
+ var me = this;
+
+ if (!Ext.isObject(item)) {
+ item = me.menu.getComponent(item);
+ }
+ if (item) {
+ if (!me.rendered) {
+ me.text = me.getButtonText(item);
+ me.iconCls = item.iconCls;
+ } else {
+ me.setText(me.getButtonText(item));
+ me.setIconCls(item.iconCls);
+ }
+ me.activeItem = item;
+ if (!item.checked) {
+ item.setChecked(true, false);
+ }
+ if (me.forceIcon) {
+ me.setIconCls(me.forceIcon);
+ }
+ if (!suppressEvent) {
+ me.fireEvent('change', me, item);
+ }
+ }
+ },
+
+
+ getActiveItem: function() {
+ return this.activeItem;
+ },
+
+
+ initComponent: function() {
+ var me = this,
+ checked = 0,
+ items;
+
+ me.addEvents(
+
+ "change"
+ );
+
+ if (me.changeHandler) {
+ me.on('change', me.changeHandler, me.scope || me);
+ delete me.changeHandler;
+ }
+
+
+
+ items = (me.menu.items||[]).concat(me.items||[]);
+ me.menu = Ext.applyIf({
+ cls: Ext.baseCSSPrefix + 'cycle-menu',
+ items: []
+ }, me.menu);
+
+
+ Ext.each(items, function(item, i) {
+ item = Ext.applyIf({
+ group: me.id,
+ itemIndex: i,
+ checkHandler: me.checkHandler,
+ scope: me,
+ checked: item.checked || false
+ }, item);
+ me.menu.items.push(item);
+ if (item.checked) {
+ checked = i;
+ }
+ });
+ me.itemCount = me.menu.items.length;
+ me.callParent(arguments);
+ me.on('click', me.toggleSelected, me);
+ me.setActiveItem(checked, me);
+
+
+ if (me.width && me.showText) {
+ me.addCls(Ext.baseCSSPrefix + 'cycle-fixed-width');
+ }
+ },
+
+
+ checkHandler: function(item, pressed) {
+ if (pressed) {
+ this.setActiveItem(item);
+ }
+ },
+
+
+ toggleSelected: function() {
+ var me = this,
+ m = me.menu,
+ checkItem;
+
+ checkItem = me.activeItem.next(':not([disabled])') || m.items.getAt(0);
+ checkItem.setChecked(true);
+ }
+});
+
+Ext.define('Ext.container.ButtonGroup', {
+ extend: 'Ext.panel.Panel',
+ alias: 'widget.buttongroup',
+ alternateClassName: 'Ext.ButtonGroup',
+
+
+
+
+ baseCls: Ext.baseCSSPrefix + 'btn-group',
+
+
+ layout: {
+ type: 'table'
+ },
+
+ defaultType: 'button',
+
+
+ frame: true,
+
+ frameHeader: false,
+
+ internalDefaults: {removeMode: 'container', hideParent: true},
+
+ initComponent : function(){
+
+ var me = this,
+ cols = me.columns;
+
+ me.noTitleCls = me.baseCls + '-notitle';
+ if (cols) {
+ me.layout = Ext.apply({}, {columns: cols}, me.layout);
+ }
+
+ if (!me.title) {
+ me.addCls(me.noTitleCls);
+ }
+ me.callParent(arguments);
+ },
+
+ afterLayout: function() {
+ var me = this;
+
+ me.callParent(arguments);
+
+
+
+ if (me.layout.table && (Ext.isIEQuirks || Ext.isIE6) && !me.width) {
+ var t = me.getTargetEl();
+ t.setWidth(me.layout.table.offsetWidth + t.getPadding('lr'));
+ }
+ },
+
+ afterRender: function() {
+ var me = this;
+
+
+ if (me.header) {
+ me.header.insert(0, {
+ xtype: 'component',
+ ui : me.ui,
+ html : ' ',
+ flex : 1
+ });
+ }
+
+ me.callParent(arguments);
+ },
+
+
+ onBeforeAdd: function(component) {
+ if (component.is('button')) {
+ component.ui = component.ui + '-toolbar';
+ }
+ this.callParent(arguments);
+ },
+
+
+ applyDefaults: function(c) {
+ if (!Ext.isString(c)) {
+ c = this.callParent(arguments);
+ var d = this.internalDefaults;
+ if (c.events) {
+ Ext.applyIf(c.initialConfig, d);
+ Ext.apply(c, d);
+ } else {
+ Ext.applyIf(c, d);
+ }
+ }
+ return c;
+ }
+
+
+
+
+
+
+});
+
+
+Ext.define('Ext.container.Viewport', {
+ extend: 'Ext.container.Container',
+ alias: 'widget.viewport',
+ requires: ['Ext.EventManager'],
+ alternateClassName: 'Ext.Viewport',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ isViewport: true,
+
+ ariaRole: 'application',
+ initComponent : function() {
+ var me = this,
+ html = Ext.fly(document.body.parentNode),
+ el;
+ me.callParent(arguments);
+ html.addCls(Ext.baseCSSPrefix + 'viewport');
+ if (me.autoScroll) {
+ html.setStyle('overflow', 'auto');
+ }
+ me.el = el = Ext.getBody();
+ el.setHeight = Ext.emptyFn;
+ el.setWidth = Ext.emptyFn;
+ el.setSize = Ext.emptyFn;
+ el.dom.scroll = 'no';
+ me.allowDomMove = false;
+
+
+ Ext.EventManager.onWindowResize(me.fireResize, me);
+ me.renderTo = me.el;
+ },
+
+ fireResize : function(w, h){
+
+ this.setSize(w, h);
+
+ }
+});
+
+
+
+
+
+Ext.define('Ext.dd.DDTarget', {
+ extend: 'Ext.dd.DragDrop',
+ constructor: function(id, sGroup, config) {
+ if (id) {
+ this.initTarget(id, sGroup, config);
+ }
+ },
+
+
+ getDragEl: Ext.emptyFn,
+
+ isValidHandleChild: Ext.emptyFn,
+
+ startDrag: Ext.emptyFn,
+
+ endDrag: Ext.emptyFn,
+
+ onDrag: Ext.emptyFn,
+
+ onDragDrop: Ext.emptyFn,
+
+ onDragEnter: Ext.emptyFn,
+
+ onDragOut: Ext.emptyFn,
+
+ onDragOver: Ext.emptyFn,
+
+ onInvalidDrop: Ext.emptyFn,
+
+ onMouseDown: Ext.emptyFn,
+
+ onMouseUp: Ext.emptyFn,
+
+ setXConstraint: Ext.emptyFn,
+
+ setYConstraint: Ext.emptyFn,
+
+ resetConstraints: Ext.emptyFn,
+
+ clearConstraints: Ext.emptyFn,
+
+ clearTicks: Ext.emptyFn,
+
+ setInitPosition: Ext.emptyFn,
+
+ setDragElId: Ext.emptyFn,
+
+ setHandleElId: Ext.emptyFn,
+
+ setOuterHandleElId: Ext.emptyFn,
+
+ addInvalidHandleClass: Ext.emptyFn,
+
+ addInvalidHandleId: Ext.emptyFn,
+
+ addInvalidHandleType: Ext.emptyFn,
+
+ removeInvalidHandleClass: Ext.emptyFn,
+
+ removeInvalidHandleId: Ext.emptyFn,
+
+ removeInvalidHandleType: Ext.emptyFn,
+
+ toString: function() {
+ return ("DDTarget " + this.id);
+ }
+});
+
+Ext.define('Ext.dd.DragTracker', {
+
+ uses: ['Ext.util.Region'],
+
+ mixins: {
+ observable: 'Ext.util.Observable'
+ },
+
+
+ active: false,
+
+
+
+
+ trackOver: false,
+
+
+
+
+
+
+ tolerance: 5,
+
+
+ autoStart: false,
+
+
+
+
+
+
+
+ constructor : function(config){
+ Ext.apply(this, config);
+ this.addEvents(
+
+ 'mouseover',
+
+
+ 'mouseout',
+
+
+ 'mousedown',
+
+
+ 'mouseup',
+
+
+ 'mousemove',
+
+
+ 'dragstart',
+
+
+ 'dragend',
+
+
+ 'drag'
+ );
+
+ this.dragRegion = Ext.create('Ext.util.Region', 0,0,0,0);
+
+ if (this.el) {
+ this.initEl(this.el);
+ }
+
+
+ this.mixins.observable.constructor.call(this);
+ if (this.disabled) {
+ this.disable();
+ }
+
+ },
+
+
+ initEl: function(el) {
+ this.el = Ext.get(el);
+
+
+ this.handle = Ext.get(this.delegate);
+
+
+ this.delegate = this.handle ? undefined : this.delegate;
+
+ if (!this.handle) {
+ this.handle = this.el;
+ }
+
+
+
+ this.mon(this.handle, {
+ mousedown: this.onMouseDown,
+ delegate: this.delegate,
+ scope: this
+ });
+
+
+
+
+ if (this.trackOver || this.overCls) {
+ this.mon(this.handle, {
+ mouseover: this.onMouseOver,
+ mouseout: this.onMouseOut,
+ delegate: this.delegate,
+ scope: this
+ });
+ }
+ },
+
+ disable: function() {
+ this.disabled = true;
+ },
+
+ enable: function() {
+ this.disabled = false;
+ },
+
+ destroy : function() {
+ this.clearListeners();
+ delete this.el;
+ },
+
+
+
+ onMouseOver: function(e, target) {
+ var me = this;
+ if (!me.disabled) {
+ if (Ext.EventManager.contains(e) || me.delegate) {
+ me.mouseIsOut = false;
+ if (me.overCls) {
+ me.el.addCls(me.overCls);
+ }
+ me.fireEvent('mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle);
+ }
+ }
+ },
+
+
+
+ onMouseOut: function(e) {
+ if (this.mouseIsDown) {
+ this.mouseIsOut = true;
+ } else {
+ if (this.overCls) {
+ this.el.removeCls(this.overCls);
+ }
+ this.fireEvent('mouseout', this, e);
+ }
+ },
+
+ onMouseDown: function(e, target){
+
+ if (this.disabled ||e.dragTracked) {
+ return;
+ }
+
+
+ this.dragTarget = this.delegate ? target : this.handle.dom;
+ this.startXY = this.lastXY = e.getXY();
+ this.startRegion = Ext.fly(this.dragTarget).getRegion();
+
+ if (this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false) {
+
+
+
+ this.mouseIsDown = true;
+
+
+ e.dragTracked = true;
+
+ if (this.preventDefault !== false) {
+ e.preventDefault();
+ }
+ Ext.getDoc().on({
+ scope: this,
+ mouseup: this.onMouseUp,
+ mousemove: this.onMouseMove,
+ selectstart: this.stopSelect
+ });
+ if (this.autoStart) {
+ this.timer = Ext.defer(this.triggerStart, this.autoStart === true ? 1000 : this.autoStart, this, [e]);
+ }
+ }
+ },
+
+ onMouseMove: function(e, target){
+
+
+ if (this.active && Ext.isIE && !e.browserEvent.button) {
+ e.preventDefault();
+ this.onMouseUp(e);
+ return;
+ }
+
+ e.preventDefault();
+ var xy = e.getXY(),
+ s = this.startXY;
+
+ this.lastXY = xy;
+ if (!this.active) {
+ if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > this.tolerance) {
+ this.triggerStart(e);
+ } else {
+ return;
+ }
+ }
+
+
+ if (this.fireEvent('mousemove', this, e) === false) {
+ this.onMouseUp(e);
+ } else {
+ this.onDrag(e);
+ this.fireEvent('drag', this, e);
+ }
+ },
+
+ onMouseUp: function(e) {
+
+
+ this.mouseIsDown = false;
+
+
+ delete e.dragTracked;
+
+
+ if (this.mouseIsOut) {
+ this.mouseIsOut = false;
+ this.onMouseOut(e);
+ }
+ e.preventDefault();
+ this.fireEvent('mouseup', this, e);
+ this.endDrag(e);
+ },
+
+
+ endDrag: function(e) {
+ var doc = Ext.getDoc(),
+ wasActive = this.active;
+
+ doc.un('mousemove', this.onMouseMove, this);
+ doc.un('mouseup', this.onMouseUp, this);
+ doc.un('selectstart', this.stopSelect, this);
+ this.clearStart();
+ this.active = false;
+ if (wasActive) {
+ this.onEnd(e);
+ this.fireEvent('dragend', this, e);
+ }
+
+ delete this._constrainRegion;
+ },
+
+ triggerStart: function(e) {
+ this.clearStart();
+ this.active = true;
+ this.onStart(e);
+ this.fireEvent('dragstart', this, e);
+ },
+
+ clearStart : function() {
+ if (this.timer) {
+ clearTimeout(this.timer);
+ delete this.timer;
+ }
+ },
+
+ stopSelect : function(e) {
+ e.stopEvent();
+ return false;
+ },
+
+
+ onBeforeStart : function(e) {
+
+ },
+
+
+ onStart : function(xy) {
+
+ },
+
+
+ onDrag : function(e) {
+
+ },
+
+
+ onEnd : function(e) {
+
+ },
+
+
+ getDragTarget : function(){
+ return this.dragTarget;
+ },
+
+
+ getDragCt : function(){
+ return this.el;
+ },
+
+
+ getConstrainRegion: function() {
+ if (this.constrainTo) {
+ if (this.constrainTo instanceof Ext.util.Region) {
+ return this.constrainTo;
+ }
+ if (!this._constrainRegion) {
+ this._constrainRegion = Ext.fly(this.constrainTo).getViewRegion();
+ }
+ } else {
+ if (!this._constrainRegion) {
+ this._constrainRegion = this.getDragCt().getViewRegion();
+ }
+ }
+ return this._constrainRegion;
+ },
+
+ getXY : function(constrain){
+ return constrain ? this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
+ },
+
+
+ getOffset : function(constrain){
+ var xy = this.getXY(constrain),
+ s = this.startXY;
+
+ return [xy[0]-s[0], xy[1]-s[1]];
+ },
+
+ constrainModes: {
+
+ point: function(xy) {
+ var dr = this.dragRegion,
+ constrainTo = this.getConstrainRegion();
+
+
+ if (!constrainTo) {
+ return xy;
+ }
+
+ dr.x = dr.left = dr[0] = dr.right = xy[0];
+ dr.y = dr.top = dr[1] = dr.bottom = xy[1];
+ dr.constrainTo(constrainTo);
+
+ return [dr.left, dr.top];
+ },
+
+
+ dragTarget: function(xy) {
+ var s = this.startXY,
+ dr = this.startRegion.copy(),
+ constrainTo = this.getConstrainRegion(),
+ adjust;
+
+
+ if (!constrainTo) {
+ return xy;
+ }
+
+
+
+
+ dr.translateBy.apply(dr, [xy[0]-s[0], xy[1]-s[1]]);
+
+
+ if (dr.right > constrainTo.right) {
+ xy[0] += adjust = (constrainTo.right - dr.right);
+ dr.left += adjust;
+ }
+ if (dr.left < constrainTo.left) {
+ xy[0] += (constrainTo.left - dr.left);
+ }
+
+
+ if (dr.bottom > constrainTo.bottom) {
+ xy[1] += adjust = (constrainTo.bottom - dr.bottom);
+ dr.top += adjust;
+ }
+ if (dr.top < constrainTo.top) {
+ xy[1] += (constrainTo.top - dr.top);
+ }
+ return xy;
+ }
+ }
+});
+
+Ext.define('Ext.dd.DragZone', {
+
+ extend: 'Ext.dd.DragSource',
+
+ constructor : function(el, config){
+ this.callParent([el, config]);
+ if (this.containerScroll) {
+ Ext.dd.ScrollManager.register(this.el);
+ }
+ },
+
+
+
+
+
+
+ getDragData : function(e){
+ return Ext.dd.Registry.getHandleFromEvent(e);
+ },
+
+
+ onInitDrag : function(x, y){
+ this.proxy.update(this.dragData.ddel.cloneNode(true));
+ this.onStartDrag(x, y);
+ return true;
+ },
+
+
+ afterRepair : function(){
+ var me = this;
+ if (Ext.enableFx) {
+ Ext.fly(me.dragData.ddel).highlight(me.repairHighlightColor);
+ }
+ me.dragging = false;
+ },
+
+
+ getRepairXY : function(e){
+ return Ext.core.Element.fly(this.dragData.ddel).getXY();
+ },
+
+ destroy : function(){
+ this.callParent();
+ if (this.containerScroll) {
+ Ext.dd.ScrollManager.unregister(this.el);
+ }
+ }
+});
+
+
+Ext.define('Ext.dd.ScrollManager', {
+ singleton: true,
+ requires: [
+ 'Ext.dd.DragDropManager'
+ ],
+
+ constructor: function() {
+ var ddm = Ext.dd.DragDropManager;
+ ddm.fireEvents = Ext.Function.createSequence(ddm.fireEvents, this.onFire, this);
+ ddm.stopDrag = Ext.Function.createSequence(ddm.stopDrag, this.onStop, this);
+ this.doScroll = Ext.Function.bind(this.doScroll, this);
+ this.ddmInstance = ddm;
+ this.els = {};
+ this.dragEl = null;
+ this.proc = {};
+ },
+
+ onStop: function(e){
+ var sm = Ext.dd.ScrollManager;
+ sm.dragEl = null;
+ sm.clearProc();
+ },
+
+ triggerRefresh: function() {
+ if (this.ddmInstance.dragCurrent) {
+ this.ddmInstance.refreshCache(this.ddmInstance.dragCurrent.groups);
+ }
+ },
+
+ doScroll: function() {
+ if (this.ddmInstance.dragCurrent) {
+ var proc = this.proc,
+ procEl = proc.el,
+ ddScrollConfig = proc.el.ddScrollConfig,
+ inc = ddScrollConfig ? ddScrollConfig.increment : this.increment;
+
+ if (!this.animate) {
+ if (procEl.scroll(proc.dir, inc)) {
+ this.triggerRefresh();
+ }
+ } else {
+ procEl.scroll(proc.dir, inc, true, this.animDuration, this.triggerRefresh);
+ }
+ }
+ },
+
+ clearProc: function() {
+ var proc = this.proc;
+ if (proc.id) {
+ clearInterval(proc.id);
+ }
+ proc.id = 0;
+ proc.el = null;
+ proc.dir = "";
+ },
+
+ startProc: function(el, dir) {
+ this.clearProc();
+ this.proc.el = el;
+ this.proc.dir = dir;
+ var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
+ freq = (el.ddScrollConfig && el.ddScrollConfig.frequency)
+ ? el.ddScrollConfig.frequency
+ : this.frequency;
+
+ if (group === undefined || this.ddmInstance.dragCurrent.ddGroup == group) {
+ this.proc.id = setInterval(this.doScroll, freq);
+ }
+ },
+
+ onFire: function(e, isDrop) {
+ if (isDrop || !this.ddmInstance.dragCurrent) {
+ return;
+ }
+ if (!this.dragEl || this.dragEl != this.ddmInstance.dragCurrent) {
+ this.dragEl = this.ddmInstance.dragCurrent;
+
+ this.refreshCache();
+ }
+
+ var xy = e.getXY(),
+ pt = e.getPoint(),
+ proc = this.proc,
+ els = this.els;
+
+ for (var id in els) {
+ var el = els[id], r = el._region;
+ var c = el.ddScrollConfig ? el.ddScrollConfig : this;
+ if (r && r.contains(pt) && el.isScrollable()) {
+ if (r.bottom - pt.y <= c.vthresh) {
+ if(proc.el != el){
+ this.startProc(el, "down");
+ }
+ return;
+ }else if (r.right - pt.x <= c.hthresh) {
+ if (proc.el != el) {
+ this.startProc(el, "left");
+ }
+ return;
+ } else if(pt.y - r.top <= c.vthresh) {
+ if (proc.el != el) {
+ this.startProc(el, "up");
+ }
+ return;
+ } else if(pt.x - r.left <= c.hthresh) {
+ if (proc.el != el) {
+ this.startProc(el, "right");
+ }
+ return;
+ }
+ }
+ }
+ this.clearProc();
+ },
+
+
+ register : function(el){
+ if (Ext.isArray(el)) {
+ for(var i = 0, len = el.length; i < len; i++) {
+ this.register(el[i]);
+ }
+ } else {
+ el = Ext.get(el);
+ this.els[el.id] = el;
+ }
+ },
+
+
+ unregister : function(el){
+ if(Ext.isArray(el)){
+ for (var i = 0, len = el.length; i < len; i++) {
+ this.unregister(el[i]);
+ }
+ }else{
+ el = Ext.get(el);
+ delete this.els[el.id];
+ }
+ },
+
+
+ vthresh : 25,
+
+ hthresh : 25,
+
+
+ increment : 100,
+
+
+ frequency : 500,
+
+
+ animate: true,
+
+
+ animDuration: 0.4,
+
+
+ ddGroup: undefined,
+
+
+ refreshCache : function(){
+ var els = this.els,
+ id;
+ for (id in els) {
+ if(typeof els[id] == 'object'){
+ els[id]._region = els[id].getRegion();
+ }
+ }
+ }
+});
+
+
+Ext.define('Ext.dd.DropTarget', {
+ extend: 'Ext.dd.DDTarget',
+ requires: ['Ext.dd.ScrollManager'],
+
+ constructor : function(el, config){
+ this.el = Ext.get(el);
+
+ Ext.apply(this, config);
+
+ if(this.containerScroll){
+ Ext.dd.ScrollManager.register(this.el);
+ }
+
+ this.callParent([this.el.dom, this.ddGroup || this.group,
+ {isTarget: true}]);
+ },
+
+
+
+
+ dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
+
+ dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
+
+
+ isTarget : true,
+
+
+ isNotifyTarget : true,
+
+
+ notifyEnter : function(dd, e, data){
+ if(this.overClass){
+ this.el.addCls(this.overClass);
+ }
+ return this.dropAllowed;
+ },
+
+
+ notifyOver : function(dd, e, data){
+ return this.dropAllowed;
+ },
+
+
+ notifyOut : function(dd, e, data){
+ if(this.overClass){
+ this.el.removeCls(this.overClass);
+ }
+ },
+
+
+ notifyDrop : function(dd, e, data){
+ return false;
+ },
+
+ destroy : function(){
+ this.callParent();
+ if(this.containerScroll){
+ Ext.dd.ScrollManager.unregister(this.el);
+ }
+ }
+});
+
+
+Ext.define('Ext.dd.Registry', {
+ singleton: true,
+ constructor: function() {
+ this.elements = {};
+ this.handles = {};
+ this.autoIdSeed = 0;
+ },
+
+ getId: function(el, autogen){
+ if(typeof el == "string"){
+ return el;
+ }
+ var id = el.id;
+ if(!id && autogen !== false){
+ id = "extdd-" + (++this.autoIdSeed);
+ el.id = id;
+ }
+ return id;
+ },
+
+
+ register : function(el, data){
+ data = data || {};
+ if (typeof el == "string") {
+ el = document.getElementById(el);
+ }
+ data.ddel = el;
+ this.elements[this.getId(el)] = data;
+ if (data.isHandle !== false) {
+ this.handles[data.ddel.id] = data;
+ }
+ if (data.handles) {
+ var hs = data.handles;
+ for (var i = 0, len = hs.length; i < len; i++) {
+ this.handles[this.getId(hs[i])] = data;
+ }
+ }
+ },
+
+
+ unregister : function(el){
+ var id = this.getId(el, false);
+ var data = this.elements[id];
+ if(data){
+ delete this.elements[id];
+ if(data.handles){
+ var hs = data.handles;
+ for (var i = 0, len = hs.length; i < len; i++) {
+ delete this.handles[this.getId(hs[i], false)];
+ }
+ }
+ }
+ },
+
+
+ getHandle : function(id){
+ if(typeof id != "string"){
+ id = id.id;
+ }
+ return this.handles[id];
+ },
+
+
+ getHandleFromEvent : function(e){
+ var t = e.getTarget();
+ return t ? this.handles[t.id] : null;
+ },
+
+
+ getTarget : function(id){
+ if(typeof id != "string"){
+ id = id.id;
+ }
+ return this.elements[id];
+ },
+
+
+ getTargetFromEvent : function(e){
+ var t = e.getTarget();
+ return t ? this.elements[t.id] || this.handles[t.id] : null;
+ }
+});
+
+Ext.define('Ext.dd.DropZone', {
+ extend: 'Ext.dd.DropTarget',
+ requires: ['Ext.dd.Registry'],
+
+
+ getTargetFromEvent : function(e){
+ return Ext.dd.Registry.getTargetFromEvent(e);
+ },
+
+
+ onNodeEnter : function(n, dd, e, data){
+
+ },
+
+
+ onNodeOver : function(n, dd, e, data){
+ return this.dropAllowed;
+ },
+
+
+ onNodeOut : function(n, dd, e, data){
+
+ },
+
+
+ onNodeDrop : function(n, dd, e, data){
+ return false;
+ },
+
+
+ onContainerOver : function(dd, e, data){
+ return this.dropNotAllowed;
+ },
+
+
+ onContainerDrop : function(dd, e, data){
+ return false;
+ },
+
+
+ notifyEnter : function(dd, e, data){
+ return this.dropNotAllowed;
+ },
+
+
+ notifyOver : function(dd, e, data){
+ var n = this.getTargetFromEvent(e);
+ if(!n) {
+ if(this.lastOverNode){
+ this.onNodeOut(this.lastOverNode, dd, e, data);
+ this.lastOverNode = null;
+ }
+ return this.onContainerOver(dd, e, data);
+ }
+ if(this.lastOverNode != n){
+ if(this.lastOverNode){
+ this.onNodeOut(this.lastOverNode, dd, e, data);
+ }
+ this.onNodeEnter(n, dd, e, data);
+ this.lastOverNode = n;
+ }
+ return this.onNodeOver(n, dd, e, data);
+ },
+
+
+ notifyOut : function(dd, e, data){
+ if(this.lastOverNode){
+ this.onNodeOut(this.lastOverNode, dd, e, data);
+ this.lastOverNode = null;
+ }
+ },
+
+
+ notifyDrop : function(dd, e, data){
+ if(this.lastOverNode){
+ this.onNodeOut(this.lastOverNode, dd, e, data);
+ this.lastOverNode = null;
+ }
+ var n = this.getTargetFromEvent(e);
+ return n ?
+ this.onNodeDrop(n, dd, e, data) :
+ this.onContainerDrop(dd, e, data);
+ },
+
+
+ triggerCacheRefresh : function() {
+ Ext.dd.DDM.refreshCache(this.groups);
+ }
+});
+
+Ext.define('Ext.flash.Component', {
+ extend: 'Ext.Component',
+ alternateClassName: 'Ext.FlashComponent',
+ alias: 'widget.flash',
+
+
+ flashVersion : '9.0.115',
+
+
+ backgroundColor: '#ffffff',
+
+
+ wmode: 'opaque',
+
+
+
+
+
+
+
+
+
+
+ swfWidth: '100%',
+
+
+ swfHeight: '100%',
+
+
+ expressInstall: false,
+
+
+
+
+ renderTpl: ['<div id="{swfId}"></div>'],
+
+ initComponent: function() {
+ if (!('swfobject' in window)) {
+ Ext.Error.raise('The SWFObject library is not loaded. Ext.flash.Component requires SWFObject version 2.2 or later: http://code.google.com/p/swfobject/');
+ }
+ if (!this.url) {
+ Ext.Error.raise('The "url" config is required for Ext.flash.Component');
+ }
+
+ this.callParent();
+ this.addEvents(
+
+ 'success',
+
+
+ 'failure'
+ );
+ },
+
+ onRender: function() {
+ var me = this,
+ params, vars, undef,
+ swfId = me.getSwfId();
+
+ me.renderData.swfId = swfId;
+
+ me.callParent(arguments);
+
+ params = Ext.apply({
+ allowScriptAccess: 'always',
+ bgcolor: me.backgroundColor,
+ wmode: me.wmode
+ }, me.flashParams);
+
+ vars = Ext.apply({
+ allowedDomain: document.location.hostname
+ }, me.flashVars);
+
+ new swfobject.embedSWF(
+ me.url,
+ swfId,
+ me.swfWidth,
+ me.swfHeight,
+ me.flashVersion,
+ me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undef,
+ vars,
+ params,
+ me.flashAttributes,
+ Ext.bind(me.swfCallback, me)
+ );
+ },
+
+
+ swfCallback: function(e) {
+ var me = this;
+ if (e.success) {
+ me.swf = Ext.get(e.ref);
+ me.onSuccess();
+ me.fireEvent('success', me);
+ } else {
+ me.onFailure();
+ me.fireEvent('failure', me);
+ }
+ },
+
+
+ getSwfId: function() {
+ return this.swfId || (this.swfId = "extswf" + this.getAutoId());
+ },
+
+ onSuccess: function() {
+
+
+ this.swf.setStyle('visibility', 'inherit');
+ },
+
+ onFailure: Ext.emptyFn,
+
+ beforeDestroy: function() {
+ var me = this,
+ swf = me.swf;
+ if (swf) {
+ swfobject.removeSWF(me.getSwfId());
+ Ext.destroy(swf);
+ delete me.swf;
+ }
+ me.callParent();
+ },
+
+ statics: {
+
+ EXPRESS_INSTALL_URL: 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf'
+ }
+});
+
+
+Ext.define('Ext.form.action.Action', {
+ alternateClassName: 'Ext.form.Action',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ constructor: function(config) {
+ if (config) {
+ Ext.apply(this, config);
+ }
+
+
+ var params = config.params;
+ if (Ext.isString(params)) {
+ this.params = Ext.Object.fromQueryString(params);
+ }
+ },
+
+
+ run: Ext.emptyFn,
+
+
+
+
+
+
+ onFailure : function(response){
+ this.response = response;
+ this.failureType = Ext.form.action.Action.CONNECT_FAILURE;
+ this.form.afterAction(this, false);
+ },
+
+
+ processResponse : function(response){
+ this.response = response;
+ if (!response.responseText && !response.responseXML) {
+ return true;
+ }
+ return (this.result = this.handleResponse(response));
+ },
+
+
+ getUrl: function() {
+ return this.url || this.form.url;
+ },
+
+
+ getMethod: function() {
+ return (this.method || this.form.method || 'POST').toUpperCase();
+ },
+
+
+ getParams: function() {
+ return Ext.apply({}, this.params, this.form.baseParams);
+ },
+
+
+ createCallback: function() {
+ var me = this,
+ undef,
+ form = me.form;
+ return {
+ success: me.onSuccess,
+ failure: me.onFailure,
+ scope: me,
+ timeout: (this.timeout * 1000) || (form.timeout * 1000),
+ upload: form.fileUpload ? me.onSuccess : undef
+ };
+ },
+
+ statics: {
+
+ CLIENT_INVALID: 'client',
+
+
+ SERVER_INVALID: 'server',
+
+
+ CONNECT_FAILURE: 'connect',
+
+
+ LOAD_FAILURE: 'load'
+
+
+ }
+});
+
+
+Ext.define('Ext.form.action.Submit', {
+ extend:'Ext.form.action.Action',
+ alternateClassName: 'Ext.form.Action.Submit',
+ alias: 'formaction.submit',
+
+ type: 'submit',
+
+
+
+
+ run : function(){
+ var form = this.form;
+ if (this.clientValidation === false || form.isValid()) {
+ this.doSubmit();
+ } else {
+
+ this.failureType = Ext.form.action.Action.CLIENT_INVALID;
+ form.afterAction(this, false);
+ }
+ },
+
+
+ doSubmit: function() {
+ var formEl,
+ ajaxOptions = Ext.apply(this.createCallback(), {
+ url: this.getUrl(),
+ method: this.getMethod(),
+ headers: this.headers
+ });
+
+
+
+ if (this.form.hasUpload()) {
+ formEl = ajaxOptions.form = this.buildForm();
+ ajaxOptions.isUpload = true;
+ } else {
+ ajaxOptions.params = this.getParams();
+ }
+
+ Ext.Ajax.request(ajaxOptions);
+
+ if (formEl) {
+ Ext.removeNode(formEl);
+ }
+ },
+
+
+ getParams: function() {
+ var nope = false,
+ configParams = this.callParent(),
+ fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
+ return Ext.apply({}, fieldParams, configParams);
+ },
+
+
+ buildForm: function() {
+ var fieldsSpec = [],
+ formSpec,
+ formEl,
+ basicForm = this.form,
+ params = this.getParams(),
+ uploadFields = [];
+
+ basicForm.getFields().each(function(field) {
+ if (field.isFileUpload()) {
+ uploadFields.push(field);
+ }
+ });
+
+ function addField(name, val) {
+ fieldsSpec.push({
+ tag: 'input',
+ type: 'hidden',
+ name: name,
+ value: val
+ });
+ }
+
+
+ Ext.iterate(params, function(key, val) {
+ if (Ext.isArray(val)) {
+ Ext.each(val, function(v) {
+ addField(key, v);
+ });
+ } else {
+ addField(key, val);
+ }
+ });
+
+ formSpec = {
+ tag: 'form',
+ action: this.getUrl(),
+ method: this.getMethod(),
+ target: this.target || '_self',
+ style: 'display:none',
+ cn: fieldsSpec
+ };
+
+
+ if (uploadFields.length) {
+ formSpec.encoding = formSpec.enctype = 'multipart/form-data';
+ }
+
+
+ formEl = Ext.core.DomHelper.append(Ext.getBody(), formSpec);
+
+
+
+
+ Ext.Array.each(uploadFields, function(field) {
+ if (field.rendered) {
+ formEl.appendChild(field.extractFileInput());
+ }
+ });
+
+ return formEl;
+ },
+
+
+
+
+ onSuccess: function(response) {
+ var form = this.form,
+ success = true,
+ result = this.processResponse(response);
+ if (result !== true && !result.success) {
+ if (result.errors) {
+ form.markInvalid(result.errors);
+ }
+ this.failureType = Ext.form.action.Action.SERVER_INVALID;
+ success = false;
+ }
+ form.afterAction(this, success);
+ },
+
+
+ handleResponse: function(response) {
+ var form = this.form,
+ errorReader = form.errorReader,
+ rs, errors, i, len, records;
+ if (errorReader) {
+ rs = errorReader.read(response);
+ records = rs.records;
+ errors = [];
+ if (records) {
+ for(i = 0, len = records.length; i < len; i++) {
+ errors[i] = records[i].data;
+ }
+ }
+ if (errors.length < 1) {
+ errors = null;
+ }
+ return {
+ success : rs.success,
+ errors : errors
+ };
+ }
+ return Ext.decode(response.responseText);
+ }
+});
+
+
+Ext.define('Ext.util.ComponentDragger', {
+
+
+
+
+
+
+
+ extend: 'Ext.dd.DragTracker',
+
+ autoStart: 500,
+
+ constructor: function(comp, config) {
+ this.comp = comp;
+ this.initialConstrainTo = config.constrainTo;
+ this.callParent([ config ]);
+ },
+
+ onStart: function(e) {
+ var me = this,
+ comp = me.comp;
+
+
+ this.startPosition = comp.getPosition();
+
+
+
+ if (comp.ghost && !comp.liveDrag) {
+ me.proxy = comp.ghost();
+ me.dragTarget = me.proxy.header.el;
+ }
+
+
+ if (me.constrain || me.constrainDelegate) {
+ me.constrainTo = me.calculateConstrainRegion();
+ }
+ },
+
+ calculateConstrainRegion: function() {
+ var me = this,
+ comp = me.comp,
+ c = me.initialConstrainTo,
+ delegateRegion,
+ elRegion,
+ shadowSize = comp.el.shadow ? comp.el.shadow.offset : 0;
+
+
+ if (!(c instanceof Ext.util.Region)) {
+ c = Ext.fly(c).getViewRegion();
+ }
+
+
+ if (shadowSize) {
+ c.adjust(0, -shadowSize, -shadowSize, shadowSize);
+ }
+
+
+
+
+ if (!me.constrainDelegate) {
+ delegateRegion = Ext.fly(me.dragTarget).getRegion();
+ elRegion = me.proxy ? me.proxy.el.getRegion() : comp.el.getRegion();
+
+ c.adjust(
+ delegateRegion.top - elRegion.top,
+ delegateRegion.right - elRegion.right,
+ delegateRegion.bottom - elRegion.bottom,
+ delegateRegion.left - elRegion.left
+ );
+ }
+ return c;
+ },
+
+
+ onDrag: function(e) {
+ var me = this,
+ comp = (me.proxy && !me.comp.liveDrag) ? me.proxy : me.comp,
+ offset = me.getOffset(me.constrain || me.constrainDelegate ? 'dragTarget' : null);
+
+ comp.setPosition.apply(comp, [me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]]);
+ },
+
+ onEnd: function(e) {
+ if (this.proxy && !this.comp.liveDrag) {
+ this.comp.unghost();
+ }
+ }
+});
+
+Ext.define("Ext.form.Labelable", {
+ requires: ['Ext.XTemplate'],
+
+
+ labelableRenderTpl: [
+ '<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
+ '<label<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
+ '<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
+ '</label>',
+ '</tpl>',
+ '<div class="{baseBodyCls} {fieldBodyCls}"<tpl if="inputId"> id="{baseBodyCls}-{inputId}"</tpl> role="presentation">{subTplMarkup}</div>',
+ '<div class="{errorMsgCls}" style="display:none"></div>',
+ '<div class="{clearCls}" role="presentation"><!-- --></div>',
+ {
+ compiled: true,
+ disableFormats: true
+ }
+ ],
+
+
+ activeErrorsTpl: [
+ '<tpl if="errors && errors.length">',
+ '<ul><tpl for="errors"><li<tpl if="xindex == xcount"> class="last"</tpl>>{.}</li></tpl></ul>',
+ '</tpl>'
+ ],
+
+
+ isFieldLabelable: true,
+
+
+ formItemCls: Ext.baseCSSPrefix + 'form-item',
+
+
+ labelCls: Ext.baseCSSPrefix + 'form-item-label',
+
+
+ errorMsgCls: Ext.baseCSSPrefix + 'form-error-msg',
+
+
+ baseBodyCls: Ext.baseCSSPrefix + 'form-item-body',
+
+
+ fieldBodyCls: '',
+
+
+ clearCls: Ext.baseCSSPrefix + 'clear',
+
+
+ invalidCls : Ext.baseCSSPrefix + 'form-invalid',
+
+
+ fieldLabel: undefined,
+
+
+ labelAlign : 'left',
+
+
+ labelWidth: 100,
+
+
+ labelPad : 5,
+
+
+ labelSeparator : ':',
+
+
+
+
+ hideLabel: false,
+
+
+ hideEmptyLabel: true,
+
+
+ preventMark: false,
+
+
+ autoFitErrors: true,
+
+
+ msgTarget: 'qtip',
+
+
+
+
+
+ initLabelable: function() {
+ this.addCls(this.formItemCls);
+
+ this.addEvents(
+
+ 'errorchange'
+ );
+ },
+
+
+ getFieldLabel: function() {
+ return this.fieldLabel || '';
+ },
+
+
+ getLabelableRenderData: function() {
+ var me = this,
+ labelAlign = me.labelAlign,
+ labelPad = me.labelPad,
+ labelStyle;
+
+
+
+ if (labelAlign === 'top') {
+ labelStyle = 'margin-bottom:' + labelPad + 'px;';
+ } else {
+ labelStyle = 'margin-right:' + labelPad + 'px;';
+
+ if (Ext.isBorderBox) {
+ labelStyle += 'width:' + me.labelWidth + 'px;';
+ }
+ }
+
+ return Ext.copyTo(
+ {
+ inputId: me.getInputId(),
+ fieldLabel: me.getFieldLabel(),
+ labelStyle: labelStyle + (me.labelStyle || ''),
+ subTplMarkup: me.getSubTplMarkup()
+ },
+ me,
+ 'hideLabel,hideEmptyLabel,labelCls,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
+ true
+ );
+ },
+
+
+ getLabelableSelectors: function() {
+ return {
+
+ labelEl: 'label.' + this.labelCls,
+
+
+ bodyEl: '.' + this.baseBodyCls,
+
+
+ errorEl: '.' + this.errorMsgCls
+ };
+ },
+
+
+ getSubTplMarkup: function() {
+ return '';
+ },
+
+
+ getInputId: function() {
+ return '';
+ },
+
+
+ getActiveError : function() {
+ return this.activeError || '';
+ },
+
+
+ hasActiveError: function() {
+ return !!this.getActiveError();
+ },
+
+
+ setActiveError: function(msg) {
+ this.activeError = msg;
+ this.activeErrors = [msg];
+ this.renderActiveError();
+ },
+
+
+ getActiveErrors: function() {
+ return this.activeErrors || [];
+ },
+
+
+ setActiveErrors: function(errors) {
+ this.activeErrors = errors;
+ this.activeError = this.getTpl('activeErrorsTpl').apply({errors: errors});
+ this.renderActiveError();
+ },
+
+
+ unsetActiveError: function() {
+ delete this.activeError;
+ delete this.activeErrors;
+ this.renderActiveError();
+ },
+
+
+ renderActiveError: function() {
+ var me = this,
+ activeError = me.getActiveError(),
+ hasError = !!activeError;
+
+ if (activeError !== me.lastActiveError) {
+ me.fireEvent('errorchange', me, activeError);
+ me.lastActiveError = activeError;
+ }
+
+ if (me.rendered && !me.isDestroyed && !me.preventMark) {
+
+ me.el[hasError ? 'addCls' : 'removeCls'](me.invalidCls);
+
+
+ me.getActionEl().dom.setAttribute('aria-invalid', hasError);
+
+
+ me.errorEl.dom.innerHTML = activeError;
+ }
+ },
+
+
+ setFieldDefaults: function(defaults) {
+ var me = this;
+ Ext.iterate(defaults, function(key, val) {
+ if (!me.hasOwnProperty(key)) {
+ me[key] = val;
+ }
+ });
+ },
+
+
+ getBodyNaturalWidth: function() {
+ return this.bodyEl.getWidth();
+ }
+
+});
+
+
+Ext.define('Ext.form.field.Field', {
+
+
+ isFormField : true,
+
+
+
+
+
+
+ disabled : false,
+
+
+ submitValue: true,
+
+
+ validateOnChange: true,
+
+
+ suspendCheckChange: 0,
+
+
+ initField: function() {
+ this.addEvents(
+
+ 'change',
+
+ 'validitychange',
+
+ 'dirtychange'
+ );
+
+ this.initValue();
+ },
+
+
+ initValue: function() {
+ var me = this;
+
+
+ me.originalValue = me.lastValue = me.value;
+
+
+ me.suspendCheckChange++;
+ me.setValue(me.value);
+ me.suspendCheckChange--;
+ },
+
+
+ getName: function() {
+ return this.name;
+ },
+
+
+ getValue: function() {
+ return this.value;
+ },
+
+
+ setValue: function(value) {
+ var me = this;
+ me.value = value;
+ me.checkChange();
+ return me;
+ },
+
+
+ isEqual: function(value1, value2) {
+ return String(value1) === String(value2);
+ },
+
+
+ getSubmitData: function() {
+ var me = this,
+ data = null;
+ if (!me.disabled && me.submitValue && !me.isFileUpload()) {
+ data = {};
+ data[me.getName()] = '' + me.getValue();
+ }
+ return data;
+ },
+
+
+ getModelData: function() {
+ var me = this,
+ data = null;
+ if (!me.disabled && !me.isFileUpload()) {
+ data = {};
+ data[me.getName()] = me.getValue();
+ }
+ return data;
+ },
+
+
+ reset : function(){
+ var me = this;
+
+ me.setValue(me.originalValue);
+ me.clearInvalid();
+
+ delete me.wasValid;
+ },
+
+
+ resetOriginalValue: function() {
+ this.originalValue = this.getValue();
+ this.checkDirty();
+ },
+
+
+ checkChange: function() {
+ if (!this.suspendCheckChange) {
+ var me = this,
+ newVal = me.getValue(),
+ oldVal = me.lastValue;
+ if (!me.isEqual(newVal, oldVal) && !me.isDestroyed) {
+ me.lastValue = newVal;
+ me.fireEvent('change', me, newVal, oldVal);
+ me.onChange(newVal, oldVal);
+ }
+ }
+ },
+
+
+ onChange: function(newVal, oldVal) {
+ if (this.validateOnChange) {
+ this.validate();
+ }
+ this.checkDirty();
+ },
+
+
+ isDirty : function() {
+ var me = this;
+ return !me.disabled && !me.isEqual(me.getValue(), me.originalValue);
+ },
+
+
+ checkDirty: function() {
+ var me = this,
+ isDirty = me.isDirty();
+ if (isDirty !== me.wasDirty) {
+ me.fireEvent('dirtychange', me, isDirty);
+ me.onDirtyChange(isDirty);
+ me.wasDirty = isDirty;
+ }
+ },
+
+
+ onDirtyChange: Ext.emptyFn,
+
+
+ getErrors: function(value) {
+ return [];
+ },
+
+
+ isValid : function() {
+ var me = this;
+ return me.disabled || Ext.isEmpty(me.getErrors());
+ },
+
+
+ validate : function() {
+ var me = this,
+ isValid = me.isValid();
+ if (isValid !== me.wasValid) {
+ me.wasValid = isValid;
+ me.fireEvent('validitychange', me, isValid);
+ }
+ return isValid;
+ },
+
+
+ batchChanges: function(fn) {
+ this.suspendCheckChange++;
+ fn();
+ this.suspendCheckChange--;
+ this.checkChange();
+ },
+
+
+ isFileUpload: function() {
+ return false;
+ },
+
+
+ extractFileInput: function() {
+ return null;
+ },
+
+
+ markInvalid: Ext.emptyFn,
+
+
+ clearInvalid: Ext.emptyFn
+
+});
+
+
+Ext.define('Ext.layout.component.field.Field', {
+
+
+
+ alias: ['layout.field'],
+
+ extend: 'Ext.layout.component.Component',
+
+ uses: ['Ext.tip.QuickTip', 'Ext.util.TextMetrics'],
+
+
+
+ type: 'field',
+
+ beforeLayout: function(width, height) {
+ var me = this;
+ return me.callParent(arguments) || (!me.owner.preventMark && me.activeError !== me.owner.getActiveError());
+ },
+
+ onLayout: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ labelStrategy = me.getLabelStrategy(),
+ errorStrategy = me.getErrorStrategy(),
+ isDefined = Ext.isDefined,
+ isNumber = Ext.isNumber,
+ lastSize, autoWidth, autoHeight, info, undef;
+
+ lastSize = me.lastComponentSize || {};
+ if (!isDefined(width)) {
+ width = lastSize.width;
+ if (width < 0) {
+ width = undef;
+ }
+ }
+ if (!isDefined(height)) {
+ height = lastSize.height;
+ if (height < 0) {
+ height = undef;
+ }
+ }
+ autoWidth = !isNumber(width);
+ autoHeight = !isNumber(height);
+
+ info = {
+ autoWidth: autoWidth,
+ autoHeight: autoHeight,
+ width: autoWidth ? owner.getBodyNaturalWidth() : width,
+ height: height,
+
+
+ insets: {
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0
+ }
+ };
+
+
+
+
+
+
+ labelStrategy.prepare(owner, info);
+ errorStrategy.prepare(owner, info);
+
+
+ labelStrategy.adjustHorizInsets(owner, info);
+ errorStrategy.adjustHorizInsets(owner, info);
+
+
+ labelStrategy.layoutHoriz(owner, info);
+ errorStrategy.layoutHoriz(owner, info);
+
+
+ labelStrategy.adjustVertInsets(owner, info);
+ errorStrategy.adjustVertInsets(owner, info);
+
+
+ labelStrategy.layoutVert(owner, info);
+ errorStrategy.layoutVert(owner, info);
+
+
+ if (autoWidth && autoHeight) {
+
+ me.setElementSize(owner.el, info.width, info.height);
+ } else {
+ me.setTargetSize(info.width, info.height);
+ }
+ me.sizeBody(info);
+
+ me.activeError = owner.getActiveError();
+ },
+
+
+
+ sizeBody: function(info) {
+ var me = this,
+ owner = me.owner,
+ insets = info.insets,
+ totalWidth = info.width,
+ totalHeight = info.height,
+ width = Ext.isNumber(totalWidth) ? totalWidth - insets.left - insets.right : totalWidth,
+ height = Ext.isNumber(totalHeight) ? totalHeight - insets.top - insets.bottom : totalHeight;
+
+
+ me.setElementSize(owner.bodyEl, width, height);
+
+
+ me.sizeBodyContents(width, height);
+ },
+
+
+ sizeBodyContents: Ext.emptyFn,
+
+
+
+ getLabelStrategy: function() {
+ var me = this,
+ strategies = me.labelStrategies,
+ labelAlign = me.owner.labelAlign;
+ return strategies[labelAlign] || strategies.base;
+ },
+
+
+ getErrorStrategy: function() {
+ var me = this,
+ owner = me.owner,
+ strategies = me.errorStrategies,
+ msgTarget = owner.msgTarget;
+ return !owner.preventMark && Ext.isString(msgTarget) ?
+ (strategies[msgTarget] || strategies.elementId) :
+ strategies.none;
+ },
+
+
+
+
+ labelStrategies: (function() {
+ var applyIf = Ext.applyIf,
+ emptyFn = Ext.emptyFn,
+ base = {
+ prepare: function(owner, info) {
+ var cls = owner.labelCls + '-' + owner.labelAlign,
+ labelEl = owner.labelEl;
+ if (labelEl && !labelEl.hasCls(cls)) {
+ labelEl.addCls(cls);
+ }
+ },
+ adjustHorizInsets: emptyFn,
+ adjustVertInsets: emptyFn,
+ layoutHoriz: emptyFn,
+ layoutVert: emptyFn
+ },
+ left = applyIf({
+ prepare: function(owner, info) {
+ base.prepare(owner, info);
+
+ if (info.autoWidth) {
+ info.width += (!owner.labelEl ? 0 : owner.labelWidth + owner.labelPad);
+ }
+ },
+ adjustHorizInsets: function(owner, info) {
+ if (owner.labelEl) {
+ info.insets.left += owner.labelWidth + owner.labelPad;
+ }
+ },
+ layoutHoriz: function(owner, info) {
+
+
+
+
+
+ var labelEl = owner.labelEl;
+ if (labelEl && !owner.isLabelSized && !Ext.isBorderBox) {
+ labelEl.setWidth(owner.labelWidth);
+ owner.isLabelSized = true;
+ }
+ }
+ }, base);
+
+
+ return {
+ base: base,
+
+
+ top: applyIf({
+ adjustVertInsets: function(owner, info) {
+ var labelEl = owner.labelEl;
+ if (labelEl) {
+ info.insets.top += Ext.util.TextMetrics.measure(labelEl, owner.fieldLabel, info.width).height +
+ labelEl.getFrameWidth('tb') + owner.labelPad;
+ }
+ }
+ }, base),
+
+
+ left: left,
+
+
+ right: left
+ };
+ })(),
+
+
+
+
+ errorStrategies: (function() {
+ function setDisplayed(el, displayed) {
+ var wasDisplayed = el.getStyle('display') !== 'none';
+ if (displayed !== wasDisplayed) {
+ el.setDisplayed(displayed);
+ }
+ }
+
+ function setStyle(el, name, value) {
+ if (el.getStyle(name) !== value) {
+ el.setStyle(name, value);
+ }
+ }
+
+ var applyIf = Ext.applyIf,
+ emptyFn = Ext.emptyFn,
+ base = {
+ prepare: function(owner) {
+ setDisplayed(owner.errorEl, false);
+ },
+ adjustHorizInsets: emptyFn,
+ adjustVertInsets: emptyFn,
+ layoutHoriz: emptyFn,
+ layoutVert: emptyFn
+ };
+
+ return {
+ none: base,
+
+
+ side: applyIf({
+ prepare: function(owner) {
+ var errorEl = owner.errorEl;
+ errorEl.addCls(Ext.baseCSSPrefix + 'form-invalid-icon');
+ Ext.layout.component.field.Field.initTip();
+ errorEl.dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
+ setDisplayed(errorEl, owner.hasActiveError());
+ },
+ adjustHorizInsets: function(owner, info) {
+ if (owner.autoFitErrors && owner.hasActiveError()) {
+ info.insets.right += owner.errorEl.getWidth();
+ }
+ },
+ layoutHoriz: function(owner, info) {
+ if (owner.hasActiveError()) {
+ setStyle(owner.errorEl, 'left', info.width - info.insets.right + 'px');
+ }
+ },
+ layoutVert: function(owner, info) {
+ if (owner.hasActiveError()) {
+ setStyle(owner.errorEl, 'top', info.insets.top + 'px');
+ }
+ }
+ }, base),
+
+
+ under: applyIf({
+ prepare: function(owner) {
+ var errorEl = owner.errorEl,
+ cls = Ext.baseCSSPrefix + 'form-invalid-under';
+ if (!errorEl.hasCls(cls)) {
+ errorEl.addCls(cls);
+ }
+ setDisplayed(errorEl, owner.hasActiveError());
+ },
+ adjustVertInsets: function(owner, info) {
+ if (owner.autoFitErrors) {
+ info.insets.bottom += owner.errorEl.getHeight();
+ }
+ },
+ layoutHoriz: function(owner, info) {
+ var errorEl = owner.errorEl,
+ insets = info.insets;
+
+ setStyle(errorEl, 'width', info.width - insets.right - insets.left + 'px');
+ setStyle(errorEl, 'marginLeft', insets.left + 'px');
+ }
+ }, base),
+
+
+ qtip: applyIf({
+ prepare: function(owner) {
+ setDisplayed(owner.errorEl, false);
+ Ext.layout.component.field.Field.initTip();
+ owner.getActionEl().dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
+ }
+ }, base),
+
+
+ title: applyIf({
+ prepare: function(owner) {
+ setDisplayed(owner.errorEl, false);
+ owner.el.dom.title = owner.getActiveError() || '';
+ }
+ }, base),
+
+
+ elementId: applyIf({
+ prepare: function(owner) {
+ setDisplayed(owner.errorEl, false);
+ var targetEl = Ext.fly(owner.msgTarget);
+ if (targetEl) {
+ targetEl.dom.innerHTML = owner.getActiveError() || '';
+ targetEl.setDisplayed(owner.hasActiveError());
+ }
+ }
+ }, base)
+ };
+ })(),
+
+ statics: {
+
+ initTip: function() {
+ var tip = this.tip;
+ if (!tip) {
+ tip = this.tip = Ext.create('Ext.tip.QuickTip', {
+ baseCls: Ext.baseCSSPrefix + 'form-invalid-tip',
+ renderTo: Ext.getBody()
+ });
+ tip.tagConfig = Ext.apply({}, {attribute: 'errorqtip'}, tip.tagConfig);
+ }
+ },
+
+
+ destroyTip: function() {
+ var tip = this.tip;
+ if (tip) {
+ tip.destroy();
+ delete this.tip;
+ }
+ }
+ }
+
+});
+
+
+Ext.define('Ext.form.field.VTypes', (function(){
+
+ var alpha = /^[a-zA-Z_]+$/,
+ alphanum = /^[a-zA-Z0-9_]+$/,
+ email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
+ url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
+
+
+ return {
+ singleton: true,
+ alternateClassName: 'Ext.form.VTypes',
+
+
+ 'email' : function(v){
+ return email.test(v);
+ },
+
+ 'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
+
+ 'emailMask' : /[a-z0-9_\.\-@\+]/i,
+
+
+ 'url' : function(v){
+ return url.test(v);
+ },
+
+ 'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
+
+
+ 'alpha' : function(v){
+ return alpha.test(v);
+ },
+
+ 'alphaText' : 'This field should only contain letters and _',
+
+ 'alphaMask' : /[a-z_]/i,
+
+
+ 'alphanum' : function(v){
+ return alphanum.test(v);
+ },
+
+ 'alphanumText' : 'This field should only contain letters, numbers and _',
+
+ 'alphanumMask' : /[a-z0-9_]/i
+ };
+})());
+
+
+Ext.define('Ext.layout.component.field.Text', {
+ extend: 'Ext.layout.component.field.Field',
+ alias: 'layout.textfield',
+ requires: ['Ext.util.TextMetrics'],
+
+ type: 'textfield',
+
+
+
+ beforeLayout: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ lastValue = this.lastValue,
+ value = owner.getRawValue();
+ this.lastValue = value;
+ return me.callParent(arguments) || (owner.grow && value !== lastValue);
+ },
+
+
+
+ sizeBodyContents: function(width, height) {
+ var size = this.adjustForGrow(width, height);
+ this.setElementSize(this.owner.inputEl, size[0], size[1]);
+ },
+
+
+
+ adjustForGrow: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ inputEl, value, calcWidth,
+ result = [width, height];
+
+ if (owner.grow) {
+ inputEl = owner.inputEl;
+
+
+ value = (inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || '') + owner.growAppend;
+ calcWidth = inputEl.getTextWidth(value) + inputEl.getBorderWidth("lr") + inputEl.getPadding("lr");
+
+
+ result[0] = Ext.Number.constrain(calcWidth, owner.growMin,
+ Math.max(owner.growMin, Math.min(owner.growMax, Ext.isNumber(width) ? width : Infinity)));
+ }
+
+ return result;
+ }
+
+});
+
+
+Ext.define('Ext.layout.component.field.TextArea', {
+ extend: 'Ext.layout.component.field.Text',
+ alias: 'layout.textareafield',
+
+ type: 'textareafield',
+
+
+
+ adjustForGrow: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ inputEl, value, max,
+ curWidth, curHeight, calcHeight,
+ result = [width, height];
+
+ if (owner.grow) {
+ inputEl = owner.inputEl;
+ curWidth = inputEl.getWidth(true);
+ curHeight = inputEl.getHeight();
+
+
+ value = inputEl.dom.value || ' ';
+ value += owner.growAppend;
+
+
+ value = value.replace(/\n/g, '<br>');
+
+
+ calcHeight = Ext.util.TextMetrics.measure(inputEl, value, curWidth).height +
+ inputEl.getBorderWidth("tb") + inputEl.getPadding("tb");
+
+
+ max = owner.growMax;
+ if (Ext.isNumber(height)) {
+ max = Math.min(max, height);
+ }
+ result[1] = Ext.Number.constrain(calcHeight, owner.growMin, max);
+ }
+
+ return result;
+ }
+
+});
+
+
+Ext.define('Ext.layout.container.Anchor', {
+
+
+
+ alias: 'layout.anchor',
+ extend: 'Ext.layout.container.Container',
+ alternateClassName: 'Ext.layout.AnchorLayout',
+
+
+
+
+
+ type: 'anchor',
+
+
+ defaultAnchor: '100%',
+
+ parseAnchorRE: /^(r|right|b|bottom)$/i,
+
+
+ onLayout: function() {
+ this.callParent(arguments);
+
+ var me = this,
+ size = me.getLayoutTargetSize(),
+ owner = me.owner,
+ target = me.getTarget(),
+ ownerWidth = size.width,
+ ownerHeight = size.height,
+ overflow = target.getStyle('overflow'),
+ components = me.getVisibleItems(owner),
+ len = components.length,
+ boxes = [],
+ box, newTargetSize, anchorWidth, anchorHeight, component, anchorSpec, calcWidth, calcHeight,
+ anchorsArray, anchor, i, el;
+
+ if (ownerWidth < 20 && ownerHeight < 20) {
+ return;
+ }
+
+
+
+
+ if (!me.clearEl) {
+ me.clearEl = target.createChild({
+ cls: Ext.baseCSSPrefix + 'clear',
+ role: 'presentation'
+ });
+ }
+
+
+ if (owner.anchorSize) {
+ if (typeof owner.anchorSize == 'number') {
+ anchorWidth = owner.anchorSize;
+ }
+ else {
+ anchorWidth = owner.anchorSize.width;
+ anchorHeight = owner.anchorSize.height;
+ }
+ }
+ else {
+ anchorWidth = owner.initialConfig.width;
+ anchorHeight = owner.initialConfig.height;
+ }
+
+
+ if (!Ext.supports.RightMargin) {
+ target.addCls(Ext.baseCSSPrefix + 'inline-children');
+ }
+
+ for (i = 0; i < len; i++) {
+ component = components[i];
+ el = component.el;
+ anchor = component.anchor;
+
+ if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)) {
+ component.anchor = anchor = me.defaultAnchor;
+ }
+
+ if (anchor) {
+ anchorSpec = component.anchorSpec;
+
+ if (!anchorSpec) {
+ anchorsArray = anchor.split(' ');
+ component.anchorSpec = anchorSpec = {
+ right: me.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
+ bottom: me.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
+ };
+ }
+ calcWidth = anchorSpec.right ? me.adjustWidthAnchor(anchorSpec.right(ownerWidth) - el.getMargin('lr'), component) : undefined;
+ calcHeight = anchorSpec.bottom ? me.adjustHeightAnchor(anchorSpec.bottom(ownerHeight) - el.getMargin('tb'), component) : undefined;
+
+ boxes.push({
+ component: component,
+ anchor: true,
+ width: calcWidth || undefined,
+ height: calcHeight || undefined
+ });
+ } else {
+ boxes.push({
+ component: component,
+ anchor: false
+ });
+ }
+ }
+
+
+ if (!Ext.supports.RightMargin) {
+ target.removeCls(Ext.baseCSSPrefix + 'inline-children');
+ }
+
+ for (i = 0; i < len; i++) {
+ box = boxes[i];
+ me.setItemSize(box.component, box.width, box.height);
+ }
+
+ if (overflow && overflow != 'hidden' && !me.adjustmentPass) {
+ newTargetSize = me.getLayoutTargetSize();
+ if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
+ me.adjustmentPass = true;
+ me.onLayout();
+ }
+ }
+
+ delete me.adjustmentPass;
+ },
+
+
+ parseAnchor: function(a, start, cstart) {
+ if (a && a != 'none') {
+ var ratio;
+
+ if (this.parseAnchorRE.test(a)) {
+ var diff = cstart - start;
+ return function(v) {
+ return v - diff;
+ };
+ }
+
+ else if (a.indexOf('%') != -1) {
+ ratio = parseFloat(a.replace('%', '')) * 0.01;
+ return function(v) {
+ return Math.floor(v * ratio);
+ };
+ }
+
+ else {
+ a = parseInt(a, 10);
+ if (!isNaN(a)) {
+ return function(v) {
+ return v + a;
+ };
+ }
+ }
+ }
+ return null;
+ },
+
+
+ adjustWidthAnchor: function(value, comp) {
+ return value;
+ },
+
+
+ adjustHeightAnchor: function(value, comp) {
+ return value;
+ }
+
+});
+
+Ext.define('Ext.form.action.Load', {
+ extend:'Ext.form.action.Action',
+ requires: ['Ext.data.Connection'],
+ alternateClassName: 'Ext.form.Action.Load',
+ alias: 'formaction.load',
+
+ type: 'load',
+
+
+ run: function() {
+ Ext.Ajax.request(Ext.apply(
+ this.createCallback(),
+ {
+ method: this.getMethod(),
+ url: this.getUrl(),
+ headers: this.headers,
+ params: this.getParams()
+ }
+ ));
+ },
+
+
+ onSuccess: function(response){
+ var result = this.processResponse(response),
+ form = this.form;
+ if (result === true || !result.success || !result.data) {
+ this.failureType = Ext.form.action.Action.LOAD_FAILURE;
+ form.afterAction(this, false);
+ return;
+ }
+ form.clearInvalid();
+ form.setValues(result.data);
+ form.afterAction(this, true);
+ },
+
+
+ handleResponse: function(response) {
+ var reader = this.form.reader,
+ rs, data;
+ if (reader) {
+ rs = reader.read(response);
+ data = rs.records && rs.records[0] ? rs.records[0].data : null;
+ return {
+ success : rs.success,
+ data : data
+ };
+ }
+ return Ext.decode(response.responseText);
+ }
+});
+
+
+
+Ext.define('Ext.window.Window', {
+ extend: 'Ext.panel.Panel',
+
+ alternateClassName: 'Ext.Window',
+
+ requires: ['Ext.util.ComponentDragger', 'Ext.util.Region', 'Ext.EventManager'],
+
+ alias: 'widget.window',
+
+
+
+
+
+
+
+
+
+
+
+ baseCls: Ext.baseCSSPrefix + 'window',
+
+
+ resizable: true,
+
+
+ draggable: true,
+
+
+ constrain: false,
+
+
+ constrainHeader: false,
+
+
+ plain: false,
+
+
+ minimizable: false,
+
+
+ maximizable: false,
+
+
+ minHeight: 100,
+
+
+ minWidth: 200,
+
+
+ expandOnShow: true,
+
+
+ collapsible: false,
+
+
+ closable: true,
+
+
+ hidden: true,
+
+
+ autoRender: true,
+
+
+ hideMode: 'visibility',
+
+
+ floating: true,
+
+ ariaRole: 'alertdialog',
+
+ itemCls: 'x-window-item',
+
+ overlapHeader: true,
+
+ ignoreHeaderBorderManagement: true,
+
+
+ initComponent: function() {
+ var me = this;
+ me.callParent();
+ me.addEvents(
+
+
+
+ 'resize',
+
+ 'maximize',
+
+ 'minimize',
+
+ 'restore'
+ );
+
+ if (me.plain) {
+ me.addClsWithUI('plain');
+ }
+
+ if (me.modal) {
+ me.ariaRole = 'dialog';
+ }
+ },
+
+
+
+
+ initStateEvents: function(){
+ var events = this.stateEvents;
+
+ Ext.each(['maximize', 'restore', 'resize', 'dragend'], function(event){
+ if (Ext.Array.indexOf(events, event)) {
+ events.push(event);
+ }
+ });
+ this.callParent();
+ },
+
+ getState: function() {
+ var me = this,
+ state = me.callParent() || {},
+ maximized = !!me.maximized;
+
+ state.maximized = maximized;
+ Ext.apply(state, {
+ size: maximized ? me.restoreSize : me.getSize(),
+ pos: maximized ? me.restorePos : me.getPosition()
+ });
+ return state;
+ },
+
+ applyState: function(state){
+ var me = this;
+
+ if (state) {
+ me.maximized = state.maximized;
+ if (me.maximized) {
+ me.hasSavedRestore = true;
+ me.restoreSize = state.size;
+ me.restorePos = state.pos;
+ } else {
+ Ext.apply(me, {
+ width: state.size.width,
+ height: state.size.height,
+ x: state.pos[0],
+ y: state.pos[1]
+ });
+ }
+ }
+ },
+
+
+ onMouseDown: function () {
+ if (this.floating) {
+ this.toFront();
+ }
+ },
+
+
+ onRender: function(ct, position) {
+ var me = this;
+ me.callParent(arguments);
+ me.focusEl = me.el;
+
+
+ if (me.maximizable) {
+ me.header.on({
+ dblclick: {
+ fn: me.toggleMaximize,
+ element: 'el',
+ scope: me
+ }
+ });
+ }
+ },
+
+
+ afterRender: function() {
+ var me = this,
+ hidden = me.hidden,
+ keyMap;
+
+ me.hidden = false;
+
+ me.callParent();
+ me.hidden = hidden;
+
+
+ me.proxy = me.getProxy();
+
+
+ me.mon(me.el, 'mousedown', me.onMouseDown, me);
+
+
+ if (me.maximized) {
+ me.maximized = false;
+ me.maximize();
+ }
+
+ if (me.closable) {
+ keyMap = me.getKeyMap();
+ keyMap.on(27, me.onEsc, me);
+ keyMap.disable();
+ }
+ },
+
+
+ initDraggable: function() {
+ var me = this,
+ ddConfig;
+
+ if (!me.header) {
+ me.updateHeader(true);
+ }
+
+ ddConfig = Ext.applyIf({
+ el: me.el,
+ delegate: '#' + me.header.id
+ }, me.draggable);
+
+
+ if (me.constrain || me.constrainHeader) {
+ ddConfig.constrain = me.constrain;
+ ddConfig.constrainDelegate = me.constrainHeader;
+ ddConfig.constrainTo = me.constrainTo || me.container;
+ }
+
+
+ me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
+ me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
+ },
+
+
+ onEsc: function(k, e) {
+ e.stopEvent();
+ this[this.closeAction]();
+ },
+
+
+ beforeDestroy: function() {
+ var me = this;
+ if (me.rendered) {
+ delete this.animateTarget;
+ me.hide();
+ Ext.destroy(
+ me.keyMap
+ );
+ }
+ me.callParent();
+ },
+
+
+ addTools: function() {
+ var me = this;
+
+
+ me.callParent();
+
+ if (me.minimizable) {
+ me.addTool({
+ type: 'minimize',
+ handler: Ext.Function.bind(me.minimize, me, [])
+ });
+ }
+ if (me.maximizable) {
+ me.addTool({
+ type: 'maximize',
+ handler: Ext.Function.bind(me.maximize, me, [])
+ });
+ me.addTool({
+ type: 'restore',
+ handler: Ext.Function.bind(me.restore, me, []),
+ hidden: true
+ });
+ }
+ },
+
+
+ getFocusEl: function() {
+ var me = this,
+ f = me.focusEl,
+ defaultComp = me.defaultButton || me.defaultFocus,
+ t = typeof db,
+ el,
+ ct;
+
+ if (Ext.isDefined(defaultComp)) {
+ if (Ext.isNumber(defaultComp)) {
+ f = me.query('button')[defaultComp];
+ } else if (Ext.isString(defaultComp)) {
+ f = me.down('#' + defaultComp);
+ } else {
+ f = defaultComp;
+ }
+ }
+ return f || me.focusEl;
+ },
+
+
+ beforeShow: function() {
+ this.callParent();
+
+ if (this.expandOnShow) {
+ this.expand(false);
+ }
+ },
+
+
+ afterShow: function(animateTarget) {
+ var me = this,
+ size;
+
+
+
+ me.callParent(arguments);
+
+ if (me.maximized) {
+ me.fitContainer();
+ }
+
+ if (me.monitorResize || me.constrain || me.constrainHeader) {
+ Ext.EventManager.onWindowResize(me.onWindowResize, me);
+ }
+ me.doConstrain();
+ if (me.keyMap) {
+ me.keyMap.enable();
+ }
+ },
+
+
+ doClose: function() {
+ var me = this;
+
+
+ if (me.hidden) {
+ me.fireEvent('close', me);
+ me[me.closeAction]();
+ } else {
+
+ me.hide(me.animTarget, me.doClose, me);
+ }
+ },
+
+
+ afterHide: function() {
+ var me = this;
+
+
+ if (me.monitorResize || me.constrain || me.constrainHeader) {
+ Ext.EventManager.removeResizeListener(me.onWindowResize, me);
+ }
+
+
+ if (me.keyMap) {
+ me.keyMap.disable();
+ }
+
+
+ me.callParent(arguments);
+ },
+
+
+ onWindowResize: function() {
+ if (this.maximized) {
+ this.fitContainer();
+ }
+ this.doConstrain();
+ },
+
+
+ minimize: function() {
+ this.fireEvent('minimize', this);
+ return this;
+ },
+
+ afterCollapse: function() {
+ var me = this;
+
+ if (me.maximizable) {
+ me.tools.maximize.hide();
+ me.tools.restore.hide();
+ }
+ if (me.resizer) {
+ me.resizer.disable();
+ }
+ me.callParent(arguments);
+ },
+
+ afterExpand: function() {
+ var me = this;
+
+ if (me.maximized) {
+ me.tools.restore.show();
+ } else if (me.maximizable) {
+ me.tools.maximize.show();
+ }
+ if (me.resizer) {
+ me.resizer.enable();
+ }
+ me.callParent(arguments);
+ },
+
+
+ maximize: function() {
+ var me = this;
+
+ if (!me.maximized) {
+ me.expand(false);
+ if (!me.hasSavedRestore) {
+ me.restoreSize = me.getSize();
+ me.restorePos = me.getPosition(true);
+ }
+ if (me.maximizable) {
+ me.tools.maximize.hide();
+ me.tools.restore.show();
+ }
+ me.maximized = true;
+ me.el.disableShadow();
+
+ if (me.dd) {
+ me.dd.disable();
+ }
+ if (me.collapseTool) {
+ me.collapseTool.hide();
+ }
+ me.el.addCls(Ext.baseCSSPrefix + 'window-maximized');
+ me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct');
+
+ me.setPosition(0, 0);
+ me.fitContainer();
+ me.fireEvent('maximize', me);
+ }
+ return me;
+ },
+
+
+ restore: function() {
+ var me = this,
+ tools = me.tools;
+
+ if (me.maximized) {
+ delete me.hasSavedRestore;
+ me.removeCls(Ext.baseCSSPrefix + 'window-maximized');
+
+
+ if (tools.restore) {
+ tools.restore.hide();
+ }
+ if (tools.maximize) {
+ tools.maximize.show();
+ }
+ if (me.collapseTool) {
+ me.collapseTool.show();
+ }
+
+
+ me.setPosition(me.restorePos);
+ me.setSize(me.restoreSize);
+
+
+ delete me.restorePos;
+ delete me.restoreSize;
+
+ me.maximized = false;
+
+ me.el.enableShadow(true);
+
+
+ if (me.dd) {
+ me.dd.enable();
+ }
+
+ me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct');
+
+ me.doConstrain();
+ me.fireEvent('restore', me);
+ }
+ return me;
+ },
+
+
+ toggleMaximize: function() {
+ return this[this.maximized ? 'restore': 'maximize']();
+ }
+
+
+});
+
+Ext.define('Ext.form.field.Base', {
+ extend: 'Ext.Component',
+ mixins: {
+ labelable: 'Ext.form.Labelable',
+ field: 'Ext.form.field.Field'
+ },
+ alias: 'widget.field',
+ alternateClassName: ['Ext.form.Field', 'Ext.form.BaseField'],
+ requires: ['Ext.util.DelayedTask', 'Ext.XTemplate', 'Ext.layout.component.field.Field'],
+
+ fieldSubTpl: [
+ '<input id="{id}" type="{type}" ',
+ '<tpl if="name">name="{name}" </tpl>',
+ '<tpl if="size">size="{size}" </tpl>',
+ '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+ 'class="{fieldCls} {typeCls}" autocomplete="off" />',
+ {
+ compiled: true,
+ disableFormats: true
+ }
+ ],
+
+
+
+
+ inputType: 'text',
+
+
+
+
+ invalidText : 'The value in this field is invalid',
+
+
+ fieldCls : Ext.baseCSSPrefix + 'form-field',
+
+
+
+
+ focusCls : Ext.baseCSSPrefix + 'form-focus',
+
+
+ dirtyCls : Ext.baseCSSPrefix + 'form-dirty',
+
+
+ checkChangeEvents: Ext.isIE && (!document.documentMode || document.documentMode < 9) ?
+ ['change', 'propertychange'] :
+ ['change', 'input', 'textInput', 'keyup', 'dragdrop'],
+
+
+ checkChangeBuffer: 50,
+
+ componentLayout: 'field',
+
+
+ readOnly : false,
+
+
+ readOnlyCls: Ext.baseCSSPrefix + 'form-readonly',
+
+
+
+
+ validateOnBlur: true,
+
+
+ hasFocus : false,
+
+ baseCls: Ext.baseCSSPrefix + 'field',
+
+ maskOnDisable: false,
+
+
+ initComponent : function() {
+ var me = this;
+
+ me.callParent();
+
+ me.subTplData = me.subTplData || {};
+
+ me.addEvents(
+
+ 'focus',
+
+ 'blur',
+
+ 'specialkey'
+ );
+
+
+ me.initLabelable();
+ me.initField();
+
+
+ if (!me.name) {
+ me.name = me.getInputId();
+ }
+ },
+
+
+ getInputId: function() {
+ return this.inputId || (this.inputId = Ext.id());
+ },
+
+
+ getSubTplData: function() {
+ var me = this,
+ type = me.inputType,
+ inputId = me.getInputId();
+
+ return Ext.applyIf(me.subTplData, {
+ id: inputId,
+ name: me.name || inputId,
+ type: type,
+ size: me.size || 20,
+ cls: me.cls,
+ fieldCls: me.fieldCls,
+ tabIdx: me.tabIndex,
+ typeCls: Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type)
+ });
+ },
+
+
+ getSubTplMarkup: function() {
+ return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
+ },
+
+ initRenderTpl: function() {
+ var me = this;
+ if (!me.hasOwnProperty('renderTpl')) {
+ me.renderTpl = me.getTpl('labelableRenderTpl');
+ }
+ return me.callParent();
+ },
+
+ initRenderData: function() {
+ return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
+ },
+
+
+ setFieldStyle: function(style) {
+ var me = this,
+ inputEl = me.inputEl;
+ if (inputEl) {
+ inputEl.applyStyles(style);
+ }
+ me.fieldStyle = style;
+ },
+
+
+ onRender : function() {
+ var me = this,
+ fieldStyle = me.fieldStyle,
+ renderSelectors = me.renderSelectors;
+
+ Ext.applyIf(renderSelectors, me.getLabelableSelectors());
+
+ Ext.applyIf(renderSelectors, {
+
+ inputEl: '.' + me.fieldCls
+ });
+
+ me.callParent(arguments);
+
+
+ me.setRawValue(me.rawValue);
+
+ if (me.readOnly) {
+ me.setReadOnly(true);
+ }
+ if (me.disabled) {
+ me.disable();
+ }
+ if (fieldStyle) {
+ me.setFieldStyle(fieldStyle);
+ }
+
+ me.renderActiveError();
+ },
+
+ initAria: function() {
+ var me = this;
+ me.callParent();
+
+
+ me.getActionEl().dom.setAttribute('aria-describedby', Ext.id(me.errorEl));
+ },
+
+ getFocusEl: function() {
+ return this.inputEl;
+ },
+
+ isFileUpload: function() {
+ return this.inputType === 'file';
+ },
+
+ extractFileInput: function() {
+ var me = this,
+ fileInput = me.isFileUpload() ? me.inputEl.dom : null,
+ clone;
+ if (fileInput) {
+ clone = fileInput.cloneNode(true);
+ fileInput.parentNode.replaceChild(clone, fileInput);
+ me.inputEl = Ext.get(clone);
+ }
+ return fileInput;
+ },
+
+
+ getSubmitData: function() {
+ var me = this,
+ data = null,
+ val;
+ if (!me.disabled && me.submitValue && !me.isFileUpload()) {
+ val = me.getSubmitValue();
+ if (val !== null) {
+ data = {};
+ data[me.getName()] = val;
+ }
+ }
+ return data;
+ },
+
+
+ getSubmitValue: function() {
+ return this.processRawValue(this.getRawValue());
+ },
+
+
+ getRawValue: function() {
+ var me = this,
+ v = (me.inputEl ? me.inputEl.getValue() : Ext.value(me.rawValue, ''));
+ me.rawValue = v;
+ return v;
+ },
+
+
+ setRawValue: function(value) {
+ var me = this;
+ value = Ext.value(value, '');
+ me.rawValue = value;
+
+
+ if (me.inputEl) {
+ me.inputEl.dom.value = value;
+ }
+ return value;
+ },
+
+
+ valueToRaw: function(value) {
+ return '' + Ext.value(value, '');
+ },
+
+
+ rawToValue: function(rawValue) {
+ return rawValue;
+ },
+
+
+ processRawValue: function(value) {
+ return value;
+ },
+
+
+ getValue: function() {
+ var me = this,
+ val = me.rawToValue(me.processRawValue(me.getRawValue()));
+ me.value = val;
+ return val;
+ },
+
+
+ setValue: function(value) {
+ var me = this;
+ me.setRawValue(me.valueToRaw(value));
+ return me.mixins.field.setValue.call(me, value);
+ },
+
+
+
+ onDisable: function() {
+ var me = this,
+ inputEl = me.inputEl;
+ me.callParent();
+ if (inputEl) {
+ inputEl.dom.disabled = true;
+ }
+ },
+
+
+ onEnable: function() {
+ var me = this,
+ inputEl = me.inputEl;
+ me.callParent();
+ if (inputEl) {
+ inputEl.dom.disabled = false;
+ }
+ },
+
+
+ setReadOnly: function(readOnly) {
+ var me = this,
+ inputEl = me.inputEl;
+ if (inputEl) {
+ inputEl.dom.readOnly = readOnly;
+ inputEl.dom.setAttribute('aria-readonly', readOnly);
+ }
+ me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls);
+ me.readOnly = readOnly;
+ },
+
+
+ fireKey: function(e){
+ if(e.isSpecialKey()){
+ this.fireEvent('specialkey', this, Ext.create('Ext.EventObjectImpl', e));
+ }
+ },
+
+
+ initEvents : function(){
+ var me = this,
+ inputEl = me.inputEl,
+ onChangeTask,
+ onChangeEvent;
+ if (inputEl) {
+ me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey, me);
+ me.mon(inputEl, 'focus', me.onFocus, me);
+
+
+
+ me.mon(inputEl, 'blur', me.onBlur, me, me.inEditor ? {buffer:10} : null);
+
+
+ onChangeTask = Ext.create('Ext.util.DelayedTask', me.checkChange, me);
+ me.onChangeEvent = onChangeEvent = function() {
+ onChangeTask.delay(me.checkChangeBuffer);
+ };
+ Ext.each(me.checkChangeEvents, function(eventName) {
+ if (eventName === 'propertychange') {
+ me.usesPropertychange = true;
+ }
+ me.mon(inputEl, eventName, onChangeEvent);
+ }, me);
+ }
+ me.callParent();
+ },
+
+ doComponentLayout: function() {
+ var me = this,
+ inputEl = me.inputEl,
+ usesPropertychange = me.usesPropertychange,
+ ename = 'propertychange',
+ onChangeEvent = me.onChangeEvent;
+
+
+
+
+ if (usesPropertychange) {
+ me.mun(inputEl, ename, onChangeEvent);
+ }
+ me.callParent(arguments);
+ if (usesPropertychange) {
+ me.mon(inputEl, ename, onChangeEvent);
+ }
+ },
+
+
+ preFocus: Ext.emptyFn,
+
+
+ onFocus: function() {
+ var me = this,
+ focusCls = me.focusCls,
+ inputEl = me.inputEl;
+ me.preFocus();
+ if (focusCls && inputEl) {
+ inputEl.addCls(focusCls);
+ }
+ if (!me.hasFocus) {
+ me.hasFocus = true;
+ me.fireEvent('focus', me);
+ }
+ },
+
+
+ beforeBlur : Ext.emptyFn,
+
+
+ onBlur : function(){
+ var me = this,
+ focusCls = me.focusCls,
+ inputEl = me.inputEl;
+ me.beforeBlur();
+ if (focusCls && inputEl) {
+ inputEl.removeCls(focusCls);
+ }
+ if (me.validateOnBlur) {
+ me.validate();
+ }
+ me.hasFocus = false;
+ me.fireEvent('blur', me);
+ me.postBlur();
+ },
+
+
+ postBlur : Ext.emptyFn,
+
+
+
+ onDirtyChange: function(isDirty) {
+ this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls);
+ },
+
+
+
+ isValid : function() {
+ var me = this;
+ return me.disabled || me.validateValue(me.processRawValue(me.getRawValue()));
+ },
+
+
+
+ validateValue: function(value) {
+ var me = this,
+ errors = me.getErrors(value),
+ isValid = Ext.isEmpty(errors);
+ if (!me.preventMark) {
+ if (isValid) {
+ me.clearInvalid();
+ } else {
+ me.markInvalid(errors);
+ }
+ }
+
+ return isValid;
+ },
+
+
+ markInvalid : function(errors) {
+
+ var me = this,
+ oldMsg = me.getActiveError();
+ me.setActiveErrors(Ext.Array.from(errors));
+ if (oldMsg !== me.getActiveError()) {
+ me.doComponentLayout();
+ }
+ },
+
+
+ clearInvalid : function() {
+
+ var me = this,
+ hadError = me.hasActiveError();
+ me.unsetActiveError();
+ if (hadError) {
+ me.doComponentLayout();
+ }
+ },
+
+
+ renderActiveError: function() {
+ var me = this,
+ hasError = me.hasActiveError();
+ if (me.inputEl) {
+
+ me.inputEl[hasError ? 'addCls' : 'removeCls'](me.invalidCls + '-field');
+ }
+ me.mixins.labelable.renderActiveError.call(me);
+ },
+
+
+ getActionEl: function() {
+ return this.inputEl || this.el;
+ }
+
+});
+
+
+Ext.define('Ext.form.field.Text', {
+ extend:'Ext.form.field.Base',
+ alias: 'widget.textfield',
+ requires: ['Ext.form.field.VTypes', 'Ext.layout.component.field.Text'],
+ alternateClassName: ['Ext.form.TextField', 'Ext.form.Text'],
+
+
+
+
+
+
+ size: 20,
+
+
+
+
+ growMin : 30,
+
+
+ growMax : 800,
+
+
+ growAppend: 'W',
+
+
+
+
+
+
+
+
+ allowBlank : true,
+
+
+ minLength : 0,
+
+
+ maxLength : Number.MAX_VALUE,
+
+
+
+
+ minLengthText : 'The minimum length for this field is {0}',
+
+
+ maxLengthText : 'The maximum length for this field is {0}',
+
+
+
+
+ blankText : 'This field is required',
+
+
+
+
+
+
+ regexText : '',
+
+
+
+
+ emptyCls : Ext.baseCSSPrefix + 'form-empty-field',
+
+ ariaRole: 'textbox',
+
+
+
+ componentLayout: 'textfield',
+
+ initComponent : function(){
+ this.callParent();
+ this.addEvents(
+
+ 'autosize',
+
+
+ 'keydown',
+
+ 'keyup',
+
+ 'keypress'
+ );
+ },
+
+
+ initEvents : function(){
+ var me = this,
+ el = me.inputEl;
+
+ me.callParent();
+ if(me.selectOnFocus || me.emptyText){
+ me.mon(el, 'mousedown', me.onMouseDown, me);
+ }
+ if(me.maskRe || (me.vtype && me.disableKeyFilter !== true && (me.maskRe = Ext.form.field.VTypes[me.vtype+'Mask']))){
+ me.mon(el, 'keypress', me.filterKeys, me);
+ }
+
+ if (me.enableKeyEvents) {
+ me.mon(el, {
+ scope: me,
+ keyup: me.onKeyUp,
+ keydown: me.onKeyDown,
+ keypress: me.onKeyPress
+ });
+ }
+ },
+
+
+ isEqual: function(value1, value2) {
+ return String(Ext.value(value1, '')) === String(Ext.value(value2, ''));
+ },
+
+
+ onChange: function() {
+ this.callParent();
+ this.autoSize();
+ },
+
+ afterRender: function(){
+ var me = this;
+ if (me.enforceMaxLength) {
+ me.inputEl.dom.maxLength = me.maxLength;
+ }
+ me.applyEmptyText();
+ me.autoSize();
+ me.callParent();
+ },
+
+ onMouseDown: function(e){
+ var me = this;
+ if(!me.hasFocus){
+ me.mon(me.inputEl, 'mouseup', Ext.emptyFn, me, { single: true, preventDefault: true });
+ }
+ },
+
+
+ processRawValue: function(value) {
+ var me = this,
+ stripRe = me.stripCharsRe,
+ newValue;
+
+ if (stripRe) {
+ newValue = value.replace(stripRe, '');
+ if (newValue !== value) {
+ me.setRawValue(newValue);
+ value = newValue;
+ }
+ }
+ return value;
+ },
+
+
+ onDisable: function(){
+ this.callParent();
+ if (Ext.isIE) {
+ this.inputEl.dom.unselectable = 'on';
+ }
+ },
+
+
+ onEnable: function(){
+ this.callParent();
+ if (Ext.isIE) {
+ this.inputEl.dom.unselectable = '';
+ }
+ },
+
+ onKeyDown: function(e) {
+ this.fireEvent('keydown', this, e);
+ },
+
+ onKeyUp: function(e) {
+ this.fireEvent('keyup', this, e);
+ },
+
+ onKeyPress: function(e) {
+ this.fireEvent('keypress', this, e);
+ },
+
+
+ reset : function(){
+ this.callParent();
+ this.applyEmptyText();
+ },
+
+ applyEmptyText : function(){
+ var me = this,
+ emptyText = me.emptyText,
+ isEmpty;
+
+ if (me.rendered && emptyText) {
+ isEmpty = me.getRawValue().length < 1 && !me.hasFocus;
+
+ if (Ext.supports.Placeholder) {
+ me.inputEl.dom.placeholder = emptyText;
+ } else if (isEmpty) {
+ me.setRawValue(emptyText);
+ }
+
+
+
+ if (isEmpty) {
+ me.inputEl.addCls(me.emptyCls);
+ }
+
+ me.autoSize();
+ }
+ },
+
+
+ preFocus : function(){
+ var me = this,
+ inputEl = me.inputEl,
+ emptyText = me.emptyText,
+ isEmpty;
+
+ if (emptyText && !Ext.supports.Placeholder && inputEl.dom.value === emptyText) {
+ me.setRawValue('');
+ isEmpty = true;
+ inputEl.removeCls(me.emptyCls);
+ } else if (Ext.supports.Placeholder) {
+ me.inputEl.removeCls(me.emptyCls);
+ }
+ if (me.selectOnFocus || isEmpty) {
+ inputEl.dom.select();
+ }
+ },
+
+ onFocus: function() {
+ var me = this;
+ me.callParent(arguments);
+ if (me.emptyText) {
+ me.autoSize();
+ }
+ },
+
+
+ postBlur : function(){
+ this.applyEmptyText();
+ },
+
+
+ filterKeys : function(e){
+ if(e.ctrlKey){
+ return;
+ }
+ var key = e.getKey(),
+ charCode = String.fromCharCode(e.getCharCode());
+
+ if(Ext.isGecko && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){
+ return;
+ }
+
+ if(!Ext.isGecko && e.isSpecialKey() && !charCode){
+ return;
+ }
+ if(!this.maskRe.test(charCode)){
+ e.stopEvent();
+ }
+ },
+
+
+ getRawValue: function() {
+ var me = this,
+ v = me.callParent();
+ if (v === me.emptyText) {
+ v = '';
+ }
+ return v;
+ },
+
+
+ setValue: function(value) {
+ var me = this,
+ inputEl = me.inputEl;
+
+ if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
+ inputEl.removeCls(me.emptyCls);
+ }
+
+ me.callParent(arguments);
+
+ me.applyEmptyText();
+ return me;
+ },
+
+
+ getErrors: function(value) {
+ var me = this,
+ errors = me.callParent(arguments),
+ validator = me.validator,
+ emptyText = me.emptyText,
+ allowBlank = me.allowBlank,
+ vtype = me.vtype,
+ vtypes = Ext.form.field.VTypes,
+ regex = me.regex,
+ format = Ext.String.format,
+ msg;
+
+ value = value || me.processRawValue(me.getRawValue());
+
+ if (Ext.isFunction(validator)) {
+ msg = validator.call(me, value);
+ if (msg !== true) {
+ errors.push(msg);
+ }
+ }
+
+ if (value.length < 1 || value === emptyText) {
+ if (!allowBlank) {
+ errors.push(me.blankText);
+ }
+
+ return errors;
+ }
+
+ if (value.length < me.minLength) {
+ errors.push(format(me.minLengthText, me.minLength));
+ }
+
+ if (value.length > me.maxLength) {
+ errors.push(format(me.maxLengthText, me.maxLength));
+ }
+
+ if (vtype) {
+ if(!vtypes[vtype](value, me)){
+ errors.push(me.vtypeText || vtypes[vtype +'Text']);
+ }
+ }
+
+ if (regex && !regex.test(value)) {
+ errors.push(me.regexText || me.invalidText);
+ }
+
+ return errors;
+ },
+
+
+ selectText : function(start, end){
+ var me = this,
+ v = me.getRawValue(),
+ doFocus = true,
+ el = me.inputEl.dom,
+ undef,
+ range;
+
+ if (v.length > 0) {
+ start = start === undef ? 0 : start;
+ end = end === undef ? v.length : end;
+ if (el.setSelectionRange) {
+ el.setSelectionRange(start, end);
+ }
+ else if(el.createTextRange) {
+ range = el.createTextRange();
+ range.moveStart('character', start);
+ range.moveEnd('character', end - v.length);
+ range.select();
+ }
+ doFocus = Ext.isGecko || Ext.isOpera;
+ }
+ if (doFocus) {
+ me.focus();
+ }
+ },
+
+
+ autoSize: function() {
+ var me = this,
+ width;
+ if (me.grow && me.rendered) {
+ me.doComponentLayout();
+ width = me.inputEl.getWidth();
+ if (width !== me.lastInputWidth) {
+ me.fireEvent('autosize', width);
+ me.lastInputWidth = width;
+ }
+ }
+ },
+
+ initAria: function() {
+ this.callParent();
+ this.getActionEl().dom.setAttribute('aria-required', this.allowBlank === false);
+ },
+
+
+ getBodyNaturalWidth: function() {
+ return Math.round(this.size * 6.5) + 20;
+ }
+
+});
+
+
+Ext.define('Ext.form.field.TextArea', {
+ extend:'Ext.form.field.Text',
+ alias: ['widget.textareafield', 'widget.textarea'],
+ alternateClassName: 'Ext.form.TextArea',
+ requires: ['Ext.XTemplate', 'Ext.layout.component.field.TextArea'],
+
+ fieldSubTpl: [
+ '<textarea id="{id}" ',
+ '<tpl if="name">name="{name}" </tpl>',
+ '<tpl if="rows">rows="{rows}" </tpl>',
+ '<tpl if="cols">cols="{cols}" </tpl>',
+ '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+ 'class="{fieldCls} {typeCls}" ',
+ 'autocomplete="off">',
+ '</textarea>',
+ {
+ compiled: true,
+ disableFormats: true
+ }
+ ],
+
+
+ growMin: 60,
+
+
+ growMax: 1000,
+
+
+ growAppend: '\n-',
+
+
+ cols: 20,
+
+
+ rows: 4,
+
+
+ enterIsSpecial: false,
+
+
+ preventScrollbars: false,
+
+
+ componentLayout: 'textareafield',
+
+
+ onRender: function(ct, position) {
+ var me = this;
+ Ext.applyIf(me.subTplData, {
+ cols: me.cols,
+ rows: me.rows
+ });
+
+ me.callParent(arguments);
+ },
+
+
+ afterRender: function(){
+ var me = this;
+
+ me.callParent(arguments);
+
+ if (me.grow) {
+ if (me.preventScrollbars) {
+ me.inputEl.setStyle('overflow', 'hidden');
+ }
+ me.inputEl.setHeight(me.growMin);
+ }
+ },
+
+
+ fireKey: function(e) {
+ if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() !== e.ENTER || e.hasModifier()))) {
+ this.fireEvent('specialkey', this, e);
+ }
+ },
+
+
+ autoSize: function() {
+ var me = this,
+ height;
+
+ if (me.grow && me.rendered) {
+ me.doComponentLayout();
+ height = me.inputEl.getHeight();
+ if (height !== me.lastInputHeight) {
+ me.fireEvent('autosize', height);
+ me.lastInputHeight = height;
+ }
+ }
+ },
+
+
+ initAria: function() {
+ this.callParent(arguments);
+ this.getActionEl().dom.setAttribute('aria-multiline', true);
+ },
+
+
+ getBodyNaturalWidth: function() {
+ return Math.round(this.cols * 6.5) + 20;
+ }
+
+});
+
+
+
+Ext.define('Ext.window.MessageBox', {
+ extend: 'Ext.window.Window',
+
+ requires: [
+ 'Ext.toolbar.Toolbar',
+ 'Ext.form.field.Text',
+ 'Ext.form.field.TextArea',
+ 'Ext.button.Button',
+ 'Ext.layout.container.Anchor',
+ 'Ext.layout.container.HBox',
+ 'Ext.ProgressBar'
+ ],
+
+ alternateClassName: 'Ext.MessageBox',
+
+ alias: 'widget.messagebox',
+
+
+ OK : 1,
+
+ YES : 2,
+
+ NO : 4,
+
+ CANCEL : 8,
+
+ OKCANCEL : 9,
+
+ YESNO : 6,
+
+ YESNOCANCEL : 14,
+
+ INFO : 'ext-mb-info',
+
+ WARNING : 'ext-mb-warning',
+
+ QUESTION : 'ext-mb-question',
+
+ ERROR : 'ext-mb-error',
+
+
+ hideMode: 'offsets',
+ closeAction: 'hide',
+ resizable: false,
+ title: ' ',
+
+ width: 600,
+ height: 500,
+ minWidth: 250,
+ maxWidth: 600,
+ minHeight: 110,
+ maxHeight: 500,
+ constrain: true,
+
+ cls: Ext.baseCSSPrefix + 'message-box',
+
+ layout: {
+ type: 'anchor'
+ },
+
+
+ defaultTextHeight : 75,
+
+ minProgressWidth : 250,
+
+ minPromptWidth: 250,
+
+ buttonText: {
+ ok: 'OK',
+ yes: 'Yes',
+ no: 'No',
+ cancel: 'Cancel'
+ },
+
+ buttonIds: [
+ 'ok', 'yes', 'no', 'cancel'
+ ],
+
+ titleText: {
+ confirm: 'Confirm',
+ prompt: 'Prompt',
+ wait: 'Loading...',
+ alert: 'Attention'
+ },
+
+ iconHeight: 35,
+
+ makeButton: function(btnIdx) {
+ var btnId = this.buttonIds[btnIdx];
+ return Ext.create('Ext.button.Button', {
+ handler: this.btnCallback,
+ itemId: btnId,
+ scope: this,
+ text: this.buttonText[btnId],
+ minWidth: 75
+ });
+ },
+
+ btnCallback: function(btn) {
+ var me = this,
+ value,
+ field;
+
+ if (me.cfg.prompt || me.cfg.multiline) {
+ if (me.cfg.multiline) {
+ field = me.textArea;
+ } else {
+ field = me.textField;
+ }
+ value = field.getValue();
+ field.reset();
+ }
+
+
+ btn.blur();
+ me.hide();
+ me.userCallback(btn.itemId, value, me.cfg);
+ },
+
+ hide: function() {
+ var me = this;
+ me.dd.endDrag();
+ me.progressBar.reset();
+ me.removeCls(me.cfg.cls);
+ me.callParent();
+ },
+
+ initComponent: function() {
+ var me = this,
+ i, button;
+
+ me.title = ' ';
+
+ me.topContainer = Ext.create('Ext.container.Container', {
+ anchor: '100%',
+ style: {
+ padding: '10px',
+ overflow: 'hidden'
+ },
+ items: [
+ me.iconComponent = Ext.create('Ext.Component', {
+ cls: 'ext-mb-icon',
+ width: 50,
+ height: me.iconHeight,
+ style: {
+ 'float': 'left'
+ }
+ }),
+ me.promptContainer = Ext.create('Ext.container.Container', {
+ layout: {
+ type: 'anchor'
+ },
+ items: [
+ me.msg = Ext.create('Ext.Component', {
+ autoEl: { tag: 'span' },
+ cls: 'ext-mb-text'
+ }),
+ me.textField = Ext.create('Ext.form.field.Text', {
+ anchor: '100%',
+ enableKeyEvents: true,
+ listeners: {
+ keydown: me.onPromptKey,
+ scope: me
+ }
+ }),
+ me.textArea = Ext.create('Ext.form.field.TextArea', {
+ anchor: '100%',
+ height: 75
+ })
+ ]
+ })
+ ]
+ });
+ me.progressBar = Ext.create('Ext.ProgressBar', {
+ anchor: '-10',
+ style: 'margin-left:10px'
+ });
+
+ me.items = [me.topContainer, me.progressBar];
+
+
+ me.msgButtons = [];
+ for (i = 0; i < 4; i++) {
+ button = me.makeButton(i);
+ me.msgButtons[button.itemId] = button;
+ me.msgButtons.push(button);
+ }
+ me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
+ ui: 'footer',
+ dock: 'bottom',
+ layout: {
+ pack: 'center'
+ },
+ items: [
+ me.msgButtons[0],
+ me.msgButtons[1],
+ me.msgButtons[2],
+ me.msgButtons[3]
+ ]
+ });
+ me.dockedItems = [me.bottomTb];
+
+ me.callParent();
+ },
+
+ onPromptKey: function(textField, e) {
+ var me = this,
+ blur;
+
+ if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
+ if (me.msgButtons.ok.isVisible()) {
+ blur = true;
+ me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
+ } else if (me.msgButtons.yes.isVisible()) {
+ me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
+ blur = true;
+ }
+
+ if (blur) {
+ me.textField.blur();
+ }
+ }
+ },
+
+ reconfigure: function(cfg) {
+ var me = this,
+ buttons = cfg.buttons || 0,
+ hideToolbar = true,
+ initialWidth = me.maxWidth,
+ i;
+
+ cfg = cfg || {};
+ me.cfg = cfg;
+ if (cfg.width) {
+ initialWidth = cfg.width;
+ }
+
+
+ delete me.defaultFocus;
+
+
+ me.animateTarget = cfg.animateTarget || undefined;
+
+
+ me.modal = cfg.modal !== false;
+
+
+ if (cfg.title) {
+ me.setTitle(cfg.title||' ');
+ }
+
+ if (!me.rendered) {
+ me.width = initialWidth;
+ me.render(Ext.getBody());
+ } else {
+ me.setSize(initialWidth, me.maxHeight);
+ }
+ me.setPosition(-10000, -10000);
+
+
+ me.closable = cfg.closable && !cfg.wait;
+ if (cfg.closable === false) {
+ me.tools.close.hide();
+ } else {
+ me.tools.close.show();
+ }
+
+
+ if (!cfg.title && !me.closable) {
+ me.header.hide();
+ } else {
+ me.header.show();
+ }
+
+
+ me.liveDrag = !cfg.proxyDrag;
+
+
+ me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
+
+
+ me.setIcon(cfg.icon);
+
+
+ if (cfg.msg) {
+ me.msg.update(cfg.msg);
+ me.msg.show();
+ } else {
+ me.msg.hide();
+ }
+
+
+ if (cfg.prompt || cfg.multiline) {
+ me.multiline = cfg.multiline;
+ if (cfg.multiline) {
+ me.textArea.setValue(cfg.value);
+ me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
+ me.textArea.show();
+ me.textField.hide();
+ me.defaultFocus = me.textArea;
+ } else {
+ me.textField.setValue(cfg.value);
+ me.textArea.hide();
+ me.textField.show();
+ me.defaultFocus = me.textField;
+ }
+ } else {
+ me.textArea.hide();
+ me.textField.hide();
+ }
+
+
+ if (cfg.progress || cfg.wait) {
+ me.progressBar.show();
+ me.updateProgress(0, cfg.progressText);
+ if(cfg.wait === true){
+ me.progressBar.wait(cfg.waitConfig);
+ }
+ } else {
+ me.progressBar.hide();
+ }
+
+
+ for (i = 0; i < 4; i++) {
+ if (buttons & Math.pow(2, i)) {
+
+
+ if (!me.defaultFocus) {
+ me.defaultFocus = me.msgButtons[i];
+ }
+ me.msgButtons[i].show();
+ hideToolbar = false;
+ } else {
+ me.msgButtons[i].hide();
+ }
+ }
+
+
+ if (hideToolbar) {
+ me.bottomTb.hide();
+ } else {
+ me.bottomTb.show();
+ }
+ me.hidden = true;
+ },
+
+
+ show: function(cfg) {
+ var me = this;
+
+ me.reconfigure(cfg);
+ me.addCls(cfg.cls);
+ if (cfg.animateTarget) {
+ me.doAutoSize(false);
+ me.callParent();
+ } else {
+ me.callParent();
+ me.doAutoSize(true);
+ }
+ return me;
+ },
+
+ afterShow: function(){
+ if (this.animateTarget) {
+ this.center();
+ }
+ this.callParent(arguments);
+ },
+
+ doAutoSize: function(center) {
+ var me = this,
+ icon = me.iconComponent,
+ iconHeight = me.iconHeight;
+
+ if (!Ext.isDefined(me.frameWidth)) {
+ me.frameWidth = me.el.getWidth() - me.body.getWidth();
+ }
+
+
+ icon.setHeight(iconHeight);
+
+
+ me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
+
+
+
+ me.topContainer.doLayout();
+ if (Ext.isIE6 || Ext.isIEQuirks) {
+
+
+
+ me.textField.setCalculatedSize(9);
+ me.textArea.setCalculatedSize(9);
+ }
+ var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25,
+ height = (me.header.rendered ? me.header.getHeight() : 0) +
+ Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
+ me.progressBar.getHeight() +
+ (me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;
+
+
+ icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
+ me.setSize(width + me.frameWidth, height + me.frameWidth);
+ if (center) {
+ me.center();
+ }
+ return me;
+ },
+
+ updateText: function(text) {
+ this.msg.update(text);
+ return this.doAutoSize(true);
+ },
+
+
+ setIcon : function(icon) {
+ var me = this;
+ me.iconComponent.removeCls(me.iconCls);
+ if (icon) {
+ me.iconComponent.show();
+ me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
+ me.iconComponent.addCls(me.iconCls = icon);
+ } else {
+ me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
+ me.iconComponent.hide();
+ }
+ return me;
+ },
+
+
+ updateProgress : function(value, progressText, msg){
+ this.progressBar.updateProgress(value, progressText);
+ if (msg){
+ this.updateText(msg);
+ }
+ return this;
+ },
+
+ onEsc: function() {
+ if (this.closable !== false) {
+ this.callParent(arguments);
+ }
+ },
+
+
+ confirm: function(cfg, msg, fn, scope) {
+ if (Ext.isString(cfg)) {
+ cfg = {
+ title: cfg,
+ icon: 'ext-mb-question',
+ msg: msg,
+ buttons: this.YESNO,
+ callback: fn,
+ scope: scope
+ };
+ }
+ return this.show(cfg);
+ },
+
+
+ prompt : function(cfg, msg, fn, scope, multiline, value){
+ if (Ext.isString(cfg)) {
+ cfg = {
+ prompt: true,
+ title: cfg,
+ minWidth: this.minPromptWidth,
+ msg: msg,
+ buttons: this.OKCANCEL,
+ callback: fn,
+ scope: scope,
+ multiline: multiline,
+ value: value
+ };
+ }
+ return this.show(cfg);
+ },
+
+
+ wait : function(cfg, title, config){
+ if (Ext.isString(cfg)) {
+ cfg = {
+ title : title,
+ msg : cfg,
+ closable: false,
+ wait: true,
+ modal: true,
+ minWidth: this.minProgressWidth,
+ waitConfig: config
+ };
+ }
+ return this.show(cfg);
+ },
+
+
+ alert: function(cfg, msg, fn, scope) {
+ if (Ext.isString(cfg)) {
+ cfg = {
+ title : cfg,
+ msg : msg,
+ buttons: this.OK,
+ fn: fn,
+ scope : scope,
+ minWidth: this.minWidth
+ };
+ }
+ return this.show(cfg);
+ },
+
+
+ progress : function(cfg, msg, progressText){
+ if (Ext.isString(cfg)) {
+ cfg = {
+ title: cfg,
+ msg: msg,
+ progressText: progressText
+ };
+ }
+ return this.show(cfg);
+ }
+}, function() {
+ Ext.MessageBox = Ext.Msg = new this();
+});
+
+
+
+
+Ext.define('Ext.form.Basic', {
+ extend: 'Ext.util.Observable',
+ alternateClassName: 'Ext.form.BasicForm',
+ requires: ['Ext.util.MixedCollection', 'Ext.form.action.Load', 'Ext.form.action.Submit',
+ 'Ext.window.MessageBox', 'Ext.data.Errors'],
+
+ constructor: function(owner, config) {
+ var me = this,
+ onItemAddOrRemove = me.onItemAddOrRemove;
+
+
+ me.owner = owner;
+
+
+ me.mon(owner, {
+ add: onItemAddOrRemove,
+ remove: onItemAddOrRemove,
+ scope: me
+ });
+
+ Ext.apply(me, config);
+
+
+ if (Ext.isString(me.paramOrder)) {
+ me.paramOrder = me.paramOrder.split(/[\s,|]/);
+ }
+
+ me.addEvents(
+
+ 'beforeaction',
+
+ 'actionfailed',
+
+ 'actioncomplete',
+
+ 'validitychange',
+
+ 'dirtychange'
+ );
+ me.callParent();
+ },
+
+
+ initialize: function(){
+ this.initialized = true;
+ this.onValidityChange(!this.hasInvalidField());
+ },
+
+
+
+
+
+
+
+
+
+
+ timeout: 30,
+
+
+
+
+
+
+ paramsAsHash: false,
+
+
+ waitTitle: 'Please Wait...',
+
+
+ trackResetOnLoad: false,
+
+
+
+
+
+
+
+ wasDirty: false,
+
+
+
+ destroy: function() {
+ this.clearListeners();
+ },
+
+
+ onItemAddOrRemove: function(parent, child) {
+ var me = this,
+ isAdding = !!child.ownerCt,
+ isContainer = child.isContainer;
+
+ function handleField(field) {
+
+ me[isAdding ? 'mon' : 'mun'](field, {
+ validitychange: me.checkValidity,
+ dirtychange: me.checkDirty,
+ scope: me,
+ buffer: 100
+ });
+
+ delete me._fields;
+ }
+
+ if (child.isFormField) {
+ handleField(child);
+ }
+ else if (isContainer) {
+
+ Ext.Array.forEach(child.query('[isFormField]'), handleField);
+ }
+
+
+ delete this._boundItems;
+
+
+ if (me.initialized) {
+ me.onValidityChange(!me.hasInvalidField());
+ }
+ },
+
+
+ getFields: function() {
+ var fields = this._fields;
+ if (!fields) {
+ fields = this._fields = Ext.create('Ext.util.MixedCollection');
+ fields.addAll(this.owner.query('[isFormField]'));
+ }
+ return fields;
+ },
+
+ getBoundItems: function() {
+ var boundItems = this._boundItems;
+ if (!boundItems) {
+ boundItems = this._boundItems = Ext.create('Ext.util.MixedCollection');
+ boundItems.addAll(this.owner.query('[formBind]'));
+ }
+ return boundItems;
+ },
+
+
+ hasInvalidField: function() {
+ return !!this.getFields().findBy(function(field) {
+ var preventMark = field.preventMark,
+ isValid;
+ field.preventMark = true;
+ isValid = field.isValid();
+ field.preventMark = preventMark;
+ return !isValid;
+ });
+ },
+
+
+ isValid: function() {
+ var me = this,
+ invalid;
+ me.batchLayouts(function() {
+ invalid = me.getFields().filterBy(function(field) {
+ return !field.validate();
+ });
+ });
+ return invalid.length < 1;
+ },
+
+
+ checkValidity: function() {
+ var me = this,
+ valid = !me.hasInvalidField();
+ if (valid !== me.wasValid) {
+ me.onValidityChange(valid);
+ me.fireEvent('validitychange', me, valid);
+ me.wasValid = valid;
+ }
+ },
+
+
+ onValidityChange: function(valid) {
+ var boundItems = this.getBoundItems();
+ if (boundItems) {
+ boundItems.each(function(cmp) {
+ if (cmp.disabled === valid) {
+ cmp.setDisabled(!valid);
+ }
+ });
+ }
+ },
+
+
+ isDirty: function() {
+ return !!this.getFields().findBy(function(f) {
+ return f.isDirty();
+ });
+ },
+
+
+ checkDirty: function() {
+ var dirty = this.isDirty();
+ if (dirty !== this.wasDirty) {
+ this.fireEvent('dirtychange', this, dirty);
+ this.wasDirty = dirty;
+ }
+ },
+
+
+ hasUpload: function() {
+ return !!this.getFields().findBy(function(f) {
+ return f.isFileUpload();
+ });
+ },
+
+
+ doAction: function(action, options) {
+ if (Ext.isString(action)) {
+ action = Ext.ClassManager.instantiateByAlias('formaction.' + action, Ext.apply({}, options, {form: this}));
+ }
+ if (this.fireEvent('beforeaction', this, action) !== false) {
+ this.beforeAction(action);
+ Ext.defer(action.run, 100, action);
+ }
+ return this;
+ },
+
+
+ submit: function(options) {
+ return this.doAction(this.standardSubmit ? 'standardsubmit' : this.api ? 'directsubmit' : 'submit', options);
+ },
+
+
+ load: function(options) {
+ return this.doAction(this.api ? 'directload' : 'load', options);
+ },
+
+
+ updateRecord: function(record) {
+ var fields = record.fields,
+ values = this.getFieldValues(),
+ name,
+ obj = {};
+
+ fields.each(function(f) {
+ name = f.name;
+ if (name in values) {
+ obj[name] = values[name];
+ }
+ });
+
+ record.beginEdit();
+ record.set(obj);
+ record.endEdit();
+
+ return this;
+ },
+
+
+ loadRecord: function(record) {
+ this._record = record;
+ return this.setValues(record.data);
+ },
+
+
+ getRecord: function() {
+ return this._record;
+ },
+
+
+ beforeAction: function(action) {
+ var waitMsg = action.waitMsg,
+ maskCls = Ext.baseCSSPrefix + 'mask-loading',
+ waitMsgTarget;
+
+
+ this.getFields().each(function(f) {
+ if (f.isFormField && f.syncValue) {
+ f.syncValue();
+ }
+ });
+
+ if (waitMsg) {
+ waitMsgTarget = this.waitMsgTarget;
+ if (waitMsgTarget === true) {
+ this.owner.el.mask(waitMsg, maskCls);
+ } else if (waitMsgTarget) {
+ waitMsgTarget = this.waitMsgTarget = Ext.get(waitMsgTarget);
+ waitMsgTarget.mask(waitMsg, maskCls);
+ } else {
+ Ext.MessageBox.wait(waitMsg, action.waitTitle || this.waitTitle);
+ }
+ }
+ },
+
+
+ afterAction: function(action, success) {
+ if (action.waitMsg) {
+ var MessageBox = Ext.MessageBox,
+ waitMsgTarget = this.waitMsgTarget;
+ if (waitMsgTarget === true) {
+ this.owner.el.unmask();
+ } else if (waitMsgTarget) {
+ waitMsgTarget.unmask();
+ } else {
+ MessageBox.updateProgress(1);
+ MessageBox.hide();
+ }
+ }
+ if (success) {
+ if (action.reset) {
+ this.reset();
+ }
+ Ext.callback(action.success, action.scope || action, [this, action]);
+ this.fireEvent('actioncomplete', this, action);
+ } else {
+ Ext.callback(action.failure, action.scope || action, [this, action]);
+ this.fireEvent('actionfailed', this, action);
+ }
+ },
+
+
+
+ findField: function(id) {
+ return this.getFields().findBy(function(f) {
+ return f.id === id || f.getName() === id;
+ });
+ },
+
+
+
+ markInvalid: function(errors) {
+ var me = this;
+
+ function mark(fieldId, msg) {
+ var field = me.findField(fieldId);
+ if (field) {
+ field.markInvalid(msg);
+ }
+ }
+
+ if (Ext.isArray(errors)) {
+ Ext.each(errors, function(err) {
+ mark(err.id, err.msg);
+ });
+ }
+ else if (errors instanceof Ext.data.Errors) {
+ errors.each(function(err) {
+ mark(err.field, err.message);
+ });
+ }
+ else {
+ Ext.iterate(errors, mark);
+ }
+ return this;
+ },
+
+
+ setValues: function(values) {
+ var me = this;
+
+ function setVal(fieldId, val) {
+ var field = me.findField(fieldId);
+ if (field) {
+ field.setValue(val);
+ if (me.trackResetOnLoad) {
+ field.resetOriginalValue();
+ }
+ }
+ }
+
+ if (Ext.isArray(values)) {
+
+ Ext.each(values, function(val) {
+ setVal(val.id, val.value);
+ });
+ } else {
+
+ Ext.iterate(values, setVal);
+ }
+ return this;
+ },
+
+
+ getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
+ var values = {};
+
+ this.getFields().each(function(field) {
+ if (!dirtyOnly || field.isDirty()) {
+ var data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText);
+ if (Ext.isObject(data)) {
+ Ext.iterate(data, function(name, val) {
+ if (includeEmptyText && val === '') {
+ val = field.emptyText || '';
+ }
+ if (name in values) {
+ var bucket = values[name],
+ isArray = Ext.isArray;
+ if (!isArray(bucket)) {
+ bucket = values[name] = [bucket];
+ }
+ if (isArray(val)) {
+ values[name] = bucket.concat(val);
+ } else {
+ bucket.push(val);
+ }
+ } else {
+ values[name] = val;
+ }
+ });
+ }
+ }
+ });
+
+ if (asString) {
+ values = Ext.Object.toQueryString(values);
+ }
+ return values;
+ },
+
+
+ getFieldValues: function(dirtyOnly) {
+ return this.getValues(false, dirtyOnly, false, true);
+ },
+
+
+ clearInvalid: function() {
+ var me = this;
+ me.batchLayouts(function() {
+ me.getFields().each(function(f) {
+ f.clearInvalid();
+ });
+ });
+ return me;
+ },
+
+
+ reset: function() {
+ var me = this;
+ me.batchLayouts(function() {
+ me.getFields().each(function(f) {
+ f.reset();
+ });
+ });
+ return me;
+ },
+
+
+ applyToFields: function(obj) {
+ this.getFields().each(function(f) {
+ Ext.apply(f, obj);
+ });
+ return this;
+ },
+
+
+ applyIfToFields: function(obj) {
+ this.getFields().each(function(f) {
+ Ext.applyIf(f, obj);
+ });
+ return this;
+ },
+
+
+ batchLayouts: function(fn) {
+ var me = this,
+ suspended = new Ext.util.HashMap();
+
+
+ me.getFields().each(function(field) {
+ var ownerCt = field.ownerCt;
+ if (!suspended.contains(ownerCt)) {
+ suspended.add(ownerCt);
+ ownerCt.oldSuspendLayout = ownerCt.suspendLayout;
+ ownerCt.suspendLayout = true;
+ }
+ });
+
+
+ fn();
+
+
+ suspended.each(function(id, ct) {
+ ct.suspendLayout = ct.oldSuspendLayout;
+ delete ct.oldSuspendLayout;
+ });
+
+
+ me.owner.doComponentLayout();
+ }
+});
+
+
+Ext.define('Ext.form.FieldAncestor', {
+
+
+
+
+
+ initFieldAncestor: function() {
+ var me = this,
+ onSubtreeChange = me.onFieldAncestorSubtreeChange;
+
+ me.addEvents(
+
+ 'fieldvaliditychange',
+
+
+ 'fielderrorchange'
+ );
+
+
+ me.on('add', onSubtreeChange, me);
+ me.on('remove', onSubtreeChange, me);
+
+ me.initFieldDefaults();
+ },
+
+
+ initFieldDefaults: function() {
+ if (!this.fieldDefaults) {
+ this.fieldDefaults = {};
+ }
+ },
+
+
+ onFieldAncestorSubtreeChange: function(parent, child) {
+ var me = this,
+ isAdding = !!child.ownerCt;
+
+ function handleCmp(cmp) {
+ var isLabelable = cmp.isFieldLabelable,
+ isField = cmp.isFormField;
+ if (isLabelable || isField) {
+ if (isLabelable) {
+ me['onLabelable' + (isAdding ? 'Added' : 'Removed')](cmp);
+ }
+ if (isField) {
+ me['onField' + (isAdding ? 'Added' : 'Removed')](cmp);
+ }
+ }
+ else if (cmp.isContainer) {
+ Ext.Array.forEach(cmp.getRefItems(), handleCmp);
+ }
+ }
+ handleCmp(child);
+ },
+
+
+ onLabelableAdded: function(labelable) {
+ var me = this;
+
+
+ me.mon(labelable, 'errorchange', me.handleFieldErrorChange, me, {buffer: 10});
+
+ labelable.setFieldDefaults(me.fieldDefaults);
+ },
+
+
+ onFieldAdded: function(field) {
+ var me = this;
+ me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
+ },
+
+
+ onLabelableRemoved: function(labelable) {
+ var me = this;
+ me.mun(labelable, 'errorchange', me.handleFieldErrorChange, me);
+ },
+
+
+ onFieldRemoved: function(field) {
+ var me = this;
+ me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
+ },
+
+
+ handleFieldValidityChange: function(field, isValid) {
+ var me = this;
+ me.fireEvent('fieldvaliditychange', me, field, isValid);
+ me.onFieldValidityChange();
+ },
+
+
+ handleFieldErrorChange: function(labelable, activeError) {
+ var me = this;
+ me.fireEvent('fielderrorchange', me, labelable, activeError);
+ me.onFieldErrorChange();
+ },
+
+
+ onFieldValidityChange: Ext.emptyFn,
+
+
+ onFieldErrorChange: Ext.emptyFn
+
+});
+
+Ext.define('Ext.layout.container.CheckboxGroup', {
+ extend: 'Ext.layout.container.Container',
+ alias: ['layout.checkboxgroup'],
+
+
+ onLayout: function() {
+ var numCols = this.getColCount(),
+ shadowCt = this.getShadowCt(),
+ owner = this.owner,
+ items = owner.items,
+ shadowItems = shadowCt.items,
+ numItems = items.length,
+ colIndex = 0,
+ i, numRows;
+
+
+
+
+
+
+ shadowItems.each(function(col) {
+ col.items.clear();
+ });
+
+
+
+ while (shadowItems.length > numCols) {
+ shadowCt.remove(shadowItems.last());
+ }
+ while (shadowItems.length < numCols) {
+ shadowCt.add({
+ xtype: 'container',
+ cls: owner.groupCls,
+ flex: 1
+ });
+ }
+
+ if (owner.vertical) {
+ numRows = Math.ceil(numItems / numCols);
+ for (i = 0; i < numItems; i++) {
+ if (i > 0 && i % numRows === 0) {
+ colIndex++;
+ }
+ shadowItems.getAt(colIndex).items.add(items.getAt(i));
+ }
+ } else {
+ for (i = 0; i < numItems; i++) {
+ colIndex = i % numCols;
+ shadowItems.getAt(colIndex).items.add(items.getAt(i));
+ }
+ }
+
+ if (!shadowCt.rendered) {
+ shadowCt.render(this.getRenderTarget());
+ } else {
+
+
+ shadowItems.each(function(col) {
+ var layout = col.getLayout();
+ layout.renderItems(layout.getLayoutItems(), layout.getRenderTarget());
+ });
+ }
+
+ shadowCt.doComponentLayout();
+ },
+
+
+
+ renderItems: Ext.emptyFn,
+
+
+
+ getShadowCt: function() {
+ var me = this,
+ shadowCt = me.shadowCt,
+ owner, items, item, columns, columnsIsArray, numCols, i;
+
+ if (!shadowCt) {
+
+ owner = me.owner;
+ columns = owner.columns;
+ columnsIsArray = Ext.isArray(columns);
+ numCols = me.getColCount();
+ items = [];
+ for(i = 0; i < numCols; i++) {
+ item = {
+ xtype: 'container',
+ cls: owner.groupCls
+ };
+ if (columnsIsArray) {
+
+
+ if (columns[i] < 1) {
+ item.flex = columns[i];
+ } else {
+ item.width = columns[i];
+ }
+ }
+ else {
+
+ item.flex = 1;
+ }
+ items.push(item);
+ }
+
+
+ shadowCt = me.shadowCt = Ext.createWidget('container', {
+ layout: 'hbox',
+ items: items,
+ ownerCt: owner
+ });
+ }
+
+ return shadowCt;
+ },
+
+
+
+ getColCount: function() {
+ var owner = this.owner,
+ colsCfg = owner.columns;
+ return Ext.isArray(colsCfg) ? colsCfg.length : (Ext.isNumber(colsCfg) ? colsCfg : owner.items.length);
+ }
+
+});
+
+
+Ext.define('Ext.form.FieldContainer', {
+ extend: 'Ext.container.Container',
+ mixins: {
+ labelable: 'Ext.form.Labelable',
+ fieldAncestor: 'Ext.form.FieldAncestor'
+ },
+ alias: 'widget.fieldcontainer',
+
+ componentLayout: 'field',
+
+
+ combineLabels: false,
+
+
+ labelConnector: ', ',
+
+
+ combineErrors: false,
+
+ maskOnDisable: false,
+
+ initComponent: function() {
+ var me = this,
+ onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
+
+
+ me.initLabelable();
+ me.initFieldAncestor();
+
+ me.callParent();
+ },
+
+
+ onLabelableAdded: function(labelable) {
+ var me = this;
+ me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
+ me.updateLabel();
+ },
+
+
+ onLabelableRemoved: function(labelable) {
+ var me = this;
+ me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
+ me.updateLabel();
+ },
+
+ onRender: function() {
+ var me = this,
+ renderSelectors = me.renderSelectors,
+ applyIf = Ext.applyIf;
+
+ applyIf(renderSelectors, me.getLabelableSelectors());
+
+ me.callParent(arguments);
+ },
+
+ initRenderTpl: function() {
+ var me = this;
+ if (!me.hasOwnProperty('renderTpl')) {
+ me.renderTpl = me.getTpl('labelableRenderTpl');
+ }
+ return me.callParent();
+ },
+
+ initRenderData: function() {
+ return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
+ },
+
+
+ getFieldLabel: function() {
+ var label = this.fieldLabel || '';
+ if (!label && this.combineLabels) {
+ label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
+ return field.getFieldLabel();
+ }).join(this.labelConnector);
+ }
+ return label;
+ },
+
+
+ updateLabel: function() {
+ var me = this,
+ label = me.labelEl;
+ if (label) {
+ label.update(me.getFieldLabel());
+ }
+ },
+
+
+
+ onFieldErrorChange: function(field, activeError) {
+ if (this.combineErrors) {
+ var me = this,
+ oldError = me.getActiveError(),
+ invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
+ return field.hasActiveError();
+ }),
+ newErrors = me.getCombinedErrors(invalidFields);
+
+ if (newErrors) {
+ me.setActiveErrors(newErrors);
+ } else {
+ me.unsetActiveError();
+ }
+
+ if (oldError !== me.getActiveError()) {
+ me.doComponentLayout();
+ }
+ }
+ },
+
+
+ getCombinedErrors: function(invalidFields) {
+ var forEach = Ext.Array.forEach,
+ errors = [];
+ forEach(invalidFields, function(field) {
+ forEach(field.getActiveErrors(), function(error) {
+ var label = field.getFieldLabel();
+ errors.push((label ? label + ': ' : '') + error);
+ });
+ });
+ return errors;
+ },
+
+ getTargetEl: function() {
+ return this.bodyEl || this.callParent();
+ }
+});
+
+
+Ext.define('Ext.form.CheckboxGroup', {
+ extend:'Ext.form.FieldContainer',
+ mixins: {
+ field: 'Ext.form.field.Field'
+ },
+ alias: 'widget.checkboxgroup',
+ requires: ['Ext.layout.container.CheckboxGroup', 'Ext.form.field.Base'],
+
+
+
+
+
+
+ columns : 'auto',
+
+
+ vertical : false,
+
+
+ allowBlank : true,
+
+
+ blankText : "You must select at least one item in this group",
+
+
+ defaultType : 'checkboxfield',
+
+
+ groupCls : Ext.baseCSSPrefix + 'form-check-group',
+
+
+ fieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body',
+
+
+ layout: 'checkboxgroup',
+
+ initComponent: function() {
+ var me = this;
+ me.callParent();
+ me.initField();
+ },
+
+
+ initValue: function() {
+ var me = this,
+ valueCfg = me.value;
+ me.originalValue = me.lastValue = valueCfg || me.getValue();
+ if (valueCfg) {
+ me.setValue(valueCfg);
+ }
+ },
+
+
+ onFieldAdded: function(field) {
+ var me = this;
+ if (field.isCheckbox) {
+ me.mon(field, 'change', me.checkChange, me);
+ }
+ me.callParent(arguments);
+ },
+
+ onFieldRemoved: function(field) {
+ var me = this;
+ if (field.isCheckbox) {
+ me.mun(field, 'change', me.checkChange, me);
+ }
+ me.callParent(arguments);
+ },
+
+
+ isEqual: function(value1, value2) {
+ var toQueryString = Ext.Object.toQueryString;
+ return toQueryString(value1) === toQueryString(value2);
+ },
+
+
+ getErrors: function() {
+ var errors = [];
+ if (!this.allowBlank && Ext.isEmpty(this.getChecked())) {
+ errors.push(this.blankText);
+ }
+ return errors;
+ },
+
+
+ getBoxes: function() {
+ return this.query('[isCheckbox]');
+ },
+
+
+ eachBox: function(fn, scope) {
+ Ext.Array.forEach(this.getBoxes(), fn, scope || this);
+ },
+
+
+ getChecked: function() {
+ return Ext.Array.filter(this.getBoxes(), function(cb) {
+ return cb.getValue();
+ });
+ },
+
+
+ isDirty: function(){
+ return Ext.Array.some(this.getBoxes(), function(cb) {
+ return cb.isDirty();
+ });
+ },
+
+
+ setReadOnly: function(readOnly) {
+ this.eachBox(function(cb) {
+ cb.setReadOnly(readOnly);
+ });
+ this.readOnly = readOnly;
+ },
+
+
+ reset: function() {
+ var me = this,
+ hadError = me.hasActiveError(),
+ preventMark = me.preventMark;
+ me.preventMark = true;
+ me.batchChanges(function() {
+ me.eachBox(function(cb) {
+ cb.reset();
+ });
+ });
+ me.preventMark = preventMark;
+ me.unsetActiveError();
+ if (hadError) {
+ me.doComponentLayout();
+ }
+ },
+
+
+ resetOriginalValue: function() {
+
+
+ Ext.defer(function() {
+ this.callParent();
+ }, 1, this);
+ },
+
+
+
+ setValue: function(value) {
+ var me = this;
+ me.batchChanges(function() {
+ me.eachBox(function(cb) {
+ var name = cb.getName(),
+ cbValue = false;
+ if (value && name in value) {
+ if (Ext.isArray(value[name])) {
+ cbValue = Ext.Array.contains(value[name], cb.inputValue);
+ } else {
+
+ cbValue = value[name];
+ }
+ }
+ cb.setValue(cbValue);
+ });
+ });
+ return me;
+ },
+
+
+
+ getValue: function() {
+ var values = {};
+ this.eachBox(function(cb) {
+ var name = cb.getName(),
+ inputValue = cb.inputValue,
+ bucket;
+ if (cb.getValue()) {
+ if (name in values) {
+ bucket = values[name];
+ if (!Ext.isArray(bucket)) {
+ bucket = values[name] = [bucket];
+ }
+ bucket.push(inputValue);
+ } else {
+ values[name] = inputValue;
+ }
+ }
+ });
+ return values;
+ },
+
+
+ getSubmitData: function() {
+ return null;
+ },
+
+
+ getModelData: function() {
+ return null;
+ },
+
+ validate: function() {
+ var me = this,
+ errors = me.getErrors(),
+ isValid = Ext.isEmpty(errors),
+ wasValid = !me.hasActiveError();
+
+ if (isValid) {
+ me.unsetActiveError();
+ } else {
+ me.setActiveError(errors);
+ }
+ if (isValid !== wasValid) {
+ me.fireEvent('validitychange', me, isValid);
+ me.doComponentLayout();
+ }
+
+ return isValid;
+ }
+
+}, function() {
+
+ this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid']);
+
+});
+
+
+
+Ext.define('Ext.form.CheckboxManager', {
+ extend: 'Ext.util.MixedCollection',
+ singleton: true,
+
+ getByName: function(name) {
+ return this.filterBy(function(item) {
+ return item.name == name;
+ });
+ },
+
+ getWithValue: function(name, value) {
+ return this.filterBy(function(item) {
+ return item.name == name && item.inputValue == value;
+ });
+ },
+
+ getChecked: function(name) {
+ return this.filterBy(function(item) {
+ return item.name == name && item.checked;
+ });
+ }
+});
+
+
+Ext.define('Ext.form.FieldSet', {
+ extend: 'Ext.container.Container',
+ alias: 'widget.fieldset',
+ uses: ['Ext.form.field.Checkbox', 'Ext.panel.Tool', 'Ext.layout.container.Anchor', 'Ext.layout.component.FieldSet'],
+
+
+
+
+
+
+
+
+
+
+ collapsed: false,
+
+
+
+
+ baseCls: Ext.baseCSSPrefix + 'fieldset',
+
+
+ layout: 'anchor',
+
+ componentLayout: 'fieldset',
+
+
+ ariaRole: '',
+
+ renderTpl: ['<div class="{baseCls}-body"></div>'],
+
+ maskOnDisable: false,
+
+ getElConfig: function(){
+ return {tag: 'fieldset', id: this.id};
+ },
+
+ initComponent: function() {
+ var me = this,
+ baseCls = me.baseCls;
+
+ me.callParent();
+
+
+ me.initLegend();
+
+
+ Ext.applyIf(me.renderSelectors, {
+ body: '.' + baseCls + '-body'
+ });
+
+ if (me.collapsed) {
+ me.addCls(baseCls + '-collapsed');
+ me.collapse();
+ }
+ },
+
+
+ onRender: function(container, position) {
+ this.callParent(arguments);
+
+ this.initLegend();
+ },
+
+
+ initLegend: function() {
+ var me = this,
+ legendItems,
+ legend = me.legend;
+
+
+ if (!legend && (me.title || me.checkboxToggle || me.collapsible)) {
+ legendItems = [];
+
+
+ if (me.checkboxToggle) {
+ legendItems.push(me.createCheckboxCmp());
+ }
+
+ else if (me.collapsible) {
+ legendItems.push(me.createToggleCmp());
+ }
+
+
+ legendItems.push(me.createTitleCmp());
+
+ legend = me.legend = Ext.create('Ext.container.Container', {
+ baseCls: me.baseCls + '-header',
+ ariaRole: '',
+ getElConfig: function(){
+ return {tag: 'legend', cls: this.baseCls};
+ },
+ items: legendItems
+ });
+ }
+
+
+ if (legend && !legend.rendered && me.rendered) {
+ me.legend.render(me.el, me.body);
+ }
+ },
+
+
+ createTitleCmp: function() {
+ var me = this;
+ me.titleCmp = Ext.create('Ext.Component', {
+ html: me.title,
+ cls: me.baseCls + '-header-text'
+ });
+ return me.titleCmp;
+
+ },
+
+
+
+
+ createCheckboxCmp: function() {
+ var me = this,
+ suffix = '-checkbox';
+
+ me.checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
+ name: me.checkboxName || me.id + suffix,
+ cls: me.baseCls + '-header' + suffix,
+ checked: !me.collapsed,
+ listeners: {
+ change: me.onCheckChange,
+ scope: me
+ }
+ });
+ return me.checkboxCmp;
+ },
+
+
+
+
+ createToggleCmp: function() {
+ var me = this;
+ me.toggleCmp = Ext.create('Ext.panel.Tool', {
+ type: 'toggle',
+ handler: me.toggle,
+ scope: me
+ });
+ return me.toggleCmp;
+ },
+
+
+ setTitle: function(title) {
+ var me = this;
+ me.title = title;
+ me.initLegend();
+ me.titleCmp.update(title);
+ return me;
+ },
+
+ getTargetEl : function() {
+ return this.body || this.frameBody || this.el;
+ },
+
+ getContentTarget: function() {
+ return this.body;
+ },
+
+
+ getRefItems: function(deep) {
+ var refItems = this.callParent(arguments),
+ legend = this.legend;
+
+
+ if (legend) {
+ refItems.unshift(legend);
+ if (deep) {
+ refItems.unshift.apply(refItems, legend.getRefItems(true));
+ }
+ }
+ return refItems;
+ },
+
+
+ expand : function(){
+ return this.setExpanded(true);
+ },
+
+
+ collapse : function() {
+ return this.setExpanded(false);
+ },
+
+
+ setExpanded: function(expanded) {
+ var me = this,
+ checkboxCmp = me.checkboxCmp,
+ toggleCmp = me.toggleCmp;
+
+ expanded = !!expanded;
+
+ if (checkboxCmp) {
+ checkboxCmp.setValue(expanded);
+ }
+
+ if (expanded) {
+ me.removeCls(me.baseCls + '-collapsed');
+ } else {
+ me.addCls(me.baseCls + '-collapsed');
+ }
+ me.collapsed = !expanded;
+ me.doComponentLayout();
+ return me;
+ },
+
+
+ toggle: function() {
+ this.setExpanded(!!this.collapsed);
+ },
+
+
+ onCheckChange: function(cmp, checked) {
+ this.setExpanded(checked);
+ },
+
+ beforeDestroy : function() {
+ var legend = this.legend;
+ if (legend) {
+ legend.destroy();
+ }
+ this.callParent();
+ }
+});
+
+
+Ext.define('Ext.form.Label', {
+ extend:'Ext.Component',
+ alias: 'widget.label',
+ requires: ['Ext.util.Format'],
+
+
+
+
+
+ maskOnDisable: false,
+ getElConfig: function(){
+ var me = this;
+ return {
+ tag: 'label',
+ id: me.id,
+ htmlFor: me.forId || '',
+ html: me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || '')
+ };
+ },
+
+
+ setText : function(text, encode){
+ var me = this;
+
+ encode = encode !== false;
+ if(encode) {
+ me.text = text;
+ delete me.html;
+ } else {
+ me.html = text;
+ delete me.text;
+ }
+
+ if(me.rendered){
+ me.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(text) : text;
+ }
+ return this;
+ }
+});
+
+
+
+Ext.define('Ext.form.Panel', {
+ extend:'Ext.panel.Panel',
+ mixins: {
+ fieldAncestor: 'Ext.form.FieldAncestor'
+ },
+ alias: 'widget.form',
+ alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'],
+ requires: ['Ext.form.Basic', 'Ext.util.TaskRunner'],
+
+
+
+
+
+
+ layout: 'anchor',
+
+ ariaRole: 'form',
+
+ initComponent: function() {
+ var me = this;
+
+ if (me.frame) {
+ me.border = false;
+ }
+
+ me.initFieldAncestor();
+ me.callParent();
+
+ me.relayEvents(me.form, [
+ 'beforeaction',
+ 'actionfailed',
+ 'actioncomplete',
+ 'validitychange',
+ 'dirtychange'
+ ]);
+
+
+ if (me.pollForChanges) {
+ me.startPolling(me.pollInterval || 500);
+ }
+ },
+
+ initItems: function() {
+
+ var me = this;
+
+ me.form = me.createForm();
+ me.callParent();
+ me.form.initialize();
+ },
+
+
+ createForm: function() {
+ return Ext.create('Ext.form.Basic', this, Ext.applyIf({listeners: {}}, this.initialConfig));
+ },
+
+
+ getForm: function() {
+ return this.form;
+ },
+
+
+ loadRecord: function(record) {
+ return this.getForm().loadRecord(record);
+ },
+
+
+ getRecord: function() {
+ return this.getForm().getRecord();
+ },
+
+
+ getValues: function() {
+ return this.getForm().getValues();
+ },
+
+ beforeDestroy: function() {
+ this.stopPolling();
+ this.form.destroy();
+ this.callParent();
+ },
+
+
+ load: function(options) {
+ this.form.load(options);
+ },
+
+
+ submit: function(options) {
+ this.form.submit(options);
+ },
+
+
+ disable: function(silent) {
+ this.callParent(arguments);
+ this.form.getFields().each(function(field) {
+ field.disable();
+ });
+ },
+
+
+ enable: function(silent) {
+ this.callParent(arguments);
+ this.form.getFields().each(function(field) {
+ field.enable();
+ });
+ },
+
+
+ startPolling: function(interval) {
+ this.stopPolling();
+ var task = Ext.create('Ext.util.TaskRunner', interval);
+ task.start({
+ interval: 0,
+ run: this.checkChange,
+ scope: this
+ });
+ this.pollTask = task;
+ },
+
+
+ stopPolling: function() {
+ var task = this.pollTask;
+ if (task) {
+ task.stopAll();
+ delete this.pollTask;
+ }
+ },
+
+
+ checkChange: function() {
+ this.form.getFields().each(function(field) {
+ field.checkChange();
+ });
+ }
+});
+
+
+Ext.define('Ext.form.RadioGroup', {
+ extend: 'Ext.form.CheckboxGroup',
+ alias: 'widget.radiogroup',
+
+
+
+ allowBlank : true,
+
+ blankText : 'You must select one item in this group',
+
+
+ defaultType : 'radiofield',
+
+
+ groupCls : Ext.baseCSSPrefix + 'form-radio-group',
+
+ getBoxes: function() {
+ return this.query('[isRadio]');
+ }
+
+});
+
+
+Ext.define('Ext.form.RadioManager', {
+ extend: 'Ext.util.MixedCollection',
+ singleton: true,
+
+ getByName: function(name) {
+ return this.filterBy(function(item) {
+ return item.name == name;
+ });
+ },
+
+ getWithValue: function(name, value) {
+ return this.filterBy(function(item) {
+ return item.name == name && item.inputValue == value;
+ });
+ },
+
+ getChecked: function(name) {
+ return this.findBy(function(item) {
+ return item.name == name && item.checked;
+ });
+ }
+});
+
+
+Ext.define('Ext.form.action.DirectLoad', {
+ extend:'Ext.form.action.Load',
+ requires: ['Ext.direct.Manager'],
+ alternateClassName: 'Ext.form.Action.DirectLoad',
+ alias: 'formaction.directload',
+
+ type: 'directload',
+
+ run: function() {
+ this.form.api.load.apply(window, this.getArgs());
+ },
+
+
+ getArgs: function() {
+ var me = this,
+ args = [],
+ form = me.form,
+ paramOrder = form.paramOrder,
+ params = me.getParams(),
+ i, len;
+
+
+ if (paramOrder) {
+ for (i = 0, len = paramOrder.length; i < len; i++) {
+ args.push(params[paramOrder[i]]);
+ }
+ }
+
+ else if (form.paramsAsHash) {
+ args.push(params);
+ }
+
+
+ args.push(me.onSuccess, me);
+
+ return args;
+ },
+
+
+
+
+ processResponse: function(result) {
+ return (this.result = result);
+ },
+
+ onSuccess: function(result, trans) {
+ if (trans.type == Ext.direct.Manager.self.exceptions.SERVER) {
+ result = {};
+ }
+ this.callParent([result]);
+ }
+});
+
+
+
+
+Ext.define('Ext.form.action.DirectSubmit', {
+ extend:'Ext.form.action.Submit',
+ requires: ['Ext.direct.Manager'],
+ alternateClassName: 'Ext.form.Action.DirectSubmit',
+ alias: 'formaction.directsubmit',
+
+ type: 'directsubmit',
+
+ doSubmit: function() {
+ var me = this,
+ callback = Ext.Function.bind(me.onSuccess, me),
+ formEl = me.buildForm();
+ me.form.api.submit(formEl, callback, me);
+ Ext.removeNode(formEl);
+ },
+
+
+
+
+ processResponse: function(result) {
+ return (this.result = result);
+ },
+
+ onSuccess: function(response, trans) {
+ if (trans.type === Ext.direct.Manager.self.exceptions.SERVER) {
+ response = {};
+ }
+ this.callParent([response]);
+ }
+});
+
+
+Ext.define('Ext.form.action.StandardSubmit', {
+ extend:'Ext.form.action.Submit',
+ alias: 'formaction.standardsubmit',
+
+
+
+
+ doSubmit: function() {
+ var form = this.buildForm();
+ form.submit();
+ Ext.removeNode(form);
+ }
+
+});
+
+
+Ext.define('Ext.form.field.Checkbox', {
+ extend: 'Ext.form.field.Base',
+ alias: ['widget.checkboxfield', 'widget.checkbox'],
+ alternateClassName: 'Ext.form.Checkbox',
+ requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager'],
+
+ fieldSubTpl: [
+ '<tpl if="boxLabel && boxLabelAlign == \'before\'">',
+ '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
+ '</tpl>',
+
+
+
+ '<input type="button" id="{id}" ',
+ '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+ 'class="{fieldCls} {typeCls}" autocomplete="off" hidefocus="true" />',
+ '<tpl if="boxLabel && boxLabelAlign == \'after\'">',
+ '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
+ '</tpl>',
+ {
+ disableFormats: true,
+ compiled: true
+ }
+ ],
+
+ isCheckbox: true,
+
+
+ focusCls: Ext.baseCSSPrefix + 'form-cb-focus',
+
+
+
+
+ fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
+
+
+ checked: false,
+
+
+ checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
+
+
+
+
+ boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
+
+
+ boxLabelAlign: 'after',
+
+
+ inputValue: 'on',
+
+
+
+
+
+
+
+
+ checkChangeEvents: [],
+ inputType: 'checkbox',
+ ariaRole: 'checkbox',
+
+
+ onRe: /^on$/i,
+
+ initComponent: function(){
+ this.callParent(arguments);
+ this.getManager().add(this);
+ },
+
+ initValue: function() {
+ var me = this,
+ checked = !!me.checked;
+
+
+ me.originalValue = me.lastValue = checked;
+
+
+ me.setValue(checked);
+ },
+
+
+ onRender : function(ct, position) {
+ var me = this;
+ Ext.applyIf(me.renderSelectors, {
+
+ boxLabelEl: 'label.' + me.boxLabelCls
+ });
+ Ext.applyIf(me.subTplData, {
+ boxLabel: me.boxLabel,
+ boxLabelCls: me.boxLabelCls,
+ boxLabelAlign: me.boxLabelAlign
+ });
+
+ me.callParent(arguments);
+ },
+
+ initEvents: function() {
+ var me = this;
+ me.callParent();
+ me.mon(me.inputEl, 'click', me.onBoxClick, me);
+ },
+
+
+ onBoxClick: function(e) {
+ var me = this;
+ if (!me.disabled && !me.readOnly) {
+ this.setValue(!this.checked);
+ }
+ },
+
+
+ getRawValue: function() {
+ return this.checked;
+ },
+
+
+ getValue: function() {
+ return this.checked;
+ },
+
+
+ getSubmitValue: function() {
+ return this.checked ? this.inputValue : (this.uncheckedValue || null);
+ },
+
+ getModelData: function() {
+ return this.getSubmitData();
+ },
+
+
+ setRawValue: function(value) {
+ var me = this,
+ inputEl = me.inputEl,
+ inputValue = me.inputValue,
+ checked = (value === true || value === 'true' || value === '1' ||
+ ((Ext.isString(value) && inputValue) ? value == inputValue : me.onRe.test(value)));
+
+ if (inputEl) {
+ inputEl.dom.setAttribute('aria-checked', checked);
+ me[checked ? 'addCls' : 'removeCls'](me.checkedCls);
+ }
+
+ me.checked = me.rawValue = checked;
+ return checked;
+ },
+
+
+ setValue: function(checked) {
+ var me = this;
+
+
+
+
+
+ if (Ext.isArray(checked)) {
+ me.getManager().getByName(me.name).each(function(cb) {
+ cb.setValue(Ext.Array.contains(checked, cb.inputValue));
+ });
+ } else {
+ me.callParent(arguments);
+ }
+
+ return me;
+ },
+
+
+ valueToRaw: function(value) {
+
+ return value;
+ },
+
+
+ onChange: function(newVal, oldVal) {
+ var me = this,
+ handler = me.handler;
+ if (handler) {
+ handler.call(me.scope || me, me, newVal);
+ }
+ me.callParent(arguments);
+ },
+
+
+ getManager: function() {
+ return Ext.form.CheckboxManager;
+ },
+
+ onEnable: function() {
+ var me = this,
+ inputEl = me.inputEl;
+ me.callParent();
+ if (inputEl) {
+
+ inputEl.dom.disabled = me.readOnly;
+ }
+ },
+
+ setReadOnly: function(readOnly) {
+ var me = this,
+ inputEl = me.inputEl;
+ if (inputEl) {
+
+ inputEl.dom.disabled = readOnly || me.disabled;
+ }
+ me.readOnly = readOnly;
+ },
+
+
+ getBodyNaturalWidth: function() {
+ var me = this,
+ bodyEl = me.bodyEl,
+ ws = 'white-space',
+ width;
+ bodyEl.setStyle(ws, 'nowrap');
+ width = bodyEl.getWidth();
+ bodyEl.setStyle(ws, '');
+ return width;
+ }
+
+});
+
+
+
+Ext.define('Ext.layout.component.field.Trigger', {
+
+
+
+ alias: ['layout.triggerfield'],
+
+ extend: 'Ext.layout.component.field.Field',
+
+
+
+ type: 'triggerfield',
+
+ sizeBodyContents: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ inputEl = owner.inputEl,
+ triggerWrap = owner.triggerWrap,
+ triggerWidth = owner.getTriggerWidth();
+
+
+
+ if (owner.hideTrigger || owner.readOnly || triggerWidth > 0) {
+
+
+ me.setElementSize(inputEl, Ext.isNumber(width) ? width - triggerWidth : width);
+
+
+ triggerWrap.setWidth(triggerWidth);
+ }
+ }
+});
+
+Ext.define('Ext.view.View', {
+ extend: 'Ext.view.AbstractView',
+ alternateClassName: 'Ext.view.View',
+ alias: 'widget.dataview',
+
+ inheritableStatics: {
+ EventMap: {
+ mousedown: 'MouseDown',
+ mouseup: 'MouseUp',
+ click: 'Click',
+ dblclick: 'DblClick',
+ contextmenu: 'ContextMenu',
+ mouseover: 'MouseOver',
+ mouseout: 'MouseOut',
+ mouseenter: 'MouseEnter',
+ mouseleave: 'MouseLeave',
+ keydown: 'KeyDown'
+ }
+ },
+
+ addCmpEvents: function() {
+ this.addEvents(
+
+ 'beforeitemmousedown',
+
+ 'beforeitemmouseup',
+
+ 'beforeitemmouseenter',
+
+ 'beforeitemmouseleave',
+
+ 'beforeitemclick',
+
+ 'beforeitemdblclick',
+
+ 'beforeitemcontextmenu',
+
+ 'beforeitemkeydown',
+
+ 'itemmousedown',
+
+ 'itemmouseup',
+
+ 'itemmouseenter',
+
+ 'itemmouseleave',
+
+ 'itemclick',
+
+ 'itemdblclick',
+
+ 'itemcontextmenu',
+
+ 'itemkeydown',
+
+ 'beforecontainermousedown',
+
+ 'beforecontainermouseup',
+
+ 'beforecontainermouseover',
+
+ 'beforecontainermouseout',
+
+ 'beforecontainerclick',
+
+ 'beforecontainerdblclick',
+
+ 'beforecontainercontextmenu',
+
+ 'beforecontainerkeydown',
+
+ 'containermouseup',
+
+ 'containermouseover',
+
+ 'containermouseout',
+
+ 'containerclick',
+
+ 'containerdblclick',
+
+ 'containercontextmenu',
+
+ 'containerkeydown',
+
+
+ 'selectionchange',
+
+ 'beforeselect'
+ );
+ },
+
+ afterRender: function(){
+ var me = this,
+ listeners;
+
+ me.callParent();
+
+ listeners = {
+ scope: me,
+ click: me.handleEvent,
+ mousedown: me.handleEvent,
+ mouseup: me.handleEvent,
+ dblclick: me.handleEvent,
+ contextmenu: me.handleEvent,
+ mouseover: me.handleEvent,
+ mouseout: me.handleEvent,
+ keydown: me.handleEvent
+ };
+
+ me.mon(me.getTargetEl(), listeners);
+
+ if (me.store) {
+ me.bindStore(me.store, true);
+ }
+ },
+
+ handleEvent: function(e) {
+ if (this.processUIEvent(e) !== false) {
+ this.processSpecialEvent(e);
+ }
+ },
+
+
+ processItemEvent: Ext.emptyFn,
+ processContainerEvent: Ext.emptyFn,
+ processSpecialEvent: Ext.emptyFn,
+
+ processUIEvent: function(e, type) {
+ type = type || e.type;
+ var me = this,
+ item = e.getTarget(me.getItemSelector(), me.getTargetEl()),
+ map = this.statics().EventMap,
+ index, record;
+
+ if (!item) {
+
+
+
+
+
+
+ if (type == 'mouseover' && me.mouseOverItem && typeof me.mouseOverItem.offsetParent === "object" && Ext.fly(me.mouseOverItem).getRegion().contains(e.getPoint())) {
+ item = me.mouseOverItem;
+ }
+
+
+ if (type == 'keydown') {
+ record = me.getSelectionModel().getLastSelected();
+ if (record) {
+ item = me.getNode(record);
+ }
+ }
+ }
+
+ if (item) {
+ index = me.indexOf(item);
+ if (!record) {
+ record = me.getRecord(item);
+ }
+
+ if (me.processItemEvent(type, record, item, index, e) === false) {
+ return false;
+ }
+
+ type = me.isNewItemEvent(type, item, e);
+ if (type === false) {
+ return false;
+ }
+
+ if (
+ (me['onBeforeItem' + map[type]](record, item, index, e) === false) ||
+ (me.fireEvent('beforeitem' + type, me, record, item, index, e) === false) ||
+ (me['onItem' + map[type]](record, item, index, e) === false)
+ ) {
+ return false;
+ }
+
+ me.fireEvent('item' + type, me, record, item, index, e);
+ }
+ else {
+ if (
+ (me.processContainerEvent(type, e) === false) ||
+ (me['onBeforeContainer' + map[type]](e) === false) ||
+ (me.fireEvent('beforecontainer' + type, me, e) === false) ||
+ (me['onContainer' + map[type]](e) === false)
+ ) {
+ return false;
+ }
+
+ me.fireEvent('container' + type, me, e);
+ }
+
+ return true;
+ },
+
+ isNewItemEvent: function(type, item, e) {
+ var me = this,
+ overItem = me.mouseOverItem,
+ contains,
+ isItem;
+
+ switch (type) {
+ case 'mouseover':
+ if (item === overItem) {
+ return false;
+ }
+ me.mouseOverItem = item;
+ return 'mouseenter';
+ break;
+
+ case 'mouseout':
+
+ if (overItem && typeof overItem.offsetParent === "object") {
+ contains = Ext.fly(me.mouseOverItem).getRegion().contains(e.getPoint());
+ isItem = Ext.fly(e.getTarget()).hasCls(me.itemSelector);
+ if (contains && isItem) {
+ return false;
+ }
+ }
+ me.mouseOverItem = null;
+ return 'mouseleave';
+ break;
+ }
+ return type;
+ },
+
+
+ onItemMouseEnter: function(record, item, index, e) {
+ if (this.trackOver) {
+ this.highlightItem(item);
+ }
+ },
+
+
+ onItemMouseLeave : function(record, item, index, e) {
+ if (this.trackOver) {
+ this.clearHighlight();
+ }
+ },
+
+
+ onItemMouseDown: Ext.emptyFn,
+ onItemMouseUp: Ext.emptyFn,
+ onItemClick: Ext.emptyFn,
+ onItemDblClick: Ext.emptyFn,
+ onItemContextMenu: Ext.emptyFn,
+ onItemKeyDown: Ext.emptyFn,
+ onBeforeItemMouseDown: Ext.emptyFn,
+ onBeforeItemMouseUp: Ext.emptyFn,
+ onBeforeItemMouseEnter: Ext.emptyFn,
+ onBeforeItemMouseLeave: Ext.emptyFn,
+ onBeforeItemClick: Ext.emptyFn,
+ onBeforeItemDblClick: Ext.emptyFn,
+ onBeforeItemContextMenu: Ext.emptyFn,
+ onBeforeItemKeyDown: Ext.emptyFn,
+
+
+ onContainerMouseDown: Ext.emptyFn,
+ onContainerMouseUp: Ext.emptyFn,
+ onContainerMouseOver: Ext.emptyFn,
+ onContainerMouseOut: Ext.emptyFn,
+ onContainerClick: Ext.emptyFn,
+ onContainerDblClick: Ext.emptyFn,
+ onContainerContextMenu: Ext.emptyFn,
+ onContainerKeyDown: Ext.emptyFn,
+ onBeforeContainerMouseDown: Ext.emptyFn,
+ onBeforeContainerMouseUp: Ext.emptyFn,
+ onBeforeContainerMouseOver: Ext.emptyFn,
+ onBeforeContainerMouseOut: Ext.emptyFn,
+ onBeforeContainerClick: Ext.emptyFn,
+ onBeforeContainerDblClick: Ext.emptyFn,
+ onBeforeContainerContextMenu: Ext.emptyFn,
+ onBeforeContainerKeyDown: Ext.emptyFn,
+
+
+ highlightItem: function(item) {
+ var me = this;
+ me.clearHighlight();
+ me.highlightedItem = item;
+ Ext.fly(item).addCls(me.overItemCls);
+ },
+
+
+ clearHighlight: function() {
+ var me = this,
+ highlighted = me.highlightedItem;
+
+ if (highlighted) {
+ Ext.fly(highlighted).removeCls(me.overItemCls);
+ delete me.highlightedItem;
+ }
+ },
+
+ refresh: function() {
+ this.clearHighlight();
+ this.callParent(arguments);
+ }
+});
+
+Ext.define('Ext.layout.component.BoundList', {
+ extend: 'Ext.layout.component.Component',
+ alias: 'layout.boundlist',
+
+ type: 'component',
+
+ beforeLayout: function() {
+ return this.callParent(arguments) || this.owner.refreshed > 0;
+ },
+
+ onLayout : function(width, height) {
+ var me = this,
+ owner = me.owner,
+ floating = owner.floating,
+ el = owner.el,
+ xy = el.getXY(),
+ isNumber = Ext.isNumber,
+ minWidth, maxWidth, minHeight, maxHeight,
+ naturalWidth, naturalHeight, constrainedWidth, constrainedHeight, undef;
+
+ if (floating) {
+
+ el.setXY([-9999,-9999]);
+ }
+
+
+ me.setTargetSize(width, height);
+
+
+ if (!isNumber(width)) {
+ minWidth = owner.minWidth;
+ maxWidth = owner.maxWidth;
+ if (isNumber(minWidth) || isNumber(maxWidth)) {
+ naturalWidth = el.getWidth();
+ if (naturalWidth < minWidth) {
+ constrainedWidth = minWidth;
+ }
+ else if (naturalWidth > maxWidth) {
+ constrainedWidth = maxWidth;
+ }
+ if (constrainedWidth) {
+ me.setTargetSize(constrainedWidth);
+ }
+ }
+ }
+
+ if (!isNumber(height)) {
+ minHeight = owner.minHeight;
+ maxHeight = owner.maxHeight;
+ if (isNumber(minHeight) || isNumber(maxHeight)) {
+ naturalHeight = el.getHeight();
+ if (naturalHeight < minHeight) {
+ constrainedHeight = minHeight;
+ }
+ else if (naturalHeight > maxHeight) {
+ constrainedHeight = maxHeight;
+ }
+ if (constrainedHeight) {
+ me.setTargetSize(undef, constrainedHeight);
+ }
+ }
+ }
+
+ if (floating) {
+
+ el.setXY(xy);
+ }
+ },
+
+ afterLayout: function() {
+ var me = this,
+ toolbar = me.owner.pagingToolbar;
+ me.callParent();
+ if (toolbar) {
+ toolbar.doComponentLayout();
+ }
+ },
+
+ setTargetSize : function(width, height) {
+ var me = this,
+ owner = me.owner,
+ listHeight = null,
+ toolbar;
+
+
+ if (Ext.isNumber(height)) {
+ listHeight = height - owner.el.getFrameWidth('tb');
+ toolbar = owner.pagingToolbar;
+ if (toolbar) {
+ listHeight -= toolbar.getHeight();
+ }
+ }
+ me.setElementSize(owner.listEl, null, listHeight);
+
+ me.callParent(arguments);
+ }
+
+});
+
+
+Ext.define('Ext.toolbar.TextItem', {
+ extend: 'Ext.toolbar.Item',
+ requires: ['Ext.XTemplate'],
+ alias: 'widget.tbtext',
+ alternateClassName: 'Ext.Toolbar.TextItem',
+
+
+ text: '',
+
+ renderTpl: '{text}',
+
+ baseCls: Ext.baseCSSPrefix + 'toolbar-text',
+
+ onRender : function() {
+ Ext.apply(this.renderData, {
+ text: this.text
+ });
+ this.callParent(arguments);
+ },
+
+
+ setText : function(t) {
+ if (this.rendered) {
+ this.el.update(t);
+ this.ownerCt.doLayout();
+ } else {
+ this.text = t;
+ }
+ }
+});
+
+Ext.define('Ext.form.field.Trigger', {
+ extend:'Ext.form.field.Text',
+ alias: ['widget.triggerfield', 'widget.trigger'],
+ requires: ['Ext.core.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
+ alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
+
+ fieldSubTpl: [
+ '<input id="{id}" type="{type}" ',
+ '<tpl if="name">name="{name}" </tpl>',
+ '<tpl if="size">size="{size}" </tpl>',
+ '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+ 'class="{fieldCls} {typeCls}" autocomplete="off" />',
+ '<div class="{triggerWrapCls}" role="presentation">',
+ '{triggerEl}',
+ '<div class="{clearCls}" role="presentation"></div>',
+ '</div>',
+ {
+ compiled: true,
+ disableFormats: true
+ }
+ ],
+
+
+
+
+ triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
+
+
+ triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
+
+
+ hideTrigger: false,
+
+
+ editable: true,
+
+
+ readOnly: false,
+
+
+
+
+ repeatTriggerClick: false,
+
+
+
+ autoSize: Ext.emptyFn,
+
+ monitorTab: true,
+
+ mimicing: false,
+
+ triggerIndexRe: /trigger-index-(\d+)/,
+
+ componentLayout: 'triggerfield',
+
+ initComponent: function() {
+ this.wrapFocusCls = this.triggerWrapCls + '-focus';
+ this.callParent(arguments);
+ },
+
+
+ onRender: function(ct, position) {
+ var me = this,
+ triggerCls,
+ triggerBaseCls = me.triggerBaseCls,
+ triggerWrapCls = me.triggerWrapCls,
+ triggerConfigs = [],
+ i;
+
+
+
+
+
+ if (!me.trigger1Cls) {
+ me.trigger1Cls = me.triggerCls;
+ }
+
+
+ for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) {
+ triggerConfigs.push({
+ cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
+ role: 'button'
+ });
+ }
+ triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
+
+ Ext.applyIf(me.renderSelectors, {
+
+ triggerWrap: '.' + triggerWrapCls
+ });
+ Ext.applyIf(me.subTplData, {
+ triggerWrapCls: triggerWrapCls,
+ triggerEl: Ext.core.DomHelper.markup(triggerConfigs),
+ clearCls: me.clearCls
+ });
+
+ me.callParent(arguments);
+
+
+ me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
+
+ me.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
+ me.initTrigger();
+ },
+
+ onEnable: function() {
+ this.callParent();
+ this.triggerWrap.unmask();
+ },
+
+ onDisable: function() {
+ this.callParent();
+ this.triggerWrap.mask();
+ },
+
+ afterRender: function() {
+ this.callParent();
+ this.updateEditState();
+ },
+
+ updateEditState: function() {
+ var me = this,
+ inputEl = me.inputEl,
+ triggerWrap = me.triggerWrap,
+ noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
+ displayed,
+ readOnly;
+
+ if (me.rendered) {
+ if (me.readOnly) {
+ inputEl.addCls(noeditCls);
+ readOnly = true;
+ displayed = false;
+ } else {
+ if (me.editable) {
+ inputEl.removeCls(noeditCls);
+ readOnly = false;
+ } else {
+ inputEl.addCls(noeditCls);
+ readOnly = true;
+ }
+ displayed = !me.hideTrigger;
+ }
+
+ triggerWrap.setDisplayed(displayed);
+ inputEl.dom.readOnly = readOnly;
+ me.doComponentLayout();
+ }
+ },
+
+
+ getTriggerWidth: function() {
+ var me = this,
+ triggerWrap = me.triggerWrap,
+ totalTriggerWidth = 0;
+ if (triggerWrap && !me.hideTrigger && !me.readOnly) {
+ me.triggerEl.each(function(trigger) {
+ totalTriggerWidth += trigger.getWidth();
+ });
+ totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
+ }
+ return totalTriggerWidth;
+ },
+
+ setHideTrigger: function(hideTrigger) {
+ if (hideTrigger != this.hideTrigger) {
+ this.hideTrigger = hideTrigger;
+ this.updateEditState();
+ }
+ },
+
+
+ setEditable: function(editable) {
+ if (editable != this.editable) {
+ this.editable = editable;
+ this.updateEditState();
+ }
+ },
+
+
+ setReadOnly: function(readOnly) {
+ if (readOnly != this.readOnly) {
+ this.readOnly = readOnly;
+ this.updateEditState();
+ }
+ },
+
+
+ initTrigger: function() {
+ var me = this,
+ triggerWrap = me.triggerWrap,
+ triggerEl = me.triggerEl;
+
+ if (me.repeatTriggerClick) {
+ me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
+ preventDefault: true,
+ handler: function(cr, e) {
+ me.onTriggerWrapClick(e);
+ }
+ });
+ } else {
+ me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
+ }
+
+ triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
+ triggerEl.each(function(el, c, i) {
+ el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
+ });
+ triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
+ triggerEl.each(function(el, c, i) {
+ el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
+ });
+ },
+
+
+ onDestroy: function() {
+ var me = this;
+ Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
+ delete me.doc;
+ me.callParent();
+ },
+
+
+ onFocus: function() {
+ var me = this;
+ this.callParent();
+ if (!me.mimicing) {
+ me.bodyEl.addCls(me.wrapFocusCls);
+ me.mimicing = true;
+ me.mon(me.doc, 'mousedown', me.mimicBlur, me, {
+ delay: 10
+ });
+ if (me.monitorTab) {
+ me.on('specialkey', me.checkTab, me);
+ }
+ }
+ },
+
+
+ checkTab: function(me, e) {
+ if (!this.ignoreMonitorTab && e.getKey() == e.TAB) {
+ this.triggerBlur();
+ }
+ },
+
+
+ onBlur: Ext.emptyFn,
+
+
+ mimicBlur: function(e) {
+ if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) {
+ this.triggerBlur();
+ }
+ },
+
+
+ triggerBlur: function() {
+ var me = this;
+ me.mimicing = false;
+ me.mun(me.doc, 'mousedown', me.mimicBlur, me);
+ if (me.monitorTab && me.inputEl) {
+ me.un('specialkey', me.checkTab, me);
+ }
+ Ext.form.field.Trigger.superclass.onBlur.call(me);
+ if (me.bodyEl) {
+ me.bodyEl.removeCls(me.wrapFocusCls);
+ }
+ },
+
+ beforeBlur: Ext.emptyFn,
+
+
+
+ validateBlur: function(e) {
+ return true;
+ },
+
+
+
+
+ onTriggerWrapClick: function(e) {
+ var me = this,
+ t = e && e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
+ match = t && t.className.match(me.triggerIndexRe),
+ idx,
+ triggerClickMethod;
+
+ if (match && !me.readOnly) {
+ idx = parseInt(match[1], 10);
+ triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
+ if (triggerClickMethod) {
+ triggerClickMethod.call(me, e);
+ }
+ }
+ },
+
+
+ onTriggerClick: Ext.emptyFn
+
+
+
+
+});
+
+
+Ext.define('Ext.form.field.Picker', {
+ extend: 'Ext.form.field.Trigger',
+ alias: 'widget.pickerfield',
+ alternateClassName: 'Ext.form.Picker',
+ requires: ['Ext.util.KeyNav'],
+
+
+ matchFieldWidth: true,
+
+
+ pickerAlign: 'tl-bl?',
+
+
+
+
+ openCls: Ext.baseCSSPrefix + 'pickerfield-open',
+
+
+
+
+ editable: true,
+
+
+ initComponent: function() {
+ this.callParent();
+
+
+ this.addEvents(
+
+ 'expand',
+
+ 'collapse',
+
+ 'select'
+ );
+ },
+
+
+ initEvents: function() {
+ var me = this;
+ me.callParent();
+
+
+ me.keyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
+ down: function() {
+ if (!me.isExpanded) {
+
+
+ me.onTriggerClick();
+ }
+ },
+ esc: me.collapse,
+ scope: me,
+ forceKeyDown: true
+ });
+
+
+ if (!me.editable) {
+ me.mon(me.inputEl, 'click', me.onTriggerClick, me);
+ }
+
+
+ if (Ext.isGecko) {
+ me.inputEl.dom.setAttribute('autocomplete', 'off');
+ }
+ },
+
+
+
+ expand: function() {
+ var me = this,
+ bodyEl, picker, collapseIf;
+
+ if (me.rendered && !me.isExpanded && !me.isDestroyed) {
+ bodyEl = me.bodyEl;
+ picker = me.getPicker();
+ collapseIf = me.collapseIf;
+
+
+ picker.show();
+ me.isExpanded = true;
+ me.alignPicker();
+ bodyEl.addCls(me.openCls);
+
+
+ me.mon(Ext.getDoc(), {
+ mousewheel: collapseIf,
+ mousedown: collapseIf,
+ scope: me
+ });
+
+ me.fireEvent('expand', me);
+ me.onExpand();
+ }
+ },
+
+ onExpand: Ext.emptyFn,
+
+
+ alignPicker: function() {
+ var me = this,
+ picker, isAbove,
+ aboveSfx = '-above';
+
+ if (this.isExpanded) {
+ picker = me.getPicker();
+ if (me.matchFieldWidth) {
+
+ picker.setSize(me.bodyEl.getWidth(), picker.store && picker.store.getCount() ? null : 0);
+ }
+ if (picker.isFloating()) {
+ picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
+
+
+
+ isAbove = picker.el.getY() < me.inputEl.getY();
+ me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
+ picker.el[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
+ }
+ }
+ },
+
+
+ collapse: function() {
+ if (this.isExpanded && !this.isDestroyed) {
+ var me = this,
+ openCls = me.openCls,
+ picker = me.picker,
+ doc = Ext.getDoc(),
+ collapseIf = me.collapseIf,
+ aboveSfx = '-above';
+
+
+ picker.hide();
+ me.isExpanded = false;
+
+
+ me.bodyEl.removeCls([openCls, openCls + aboveSfx]);
+ picker.el.removeCls(picker.baseCls + aboveSfx);
+
+
+ doc.un('mousewheel', collapseIf, me);
+ doc.un('mousedown', collapseIf, me);
+
+ me.fireEvent('collapse', me);
+ me.onCollapse();
+ }
+ },
+
+ onCollapse: Ext.emptyFn,
+
+
+
+ collapseIf: function(e) {
+ var me = this;
+ if (!me.isDestroyed && !e.within(me.bodyEl, false, true) && !e.within(me.picker.el, false, true)) {
+ me.collapse();
+ }
+ },
+
+
+ getPicker: function() {
+ var me = this;
+ return me.picker || (me.picker = me.createPicker());
+ },
+
+
+ createPicker: Ext.emptyFn,
+
+
+ onTriggerClick: function() {
+ var me = this;
+ if (!me.readOnly && !me.disabled) {
+ if (me.isExpanded) {
+ me.collapse();
+ } else {
+ me.expand();
+ }
+ me.inputEl.focus();
+ }
+ },
+
+ mimicBlur: function(e) {
+ var me = this,
+ picker = me.picker;
+
+ if (!picker || !e.within(picker.el, false, true)) {
+ me.callParent(arguments);
+ }
+ },
+
+ onDestroy : function(){
+ var me = this;
+ Ext.destroy(me.picker, me.keyNav);
+ me.callParent();
+ }
+
+});
+
+
+
+Ext.define('Ext.form.field.Spinner', {
+ extend: 'Ext.form.field.Trigger',
+ alias: 'widget.spinnerfield',
+ alternateClassName: 'Ext.form.Spinner',
+ requires: ['Ext.util.KeyNav'],
+
+ trigger1Cls: Ext.baseCSSPrefix + 'form-spinner-up',
+ trigger2Cls: Ext.baseCSSPrefix + 'form-spinner-down',
+
+
+ spinUpEnabled: true,
+
+
+ spinDownEnabled: true,
+
+
+ keyNavEnabled: true,
+
+
+ mouseWheelEnabled: true,
+
+
+ repeatTriggerClick: true,
+
+
+ onSpinUp: Ext.emptyFn,
+
+
+ onSpinDown: Ext.emptyFn,
+
+ initComponent: function() {
+ this.callParent();
+
+ this.addEvents(
+
+ 'spin',
+
+
+ 'spinup',
+
+
+ 'spindown'
+ );
+ },
+
+
+ onRender: function() {
+ var me = this,
+ triggers;
+
+ me.callParent(arguments);
+ triggers = me.triggerEl;
+
+
+ me.spinUpEl = triggers.item(0);
+
+ me.spinDownEl = triggers.item(1);
+
+
+ me.setSpinUpEnabled(me.spinUpEnabled);
+ me.setSpinDownEnabled(me.spinDownEnabled);
+
+
+ if (me.keyNavEnabled) {
+ me.spinnerKeyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
+ scope: me,
+ up: me.spinUp,
+ down: me.spinDown
+ });
+ }
+
+
+ if (me.mouseWheelEnabled) {
+ me.mon(me.bodyEl, 'mousewheel', me.onMouseWheel, me);
+ }
+ },
+
+
+ getTriggerWidth: function() {
+ return this.hideTrigger || this.readOnly ? 0 : this.spinUpEl.getWidth() + this.triggerWrap.getFrameWidth('lr');
+ },
+
+
+ onTrigger1Click: function() {
+ this.spinUp();
+ },
+
+
+ onTrigger2Click: function() {
+ this.spinDown();
+ },
+
+
+ spinUp: function() {
+ var me = this;
+ if (me.spinUpEnabled && !me.disabled) {
+ me.fireEvent('spin', me, 'up');
+ me.fireEvent('spinup', me);
+ me.onSpinUp();
+ }
+ },
+
+
+ spinDown: function() {
+ var me = this;
+ if (me.spinDownEnabled && !me.disabled) {
+ me.fireEvent('spin', me, 'down');
+ me.fireEvent('spindown', me);
+ me.onSpinDown();
+ }
+ },
+
+
+ setSpinUpEnabled: function(enabled) {
+ var me = this,
+ wasEnabled = me.spinUpEnabled;
+ me.spinUpEnabled = enabled;
+ if (wasEnabled !== enabled && me.rendered) {
+ me.spinUpEl[enabled ? 'removeCls' : 'addCls'](me.trigger1Cls + '-disabled');
+ }
+ },
+
+
+ setSpinDownEnabled: function(enabled) {
+ var me = this,
+ wasEnabled = me.spinDownEnabled;
+ me.spinDownEnabled = enabled;
+ if (wasEnabled !== enabled && me.rendered) {
+ me.spinDownEl[enabled ? 'removeCls' : 'addCls'](me.trigger2Cls + '-disabled');
+ }
+ },
+
+
+ onMouseWheel: function(e) {
+ var me = this,
+ delta;
+ if (me.hasFocus) {
+ delta = e.getWheelDelta();
+ if (delta > 0) {
+ me.spinUp();
+ }
+ else if (delta < 0) {
+ me.spinDown();
+ }
+ e.stopEvent();
+ }
+ },
+
+ onDestroy: function() {
+ Ext.destroyMembers(this, 'spinnerKeyNav', 'spinUpEl', 'spinDownEl');
+ this.callParent();
+ }
+
+});
+
+Ext.define('Ext.form.field.Number', {
+ extend:'Ext.form.field.Spinner',
+ alias: 'widget.numberfield',
+ alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'],
+
+
+
+
+
+ allowDecimals : true,
+
+
+ decimalSeparator : '.',
+
+
+ decimalPrecision : 2,
+
+
+ minValue: Number.NEGATIVE_INFINITY,
+
+
+ maxValue: Number.MAX_VALUE,
+
+
+ step: 1,
+
+
+ minText : 'The minimum value for this field is {0}',
+
+
+ maxText : 'The maximum value for this field is {0}',
+
+
+ nanText : '{0} is not a valid number',
+
+
+ negativeText : 'The value cannot be negative',
+
+
+ baseChars : '0123456789',
+
+
+ autoStripChars: false,
+
+ initComponent: function() {
+ var me = this,
+ allowed;
+
+ this.callParent();
+
+ me.setMinValue(me.minValue);
+ me.setMaxValue(me.maxValue);
+
+
+ allowed = me.baseChars + '';
+ if (me.allowDecimals) {
+ allowed += me.decimalSeparator;
+ }
+ if (me.minValue < 0) {
+ allowed += '-';
+ }
+ allowed = Ext.String.escapeRegex(allowed);
+ me.maskRe = new RegExp('[' + allowed + ']');
+ if (me.autoStripChars) {
+ me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
+ }
+ },
+
+
+ getErrors: function(value) {
+ var me = this,
+ errors = me.callParent(arguments),
+ format = Ext.String.format,
+ num;
+
+ value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue());
+
+ if (value.length < 1) {
+ return errors;
+ }
+
+ value = String(value).replace(me.decimalSeparator, '.');
+
+ if(isNaN(value)){
+ errors.push(format(me.nanText, value));
+ }
+
+ num = me.parseValue(value);
+
+ if (me.minValue === 0 && num < 0) {
+ errors.push(this.negativeText);
+ }
+ else if (num < me.minValue) {
+ errors.push(format(me.minText, me.minValue));
+ }
+
+ if (num > me.maxValue) {
+ errors.push(format(me.maxText, me.maxValue));
+ }
+
+
+ return errors;
+ },
+
+ rawToValue: function(rawValue) {
+ return this.fixPrecision(this.parseValue(rawValue)) || rawValue || null;
+ },
+
+ valueToRaw: function(value) {
+ var me = this,
+ decimalSeparator = me.decimalSeparator;
+ value = me.parseValue(value);
+ value = me.fixPrecision(value);
+ value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));
+ value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator);
+ return value;
+ },
+
+ onChange: function() {
+ var me = this,
+ value = me.getValue(),
+ valueIsNull = value === null;
+
+ me.callParent(arguments);
+
+
+ me.setSpinUpEnabled(valueIsNull || value < me.maxValue);
+ me.setSpinDownEnabled(valueIsNull || value > me.minValue);
+ },
+
+
+ setMinValue : function(value) {
+ this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
+ },
+
+
+ setMaxValue: function(value) {
+ this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
+ },
+
+
+ parseValue : function(value) {
+ value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
+ return isNaN(value) ? null : value;
+ },
+
+
+ fixPrecision : function(value) {
+ var me = this,
+ nan = isNaN(value),
+ precision = me.decimalPrecision;
+
+ if (nan || !value) {
+ return nan ? '' : value;
+ } else if (!me.allowDecimals || precision <= 0) {
+ precision = 0;
+ }
+
+ return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
+ },
+
+ beforeBlur : function() {
+ var me = this,
+ v = me.parseValue(me.getRawValue());
+
+ if (!Ext.isEmpty(v)) {
+ me.setValue(v);
+ }
+ },
+
+ onSpinUp: function() {
+ var me = this;
+ if (!me.readOnly) {
+ me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
+ }
+ },
+
+ onSpinDown: function() {
+ var me = this;
+ if (!me.readOnly) {
+ me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));
+ }
+ }
+});
+
+
+Ext.define('Ext.toolbar.Paging', {
+ extend: 'Ext.toolbar.Toolbar',
+ alias: 'widget.pagingtoolbar',
+ alternateClassName: 'Ext.PagingToolbar',
+ requires: ['Ext.toolbar.TextItem', 'Ext.form.field.Number'],
+
+
+ displayInfo: false,
+
+ prependButtons: false,
+
+ displayMsg : 'Displaying {0} - {1} of {2}',
+
+ emptyMsg : 'No data to display',
+
+ beforePageText : 'Page',
+
+ afterPageText : 'of {0}',
+
+ firstText : 'First Page',
+
+ prevText : 'Previous Page',
+
+ nextText : 'Next Page',
+
+ lastText : 'Last Page',
+
+ refreshText : 'Refresh',
+
+ inputItemWidth : 30,
+
+
+ getPagingItems: function() {
+ var me = this;
+
+ return [{
+ itemId: 'first',
+ tooltip: me.firstText,
+ overflowText: me.firstText,
+ iconCls: Ext.baseCSSPrefix + 'tbar-page-first',
+ disabled: true,
+ handler: me.moveFirst,
+ scope: me
+ },{
+ itemId: 'prev',
+ tooltip: me.prevText,
+ overflowText: me.prevText,
+ iconCls: Ext.baseCSSPrefix + 'tbar-page-prev',
+ disabled: true,
+ handler: me.movePrevious,
+ scope: me
+ },
+ '-',
+ me.beforePageText,
+ {
+ xtype: 'numberfield',
+ itemId: 'inputItem',
+ name: 'inputItem',
+ cls: Ext.baseCSSPrefix + 'tbar-page-number',
+ allowDecimals: false,
+ minValue: 1,
+ hideTrigger: true,
+ enableKeyEvents: true,
+ selectOnFocus: true,
+ submitValue: false,
+ width: me.inputItemWidth,
+ margins: '-1 2 3 2',
+ listeners: {
+ scope: me,
+ keydown: me.onPagingKeyDown,
+ blur: me.onPagingBlur
+ }
+ },{
+ xtype: 'tbtext',
+ itemId: 'afterTextItem',
+ text: Ext.String.format(me.afterPageText, 1)
+ },
+ '-',
+ {
+ itemId: 'next',
+ tooltip: me.nextText,
+ overflowText: me.nextText,
+ iconCls: Ext.baseCSSPrefix + 'tbar-page-next',
+ disabled: true,
+ handler: me.moveNext,
+ scope: me
+ },{
+ itemId: 'last',
+ tooltip: me.lastText,
+ overflowText: me.lastText,
+ iconCls: Ext.baseCSSPrefix + 'tbar-page-last',
+ disabled: true,
+ handler: me.moveLast,
+ scope: me
+ },
+ '-',
+ {
+ itemId: 'refresh',
+ tooltip: me.refreshText,
+ overflowText: me.refreshText,
+ iconCls: Ext.baseCSSPrefix + 'tbar-loading',
+ handler: me.doRefresh,
+ scope: me
+ }];
+ },
+
+ initComponent : function(){
+ var me = this,
+ pagingItems = me.getPagingItems(),
+ userItems = me.items || me.buttons || [];
+
+ if (me.prependButtons) {
+ me.items = userItems.concat(pagingItems);
+ } else {
+ me.items = pagingItems.concat(userItems);
+ }
+ delete me.buttons;
+
+ if (me.displayInfo) {
+ me.items.push('->');
+ me.items.push({xtype: 'tbtext', itemId: 'displayItem'});
+ }
+
+ me.callParent();
+
+ me.addEvents(
+
+ 'change',
+
+ 'beforechange'
+ );
+ me.on('afterlayout', me.onLoad, me, {single: true});
+
+ me.bindStore(me.store, true);
+ },
+
+ updateInfo : function(){
+ var me = this,
+ displayItem = me.child('#displayItem'),
+ store = me.store,
+ pageData = me.getPageData(),
+ count, msg;
+
+ if (displayItem) {
+ count = store.getCount();
+ if (count === 0) {
+ msg = me.emptyMsg;
+ } else {
+ msg = Ext.String.format(
+ me.displayMsg,
+ pageData.fromRecord,
+ pageData.toRecord,
+ pageData.total
+ );
+ }
+ displayItem.setText(msg);
+ me.doComponentLayout();
+ }
+ },
+
+
+ onLoad : function(){
+ var me = this,
+ pageData,
+ currPage,
+ pageCount,
+ afterText;
+
+ if (!me.rendered) {
+ return;
+ }
+
+ pageData = me.getPageData();
+ currPage = pageData.currentPage;
+ pageCount = pageData.pageCount;
+ afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount);
+
+ me.child('#afterTextItem').setText(afterText);
+ me.child('#inputItem').setValue(currPage);
+ me.child('#first').setDisabled(currPage === 1);
+ me.child('#prev').setDisabled(currPage === 1);
+ me.child('#next').setDisabled(currPage === pageCount);
+ me.child('#last').setDisabled(currPage === pageCount);
+ me.child('#refresh').enable();
+ me.updateInfo();
+ me.fireEvent('change', me, pageData);
+ },
+
+
+ getPageData : function(){
+ var store = this.store,
+ totalCount = store.getTotalCount();
+
+ return {
+ total : totalCount,
+ currentPage : store.currentPage,
+ pageCount: Math.ceil(totalCount / store.pageSize),
+
+ fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
+ toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
+
+ };
+ },
+
+
+ onLoadError : function(){
+ if (!this.rendered) {
+ return;
+ }
+ this.child('#refresh').enable();
+ },
+
+
+ readPageFromInput : function(pageData){
+ var v = this.child('#inputItem').getValue(),
+ pageNum = parseInt(v, 10);
+
+ if (!v || isNaN(pageNum)) {
+ this.child('#inputItem').setValue(pageData.currentPage);
+ return false;
+ }
+ return pageNum;
+ },
+
+ onPagingFocus : function(){
+ this.child('#inputItem').select();
+ },
+
+
+ onPagingBlur : function(e){
+ var curPage = this.getPageData().currentPage;
+ this.child('#inputItem').setValue(curPage);
+ },
+
+
+ onPagingKeyDown : function(field, e){
+ var k = e.getKey(),
+ pageData = this.getPageData(),
+ increment = e.shiftKey ? 10 : 1,
+ pageNum,
+ me = this;
+
+ if (k == e.RETURN) {
+ e.stopEvent();
+ pageNum = me.readPageFromInput(pageData);
+ if (pageNum !== false) {
+ pageNum = Math.min(Math.max(1, pageNum), pageData.total);
+ if(me.fireEvent('beforechange', me, pageNum) !== false){
+ me.store.loadPage(pageNum);
+ }
+ }
+ } else if (k == e.HOME || k == e.END) {
+ e.stopEvent();
+ pageNum = k == e.HOME ? 1 : pageData.pageCount;
+ field.setValue(pageNum);
+ } else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
+ e.stopEvent();
+ pageNum = me.readPageFromInput(pageData);
+ if (pageNum) {
+ if (k == e.DOWN || k == e.PAGEDOWN) {
+ increment *= -1;
+ }
+ pageNum += increment;
+ if (pageNum >= 1 && pageNum <= pageData.pages) {
+ field.setValue(pageNum);
+ }
+ }
+ }
+ },
+
+
+ beforeLoad : function(){
+ if(this.rendered && this.refresh){
+ this.refresh.disable();
+ }
+ },
+
+
+ doLoad : function(start){
+ if(this.fireEvent('beforechange', this, o) !== false){
+ this.store.load();
+ }
+ },
+
+
+ moveFirst : function(){
+ var me = this;
+ if(me.fireEvent('beforechange', me, 1) !== false){
+ me.store.loadPage(1);
+ }
+ },
+
+
+ movePrevious : function(){
+ var me = this,
+ prev = me.store.currentPage - 1;
+
+ if(me.fireEvent('beforechange', me, prev) !== false){
+ me.store.previousPage();
+ }
+ },
+
+
+ moveNext : function(){
+ var me = this;
+ if(me.fireEvent('beforechange', me, me.store.currentPage + 1) !== false){
+ me.store.nextPage();
+ }
+ },
+
+
+ moveLast : function(){
+ var me = this,
+ last = this.getPageData().pageCount;
+
+ if(me.fireEvent('beforechange', me, last) !== false){
+ me.store.loadPage(last);
+ }
+ },
+
+
+ doRefresh : function(){
+ var me = this,
+ current = me.store.currentPage;
+
+ if(me.fireEvent('beforechange', me, current) !== false){
+ me.store.loadPage(current);
+ }
+ },
+
+
+ bindStore : function(store, initial){
+ var me = this;
+
+ if (!initial && me.store) {
+ if(store !== me.store && me.store.autoDestroy){
+ me.store.destroy();
+ }else{
+ me.store.un('beforeload', me.beforeLoad, me);
+ me.store.un('load', me.onLoad, me);
+ me.store.un('exception', me.onLoadError, me);
+ }
+ if(!store){
+ me.store = null;
+ }
+ }
+ if (store) {
+ store = Ext.data.StoreManager.lookup(store);
+ store.on({
+ scope: me,
+ beforeload: me.beforeLoad,
+ load: me.onLoad,
+ exception: me.onLoadError
+ });
+ }
+ me.store = store;
+ },
+
+
+ unbind : function(store){
+ this.bindStore(null);
+ },
+
+
+ bind : function(store){
+ this.bindStore(store);
+ },
+
+
+ onDestroy : function(){
+ this.bindStore(null);
+ this.callParent();
+ }
+});
+
+
+Ext.define('Ext.view.BoundList', {
+ extend: 'Ext.view.View',
+ alias: 'widget.boundlist',
+ alternateClassName: 'Ext.BoundList',
+ requires: ['Ext.layout.component.BoundList', 'Ext.toolbar.Paging'],
+
+
+ pageSize: 0,
+
+
+
+
+ autoScroll: true,
+ baseCls: Ext.baseCSSPrefix + 'boundlist',
+ listItemCls: '',
+ shadow: false,
+ trackOver: true,
+ refreshed: 0,
+
+ ariaRole: 'listbox',
+
+ componentLayout: 'boundlist',
+
+ renderTpl: ['<div class="list-ct"></div>'],
+
+ initComponent: function() {
+ var me = this,
+ baseCls = me.baseCls,
+ itemCls = baseCls + '-item';
+ me.itemCls = itemCls;
+ me.selectedItemCls = baseCls + '-selected';
+ me.overItemCls = baseCls + '-item-over';
+ me.itemSelector = "." + itemCls;
+
+ if (me.floating) {
+ me.addCls(baseCls + '-floating');
+ }
+
+
+
+ me.tpl = Ext.create('Ext.XTemplate',
+ '<ul><tpl for=".">',
+ '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
+ '</tpl></ul>'
+ );
+
+ if (me.pageSize) {
+ me.pagingToolbar = me.createPagingToolbar();
+ }
+
+ me.callParent();
+
+ Ext.applyIf(me.renderSelectors, {
+ listEl: '.list-ct'
+ });
+ },
+
+ createPagingToolbar: function() {
+ return Ext.widget('pagingtoolbar', {
+ pageSize: this.pageSize,
+ store: this.store,
+ border: false
+ });
+ },
+
+ onRender: function() {
+ var me = this,
+ toolbar = me.pagingToolbar;
+ me.callParent(arguments);
+ if (toolbar) {
+ toolbar.render(me.el);
+ }
+ },
+
+ bindStore : function(store, initial) {
+ var me = this,
+ toolbar = me.pagingToolbar;
+ me.callParent(arguments);
+ if (toolbar) {
+ toolbar.bindStore(store, initial);
+ }
+ },
+
+ getTargetEl: function() {
+ return this.listEl || this.el;
+ },
+
+ getInnerTpl: function(displayField) {
+ return '{' + displayField + '}';
+ },
+
+ refresh: function() {
+ var me = this;
+ me.callParent();
+ if (me.isVisible()) {
+ me.refreshed++;
+ me.doComponentLayout();
+ me.refreshed--;
+ }
+ },
+
+ initAria: function() {
+ this.callParent();
+
+ var selModel = this.getSelectionModel(),
+ mode = selModel.getSelectionMode(),
+ actionEl = this.getActionEl();
+
+
+ if (mode !== 'SINGLE') {
+ actionEl.dom.setAttribute('aria-multiselectable', true);
+ }
+ },
+
+ onDestroy: function() {
+ Ext.destroyMembers(this, 'pagingToolbar', 'listEl');
+ this.callParent();
+ }
+});
+
+
+Ext.define('Ext.view.BoundListKeyNav', {
+ extend: 'Ext.util.KeyNav',
+ requires: 'Ext.view.BoundList',
+
+
+
+ constructor: function(el, config) {
+ var me = this;
+ me.boundList = config.boundList;
+ me.callParent([el, Ext.apply({}, config, me.defaultHandlers)]);
+ },
+
+ defaultHandlers: {
+ up: function() {
+ var me = this,
+ boundList = me.boundList,
+ allItems = boundList.all,
+ oldItem = boundList.highlightedItem,
+ oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
+ newItemIdx = oldItemIdx > 0 ? oldItemIdx - 1 : allItems.getCount() - 1;
+ me.highlightAt(newItemIdx);
+ },
+
+ down: function() {
+ var me = this,
+ boundList = me.boundList,
+ allItems = boundList.all,
+ oldItem = boundList.highlightedItem,
+ oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
+ newItemIdx = oldItemIdx < allItems.getCount() - 1 ? oldItemIdx + 1 : 0;
+ me.highlightAt(newItemIdx);
+ },
+
+ pageup: function() {
+
+ },
+
+ pagedown: function() {
+
+ },
+
+ home: function() {
+ this.highlightAt(0);
+ },
+
+ end: function() {
+ var me = this;
+ me.highlightAt(me.boundList.all.getCount() - 1);
+ },
+
+ enter: function(e) {
+ this.selectHighlighted(e);
+ }
+ },
+
+
+ highlightAt: function(index) {
+ var boundList = this.boundList,
+ item = boundList.all.item(index);
+ if (item) {
+ item = item.dom;
+ boundList.highlightItem(item);
+ boundList.getTargetEl().scrollChildIntoView(item, false);
+ }
+ },
+
+
+ selectHighlighted: function(e) {
+ var me = this,
+ boundList = me.boundList,
+ highlighted = boundList.highlightedItem,
+ selModel = boundList.getSelectionModel();
+ if (highlighted) {
+ selModel.selectWithEvent(boundList.getRecord(highlighted), e);
+ }
+ }
+
+});
+
+Ext.define('Ext.form.field.ComboBox', {
+ extend:'Ext.form.field.Picker',
+ requires: ['Ext.util.DelayedTask', 'Ext.EventObject', 'Ext.view.BoundList', 'Ext.view.BoundListKeyNav', 'Ext.data.StoreManager'],
+ alternateClassName: 'Ext.form.ComboBox',
+ alias: ['widget.combobox', 'widget.combo'],
+
+
+ triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
+
+
+
+
+ multiSelect: false,
+
+
+ delimiter: ', ',
+
+
+ displayField: 'text',
+
+
+
+
+ triggerAction: 'all',
+
+
+ allQuery: '',
+
+
+ queryParam: 'query',
+
+
+ queryMode: 'remote',
+
+ queryCaching: true,
+
+
+ pageSize: 0,
+
+
+
+
+
+
+ autoSelect: true,
+
+
+ typeAhead: false,
+
+
+ typeAheadDelay: 250,
+
+
+ selectOnTab: true,
+
+
+ forceSelection: false,
+
+
+
+
+
+
+ defaultListConfig: {
+ emptyText: '',
+ loadingText: 'Loading...',
+ loadingHeight: 70,
+ minWidth: 70,
+ maxHeight: 300,
+ shadow: 'sides'
+ },
+
+
+
+
+
+
+ ignoreSelection: 0,
+
+ initComponent: function() {
+ var me = this,
+ isDefined = Ext.isDefined,
+ store = me.store,
+ transform = me.transform,
+ transformSelect, isLocalMode;
+
+ if (!store && !transform) {
+ Ext.Error.raise('Either a valid store, or a HTML select to transform, must be configured on the combo.');
+ }
+ if (me.typeAhead && me.multiSelect) {
+ Ext.Error.raise('typeAhead and multiSelect are mutually exclusive options -- please remove one of them.');
+ }
+ if (me.typeAhead && !me.editable) {
+ Ext.Error.raise('If typeAhead is enabled the combo must be editable: true -- please change one of those settings.');
+ }
+ if (me.selectOnFocus && !me.editable) {
+ Ext.Error.raise('If selectOnFocus is enabled the combo must be editable: true -- please change one of those settings.');
+ }
+
+ this.addEvents(
+
+
+
+ 'beforequery',
+
+
+ 'select'
+ );
+
+
+ if (!store && transform) {
+ transformSelect = Ext.getDom(transform);
+ if (transformSelect) {
+ store = Ext.Array.map(Ext.Array.from(transformSelect.options), function(option) {
+ return [option.value, option.text];
+ });
+ if (!me.name) {
+ me.name = transformSelect.name;
+ }
+ if (!('value' in me)) {
+ me.value = transformSelect.value;
+ }
+ }
+ }
+
+ me.bindStore(store, true);
+ store = me.store;
+ if (store.autoCreated) {
+ me.queryMode = 'local';
+ me.valueField = me.displayField = 'field1';
+ if (!store.expanded) {
+ me.displayField = 'field2';
+ }
+ }
+
+
+ if (!isDefined(me.valueField)) {
+ me.valueField = me.displayField;
+ }
+
+ isLocalMode = me.queryMode === 'local';
+ if (!isDefined(me.queryDelay)) {
+ me.queryDelay = isLocalMode ? 10 : 500;
+ }
+ if (!isDefined(me.minChars)) {
+ me.minChars = isLocalMode ? 0 : 4;
+ }
+
+ if (!me.displayTpl) {
+ me.displayTpl = Ext.create('Ext.XTemplate',
+ '<tpl for=".">' +
+ '{[typeof values === "string" ? values : values.' + me.displayField + ']}' +
+ '<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +
+ '</tpl>'
+ );
+ } else if (Ext.isString(me.displayTpl)) {
+ me.displayTpl = Ext.create('Ext.XTemplate', me.displayTpl);
+ }
+
+ me.callParent();
+
+ me.doQueryTask = Ext.create('Ext.util.DelayedTask', me.doRawQuery, me);
+
+
+ if (me.store.getCount() > 0) {
+ me.setValue(me.value);
+ }
+
+
+ if (transformSelect) {
+ me.render(transformSelect.parentNode, transformSelect);
+ Ext.removeNode(transformSelect);
+ delete me.renderTo;
+ }
+ },
+
+ beforeBlur: function() {
+ var me = this;
+ me.doQueryTask.cancel();
+ if (me.forceSelection) {
+ me.assertValue();
+ } else {
+ me.collapse();
+ }
+ },
+
+
+ assertValue: function() {
+ var me = this,
+ value = me.getRawValue(),
+ rec;
+
+ if (me.multiSelect) {
+
+
+ if (value !== me.getDisplayValue()) {
+ me.setValue(me.lastSelection);
+ }
+ } else {
+
+
+ rec = me.findRecordByDisplay(value);
+ if (rec) {
+ me.select(rec);
+ } else {
+ me.setValue(me.lastSelection);
+ }
+ }
+ me.collapse();
+ },
+
+ onTypeAhead: function() {
+ var me = this,
+ displayField = me.displayField,
+ record = me.store.findRecord(displayField, me.getRawValue()),
+ boundList = me.getPicker(),
+ newValue, len, selStart;
+
+ if (record) {
+ newValue = record.get(displayField);
+ len = newValue.length;
+ selStart = me.getRawValue().length;
+
+ boundList.highlightItem(boundList.getNode(record));
+
+ if (selStart !== 0 && selStart !== len) {
+ me.setRawValue(newValue);
+ me.selectText(selStart, newValue.length);
+ }
+ }
+ },
+
+
+
+ resetToDefault: function() {
+
+ },
+
+ bindStore: function(store, initial) {
+ var me = this,
+ oldStore = me.store;
+
+
+
+ if (oldStore && !initial) {
+ if (oldStore !== store && oldStore.autoDestroy) {
+ oldStore.destroy();
+ } else {
+ oldStore.un({
+ scope: me,
+ load: me.onLoad,
+ exception: me.collapse
+ });
+ }
+ if (!store) {
+ me.store = null;
+ if (me.picker) {
+ me.picker.bindStore(null);
+ }
+ }
+ }
+ if (store) {
+ if (!initial) {
+ me.resetToDefault();
+ }
+
+ me.store = Ext.data.StoreManager.lookup(store);
+ me.store.on({
+ scope: me,
+ load: me.onLoad,
+ exception: me.collapse
+ });
+
+ if (me.picker) {
+ me.picker.bindStore(store);
+ }
+ }
+ },
+
+ onLoad: function() {
+ var me = this,
+ value = me.value;
+
+ me.syncSelection();
+ if (me.picker && !me.picker.getSelectionModel().hasSelection()) {
+ me.doAutoSelect();
+ }
+ },
+
+
+ doRawQuery: function() {
+ this.doQuery(this.getRawValue());
+ },
+
+
+ doQuery: function(queryString, forceAll) {
+ queryString = queryString || '';
+
+
+
+ var me = this,
+ qe = {
+ query: queryString,
+ forceAll: forceAll,
+ combo: me,
+ cancel: false
+ },
+ store = me.store,
+ isLocalMode = me.queryMode === 'local';
+
+ if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
+ return false;
+ }
+
+
+ queryString = qe.query;
+ forceAll = qe.forceAll;
+
+
+ if (forceAll || (queryString.length >= me.minChars)) {
+
+ me.expand();
+
+
+ if (!me.queryCaching || me.lastQuery !== queryString) {
+ me.lastQuery = queryString;
+ store.clearFilter(!forceAll);
+ if (isLocalMode) {
+ if (!forceAll) {
+ store.filter(me.displayField, queryString);
+ }
+ } else {
+ store.load({
+ params: me.getParams(queryString)
+ });
+ }
+ }
+
+
+ if (me.getRawValue() !== me.getDisplayValue()) {
+ me.ignoreSelection++;
+ me.picker.getSelectionModel().deselectAll();
+ me.ignoreSelection--;
+ }
+
+ if (isLocalMode) {
+ me.doAutoSelect();
+ }
+ if (me.typeAhead) {
+ me.doTypeAhead();
+ }
+ }
+ return true;
+ },
+
+
+ getParams: function(queryString) {
+ var p = {},
+ pageSize = this.pageSize;
+ p[this.queryParam] = queryString;
+ if (pageSize) {
+ p.start = 0;
+ p.limit = pageSize;
+ }
+ return p;
+ },
+
+
+ doAutoSelect: function() {
+ var me = this,
+ picker = me.picker,
+ lastSelected, itemNode;
+ if (picker && me.autoSelect && me.store.getCount() > 0) {
+
+ lastSelected = picker.getSelectionModel().lastSelected;
+ itemNode = picker.getNode(lastSelected || 0);
+ if (itemNode) {
+ picker.highlightItem(itemNode);
+ picker.listEl.scrollChildIntoView(itemNode, false);
+ }
+ }
+ },
+
+ doTypeAhead: function() {
+ if (!this.typeAheadTask) {
+ this.typeAheadTask = Ext.create('Ext.util.DelayedTask', this.onTypeAhead, this);
+ }
+ if (this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
+ this.typeAheadTask.delay(this.typeAheadDelay);
+ }
+ },
+
+ onTriggerClick: function() {
+ var me = this;
+ if (!me.readOnly && !me.disabled) {
+ if (me.isExpanded) {
+ me.collapse();
+ } else {
+ me.onFocus({});
+ if (me.triggerAction === 'all') {
+ me.doQuery(me.allQuery, true);
+ } else {
+ me.doQuery(me.getRawValue());
+ }
+ }
+ me.inputEl.focus();
+ }
+ },
+
+
+
+ onKeyUp: function(e, t) {
+ var me = this,
+ key = e.getKey();
+
+ if (!me.readOnly && !me.disabled && me.editable) {
+ me.lastKey = key;
+
+
+
+
+ if (!e.isSpecialKey() || key == e.BACKSPACE || key == e.DELETE) {
+ me.doQueryTask.delay(me.queryDelay);
+ }
+ }
+ },
+
+ initEvents: function() {
+ var me = this;
+ me.callParent();
+
+
+ me.mon(me.inputEl, 'keyup', me.onKeyUp, me);
+ },
+
+ createPicker: function() {
+ var me = this,
+ picker,
+ menuCls = Ext.baseCSSPrefix + 'menu',
+ opts = Ext.apply({
+ selModel: {
+ mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
+ },
+ floating: true,
+ hidden: true,
+ ownerCt: me.ownerCt,
+ cls: me.el.up('.' + menuCls) ? menuCls : '',
+ store: me.store,
+ displayField: me.displayField,
+ focusOnToFront: false,
+ pageSize: me.pageSize
+ }, me.listConfig, me.defaultListConfig);
+
+ picker = me.picker = Ext.create('Ext.view.BoundList', opts);
+
+ me.mon(picker, {
+ itemclick: me.onItemClick,
+ refresh: me.onListRefresh,
+ scope: me
+ });
+
+ me.mon(picker.getSelectionModel(), {
+ selectionChange: me.onListSelectionChange,
+ scope: me
+ });
+
+ return picker;
+ },
+
+ onListRefresh: function() {
+ this.alignPicker();
+ this.syncSelection();
+ },
+
+ onItemClick: function(picker, record){
+
+ var me = this,
+ lastSelection = me.lastSelection,
+ valueField = me.valueField,
+ selected;
+
+ if (!me.multiSelect && lastSelection) {
+ selected = lastSelection[0];
+ if (record.get(valueField) === selected.get(valueField)) {
+ me.collapse();
+ }
+ }
+ },
+
+ onListSelectionChange: function(list, selectedRecords) {
+ var me = this;
+
+
+ if (!me.ignoreSelection && me.isExpanded) {
+ if (!me.multiSelect) {
+ Ext.defer(me.collapse, 1, me);
+ }
+ me.setValue(selectedRecords, false);
+ if (selectedRecords.length > 0) {
+ me.fireEvent('select', me, selectedRecords);
+ }
+ me.inputEl.focus();
+ }
+ },
+
+
+ onExpand: function() {
+ var me = this,
+ keyNav = me.listKeyNav,
+ selectOnTab = me.selectOnTab,
+ picker = me.getPicker();
+
+
+ if (keyNav) {
+ keyNav.enable();
+ } else {
+ keyNav = me.listKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
+ boundList: picker,
+ forceKeyDown: true,
+ tab: function(e) {
+ if (selectOnTab) {
+ this.selectHighlighted(e);
+ me.triggerBlur();
+ }
+
+ return true;
+ }
+ });
+ }
+
+
+ if (selectOnTab) {
+ me.ignoreMonitorTab = true;
+ }
+
+ Ext.defer(keyNav.enable, 1, keyNav);
+ me.inputEl.focus();
+ },
+
+
+ onCollapse: function() {
+ var me = this,
+ keyNav = me.listKeyNav;
+ if (keyNav) {
+ keyNav.disable();
+ me.ignoreMonitorTab = false;
+ }
+ },
+
+
+ select: function(r) {
+ this.setValue(r, true);
+ },
+
+
+ findRecord: function(field, value) {
+ var ds = this.store,
+ idx = ds.findExact(field, value);
+ return idx !== -1 ? ds.getAt(idx) : false;
+ },
+ findRecordByValue: function(value) {
+ return this.findRecord(this.valueField, value);
+ },
+ findRecordByDisplay: function(value) {
+ return this.findRecord(this.displayField, value);
+ },
+
+
+ setValue: function(value, doSelect) {
+ var me = this,
+ valueNotFoundText = me.valueNotFoundText,
+ inputEl = me.inputEl,
+ i, len, record,
+ models = [],
+ displayTplData = [],
+ processedValue = [];
+
+ if (me.store.loading) {
+
+ me.value = value;
+ return me;
+ }
+
+
+ value = Ext.Array.from(value);
+
+
+ for (i = 0, len = value.length; i < len; i++) {
+ record = value[i];
+ if (!record || !record.isModel) {
+ record = me.findRecordByValue(record);
+ }
+
+ if (record) {
+ models.push(record);
+ displayTplData.push(record.data);
+ processedValue.push(record.get(me.valueField));
+ }
+
+
+ else {
+
+ if (Ext.isDefined(valueNotFoundText)) {
+ displayTplData.push(valueNotFoundText);
+ }
+ processedValue.push(value[i]);
+ }
+ }
+
+
+ me.value = me.multiSelect ? processedValue : processedValue[0];
+ if (!Ext.isDefined(me.value)) {
+ me.value = null;
+ }
+ me.displayTplData = displayTplData;
+ me.lastSelection = me.valueModels = models;
+
+ if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
+ inputEl.removeCls(me.emptyCls);
+ }
+
+
+ me.setRawValue(me.getDisplayValue());
+ me.checkChange();
+
+ if (doSelect !== false) {
+ me.syncSelection();
+ }
+ me.applyEmptyText();
+
+ return me;
+ },
+
+
+ getDisplayValue: function() {
+ return this.displayTpl.apply(this.displayTplData);
+ },
+
+ getValue: function() {
+
+
+
+ var me = this,
+ picker = me.picker,
+ rawValue = me.getRawValue(),
+ value = me.value;
+
+ if (me.getDisplayValue() !== rawValue) {
+ value = rawValue;
+ me.value = me.displayTplData = me.valueModels = null;
+ if (picker) {
+ me.ignoreSelection++;
+ picker.getSelectionModel().deselectAll();
+ me.ignoreSelection--;
+ }
+ }
+
+ return value;
+ },
+
+ getSubmitValue: function() {
+ return this.getValue();
+ },
+
+ isEqual: function(v1, v2) {
+ var fromArray = Ext.Array.from,
+ i, len;
+
+ v1 = fromArray(v1);
+ v2 = fromArray(v2);
+ len = v1.length;
+
+ if (len !== v2.length) {
+ return false;
+ }
+
+ for(i = 0; i < len; i++) {
+ if (v2[i] !== v1[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+
+ clearValue: function() {
+ this.setValue([]);
+ },
+
+
+ syncSelection: function() {
+ var me = this,
+ ExtArray = Ext.Array,
+ picker = me.picker,
+ selection, selModel;
+ if (picker) {
+
+ selection = [];
+ ExtArray.forEach(me.valueModels || [], function(value) {
+ if (value && value.isModel && me.store.indexOf(value) >= 0) {
+ selection.push(value);
+ }
+ });
+
+
+ me.ignoreSelection++;
+ selModel = picker.getSelectionModel();
+ selModel.deselectAll();
+ if (selection.length) {
+ selModel.select(selection);
+ }
+ me.ignoreSelection--;
+ }
+ }
+});
+
+
+Ext.define('Ext.picker.Month', {
+ extend: 'Ext.Component',
+ requires: ['Ext.XTemplate', 'Ext.util.ClickRepeater', 'Ext.Date', 'Ext.button.Button'],
+ alias: 'widget.monthpicker',
+ alternateClassName: 'Ext.MonthPicker',
+
+ renderTpl: [
+ '<div class="{baseCls}-body">',
+ '<div class="{baseCls}-months">',
+ '<tpl for="months">',
+ '<div class="{parent.baseCls}-item {parent.baseCls}-month"><a href="#" hidefocus="on">{.}</a></div>',
+ '</tpl>',
+ '</div>',
+ '<div class="{baseCls}-years">',
+ '<div class="{baseCls}-yearnav">',
+ '<button class="{baseCls}-yearnav-prev"></button>',
+ '<button class="{baseCls}-yearnav-next"></button>',
+ '</div>',
+ '<tpl for="years">',
+ '<div class="{parent.baseCls}-item {parent.baseCls}-year"><a href="#" hidefocus="on">{.}</a></div>',
+ '</tpl>',
+ '</div>',
+ '</div>',
+ '<div class="' + Ext.baseCSSPrefix + 'clear"></div>',
+ '<tpl if="showButtons">',
+ '<div class="{baseCls}-buttons"></div>',
+ '</tpl>'
+ ],
+
+
+ okText: 'OK',
+
+
+ cancelText: 'Cancel',
+
+
+ baseCls: Ext.baseCSSPrefix + 'monthpicker',
+
+
+ showButtons: true,
+
+
+
+
+
+ width: 175,
+
+ height: 195,
+
+
+
+ totalYears: 10,
+ yearOffset: 5,
+ monthOffset: 6,
+
+
+ initComponent: function(){
+ var me = this;
+
+ me.selectedCls = me.baseCls + '-selected';
+ me.addEvents(
+
+ 'cancelclick',
+
+
+ 'monthclick',
+
+
+ 'monthdblclick',
+
+
+ 'okclick',
+
+
+ 'select',
+
+
+ 'yearclick',
+
+
+ 'yeardblclick'
+ );
+
+ me.setValue(me.value);
+ me.activeYear = me.getYear(new Date().getFullYear() - 4, -4);
+ this.callParent();
+ },
+
+
+ onRender: function(ct, position){
+ var me = this,
+ i = 0,
+ months = [],
+ shortName = Ext.Date.getShortMonthName,
+ monthLen = me.monthOffset;
+
+ for (; i < monthLen; ++i) {
+ months.push(shortName(i), shortName(i + monthLen));
+ }
+
+ Ext.apply(me.renderData, {
+ months: months,
+ years: me.getYears(),
+ showButtons: me.showButtons
+ });
+
+ Ext.apply(me.renderSelectors, {
+ bodyEl: '.' + me.baseCls + '-body',
+ prevEl: '.' + me.baseCls + '-yearnav-prev',
+ nextEl: '.' + me.baseCls + '-yearnav-next',
+ buttonsEl: '.' + me.baseCls + '-buttons'
+ });
+ this.callParent([ct, position]);
+ },
+
+
+ afterRender: function(){
+ var me = this,
+ body = me.bodyEl,
+ buttonsEl = me.buttonsEl;
+
+ me.callParent();
+
+ me.mon(body, 'click', me.onBodyClick, me);
+ me.mon(body, 'dblclick', me.onBodyClick, me);
+
+
+ me.years = body.select('.' + me.baseCls + '-year a');
+ me.months = body.select('.' + me.baseCls + '-month a');
+
+ if (me.showButtons) {
+ me.okBtn = Ext.create('Ext.button.Button', {
+ text: me.okText,
+ renderTo: buttonsEl,
+ handler: me.onOkClick,
+ scope: me
+ });
+ me.cancelBtn = Ext.create('Ext.button.Button', {
+ text: me.cancelText,
+ renderTo: buttonsEl,
+ handler: me.onCancelClick,
+ scope: me
+ });
+ }
+
+ me.backRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
+ handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
+ });
+
+ me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
+ me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
+ handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
+ });
+ me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
+ me.updateBody();
+ },
+
+
+ setValue: function(value){
+ var me = this,
+ active = me.activeYear,
+ offset = me.monthOffset,
+ year,
+ index;
+
+ if (!value) {
+ me.value = [null, null];
+ } else if (Ext.isDate(value)) {
+ me.value = [value.getMonth(), value.getFullYear()];
+ } else {
+ me.value = [value[0], value[1]];
+ }
+
+ if (me.rendered) {
+ year = me.value[1];
+ if (year !== null) {
+ if ((year < active || year > active + me.yearOffset)) {
+ me.activeYear = year - me.yearOffset + 1;
+ }
+ }
+ me.updateBody();
+ }
+
+ return me;
+ },
+
+
+ getValue: function(){
+ return this.value;
+ },
+
+
+ hasSelection: function(){
+ var value = this.value;
+ return value[0] !== null && value[1] !== null;
+ },
+
+
+ getYears: function(){
+ var me = this,
+ offset = me.yearOffset,
+ start = me.activeYear,
+ end = start + offset,
+ i = start,
+ years = [];
+
+ for (; i < end; ++i) {
+ years.push(i, i + offset);
+ }
+
+ return years;
+ },
+
+
+ updateBody: function(){
+ var me = this,
+ years = me.years,
+ months = me.months,
+ yearNumbers = me.getYears(),
+ cls = me.selectedCls,
+ value = me.getYear(null),
+ month = me.value[0],
+ monthOffset = me.monthOffset,
+ year;
+
+ if (me.rendered) {
+ years.removeCls(cls);
+ months.removeCls(cls);
+ years.each(function(el, all, index){
+ year = yearNumbers[index];
+ el.dom.innerHTML = year;
+ if (year == value) {
+ el.dom.className = cls;
+ }
+ });
+ if (month !== null) {
+ if (month < monthOffset) {
+ month = month * 2;
+ } else {
+ month = (month - monthOffset) * 2 + 1;
+ }
+ months.item(month).addCls(cls);
+ }
+ }
+ },
+
+
+ getYear: function(defaultValue, offset) {
+ var year = this.value[1];
+ offset = offset || 0;
+ return year === null ? defaultValue : year + offset;
+ },
+
+
+ onBodyClick: function(e, t) {
+ var me = this,
+ isDouble = e.type == 'dblclick';
+
+ if (e.getTarget('.' + me.baseCls + '-month')) {
+ e.stopEvent();
+ me.onMonthClick(t, isDouble);
+ } else if (e.getTarget('.' + me.baseCls + '-year')) {
+ e.stopEvent();
+ me.onYearClick(t, isDouble);
+ }
+ },
+
+
+ adjustYear: function(offset){
+ if (typeof offset != 'number') {
+ offset = this.totalYears;
+ }
+ this.activeYear += offset;
+ this.updateBody();
+ },
+
+
+ onOkClick: function(){
+ this.fireEvent('okclick', this, this.value);
+ },
+
+
+ onCancelClick: function(){
+ this.fireEvent('cancelclick', this);
+ },
+
+
+ onMonthClick: function(target, isDouble){
+ var me = this;
+ me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset);
+ me.updateBody();
+ me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
+ me.fireEvent('select', me, me.value);
+ },
+
+
+ onYearClick: function(target, isDouble){
+ var me = this;
+ me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset);
+ me.updateBody();
+ me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
+ me.fireEvent('select', me, me.value);
+
+ },
+
+
+ resolveOffset: function(index, offset){
+ if (index % 2 === 0) {
+ return (index / 2);
+ } else {
+ return offset + Math.floor(index / 2);
+ }
+ },
+
+
+ beforeDestroy: function(){
+ var me = this;
+ me.years = me.months = null;
+ Ext.destroyMembers('backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn');
+ this.callParent();
+ }
+});
+
+
+Ext.define('Ext.picker.Date', {
+ extend: 'Ext.Component',
+ requires: [
+ 'Ext.XTemplate',
+ 'Ext.button.Button',
+ 'Ext.button.Split',
+ 'Ext.util.ClickRepeater',
+ 'Ext.util.KeyNav',
+ 'Ext.EventObject',
+ 'Ext.fx.Manager',
+ 'Ext.picker.Month'
+ ],
+ alias: 'widget.datepicker',
+ alternateClassName: 'Ext.DatePicker',
+
+ renderTpl: [
+ '<div class="{cls}" id="{id}" role="grid" title="{ariaTitle} {value:this.longDay}">',
+ '<div role="presentation" class="{baseCls}-header">',
+ '<div class="{baseCls}-prev"><a href="#" role="button" title="{prevText}"></a></div>',
+ '<div class="{baseCls}-month"></div>',
+ '<div class="{baseCls}-next"><a href="#" role="button" title="{nextText}"></a></div>',
+ '</div>',
+ '<table class="{baseCls}-inner" cellspacing="0" role="presentation">',
+ '<thead role="presentation"><tr role="presentation">',
+ '<tpl for="dayNames">',
+ '<th role="columnheader" title="{.}"><span>{.:this.firstInitial}</span></th>',
+ '</tpl>',
+ '</tr></thead>',
+ '<tbody role="presentation"><tr role="presentation">',
+ '<tpl for="days">',
+ '{#:this.isEndOfWeek}',
+ '<td role="gridcell" id="{[Ext.id()]}">',
+ '<a role="presentation" href="#" hidefocus="on" class="{parent.baseCls}-date" tabIndex="1">',
+ '<em role="presentation"><span role="presentation"></span></em>',
+ '</a>',
+ '</td>',
+ '</tpl>',
+ '</tr></tbody>',
+ '</table>',
+ '<tpl if="showToday">',
+ '<div role="presentation" class="{baseCls}-footer"></div>',
+ '</tpl>',
+ '</div>',
+ {
+ firstInitial: function(value) {
+ return value.substr(0,1);
+ },
+ isEndOfWeek: function(value) {
+
+
+ value--;
+ var end = value % 7 === 0 && value !== 0;
+ return end ? '</tr><tr role="row">' : '';
+ },
+ longDay: function(value){
+ return Ext.Date.format(value, this.longDayFormat);
+ }
+ }
+ ],
+
+ ariaTitle: 'Date Picker',
+
+ todayText : 'Today',
+
+
+
+ todayTip : '{0} (Spacebar)',
+
+ minText : 'This date is before the minimum date',
+
+ maxText : 'This date is after the maximum date',
+
+
+ disabledDaysText : 'Disabled',
+
+ disabledDatesText : 'Disabled',
+
+
+
+ nextText : 'Next Month (Control+Right)',
+
+ prevText : 'Previous Month (Control+Left)',
+
+ monthYearText : 'Choose a month (Control+Up/Down to move years)',
+
+ startDay : 0,
+
+ showToday : true,
+
+
+
+
+
+
+
+ disableAnim: true,
+
+
+ baseCls: Ext.baseCSSPrefix + 'datepicker',
+
+
+
+
+
+
+ longDayFormat: 'F d, Y',
+
+
+
+
+ focusOnShow: false,
+
+
+
+ focusOnSelect: true,
+
+ width: 178,
+
+
+
+ initHour: 12,
+
+ numDays: 42,
+
+
+ initComponent : function() {
+ var me = this,
+ clearTime = Ext.Date.clearTime;
+
+ me.selectedCls = me.baseCls + '-selected';
+ me.disabledCellCls = me.baseCls + '-disabled';
+ me.prevCls = me.baseCls + '-prevday';
+ me.activeCls = me.baseCls + '-active';
+ me.nextCls = me.baseCls + '-prevday';
+ me.todayCls = me.baseCls + '-today';
+ me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
+ this.callParent();
+
+ me.value = me.value ?
+ clearTime(me.value, true) : clearTime(new Date());
+
+ me.addEvents(
+
+ 'select'
+ );
+
+ me.initDisabledDays();
+ },
+
+
+ onRender : function(container, position){
+
+
+ var me = this,
+ days = new Array(me.numDays),
+ today = Ext.Date.format(new Date(), me.format);
+
+ Ext.applyIf(me, {
+ renderData: {},
+ renderSelectors: {}
+ });
+
+ Ext.apply(me.renderData, {
+ dayNames: me.dayNames,
+ ariaTitle: me.ariaTitle,
+ value: me.value,
+ showToday: me.showToday,
+ prevText: me.prevText,
+ nextText: me.nextText,
+ days: days
+ });
+ me.getTpl('renderTpl').longDayFormat = me.longDayFormat;
+
+ Ext.apply(me.renderSelectors, {
+ eventEl: 'table.' + me.baseCls + '-inner',
+ prevEl: '.' + me.baseCls + '-prev a',
+ nextEl: '.' + me.baseCls + '-next a',
+ middleBtnEl: '.' + me.baseCls + '-month',
+ footerEl: '.' + me.baseCls + '-footer'
+ });
+
+ this.callParent(arguments);
+ me.el.unselectable();
+
+ me.cells = me.eventEl.select('tbody td');
+ me.textNodes = me.eventEl.query('tbody td span');
+
+ me.monthBtn = Ext.create('Ext.button.Split', {
+ text: '',
+ tooltip: me.monthYearText,
+ renderTo: me.middleBtnEl
+ });
+
+
+
+ me.todayBtn = Ext.create('Ext.button.Button', {
+ renderTo: me.footerEl,
+ text: Ext.String.format(me.todayText, today),
+ tooltip: Ext.String.format(me.todayTip, today),
+ handler: me.selectToday,
+ scope: me
+ });
+ },
+
+
+ initEvents: function(){
+ var me = this,
+ eDate = Ext.Date,
+ day = eDate.DAY;
+
+ this.callParent();
+
+ me.prevRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
+ handler: me.showPrevMonth,
+ scope: me,
+ preventDefault: true,
+ stopDefault: true
+ });
+
+ me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
+ handler: me.showNextMonth,
+ scope: me,
+ preventDefault:true,
+ stopDefault:true
+ });
+
+ me.keyNav = Ext.create('Ext.util.KeyNav', me.eventEl, Ext.apply({
+ scope: me,
+ 'left' : function(e){
+ if(e.ctrlKey){
+ me.showPrevMonth();
+ }else{
+ me.update(eDate.add(me.activeDate, day, -1));
+ }
+ },
+
+ 'right' : function(e){
+ if(e.ctrlKey){
+ me.showNextMonth();
+ }else{
+ me.update(eDate.add(me.activeDate, day, 1));
+ }
+ },
+
+ 'up' : function(e){
+ if(e.ctrlKey){
+ me.showNextYear();
+ }else{
+ me.update(eDate.add(me.activeDate, day, -7));
+ }
+ },
+
+ 'down' : function(e){
+ if(e.ctrlKey){
+ me.showPrevYear();
+ }else{
+ me.update(eDate.add(me.activeDate, day, 7));
+ }
+ },
+ 'pageUp' : me.showNextMonth,
+ 'pageDown' : me.showPrevMonth,
+ 'enter' : function(e){
+ e.stopPropagation();
+ return true;
+ }
+ }, me.keyNavConfig));
+
+ if(me.showToday){
+ me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday, me);
+ }
+ me.mon(me.eventEl, 'mousewheel', me.handleMouseWheel, me);
+ me.mon(me.eventEl, 'click', me.handleDateClick, me, {delegate: 'a.' + me.baseCls + '-date'});
+ me.mon(me.monthBtn, 'click', me.showMonthPicker, me);
+ me.mon(me.monthBtn, 'arrowclick', me.showMonthPicker, me);
+ me.update(me.value);
+ },
+
+
+ initDisabledDays : function(){
+ var me = this,
+ dd = me.disabledDates,
+ re = '(?:',
+ len;
+
+ if(!me.disabledDatesRE && dd){
+ len = dd.length - 1;
+
+ Ext.each(dd, function(d, i){
+ re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(d, me.format)) + '$' : dd[i];
+ if(i != len){
+ re += '|';
+ }
+ }, me);
+ me.disabledDatesRE = new RegExp(re + ')');
+ }
+ },
+
+
+ setDisabledDates : function(dd){
+ var me = this;
+
+ if(Ext.isArray(dd)){
+ me.disabledDates = dd;
+ me.disabledDatesRE = null;
+ }else{
+ me.disabledDatesRE = dd;
+ }
+ me.initDisabledDays();
+ me.update(me.value, true);
+ return me;
+ },
+
+
+ setDisabledDays : function(dd){
+ this.disabledDays = dd;
+ return this.update(this.value, true);
+ },
+
+
+ setMinDate : function(dt){
+ this.minDate = dt;
+ return this.update(this.value, true);
+ },
+
+
+ setMaxDate : function(dt){
+ this.maxDate = dt;
+ return this.update(this.value, true);
+ },
+
+
+ setValue : function(value){
+ this.value = Ext.Date.clearTime(value, true);
+ return this.update(this.value);
+ },
+
+
+ getValue : function(){
+ return this.value;
+ },
+
+
+ focus : function(){
+ this.update(this.activeDate);
+ },
+
+
+ onEnable: function(){
+ this.callParent();
+ this.setDisabledStatus(false);
+ this.update(this.activeDate);
+
+ },
+
+
+ onDisable : function(){
+ this.callParent();
+ this.setDisabledStatus(true);
+ },
+
+
+ setDisabledStatus : function(disabled){
+ var me = this;
+
+ me.keyNav.setDisabled(disabled);
+ me.prevRepeater.setDisabled(disabled);
+ me.nextRepeater.setDisabled(disabled);
+ if (me.showToday) {
+ me.todayKeyListener.setDisabled(disabled);
+ me.todayBtn.setDisabled(disabled);
+ }
+ },
+
+
+ getActive: function(){
+ return this.activeDate || me.value;
+ },
+
+
+ runAnimation: function(isHide){
+ var options = {
+ target: this.monthPicker,
+ duration: 200
+ };
+
+ Ext.fx.Manager.run();
+ if (isHide) {
+
+ } else {
+
+ }
+ Ext.create('Ext.fx.Anim', options);
+ },
+
+
+ hideMonthPicker : function(){
+ var me = this,
+ picker = me.monthPicker;
+
+ if (picker) {
+ if (me.disableAnim) {
+ picker.hide();
+ } else {
+ this.runAnimation(true);
+ }
+ }
+ return me;
+ },
+
+
+ showMonthPicker : function(){
+
+ var me = this,
+ picker,
+ size,
+ top,
+ left;
+
+
+ if (me.rendered && !me.disabled) {
+ size = me.getSize();
+ picker = me.createMonthPicker();
+ picker.show();
+ picker.setSize(size);
+ picker.setValue(me.getActive());
+
+ if (me.disableAnim) {
+ picker.setPosition(-1, -1);
+ } else {
+ me.runAnimation(false);
+ }
+ }
+ return me;
+ },
+
+
+ createMonthPicker: function(){
+ var me = this,
+ picker = me.monthPicker;
+
+ if (!picker) {
+ me.monthPicker = picker = Ext.create('Ext.picker.Month', {
+ renderTo: me.el,
+ floating: true,
+ shadow: false,
+ listeners: {
+ scope: me,
+ cancelclick: me.onCancelClick,
+ okclick: me.onOkClick,
+ yeardblclick: me.onOkClick,
+ monthdblclick: me.onOkClick
+ }
+ });
+
+ me.on('beforehide', me.hideMonthPicker, me);
+ }
+ return picker;
+ },
+
+
+ onOkClick: function(picker, value){
+ var me = this,
+ month = value[0],
+ year = value[1],
+ date = new Date(year, month, me.getActive().getDate());
+
+ if (date.getMonth() !== month) {
+
+ date = new Date(year, month, 1).getLastDateOfMonth();
+ }
+ me.update(date);
+ me.hideMonthPicker();
+ },
+
+
+ onCancelClick: function(){
+ this.hideMonthPicker();
+ },
+
+
+ showPrevMonth : function(e){
+ return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
+ },
+
+
+ showNextMonth : function(e){
+ return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
+ },
+
+
+ showPrevYear : function(){
+ this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
+ },
+
+
+ showNextYear : function(){
+ this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
+ },
+
+
+ handleMouseWheel : function(e){
+ e.stopEvent();
+ if(!this.disabled){
+ var delta = e.getWheelDelta();
+ if(delta > 0){
+ this.showPrevMonth();
+ } else if(delta < 0){
+ this.showNextMonth();
+ }
+ }
+ },
+
+
+ handleDateClick : function(e, t){
+ var me = this,
+ handler = me.handler;
+
+ e.stopEvent();
+ if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
+ me.cancelFocus = me.focusOnSelect === false;
+ me.setValue(new Date(t.dateValue));
+ delete me.cancelFocus;
+ me.fireEvent('select', me, me.value);
+ if (handler) {
+ handler.call(me.scope || me, me, me.value);
+ }
+
+
+
+
+ me.onSelect();
+ }
+ },
+
+
+ onSelect: function() {
+ if (this.hideOnSelect) {
+ this.hide();
+ }
+ },
+
+
+ selectToday : function(){
+ var me = this,
+ btn = me.todayBtn,
+ handler = me.handler;
+
+ if(btn && !btn.disabled){
+ me.setValue(Ext.Date.clearTime(new Date()));
+ me.fireEvent('select', me, me.value);
+ if (handler) {
+ handler.call(me.scope || me, me, me.value);
+ }
+ me.onSelect();
+ }
+ return me;
+ },
+
+
+ selectedUpdate: function(date, active){
+ var me = this,
+ t = date.getTime(),
+ cells = me.cells,
+ cls = me.selectedCls;
+
+ cells.removeCls(cls);
+ cells.each(function(c){
+ if (c.dom.firstChild.dateValue == t) {
+ me.el.dom.setAttribute('aria-activedescendent', c.dom.id);
+ c.addCls(cls);
+ if(me.isVisible() && !me.cancelFocus){
+ Ext.fly(c.dom.firstChild).focus(50);
+ }
+ return false;
+ }
+ }, this);
+ },
+
+
+ fullUpdate: function(date, active){
+ var me = this,
+ cells = me.cells.elements,
+ textNodes = me.textNodes,
+ disabledCls = me.disabledCellCls,
+ eDate = Ext.Date,
+ i = 0,
+ extraDays = 0,
+ visible = me.isVisible(),
+ sel = +eDate.clearTime(date, true),
+ today = +eDate.clearTime(new Date()),
+ min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
+ max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
+ ddMatch = me.disabledDatesRE,
+ ddText = me.disabledDatesText,
+ ddays = me.disabledDays ? me.disabledDays.join('') : false,
+ ddaysText = me.disabledDaysText,
+ format = me.format,
+ days = eDate.getDaysInMonth(date),
+ firstOfMonth = eDate.getFirstDateOfMonth(date),
+ startingPos = firstOfMonth.getDay() - me.startDay,
+ previousMonth = eDate.add(date, eDate.MONTH, -1),
+ longDayFormat = me.longDayFormat,
+ prevStart,
+ current,
+ disableToday,
+ tempDate,
+ setCellClass,
+ html,
+ cls,
+ formatValue,
+ value;
+
+ if (startingPos < 0) {
+ startingPos += 7;
+ }
+
+ days += startingPos;
+ prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
+ current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
+
+ if (me.showToday) {
+ tempDate = eDate.clearTime(new Date());
+ disableToday = (tempDate < min || tempDate > max ||
+ (ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) ||
+ (ddays && ddays.indexOf(tempDate.getDay()) != -1));
+
+ if (!me.disabled) {
+ me.todayBtn.setDisabled(disableToday);
+ me.todayKeyListener.setDisabled(disableToday);
+ }
+ }
+
+ setCellClass = function(cell){
+ value = +eDate.clearTime(current, true);
+ cell.title = eDate.format(current, longDayFormat);
+
+ cell.firstChild.dateValue = value;
+ if(value == today){
+ cell.className += ' ' + me.todayCls;
+ cell.title = me.todayText;
+ }
+ if(value == sel){
+ cell.className += ' ' + me.selectedCls;
+ me.el.dom.setAttribute('aria-activedescendant', cell.id);
+ if (visible && me.floating) {
+ Ext.fly(cell.firstChild).focus(50);
+ }
+ }
+
+ if(value < min) {
+ cell.className = disabledCls;
+ cell.title = me.minText;
+ return;
+ }
+ if(value > max) {
+ cell.className = disabledCls;
+ cell.title = me.maxText;
+ return;
+ }
+ if(ddays){
+ if(ddays.indexOf(current.getDay()) != -1){
+ cell.title = ddaysText;
+ cell.className = disabledCls;
+ }
+ }
+ if(ddMatch && format){
+ formatValue = eDate.dateFormat(current, format);
+ if(ddMatch.test(formatValue)){
+ cell.title = ddText.replace('%0', formatValue);
+ cell.className = disabledCls;
+ }
+ }
+ };
+
+ for(; i < me.numDays; ++i) {
+ if (i < startingPos) {
+ html = (++prevStart);
+ cls = me.prevCls;
+ } else if (i >= days) {
+ html = (++extraDays);
+ cls = me.nextCls;
+ } else {
+ html = i - startingPos + 1;
+ cls = me.activeCls;
+ }
+ textNodes[i].innerHTML = html;
+ cells[i].className = cls;
+ current.setDate(current.getDate() + 1);
+ setCellClass(cells[i]);
+ }
+
+ me.monthBtn.setText(me.monthNames[date.getMonth()] + ' ' + date.getFullYear());
+ },
+
+
+ update : function(date, forceRefresh){
+ var me = this,
+ active = me.activeDate;
+
+ if (me.rendered) {
+ me.activeDate = date;
+ if(!forceRefresh && active && me.el && active.getMonth() == date.getMonth() && active.getFullYear() == date.getFullYear()){
+ me.selectedUpdate(date, active);
+ } else {
+ me.fullUpdate(date, active);
+ }
+ }
+ return me;
+ },
+
+
+ beforeDestroy : function() {
+ var me = this;
+
+ if (me.rendered) {
+ Ext.destroy(
+ me.todayKeyListener,
+ me.keyNav,
+ me.monthPicker,
+ me.monthBtn,
+ me.nextRepeater,
+ me.prevRepeater,
+ me.todayBtn
+ );
+ delete me.textNodes;
+ delete me.cells.elements;
+ }
+ },
+
+
+ onShow: function() {
+ this.callParent(arguments);
+ if (this.focusOnShow) {
+ this.focus();
+ }
+ }
+},
+
+
+function() {
+ var proto = this.prototype;
+
+ proto.monthNames = Ext.Date.monthNames;
+
+ proto.dayNames = Ext.Date.dayNames;
+
+ proto.format = Ext.Date.defaultFormat;
+});
+
+
+Ext.define('Ext.form.field.Date', {
+ extend:'Ext.form.field.Picker',
+ alias: 'widget.datefield',
+ requires: ['Ext.picker.Date'],
+ alternateClassName: ['Ext.form.DateField', 'Ext.form.Date'],
+
+
+ format : "m/d/Y",
+
+ altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",
+
+ disabledDaysText : "Disabled",
+
+ disabledDatesText : "Disabled",
+
+ minText : "The date in this field must be equal to or after {0}",
+
+ maxText : "The date in this field must be equal to or before {0}",
+
+ invalidText : "{0} is not a valid date - it must be in the format {1}",
+
+ triggerCls : Ext.baseCSSPrefix + 'form-date-trigger',
+
+ showToday : true,
+
+
+
+
+
+
+
+
+
+ initTime: '12',
+
+ initTimeFormat: 'H',
+
+ matchFieldWidth: false,
+
+ startDay: 0,
+
+ initComponent : function(){
+ var me = this,
+ isString = Ext.isString,
+ min, max;
+
+ min = me.minValue;
+ max = me.maxValue;
+ if(isString(min)){
+ me.minValue = me.parseDate(min);
+ }
+ if(isString(max)){
+ me.maxValue = me.parseDate(max);
+ }
+ me.disabledDatesRE = null;
+ me.initDisabledDays();
+
+ me.callParent();
+ },
+
+ initValue: function() {
+ var me = this,
+ value = me.value;
+
+
+ if (Ext.isString(value)) {
+ me.value = me.rawToValue(value);
+ }
+
+ me.callParent();
+ },
+
+
+ initDisabledDays : function(){
+ if(this.disabledDates){
+ var dd = this.disabledDates,
+ len = dd.length - 1,
+ re = "(?:";
+
+ Ext.each(dd, function(d, i){
+ re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(d.dateFormat(this.format)) + '$' : dd[i];
+ if (i !== len) {
+ re += '|';
+ }
+ }, this);
+ this.disabledDatesRE = new RegExp(re + ')');
+ }
+ },
+
+
+ setDisabledDates : function(dd){
+ var me = this,
+ picker = me.picker;
+
+ me.disabledDates = dd;
+ me.initDisabledDays();
+ if (picker) {
+ picker.setDisabledDates(me.disabledDatesRE);
+ }
+ },
+
+
+ setDisabledDays : function(dd){
+ var picker = this.picker;
+
+ this.disabledDays = dd;
+ if (picker) {
+ picker.setDisabledDays(dd);
+ }
+ },
+
+
+ setMinValue : function(dt){
+ var me = this,
+ picker = me.picker,
+ minValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
+
+ me.minValue = minValue;
+ if (picker) {
+ picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue));
+ picker.setMinDate(minValue);
+ }
+ },
+
+
+ setMaxValue : function(dt){
+ var me = this,
+ picker = me.picker,
+ maxValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
+
+ me.maxValue = maxValue;
+ if (picker) {
+ picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue));
+ picker.setMaxDate(maxValue);
+ }
+ },
+
+
+ getErrors: function(value) {
+ var me = this,
+ format = Ext.String.format,
+ clearTime = Ext.Date.clearTime,
+ errors = me.callParent(arguments),
+ disabledDays = me.disabledDays,
+ disabledDatesRE = me.disabledDatesRE,
+ minValue = me.minValue,
+ maxValue = me.maxValue,
+ len = disabledDays ? disabledDays.length : 0,
+ i = 0,
+ svalue,
+ fvalue,
+ day,
+ time;
+
+ value = me.formatDate(value || me.processRawValue(me.getRawValue()));
+
+ if (value === null || value.length < 1) {
+ return errors;
+ }
+
+ svalue = value;
+ value = me.parseDate(value);
+ if (!value) {
+ errors.push(format(me.invalidText, svalue, me.format));
+ return errors;
+ }
+
+ time = value.getTime();
+ if (minValue && time < clearTime(minValue).getTime()) {
+ errors.push(format(me.minText, me.formatDate(minValue)));
+ }
+
+ if (maxValue && time > clearTime(maxValue).getTime()) {
+ errors.push(format(me.maxText, me.formatDate(maxValue)));
+ }
+
+ if (disabledDays) {
+ day = value.getDay();
+
+ for(; i < len; i++) {
+ if (day === disabledDays[i]) {
+ errors.push(me.disabledDaysText);
+ break;
+ }
+ }
+ }
+
+ fvalue = me.formatDate(value);
+ if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
+ errors.push(format(me.disabledDatesText, fvalue));
+ }
+
+ return errors;
+ },
+
+ rawToValue: function(rawValue) {
+ return this.parseDate(rawValue) || rawValue || null;
+ },
+
+ valueToRaw: function(value) {
+ return this.formatDate(this.parseDate(value));
+ },
+
+
+
+
+ safeParse : function(value, format) {
+ var me = this,
+ utilDate = Ext.Date,
+ parsedDate,
+ result = null;
+
+ if (utilDate.formatContainsHourInfo(format)) {
+
+ result = utilDate.parse(value, format);
+ } else {
+
+ parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat);
+ if (parsedDate) {
+ result = utilDate.clearTime(parsedDate);
+ }
+ }
+ return result;
+ },
+
+
+ getSubmitValue: function() {
+ var me = this,
+ format = me.submitFormat || me.format,
+ value = me.getValue();
+
+ return value ? Ext.Date.format(value, format) : null;
+ },
+
+
+ parseDate : function(value) {
+ if(!value || Ext.isDate(value)){
+ return value;
+ }
+
+ var me = this,
+ val = me.safeParse(value, me.format),
+ altFormats = me.altFormats,
+ altFormatsArray = me.altFormatsArray,
+ i = 0,
+ len;
+
+ if (!val && altFormats) {
+ altFormatsArray = altFormatsArray || altFormats.split('|');
+ len = altFormatsArray.length;
+ for (; i < len && !val; ++i) {
+ val = me.safeParse(value, altFormatsArray[i]);
+ }
+ }
+ return val;
+ },
+
+
+ formatDate : function(date){
+ return Ext.isDate(date) ? Ext.Date.dateFormat(date, this.format) : date;
+ },
+
+ createPicker: function() {
+ var me = this,
+ format = Ext.String.format;
+
+ return Ext.create('Ext.picker.Date', {
+ ownerCt: this.ownerCt,
+ renderTo: document.body,
+ floating: true,
+ hidden: true,
+ focusOnShow: true,
+ minDate: me.minValue,
+ maxDate: me.maxValue,
+ disabledDatesRE: me.disabledDatesRE,
+ disabledDatesText: me.disabledDatesText,
+ disabledDays: me.disabledDays,
+ disabledDaysText: me.disabledDaysText,
+ format: me.format,
+ showToday: me.showToday,
+ startDay: me.startDay,
+ minText: format(me.minText, me.formatDate(me.minValue)),
+ maxText: format(me.maxText, me.formatDate(me.maxValue)),
+ listeners: {
+ scope: me,
+ select: me.onSelect
+ },
+ keyNavConfig: {
+ esc: function() {
+ me.collapse();
+ }
+ }
+ });
+ },
+
+ onSelect: function(m, d) {
+ this.setValue(d);
+ this.fireEvent('select', this, d);
+ this.collapse();
+ },
+
+
+ onExpand: function() {
+ var me = this,
+ value = me.getValue();
+ me.picker.setValue(value instanceof Date ? value : new Date());
+ },
+
+
+ onCollapse: function() {
+ this.focus(false, 60);
+ },
+
+
+ beforeBlur : function(){
+ var v = this.parseDate(this.getRawValue());
+ if(v){
+ this.setValue(v);
+ }
+ }
+
+
+
+
+
+});
+
+
+Ext.define('Ext.form.field.Display', {
+ extend:'Ext.form.field.Base',
+ alias: 'widget.displayfield',
+ requires: ['Ext.util.Format', 'Ext.XTemplate'],
+ alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'],
+ fieldSubTpl: [
+ '<div id="{id}" class="{fieldCls}"></div>',
+ {
+ compiled: true,
+ disableFormats: true
+ }
+ ],
+
+
+ fieldCls: Ext.baseCSSPrefix + 'form-display-field',
+
+
+ htmlEncode: false,
+
+ validateOnChange: false,
+
+ initEvents: Ext.emptyFn,
+
+ submitValue: false,
+
+ isValid: function() {
+ return true;
+ },
+
+ validate: function() {
+ return true;
+ },
+
+ getRawValue: function() {
+ return this.rawValue;
+ },
+
+ setRawValue: function(value) {
+ var me = this;
+ value = Ext.value(value, '');
+ me.rawValue = value;
+ if (me.rendered) {
+ me.inputEl.dom.innerHTML = me.htmlEncode ? Ext.util.Format.htmlEncode(value) : value;
+ }
+ return value;
+ },
+
+
+ getContentTarget: function() {
+ return this.inputEl;
+ }
+
+
+
+
+
+
+
+});
+
+
+Ext.define("Ext.form.field.File", {
+ extend: 'Ext.form.field.Text',
+ alias: ['widget.filefield', 'widget.fileuploadfield'],
+ alternateClassName: ['Ext.form.FileUploadField', 'Ext.ux.form.FileUploadField', 'Ext.form.File'],
+ uses: ['Ext.button.Button', 'Ext.layout.component.field.File'],
+
+
+ buttonText: 'Browse...',
+
+
+ buttonOnly: false,
+
+
+ buttonMargin: 3,
+
+
+
+
+
+
+
+
+
+
+ fieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap',
+
+
+
+ readOnly: true,
+ componentLayout: 'filefield',
+
+
+ onRender: function() {
+ var me = this,
+ inputEl;
+
+ me.callParent(arguments);
+
+ me.createButton();
+ me.createFileInput();
+
+
+
+ if (me.disabled) {
+ me.disableItems();
+ }
+
+ inputEl = me.inputEl;
+ inputEl.dom.removeAttribute('name');
+ if (me.buttonOnly) {
+ inputEl.setDisplayed(false);
+ }
+ },
+
+
+ createButton: function() {
+ var me = this;
+ me.button = Ext.widget('button', Ext.apply({
+ renderTo: me.bodyEl,
+ text: me.buttonText,
+ cls: Ext.baseCSSPrefix + 'form-file-btn',
+ preventDefault: false,
+ ownerCt: me,
+ style: me.buttonOnly ? '' : 'margin-left:' + me.buttonMargin + 'px'
+ }, me.buttonConfig));
+ },
+
+
+ createFileInput : function() {
+ var me = this;
+ me.fileInputEl = me.button.el.createChild({
+ name: me.getName(),
+ cls: Ext.baseCSSPrefix + 'form-file-input',
+ tag: 'input',
+ type: 'file',
+ size: 1
+ }).on('change', me.onFileChange, me);
+ },
+
+
+ onFileChange: function() {
+ this.lastValue = null;
+ Ext.form.field.File.superclass.setValue.call(this, this.fileInputEl.dom.value);
+ },
+
+
+ setValue: Ext.emptyFn,
+
+ reset : function(){
+ this.fileInputEl.remove();
+ this.createFileInput();
+ this.callParent();
+ },
+
+ onDisable: function(){
+ this.callParent();
+ this.disableItems();
+ },
+
+ disableItems: function(){
+ var file = this.fileInputEl,
+ button = this.button;
+
+ if (file) {
+ file.dom.disabled = true;
+ }
+ if (button) {
+ button.disable();
+ }
+ },
+
+ onEnable: function(){
+ var me = this;
+ me.callParent();
+ me.fileInputEl.dom.disabled = false;
+ me.button.enable();
+ },
+
+ isFileUpload: function() {
+ return true;
+ },
+
+ extractFileInput: function() {
+ var fileInput = this.fileInputEl.dom;
+ this.reset();
+ return fileInput;
+ },
+
+ onDestroy: function(){
+ Ext.destroyMembers(this, 'fileInputEl', 'button');
+ this.callParent();
+ }
+
+
+});
+
+
+Ext.define('Ext.form.field.Hidden', {
+ extend:'Ext.form.field.Base',
+ alias: ['widget.hiddenfield', 'widget.hidden'],
+ alternateClassName: 'Ext.form.Hidden',
+
+
+ inputType : 'hidden',
+ hideLabel: true,
+
+ initComponent: function(){
+ this.formItemCls += '-hidden';
+ this.callParent();
+ },
+
+
+ initEvents: Ext.emptyFn,
+ setSize : Ext.emptyFn,
+ setWidth : Ext.emptyFn,
+ setHeight : Ext.emptyFn,
+ setPosition : Ext.emptyFn,
+ setPagePosition : Ext.emptyFn,
+ markInvalid : Ext.emptyFn,
+ clearInvalid : Ext.emptyFn
+});
+
+
+Ext.define('Ext.picker.Color', {
+ extend: 'Ext.Component',
+ requires: 'Ext.XTemplate',
+ alias: 'widget.colorpicker',
+ alternateClassName: 'Ext.ColorPalette',
+
+
+ componentCls : Ext.baseCSSPrefix + 'color-picker',
+
+
+ selectedCls: Ext.baseCSSPrefix + 'color-picker-selected',
+
+
+ value : null,
+
+
+ clickEvent :'click',
+
+
+ allowReselect : false,
+
+
+ colors : [
+ '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
+ '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
+ 'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
+ 'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
+ 'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
+ ],
+
+
+
+
+ colorRe: /(?:^|\s)color-(.{6})(?:\s|$)/,
+
+ constructor: function() {
+ this.renderTpl = Ext.create('Ext.XTemplate', '<tpl for="colors"><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on"> </span></em></a></tpl>');
+ this.callParent(arguments);
+ },
+
+
+ initComponent : function(){
+ var me = this;
+
+ this.callParent(arguments);
+ me.addEvents(
+
+ 'select'
+ );
+
+ if (me.handler) {
+ me.on('select', me.handler, me.scope, true);
+ }
+ },
+
+
+
+ onRender : function(container, position){
+ var me = this,
+ clickEvent = me.clickEvent;
+
+ Ext.apply(me.renderData, {
+ itemCls: me.itemCls,
+ colors: me.colors
+ });
+ this.callParent(arguments);
+
+ me.mon(me.el, clickEvent, me.handleClick, me, {delegate: 'a'});
+
+ if(clickEvent != 'click'){
+ me.mon(me.el, 'click', Ext.emptyFn, me, {delegate: 'a', stopEvent: true});
+ }
+ },
+
+
+ afterRender : function(){
+ var me = this,
+ value;
+
+ this.callParent(arguments);
+ if (me.value) {
+ value = me.value;
+ me.value = null;
+ me.select(value, true);
+ }
+ },
+
+
+ handleClick : function(event, target){
+ var me = this,
+ color;
+
+ event.stopEvent();
+ if (!me.disabled) {
+ color = target.className.match(me.colorRe)[1];
+ me.select(color.toUpperCase());
+ }
+ },
+
+
+ select : function(color, suppressEvent){
+
+ var me = this,
+ selectedCls = me.selectedCls,
+ value = me.value,
+ el;
+
+ color = color.replace('#', '');
+ if (!me.rendered) {
+ me.value = color;
+ return;
+ }
+
+
+ if (color != value || me.allowReselect) {
+ el = me.el;
+
+ if (me.value) {
+ el.down('a.color-' + value).removeCls(selectedCls);
+ }
+ el.down('a.color-' + color).addCls(selectedCls);
+ me.value = color;
+ if (suppressEvent !== true) {
+ me.fireEvent('select', me, color);
+ }
+ }
+ },
+
+
+ getValue: function(){
+ return this.value || null;
+ }
+});
+
+
+
+Ext.define('Ext.layout.component.field.HtmlEditor', {
+ extend: 'Ext.layout.component.field.Field',
+ alias: ['layout.htmleditor'],
+
+ type: 'htmleditor',
+
+ sizeBodyContents: function(width, height) {
+ var me = this,
+ owner = me.owner,
+ bodyEl = owner.bodyEl,
+ toolbar = owner.getToolbar(),
+ textarea = owner.textareaEl,
+ iframe = owner.iframeEl,
+ editorHeight;
+
+ if (Ext.isNumber(width)) {
+ width -= bodyEl.getFrameWidth('lr');
+ }
+ toolbar.setWidth(width);
+ textarea.setWidth(width);
+ iframe.setWidth(width);
+
+
+ if (Ext.isNumber(height)) {
+ editorHeight = height - toolbar.getHeight() - bodyEl.getFrameWidth('tb');
+ textarea.setHeight(editorHeight);
+ iframe.setHeight(editorHeight);
+ }
+ }
+});
+
+Ext.define('Ext.form.field.HtmlEditor', {
+ extend:'Ext.Component',
+ mixins: {
+ labelable: 'Ext.form.Labelable',
+ field: 'Ext.form.field.Field'
+ },
+ alias: 'widget.htmleditor',
+ alternateClassName: 'Ext.form.HtmlEditor',
+ requires: [
+ 'Ext.tip.QuickTipManager',
+ 'Ext.picker.Color',
+ 'Ext.toolbar.Item',
+ 'Ext.toolbar.Toolbar',
+ 'Ext.util.Format',
+ 'Ext.layout.component.field.HtmlEditor'
+ ],
+
+ fieldSubTpl: [
+ '<div class="{toolbarWrapCls}"></div>',
+ '<textarea id="{id}" name="{name}" tabIndex="-1" class="{textareaCls}" ',
+ 'style="{size}" autocomplete="off"></textarea>',
+ '<iframe name="{iframeName}" frameBorder="0" style="overflow:auto;{size}" src="{iframeSrc}"></iframe>',
+ {
+ compiled: true,
+ disableFormats: true
+ }
+ ],
+
+
+ enableFormat : true,
+
+ enableFontSize : true,
+
+ enableColors : true,
+
+ enableAlignments : true,
+
+ enableLists : true,
+
+ enableSourceEdit : true,
+
+ enableLinks : true,
+
+ enableFont : true,
+
+ createLinkText : 'Please enter the URL for the link:',
+
+ defaultLinkValue : 'http:/'+'/',
+
+ fontFamilies : [
+ 'Arial',
+ 'Courier New',
+ 'Tahoma',
+ 'Times New Roman',
+ 'Verdana'
+ ],
+ defaultFont: 'tahoma',
+
+ defaultValue: (Ext.isOpera || Ext.isIE6) ? ' ' : '​',
+
+ fieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap',
+
+ componentLayout: 'htmleditor',
+
+
+ initialized : false,
+ activated : false,
+ sourceEditMode : false,
+ iframePad:3,
+ hideMode:'offsets',
+
+ maskOnDisable: true,
+
+
+ initComponent : function(){
+ var me = this;
+
+ me.addEvents(
+
+ 'initialize',
+
+ 'activate',
+
+ 'beforesync',
+
+ 'beforepush',
+
+ 'sync',
+
+ 'push',
+
+ 'editmodechange'
+ );
+
+ me.callParent(arguments);
+
+
+ me.initLabelable();
+ me.initField();
+ },
+
+
+ createToolbar : function(editor){
+ var me = this,
+ items = [],
+ tipsEnabled = Ext.tip.QuickTipManager && Ext.tip.QuickTipManager.isEnabled(),
+ baseCSSPrefix = Ext.baseCSSPrefix,
+ fontSelectItem, toolbar, undef;
+
+ function btn(id, toggle, handler){
+ return {
+ itemId : id,
+ cls : baseCSSPrefix + 'btn-icon',
+ iconCls: baseCSSPrefix + 'edit-'+id,
+ enableToggle:toggle !== false,
+ scope: editor,
+ handler:handler||editor.relayBtnCmd,
+ clickEvent:'mousedown',
+ tooltip: tipsEnabled ? editor.buttonTips[id] || undef : undef,
+ overflowText: editor.buttonTips[id].title || undef,
+ tabIndex:-1
+ };
+ }
+
+
+ if (me.enableFont && !Ext.isSafari2) {
+ fontSelectItem = Ext.widget('component', {
+ renderTpl: [
+ '<select class="{cls}">',
+ '<tpl for="fonts">',
+ '<option value="{[values.toLowerCase()]}" style="font-family:{.}"<tpl if="values.toLowerCase()==parent.defaultFont"> selected</tpl>>{.}</option>',
+ '</tpl>',
+ '</select>'
+ ],
+ renderData: {
+ cls: baseCSSPrefix + 'font-select',
+ fonts: me.fontFamilies,
+ defaultFont: me.defaultFont
+ },
+ renderSelectors: {
+ selectEl: 'select'
+ },
+ onDisable: function() {
+ var selectEl = this.selectEl;
+ if (selectEl) {
+ selectEl.dom.disabled = true;
+ }
+ Ext.Component.superclass.onDisable.apply(this, arguments);
+ },
+ onEnable: function() {
+ var selectEl = this.selectEl;
+ if (selectEl) {
+ selectEl.dom.disabled = false;
+ }
+ Ext.Component.superclass.onEnable.apply(this, arguments);
+ }
+ });
+
+ items.push(
+ fontSelectItem,
+ '-'
+ );
+ }
+
+ if (me.enableFormat) {
+ items.push(
+ btn('bold'),
+ btn('italic'),
+ btn('underline')
+ );
+ }
+
+ if (me.enableFontSize) {
+ items.push(
+ '-',
+ btn('increasefontsize', false, me.adjustFont),
+ btn('decreasefontsize', false, me.adjustFont)
+ );
+ }
+
+ if (me.enableColors) {
+ items.push(
+ '-', {
+ itemId: 'forecolor',
+ cls: baseCSSPrefix + 'btn-icon',
+ iconCls: baseCSSPrefix + 'edit-forecolor',
+ overflowText: editor.buttonTips.forecolor.title,
+ tooltip: tipsEnabled ? editor.buttonTips.forecolor || undef : undef,
+ tabIndex:-1,
+ menu : Ext.widget('menu', {
+ plain: true,
+ items: [{
+ xtype: 'colorpicker',
+ allowReselect: true,
+ focus: Ext.emptyFn,
+ value: '000000',
+ plain: true,
+ clickEvent: 'mousedown',
+ handler: function(cp, color) {
+ me.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+ me.deferFocus();
+ this.up('menu').hide();
+ }
+ }]
+ })
+ }, {
+ itemId: 'backcolor',
+ cls: baseCSSPrefix + 'btn-icon',
+ iconCls: baseCSSPrefix + 'edit-backcolor',
+ overflowText: editor.buttonTips.backcolor.title,
+ tooltip: tipsEnabled ? editor.buttonTips.backcolor || undef : undef,
+ tabIndex:-1,
+ menu : Ext.widget('menu', {
+ plain: true,
+ items: [{
+ xtype: 'colorpicker',
+ focus: Ext.emptyFn,
+ value: 'FFFFFF',
+ plain: true,
+ allowReselect: true,
+ clickEvent: 'mousedown',
+ handler: function(cp, color) {
+ if (Ext.isGecko) {
+ me.execCmd('useCSS', false);
+ me.execCmd('hilitecolor', color);
+ me.execCmd('useCSS', true);
+ me.deferFocus();
+ } else {
+ me.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+ me.deferFocus();
+ }
+ this.up('menu').hide();
+ }
+ }]
+ })
+ }
+ );
+ }
+
+ if (me.enableAlignments) {
+ items.push(
+ '-',
+ btn('justifyleft'),
+ btn('justifycenter'),
+ btn('justifyright')
+ );
+ }
+
+ if (!Ext.isSafari2) {
+ if (me.enableLinks) {
+ items.push(
+ '-',
+ btn('createlink', false, me.createLink)
+ );
+ }
+
+ if (me.enableLists) {
+ items.push(
+ '-',
+ btn('insertorderedlist'),
+ btn('insertunorderedlist')
+ );
+ }
+ if (me.enableSourceEdit) {
+ items.push(
+ '-',
+ btn('sourceedit', true, function(btn){
+ me.toggleSourceEdit(!me.sourceEditMode);
+ })
+ );
+ }
+ }
+
+
+ toolbar = Ext.widget('toolbar', {
+ renderTo: me.toolbarWrap,
+ enableOverflow: true,
+ items: items
+ });
+
+ if (fontSelectItem) {
+ me.fontSelect = fontSelectItem.selectEl;
+
+ me.mon(me.fontSelect, 'change', function(){
+ me.relayCmd('fontname', me.fontSelect.dom.value);
+ me.deferFocus();
+ });
+ }
+
+
+ me.mon(toolbar.el, 'click', function(e){
+ e.preventDefault();
+ });
+
+ me.toolbar = toolbar;
+ },
+
+ onDisable: function() {
+ this.bodyEl.mask();
+ this.callParent(arguments);
+ },
+
+ onEnable: function() {
+ this.bodyEl.unmask();
+ this.callParent(arguments);
+ },
+
+
+ setReadOnly: function(readOnly) {
+ var me = this,
+ textareaEl = me.textareaEl,
+ iframeEl = me.iframeEl,
+ body;
+
+ me.readOnly = readOnly;
+
+ if (textareaEl) {
+ textareaEl.dom.readOnly = readOnly;
+ }
+
+ if (me.initialized) {
+ body = me.getEditorBody();
+ if (Ext.isIE) {
+
+ iframeEl.setDisplayed(false);
+ body.contentEditable = !readOnly;
+ iframeEl.setDisplayed(true);
+ } else {
+ me.setDesignMode(!readOnly);
+ }
+ if (body) {
+ body.style.cursor = readOnly ? 'default' : 'text';
+ }
+ me.disableItems(readOnly);
+ }
+ },
+
+
+ getDocMarkup: function() {
+ var me = this,
+ h = me.iframeEl.getHeight() - me.iframePad * 2;
+ return Ext.String.format('<html><head><style type="text/css">body{border:0;margin:0;padding:{0}px;height:{1}px;cursor:text}</style></head><body></body></html>', me.iframePad, h);
+ },
+
+
+ getEditorBody: function() {
+ var doc = this.getDoc();
+ return doc.body || doc.documentElement;
+ },
+
+
+ getDoc: function() {
+ return (!Ext.isIE && this.iframeEl.dom.contentDocument) || this.getWin().document;
+ },
+
+
+ getWin: function() {
+ return Ext.isIE ? this.iframeEl.dom.contentWindow : window.frames[this.iframeEl.dom.name];
+ },
+
+
+ onRender: function() {
+ var me = this,
+ renderSelectors = me.renderSelectors;
+
+ Ext.applyIf(renderSelectors, me.getLabelableSelectors());
+
+ Ext.applyIf(renderSelectors, {
+ toolbarWrap: 'div.' + Ext.baseCSSPrefix + 'html-editor-tb',
+ iframeEl: 'iframe',
+ textareaEl: 'textarea'
+ });
+
+ me.callParent(arguments);
+
+ me.textareaEl.dom.value = me.value || '';
+
+
+ me.monitorTask = Ext.TaskManager.start({
+ run: me.checkDesignMode,
+ scope: me,
+ interval:100
+ });
+
+ me.createToolbar(me);
+ me.disableItems(true);
+ },
+
+ initRenderTpl: function() {
+ var me = this;
+ if (!me.hasOwnProperty('renderTpl')) {
+ me.renderTpl = me.getTpl('labelableRenderTpl');
+ }
+ return me.callParent();
+ },
+
+ initRenderData: function() {
+ return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
+ },
+
+ getSubTplData: function() {
+ var cssPrefix = Ext.baseCSSPrefix;
+ return {
+ toolbarWrapCls: cssPrefix + 'html-editor-tb',
+ textareaCls: cssPrefix + 'hidden',
+ iframeName: Ext.id(),
+ iframeSrc: Ext.SSL_SECURE_URL,
+ size: 'height:100px;'
+ };
+ },
+
+ getSubTplMarkup: function() {
+ return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
+ },
+
+ getBodyNaturalWidth: function() {
+ return 565;
+ },
+
+ initFrameDoc: function() {
+ var me = this,
+ doc, task;
+
+ Ext.TaskManager.stop(me.monitorTask);
+
+ doc = me.getDoc();
+ me.win = me.getWin();
+
+ doc.open();
+ doc.write(me.getDocMarkup());
+ doc.close();
+
+ task = {
+ run: function() {
+ var doc = me.getDoc();
+ if (doc.body || doc.readyState === 'complete') {
+ Ext.TaskManager.stop(task);
+ me.setDesignMode(true);
+ Ext.defer(me.initEditor, 10, me);
+ }
+ },
+ interval : 10,
+ duration:10000,
+ scope: me
+ };
+ Ext.TaskManager.start(task);
+ },
+
+ checkDesignMode: function() {
+ var me = this,
+ doc = me.getDoc();
+ if (doc && (!doc.editorInitialized || me.getDesignMode() !== 'on')) {
+ me.initFrameDoc();
+ }
+ },
+
+
+ setDesignMode: function(mode) {
+ var me = this,
+ doc = me.getDoc();
+ if (doc) {
+ if (me.readOnly) {
+ mode = false;
+ }
+ doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
+ }
+ },
+
+
+ getDesignMode: function() {
+ var doc = this.getDoc();
+ return !doc ? '' : String(doc.designMode).toLowerCase();
+ },
+
+ disableItems: function(disabled) {
+ this.getToolbar().items.each(function(item){
+ if(item.getItemId() !== 'sourceedit'){
+ item.setDisabled(disabled);
+ }
+ });
+ },
+
+
+ toggleSourceEdit: function(sourceEditMode) {
+ var me = this,
+ iframe = me.iframeEl,
+ textarea = me.textareaEl,
+ hiddenCls = Ext.baseCSSPrefix + 'hidden',
+ btn = me.getToolbar().getComponent('sourceedit');
+
+ if (!Ext.isBoolean(sourceEditMode)) {
+ sourceEditMode = !me.sourceEditMode;
+ }
+ me.sourceEditMode = sourceEditMode;
+
+ if (btn.pressed !== sourceEditMode) {
+ btn.toggle(sourceEditMode);
+ }
+ if (sourceEditMode) {
+ me.disableItems(true);
+ me.syncValue();
+ iframe.addCls(hiddenCls);
+ textarea.removeCls(hiddenCls);
+ textarea.dom.removeAttribute('tabIndex');
+ textarea.focus();
+ }
+ else {
+ if (me.initialized) {
+ me.disableItems(me.readOnly);
+ }
+ me.pushValue();
+ iframe.removeCls(hiddenCls);
+ textarea.addCls(hiddenCls);
+ textarea.dom.setAttribute('tabIndex', -1);
+ me.deferFocus();
+ }
+ me.fireEvent('editmodechange', me, sourceEditMode);
+ me.doComponentLayout();
+ },
+
+
+ createLink : function() {
+ var url = prompt(this.createLinkText, this.defaultLinkValue);
+ if (url && url !== 'http:/'+'/') {
+ this.relayCmd('createlink', url);
+ }
+ },
+
+ clearInvalid: Ext.emptyFn,
+
+
+ setValue: function(value) {
+ var me = this,
+ textarea = me.textareaEl;
+ me.mixins.field.setValue.call(me, value);
+ if (value === null || value === undefined) {
+ value = '';
+ }
+ if (textarea) {
+ textarea.dom.value = value;
+ }
+ me.pushValue();
+ return this;
+ },
+
+
+ cleanHtml: function(html) {
+ html = String(html);
+ if (Ext.isWebKit) {
+ html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
+ }
+
+
+ if (html.charCodeAt(0) === this.defaultValue.replace(/\D/g, '')) {
+ html = html.substring(1);
+ }
+ return html;
+ },
+
+
+ syncValue : function(){
+ var me = this,
+ body, html, bodyStyle, match;
+ if (me.initialized) {
+ body = me.getEditorBody();
+ html = body.innerHTML;
+ if (Ext.isWebKit) {
+ bodyStyle = body.getAttribute('style');
+ match = bodyStyle.match(/text-align:(.*?);/i);
+ if (match && match[1]) {
+ html = '<div style="' + match[0] + '">' + html + '</div>';
+ }
+ }
+ html = me.cleanHtml(html);
+ if (me.fireEvent('beforesync', me, html) !== false) {
+ me.textareaEl.dom.value = html;
+ me.fireEvent('sync', me, html);
+ }
+ }
+ },
+
+
+ getValue : function() {
+ var me = this,
+ value;
+ if (!me.sourceEditMode) {
+ me.syncValue();
+ }
+ value = me.rendered ? me.textareaEl.dom.value : me.value;
+ me.value = value;
+ return value;
+ },
+
+
+ pushValue: function() {
+ var me = this,
+ v;
+ if(me.initialized){
+ v = me.textareaEl.dom.value || '';
+ if (!me.activated && v.length < 1) {
+ v = me.defaultValue;
+ }
+ if (me.fireEvent('beforepush', me, v) !== false) {
+ me.getEditorBody().innerHTML = v;
+ if (Ext.isGecko) {
+
+ me.setDesignMode(false);
+ me.setDesignMode(true);
+ }
+ me.fireEvent('push', me, v);
+ }
+ }
+ },
+
+
+ deferFocus : function(){
+ this.focus(false, true);
+ },
+
+ getFocusEl: function() {
+ var me = this,
+ win = me.win;
+ return win && !me.sourceEditMode ? win : me.textareaEl;
+ },
+
+
+ initEditor : function(){
+
+ try {
+ var me = this,
+ dbody = me.getEditorBody(),
+ ss = me.textareaEl.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
+ doc,
+ fn;
+
+ ss['background-attachment'] = 'fixed';
+ dbody.bgProperties = 'fixed';
+
+ Ext.core.DomHelper.applyStyles(dbody, ss);
+
+ doc = me.getDoc();
+
+ if (doc) {
+ try {
+ Ext.EventManager.removeAll(doc);
+ } catch(e) {}
+ }
+
+
+ fn = Ext.Function.bind(me.onEditorEvent, me);
+ Ext.EventManager.on(doc, {
+ mousedown: fn,
+ dblclick: fn,
+ click: fn,
+ keyup: fn,
+ buffer:100
+ });
+
+
+
+
+
+
+ fn = me.onRelayedEvent;
+ Ext.EventManager.on(doc, {
+ mousedown: fn,
+ mousemove: fn,
+ mouseup: fn,
+ click: fn,
+ dblclick: fn,
+ scope: me
+ });
+
+ if (Ext.isGecko) {
+ Ext.EventManager.on(doc, 'keypress', me.applyCommand, me);
+ }
+ if (me.fixKeys) {
+ Ext.EventManager.on(doc, 'keydown', me.fixKeys, me);
+ }
+
+
+ Ext.EventManager.on(window, 'unload', me.beforeDestroy, me);
+ doc.editorInitialized = true;
+
+ me.initialized = true;
+ me.pushValue();
+ me.setReadOnly(me.readOnly);
+ me.fireEvent('initialize', me);
+ } catch(ex) {
+
+ }
+ },
+
+
+ beforeDestroy : function(){
+ var me = this,
+ monitorTask = me.monitorTask,
+ doc, prop;
+
+ if (monitorTask) {
+ Ext.TaskManager.stop(monitorTask);
+ }
+ if (me.rendered) {
+ try {
+ doc = me.getDoc();
+ if (doc) {
+ Ext.EventManager.removeAll(doc);
+ for (prop in doc) {
+ if (doc.hasOwnProperty(prop)) {
+ delete doc[prop];
+ }
+ }
+ }
+ } catch(e) {
+
+ }
+ Ext.destroyMembers('tb', 'toolbarWrap', 'iframeEl', 'textareaEl');
+ }
+ me.callParent();
+ },
+
+
+ onRelayedEvent: function (event) {
+
+
+ var iframeEl = this.iframeEl,
+ iframeXY = iframeEl.getXY(),
+ eventXY = event.getXY();
+
+
+
+ event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
+
+ event.injectEvent(iframeEl);
+
+ event.xy = eventXY;
+ },
+
+
+ onFirstFocus : function(){
+ var me = this,
+ selection, range;
+ me.activated = true;
+ me.disableItems(me.readOnly);
+ if (Ext.isGecko) {
+ me.win.focus();
+ selection = me.win.getSelection();
+ if (!selection.focusNode || selection.focusNode.nodeType !== 3) {
+ range = selection.getRangeAt(0);
+ range.selectNodeContents(me.getEditorBody());
+ range.collapse(true);
+ me.deferFocus();
+ }
+ try {
+ me.execCmd('useCSS', true);
+ me.execCmd('styleWithCSS', false);
+ } catch(e) {
+
+ }
+ }
+ me.fireEvent('activate', me);
+ },
+
+
+ adjustFont: function(btn) {
+ var adjust = btn.getItemId() === 'increasefontsize' ? 1 : -1,
+ size = this.getDoc().queryCommandValue('FontSize') || '2',
+ isPxSize = Ext.isString(size) && size.indexOf('px') !== -1,
+ isSafari;
+ size = parseInt(size, 10);
+ if (isPxSize) {
+
+
+ if (size <= 10) {
+ size = 1 + adjust;
+ }
+ else if (size <= 13) {
+ size = 2 + adjust;
+ }
+ else if (size <= 16) {
+ size = 3 + adjust;
+ }
+ else if (size <= 18) {
+ size = 4 + adjust;
+ }
+ else if (size <= 24) {
+ size = 5 + adjust;
+ }
+ else {
+ size = 6 + adjust;
+ }
+ size = Ext.Number.constrain(size, 1, 6);
+ } else {
+ isSafari = Ext.isSafari;
+ if (isSafari) {
+ adjust *= 2;
+ }
+ size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0);
+ }
+ this.execCmd('FontSize', size);
+ },
+
+
+ onEditorEvent: function(e) {
+ this.updateToolbar();
+ },
+
+
+ updateToolbar: function() {
+ var me = this,
+ btns, doc, name, fontSelect;
+
+ if (me.readOnly) {
+ return;
+ }
+
+ if (!me.activated) {
+ me.onFirstFocus();
+ return;
+ }
+
+ btns = me.getToolbar().items.map;
+ doc = me.getDoc();
+
+ if (me.enableFont && !Ext.isSafari2) {
+ name = (doc.queryCommandValue('FontName') || me.defaultFont).toLowerCase();
+ fontSelect = me.fontSelect.dom;
+ if (name !== fontSelect.value) {
+ fontSelect.value = name;
+ }
+ }
+
+ function updateButtons() {
+ Ext.Array.forEach(Ext.Array.toArray(arguments), function(name) {
+ btns[name].toggle(doc.queryCommandState(name));
+ });
+ }
+ if(me.enableFormat){
+ updateButtons('bold', 'italic', 'underline');
+ }
+ if(me.enableAlignments){
+ updateButtons('justifyleft', 'justifycenter', 'justifyright');
+ }
+ if(!Ext.isSafari2 && me.enableLists){
+ updateButtons('insertorderedlist', 'insertunorderedlist');
+ }
+
+ Ext.menu.Manager.hideAll();
+
+ me.syncValue();
+ },
+
+
+ relayBtnCmd: function(btn) {
+ this.relayCmd(btn.getItemId());
+ },
+
+
+ relayCmd: function(cmd, value) {
+ Ext.defer(function() {
+ var me = this;
+ me.focus();
+ me.execCmd(cmd, value);
+ me.updateToolbar();
+ }, 10, this);
+ },
+
+
+ execCmd : function(cmd, value){
+ var me = this,
+ doc = me.getDoc(),
+ undef;
+ doc.execCommand(cmd, false, value === undef ? null : value);
+ me.syncValue();
+ },
+
+
+ applyCommand : function(e){
+ if (e.ctrlKey) {
+ var me = this,
+ c = e.getCharCode(), cmd;
+ if (c > 0) {
+ c = String.fromCharCode(c);
+ switch (c) {
+ case 'b':
+ cmd = 'bold';
+ break;
+ case 'i':
+ cmd = 'italic';
+ break;
+ case 'u':
+ cmd = 'underline';
+ break;
+ }
+ if (cmd) {
+ me.win.focus();
+ me.execCmd(cmd);
+ me.deferFocus();
+ e.preventDefault();
+ }
+ }
+ }
+ },
+
+
+ insertAtCursor : function(text){
+ var me = this,
+ range;
+
+ if (me.activated) {
+ me.win.focus();
+ if (Ext.isIE) {
+ range = me.getDoc().selection.createRange();
+ if (range) {
+ range.pasteHTML(text);
+ me.syncValue();
+ me.deferFocus();
+ }
+ }else{
+ me.execCmd('InsertHTML', text);
+ me.deferFocus();
+ }
+ }
+ },
+
+
+ fixKeys: function() {
+ if (Ext.isIE) {
+ return function(e){
+ var me = this,
+ k = e.getKey(),
+ doc = me.getDoc(),
+ range, target;
+ if (k === e.TAB) {
+ e.stopEvent();
+ range = doc.selection.createRange();
+ if(range){
+ range.collapse(true);
+ range.pasteHTML(' ');
+ me.deferFocus();
+ }
+ }
+ else if (k === e.ENTER) {
+ range = doc.selection.createRange();
+ if (range) {
+ target = range.parentElement();
+ if(!target || target.tagName.toLowerCase() !== 'li'){
+ e.stopEvent();
+ range.pasteHTML('<br />');
+ range.collapse(false);
+ range.select();
+ }
+ }
+ }
+ };
+ }
+
+ if (Ext.isOpera) {
+ return function(e){
+ var me = this;
+ if (e.getKey() === e.TAB) {
+ e.stopEvent();
+ me.win.focus();
+ me.execCmd('InsertHTML',' ');
+ me.deferFocus();
+ }
+ };
+ }
+
+ if (Ext.isWebKit) {
+ return function(e){
+ var me = this,
+ k = e.getKey();
+ if (k === e.TAB) {
+ e.stopEvent();
+ me.execCmd('InsertText','\t');
+ me.deferFocus();
+ }
+ else if (k === e.ENTER) {
+ e.stopEvent();
+ me.execCmd('InsertHtml','<br /><br />');
+ me.deferFocus();
+ }
+ };
+ }
+
+ return null;
+ }(),
+
+
+ getToolbar : function(){
+ return this.toolbar;
+ },
+
+
+ buttonTips : {
+ bold : {
+ title: 'Bold (Ctrl+B)',
+ text: 'Make the selected text bold.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ italic : {
+ title: 'Italic (Ctrl+I)',
+ text: 'Make the selected text italic.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ underline : {
+ title: 'Underline (Ctrl+U)',
+ text: 'Underline the selected text.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ increasefontsize : {
+ title: 'Grow Text',
+ text: 'Increase the font size.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ decreasefontsize : {
+ title: 'Shrink Text',
+ text: 'Decrease the font size.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ backcolor : {
+ title: 'Text Highlight Color',
+ text: 'Change the background color of the selected text.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ forecolor : {
+ title: 'Font Color',
+ text: 'Change the color of the selected text.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ justifyleft : {
+ title: 'Align Text Left',
+ text: 'Align text to the left.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ justifycenter : {
+ title: 'Center Text',
+ text: 'Center text in the editor.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ justifyright : {
+ title: 'Align Text Right',
+ text: 'Align text to the right.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ insertunorderedlist : {
+ title: 'Bullet List',
+ text: 'Start a bulleted list.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ insertorderedlist : {
+ title: 'Numbered List',
+ text: 'Start a numbered list.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ createlink : {
+ title: 'Hyperlink',
+ text: 'Make the selected text a hyperlink.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ },
+ sourceedit : {
+ title: 'Source Edit',
+ text: 'Switch to source editing mode.',
+ cls: Ext.baseCSSPrefix + 'html-editor-tip'
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+});
+
+
+Ext.define('Ext.form.field.Radio', {
+ extend:'Ext.form.field.Checkbox',
+ alias: ['widget.radiofield', 'widget.radio'],
+ alternateClassName: 'Ext.form.Radio',
+ requires: ['Ext.form.RadioManager'],
+
+ isRadio: true,
+
+
+
+
+ inputType: 'radio',
+ ariaRole: 'radio',
+
+
+ getGroupValue: function() {
+ var selected = this.getManager().getChecked(this.name);
+ return selected ? selected.inputValue : null;
+ },
+
+
+ onBoxClick: function(e) {
+ var me = this;
+ if (!me.disabled && !me.readOnly) {
+ this.setValue(true);
+ }
+ },
+
+
+ setValue: function(v) {
+ var me = this,
+ active;
+
+ if (Ext.isBoolean(v)) {
+ me.callParent(arguments);
+ } else {
+ active = me.getManager().getWithValue(me.name, v).getAt(0);
+ if (active) {
+ active.setValue(true);
+ }
+ }
+ return me;
+ },
+
+
+ getSubmitValue: function() {
+ return this.checked ? this.inputValue : null;
+ },
+
+
+ onChange: function(newVal, oldVal) {
+ var me = this;
+ me.callParent(arguments);
+
+ if (newVal) {
+ this.getManager().getByName(me.name).each(function(item){
+ if (item !== me) {
+ item.setValue(false);
+ }
+ }, me);
+ }
+ },
+
+
+ beforeDestroy: function(){
+ this.callParent();
+ this.getManager().removeAtKey(this.id);
+ },
+
+
+ getManager: function() {
+ return Ext.form.RadioManager;
+ }
+});
+
+
+Ext.define('Ext.picker.Time', {
+ extend: 'Ext.view.BoundList',
+ alias: 'widget.timepicker',
+ requires: ['Ext.data.Store', 'Ext.Date'],
+
+
+
+
+
+
+ increment: 15,
+
+
+ format : "g:i A",
+
+
+ displayField: 'disp',
+
+
+ initDate: [2008,1,1],
+
+ componentCls: Ext.baseCSSPrefix + 'timepicker',
+
+
+ loadingText: '',
+
+ initComponent: function() {
+ var me = this,
+ dateUtil = Ext.Date,
+ clearTime = dateUtil.clearTime,
+ initDate = me.initDate.join('/');
+
+
+ me.absMin = clearTime(new Date(initDate));
+ me.absMax = dateUtil.add(clearTime(new Date(initDate)), 'mi', (24 * 60) - 1);
+
+ me.store = me.createStore();
+ me.updateList();
+
+ this.callParent();
+ },
+
+
+ setMinValue: function(value) {
+ this.minValue = value;
+ this.updateList();
+ },
+
+
+ setMaxValue: function(value) {
+ this.maxValue = value;
+ this.updateList();
+ },
+
+
+ normalizeDate: function(date) {
+ var initDate = this.initDate;
+ date.setFullYear(initDate[0], initDate[1] - 1, initDate[2]);
+ return date;
+ },
+
+
+ updateList: function() {
+ var me = this,
+ min = me.normalizeDate(me.minValue || me.absMin),
+ max = me.normalizeDate(me.maxValue || me.absMax);
+
+ me.store.filterBy(function(record) {
+ var date = record.get('date');
+ return date >= min && date <= max;
+ });
+ },
+
+
+ createStore: function() {
+ var me = this,
+ utilDate = Ext.Date,
+ times = [],
+ min = me.absMin,
+ max = me.absMax;
+
+ while(min <= max){
+ times.push({
+ disp: utilDate.dateFormat(min, me.format),
+ date: min
+ });
+ min = utilDate.add(min, 'mi', me.increment);
+ }
+
+ return Ext.create('Ext.data.Store', {
+ fields: ['disp', 'date'],
+ data: times
+ });
+ }
+
+});
+
+
+Ext.define('Ext.form.field.Time', {
+ extend:'Ext.form.field.Picker',
+ alias: 'widget.timefield',
+ requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
+ alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
+
+
+ triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
+
+
+
+
+
+
+ minText : "The time in this field must be equal to or after {0}",
+
+
+ maxText : "The time in this field must be equal to or before {0}",
+
+
+ invalidText : "{0} is not a valid time",
+
+
+ format : "g:i A",
+
+
+
+
+ altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",
+
+
+ increment: 15,
+
+
+ pickerMaxHeight: 300,
+
+
+ selectOnTab: true,
+
+
+ initDate: '1/1/2008',
+ initDateFormat: 'j/n/Y',
+
+
+ initComponent: function() {
+ var me = this,
+ min = me.minValue,
+ max = me.maxValue;
+ if (min) {
+ me.setMinValue(min);
+ }
+ if (max) {
+ me.setMaxValue(max);
+ }
+ this.callParent();
+ },
+
+ initValue: function() {
+ var me = this,
+ value = me.value;
+
+
+ if (Ext.isString(value)) {
+ me.value = me.rawToValue(value);
+ }
+
+ me.callParent();
+ },
+
+
+ setMinValue: function(value) {
+ var me = this,
+ picker = me.picker;
+ me.setLimit(value, true);
+ if (picker) {
+ picker.setMinValue(me.minValue);
+ }
+ },
+
+
+ setMaxValue: function(value) {
+ var me = this,
+ picker = me.picker;
+ me.setLimit(value, false);
+ if (picker) {
+ picker.setMaxValue(me.maxValue);
+ }
+ },
+
+
+ setLimit: function(value, isMin) {
+ var me = this,
+ d, val;
+ if (Ext.isString(value)) {
+ d = me.parseDate(value);
+ }
+ else if (Ext.isDate(value)) {
+ d = value;
+ }
+ if (d) {
+ val = Ext.Date.clearTime(new Date(me.initDate));
+ val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
+ me[isMin ? 'minValue' : 'maxValue'] = val;
+ }
+ },
+
+ rawToValue: function(rawValue) {
+ return this.parseDate(rawValue) || rawValue || null;
+ },
+
+ valueToRaw: function(value) {
+ return this.formatDate(this.parseDate(value));
+ },
+
+
+ getErrors: function(value) {
+ var me = this,
+ format = Ext.String.format,
+ errors = me.callParent(arguments),
+ minValue = me.minValue,
+ maxValue = me.maxValue,
+ date;
+
+ value = me.formatDate(value || me.processRawValue(me.getRawValue()));
+
+ if (value === null || value.length < 1) {
+ return errors;
+ }
+
+ date = me.parseDate(value);
+ if (!date) {
+ errors.push(format(me.invalidText, value, me.format));
+ return errors;
+ }
+
+ if (minValue && date < minValue) {
+ errors.push(format(me.minText, me.formatDate(minValue)));
+ }
+
+ if (maxValue && date > maxValue) {
+ errors.push(format(me.maxText, me.formatDate(maxValue)));
+ }
+
+ return errors;
+ },
+
+ formatDate: function() {
+ return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
+ },
+
+
+ parseDate: function(value) {
+ if (!value || Ext.isDate(value)) {
+ return value;
+ }
+
+ var me = this,
+ val = me.safeParse(value, me.format),
+ altFormats = me.altFormats,
+ altFormatsArray = me.altFormatsArray,
+ i = 0,
+ len;
+
+ if (!val && altFormats) {
+ altFormatsArray = altFormatsArray || altFormats.split('|');
+ len = altFormatsArray.length;
+ for (; i < len && !val; ++i) {
+ val = me.safeParse(value, altFormatsArray[i]);
+ }
+ }
+ return val;
+ },
+
+ safeParse: function(value, format){
+ var me = this,
+ utilDate = Ext.Date,
+ parsedDate,
+ result = null;
+
+ if (utilDate.formatContainsDateInfo(format)) {
+
+ result = utilDate.parse(value, format);
+ } else {
+
+ parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
+ if (parsedDate) {
+ result = parsedDate;
+ }
+ }
+ return result;
+ },
+
+
+ getSubmitValue: function() {
+ var me = this,
+ format = me.submitFormat || me.format,
+ value = me.getValue();
+
+ return value ? Ext.Date.format(value, format) : null;
+ },
+
+
+ createPicker: function() {
+ var me = this,
+ picker = Ext.create('Ext.picker.Time', {
+ selModel: {
+ mode: 'SINGLE'
+ },
+ floating: true,
+ hidden: true,
+ minValue: me.minValue,
+ maxValue: me.maxValue,
+ increment: me.increment,
+ format: me.format,
+ ownerCt: this.ownerCt,
+ renderTo: document.body,
+ maxHeight: me.pickerMaxHeight,
+ focusOnToFront: false
+ });
+
+ me.mon(picker.getSelectionModel(), {
+ selectionchange: me.onListSelect,
+ scope: me
+ });
+
+ return picker;
+ },
+
+
+ onExpand: function() {
+ var me = this,
+ keyNav = me.pickerKeyNav,
+ selectOnTab = me.selectOnTab,
+ picker = me.getPicker(),
+ lastSelected = picker.getSelectionModel().lastSelected,
+ itemNode;
+
+ if (!keyNav) {
+ keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
+ boundList: picker,
+ forceKeyDown: true,
+ tab: function(e) {
+ if (selectOnTab) {
+ this.selectHighlighted(e);
+ me.triggerBlur();
+ }
+
+ return true;
+ }
+ });
+
+ if (selectOnTab) {
+ me.ignoreMonitorTab = true;
+ }
+ }
+ Ext.defer(keyNav.enable, 1, keyNav);
+
+
+ if (lastSelected) {
+ itemNode = picker.getNode(lastSelected);
+ if (itemNode) {
+ picker.highlightItem(itemNode);
+ picker.el.scrollChildIntoView(itemNode, false);
+ }
+ }
+ },
+
+
+ onCollapse: function() {
+ var me = this,
+ keyNav = me.pickerKeyNav;
+ if (keyNav) {
+ keyNav.disable();
+ me.ignoreMonitorTab = false;
+ }
+ },
+
+
+ onListSelect: function(list, recordArray) {
+ var me = this,
+ record = recordArray[0],
+ val = record ? record.get('date') : null;
+ me.setValue(val);
+ me.fireEvent('select', me, val);
+ me.picker.clearHighlight();
+ me.collapse();
+ me.inputEl.focus();
+ }
+});
+
+
+
+Ext.define('Ext.grid.CellEditor', {
+ extend: 'Ext.Editor',
+ constructor: function(config) {
+ if (config.field) {
+ config.field.monitorTab = false;
+ }
+ config.autoSize = {
+ width: 'boundEl'
+ };
+ this.callParent(arguments);
+ },
+
+
+ onShow: function() {
+ var first = this.boundEl.first();
+ if (first) {
+ first.hide();
+ }
+ this.callParent(arguments);
+ },
+
+
+ onHide: function() {
+ var first = this.boundEl.first();
+ if (first) {
+ first.show();
+ }
+ this.callParent(arguments);
+ },
+
+
+ afterRender: function() {
+ this.callParent(arguments);
+ var field = this.field;
+ if (field.isXType('checkboxfield')) {
+ field.mon(field.inputEl, 'mousedown', this.onCheckBoxMouseDown, this);
+ field.mon(field.inputEl, 'click', this.onCheckBoxClick, this);
+ }
+ },
+
+
+ onCheckBoxMouseDown: function() {
+ this.completeEdit = Ext.emptyFn;
+ },
+
+
+ onCheckBoxClick: function() {
+ delete this.completeEdit;
+ this.field.focus(false, 10);
+ },
+
+ alignment: "tl-tl",
+ hideEl : false,
+ cls: Ext.baseCSSPrefix + "small-editor " + Ext.baseCSSPrefix + "grid-editor",
+ shim: false,
+ shadow: false
+});
+
+Ext.define('Ext.grid.ColumnLayout', {
+ extend: 'Ext.layout.container.HBox',
+ alias: 'layout.gridcolumn',
+ type : 'column',
+
+
+ clearInnerCtOnLayout: false,
+
+ constructor: function() {
+ var me = this;
+ me.callParent(arguments);
+ if (!Ext.isDefined(me.availableSpaceOffset)) {
+ me.availableSpaceOffset = (Ext.getScrollBarWidth() - 2);
+ }
+ },
+
+ beforeLayout: function() {
+ var me = this,
+ i = 0,
+ items = me.getLayoutItems(),
+ len = items.length,
+ item, returnValue;
+
+ returnValue = me.callParent(arguments);
+
+
+ me.innerCt.setHeight(23);
+
+
+ if (me.align == 'stretchmax') {
+ for (; i < len; i++) {
+ item = items[i];
+ item.el.setStyle({
+ height: 'auto'
+ });
+ item.titleContainer.setStyle({
+ height: 'auto',
+ paddingTop: '0'
+ });
+ if (item.componentLayout && item.componentLayout.lastComponentSize) {
+ item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
+ }
+ }
+ }
+ return returnValue;
+ },
+
+
+ calculateChildBoxes: function(visibleItems, targetSize) {
+ var me = this,
+ calculations = me.callParent(arguments),
+ boxes = calculations.boxes,
+ metaData = calculations.meta,
+ len = boxes.length, i = 0, box, item;
+
+ if (targetSize.width && !me.isColumn) {
+
+ if (me.owner.forceFit) {
+
+ for (; i < len; i++) {
+ box = boxes[i];
+ item = box.component;
+
+
+ item.minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
+
+
+
+ item.flex = box.width;
+ }
+
+
+ calculations = me.callParent(arguments);
+ }
+ else if (metaData.tooNarrow) {
+ targetSize.width = metaData.desiredSize;
+ }
+ }
+
+ return calculations;
+ },
+
+ afterLayout: function() {
+ var me = this,
+ i = 0,
+ items = me.getLayoutItems(),
+ len = items.length;
+
+ me.callParent(arguments);
+
+
+ if (me.align == 'stretchmax') {
+ for (; i < len; i++) {
+ items[i].setPadding();
+ }
+ }
+ },
+
+
+
+ updateInnerCtSize: function(tSize, calcs) {
+ var me = this,
+ extra = 0;
+
+
+ if (!me.isColumn && calcs.meta.tooNarrow) {
+ if (
+ Ext.isWebKit ||
+ Ext.isGecko ||
+ (Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7 || Ext.isIE8))
+ ) {
+ extra = 1;
+
+ } else if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
+ extra = 2;
+ }
+
+
+ extra++;
+ tSize.width = calcs.meta.desiredSize + (me.reserveOffset ? me.availableSpaceOffset : 0) + extra;
+ }
+ return me.callParent(arguments);
+ },
+
+ doOwnerCtLayouts: function() {
+ var ownerCt = this.owner.ownerCt;
+ if (!ownerCt.componentLayout.layoutBusy) {
+ ownerCt.doComponentLayout();
+ }
+ }
+});
+
+Ext.define('Ext.grid.LockingView', {
+
+ mixins: {
+ observable: 'Ext.util.Observable'
+ },
+
+ eventRelayRe: /^(beforeitem|beforecontainer|item|container|cell)/,
+
+ constructor: function(config){
+ var me = this,
+ eventNames = [],
+ eventRe = me.eventRelayRe,
+ locked = config.locked.getView(),
+ normal = config.normal.getView(),
+ events,
+ event;
+
+ Ext.apply(me, {
+ lockedView: locked,
+ normalView: normal,
+ lockedGrid: config.locked,
+ normalGrid: config.normal,
+ panel: config.panel
+ });
+ me.mixins.observable.constructor.call(me, config);
+
+
+ events = locked.events;
+ for (event in events) {
+ if (events.hasOwnProperty(event) && eventRe.test(event)) {
+ eventNames.push(event);
+ }
+ }
+ me.relayEvents(locked, eventNames);
+ me.relayEvents(normal, eventNames);
+
+ normal.on({
+ scope: me,
+ itemmouseleave: me.onItemMouseLeave,
+ itemmouseenter: me.onItemMouseEnter
+ });
+
+ locked.on({
+ scope: me,
+ itemmouseleave: me.onItemMouseLeave,
+ itemmouseenter: me.onItemMouseEnter
+ });
+ },
+
+ getGridColumns: function() {
+ var cols = this.lockedGrid.headerCt.getGridColumns();
+ return cols.concat(this.normalGrid.headerCt.getGridColumns());
+ },
+
+ onItemMouseEnter: function(view, record){
+ var me = this,
+ locked = me.lockedView,
+ other = me.normalView,
+ item;
+
+ if (view.trackOver) {
+ if (view !== locked) {
+ other = locked;
+ }
+ item = other.getNode(record);
+ other.highlightItem(item);
+ }
+ },
+
+ onItemMouseLeave: function(view, record){
+ var me = this,
+ locked = me.lockedView,
+ other = me.normalView;
+
+ if (view.trackOver) {
+ if (view !== locked) {
+ other = locked;
+ }
+ other.clearHighlight();
+ }
+ },
+
+ relayFn: function(name, args){
+ args = args || [];
+
+ var view = this.lockedView;
+ view[name].apply(view, args || []);
+ view = this.normalView;
+ view[name].apply(view, args || []);
+ },
+
+ getSelectionModel: function(){
+ return this.panel.getSelectionModel();
+ },
+
+ getStore: function(){
+ return this.panel.store;
+ },
+
+ getNode: function(nodeInfo){
+
+ return this.normalView.getNode(nodeInfo);
+ },
+
+ getCell: function(record, column){
+ var view = this.lockedView,
+ row;
+
+
+ if (view.getHeaderAtIndex(column) === -1) {
+ view = this.normalView;
+ }
+
+ row = view.getNode(record);
+ return Ext.fly(row).down(column.getCellSelector());
+ },
+
+ getRecord: function(node){
+ var result = this.lockedView.getRecord(node);
+ if (!node) {
+ result = this.normalView.getRecord(node);
+ }
+ return result;
+ },
+
+ refreshNode: function(){
+ this.relayFn('refreshNode', arguments);
+ },
+
+ refresh: function(){
+ this.relayFn('refresh', arguments);
+ },
+
+ bindStore: function(){
+ this.relayFn('bindStore', arguments);
+ },
+
+ addRowCls: function(){
+ this.relayFn('addRowCls', arguments);
+ },
+
+ removeRowCls: function(){
+ this.relayFn('removeRowCls', arguments);
+ }
+
+});
+
+Ext.define('Ext.grid.Lockable', {
+
+ requires: ['Ext.grid.LockingView'],
+
+
+ syncRowHeight: true,
+
+
+
+
+
+
+
+
+ spacerHidden: true,
+
+
+ unlockText: 'Unlock',
+ lockText: 'Lock',
+
+ determineXTypeToCreate: function() {
+ var me = this,
+ typeToCreate;
+
+ if (me.subGridXType) {
+ typeToCreate = me.subGridXType;
+ } else {
+ var xtypes = this.getXTypes().split('/'),
+ xtypesLn = xtypes.length,
+ xtype = xtypes[xtypesLn - 1],
+ superxtype = xtypes[xtypesLn - 2];
+
+ if (superxtype !== 'tablepanel') {
+ typeToCreate = superxtype;
+ } else {
+ typeToCreate = xtype;
+ }
+ }
+
+ return typeToCreate;
+ },
+
+
+
+ injectLockable: function() {
+
+ this.lockable = true;
+
+
+ this.hasView = true;
+
+ var me = this,
+
+
+
+ xtype = me.determineXTypeToCreate(),
+
+ selModel = me.getSelectionModel(),
+ lockedGrid = {
+ xtype: xtype,
+
+ enableAnimations: false,
+ scroll: false,
+ scrollerOwner: false,
+ selModel: selModel,
+ border: false,
+ cls: Ext.baseCSSPrefix + 'grid-inner-locked'
+ },
+ normalGrid = {
+ xtype: xtype,
+ enableAnimations: false,
+ scrollerOwner: false,
+ selModel: selModel,
+ border: false
+ },
+ i = 0,
+ columns,
+ lockedHeaderCt,
+ normalHeaderCt;
+
+ me.addCls(Ext.baseCSSPrefix + 'grid-locked');
+
+
+
+
+ Ext.copyTo(normalGrid, me, me.normalCfgCopy);
+ Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
+ for (; i < me.normalCfgCopy.length; i++) {
+ delete me[me.normalCfgCopy[i]];
+ }
+ for (i = 0; i < me.lockedCfgCopy.length; i++) {
+ delete me[me.lockedCfgCopy[i]];
+ }
+
+ me.lockedHeights = [];
+ me.normalHeights = [];
+
+ columns = me.processColumns(me.columns);
+
+ lockedGrid.width = columns.lockedWidth;
+ lockedGrid.columns = columns.locked;
+ normalGrid.columns = columns.normal;
+
+ me.store = Ext.StoreManager.lookup(me.store);
+ lockedGrid.store = me.store;
+ normalGrid.store = me.store;
+
+
+ normalGrid.flex = 1;
+ lockedGrid.viewConfig = me.lockedViewConfig || {};
+ lockedGrid.viewConfig.loadingUseMsg = false;
+ normalGrid.viewConfig = me.normalViewConfig || {};
+
+ Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
+ Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
+
+ me.normalGrid = Ext.ComponentManager.create(normalGrid);
+ me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
+
+ me.view = Ext.create('Ext.grid.LockingView', {
+ locked: me.lockedGrid,
+ normal: me.normalGrid,
+ panel: me
+ });
+
+ if (me.syncRowHeight) {
+ me.lockedGrid.getView().on({
+ refresh: me.onLockedGridAfterRefresh,
+ itemupdate: me.onLockedGridAfterUpdate,
+ scope: me
+ });
+
+ me.normalGrid.getView().on({
+ refresh: me.onNormalGridAfterRefresh,
+ itemupdate: me.onNormalGridAfterUpdate,
+ scope: me
+ });
+ }
+
+ lockedHeaderCt = me.lockedGrid.headerCt;
+ normalHeaderCt = me.normalGrid.headerCt;
+
+ lockedHeaderCt.lockedCt = true;
+ lockedHeaderCt.lockableInjected = true;
+ normalHeaderCt.lockableInjected = true;
+
+ lockedHeaderCt.on({
+ columnshow: me.onLockedHeaderShow,
+ columnhide: me.onLockedHeaderHide,
+ columnmove: me.onLockedHeaderMove,
+ sortchange: me.onLockedHeaderSortChange,
+ columnresize: me.onLockedHeaderResize,
+ scope: me
+ });
+
+ normalHeaderCt.on({
+ columnmove: me.onNormalHeaderMove,
+ sortchange: me.onNormalHeaderSortChange,
+ scope: me
+ });
+
+ me.normalGrid.on({
+ scrollershow: me.onScrollerShow,
+ scrollerhide: me.onScrollerHide,
+ scope: me
+ });
+
+ me.lockedGrid.on('afterlayout', me.onLockedGridAfterLayout, me, {single: true});
+
+ me.modifyHeaderCt();
+ me.items = [me.lockedGrid, me.normalGrid];
+
+ me.layout = {
+ type: 'hbox',
+ align: 'stretch'
+ };
+ },
+
+ processColumns: function(columns){
+
+ var i = 0,
+ len = columns.length,
+ lockedWidth = 0,
+ lockedHeaders = [],
+ normalHeaders = [],
+ column;
+
+ for (; i < len; ++i) {
+ column = columns[i];
+
+
+ column.processed = true;
+ if (column.locked) {
+ if (column.flex) {
+ Ext.Error.raise("Columns which are locked do NOT support a flex width. You must set a width on the " + columns[i].text + "column.");
+ }
+ lockedWidth += column.width;
+ lockedHeaders.push(column);
+ } else {
+ normalHeaders.push(column);
+ }
+ }
+ return {
+ lockedWidth: lockedWidth,
+ locked: lockedHeaders,
+ normal: normalHeaders
+ };
+ },
+
+
+ onLockedGridAfterLayout: function() {
+ var me = this,
+ lockedView = me.lockedGrid.getView();
+ lockedView.on({
+ refresh: me.createSpacer,
+ beforerefresh: me.destroySpacer,
+ scope: me
+ });
+ },
+
+
+ onLockedHeaderMove: function() {
+ if (this.syncRowHeight) {
+ this.onNormalGridAfterRefresh();
+ }
+ },
+
+
+ onNormalHeaderMove: function() {
+ if (this.syncRowHeight) {
+ this.onLockedGridAfterRefresh();
+ }
+ },
+
+
+
+ createSpacer: function() {
+ var me = this,
+
+
+ w = Ext.getScrollBarWidth() + (Ext.isIE ? 2 : 0),
+ view = me.lockedGrid.getView(),
+ el = view.el;
+
+ me.spacerEl = Ext.core.DomHelper.append(el, {
+ cls: me.spacerHidden ? (Ext.baseCSSPrefix + 'hidden') : '',
+ style: 'height: ' + w + 'px;'
+ }, true);
+ },
+
+ destroySpacer: function() {
+ var me = this;
+ if (me.spacerEl) {
+ me.spacerEl.destroy();
+ delete me.spacerEl;
+ }
+ },
+
+
+ onLockedGridAfterRefresh: function() {
+ var me = this,
+ view = me.lockedGrid.getView(),
+ el = view.el,
+ rowEls = el.query(view.getItemSelector()),
+ ln = rowEls.length,
+ i = 0;
+
+
+ me.lockedHeights = [];
+
+ for (; i < ln; i++) {
+ me.lockedHeights[i] = rowEls[i].clientHeight;
+ }
+ me.syncRowHeights();
+ },
+
+
+ onNormalGridAfterRefresh: function() {
+ var me = this,
+ view = me.normalGrid.getView(),
+ el = view.el,
+ rowEls = el.query(view.getItemSelector()),
+ ln = rowEls.length,
+ i = 0;
+
+
+ me.normalHeights = [];
+
+ for (; i < ln; i++) {
+ me.normalHeights[i] = rowEls[i].clientHeight;
+ }
+ me.syncRowHeights();
+ },
+
+
+ onLockedGridAfterUpdate: function(record, index, node) {
+ this.lockedHeights[index] = node.clientHeight;
+ this.syncRowHeights();
+ },
+
+
+ onNormalGridAfterUpdate: function(record, index, node) {
+ this.normalHeights[index] = node.clientHeight;
+ this.syncRowHeights();
+ },
+
+
+
+ syncRowHeights: function() {
+ var me = this,
+ lockedHeights = me.lockedHeights,
+ normalHeights = me.normalHeights,
+ calcHeights = [],
+ ln = lockedHeights.length,
+ i = 0,
+ lockedView, normalView,
+ lockedRowEls, normalRowEls,
+ vertScroller = me.getVerticalScroller(),
+ scrollTop;
+
+
+
+ if (lockedHeights.length && normalHeights.length) {
+ lockedView = me.lockedGrid.getView();
+ normalView = me.normalGrid.getView();
+ lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
+ normalRowEls = normalView.el.query(normalView.getItemSelector());
+
+
+ for (; i < ln; i++) {
+
+ if (!isNaN(lockedHeights[i]) && !isNaN(normalHeights[i])) {
+ if (lockedHeights[i] > normalHeights[i]) {
+ Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
+ } else if (lockedHeights[i] < normalHeights[i]) {
+ Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
+ }
+ }
+ }
+
+
+ me.normalGrid.invalidateScroller();
+
+
+
+ if (vertScroller && vertScroller.setViewScrollTop) {
+ vertScroller.setViewScrollTop(me.virtualScrollTop);
+ } else {
+
+
+
+ scrollTop = normalView.el.dom.scrollTop;
+ normalView.el.dom.scrollTop = scrollTop;
+ lockedView.el.dom.scrollTop = scrollTop;
+ }
+
+
+ me.lockedHeights = [];
+ me.normalHeights = [];
+ }
+ },
+
+
+ onScrollerShow: function(scroller, direction) {
+ if (direction === 'horizontal') {
+ this.spacerHidden = false;
+ this.spacerEl.removeCls(Ext.baseCSSPrefix + 'hidden');
+ }
+ },
+
+
+ onScrollerHide: function(scroller, direction) {
+ if (direction === 'horizontal') {
+ this.spacerHidden = true;
+ this.spacerEl.addCls(Ext.baseCSSPrefix + 'hidden');
+ }
+ },
+
+
+
+ modifyHeaderCt: function() {
+ var me = this;
+ me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(true);
+ me.normalGrid.headerCt.getMenuItems = me.getMenuItems(false);
+ },
+
+ onUnlockMenuClick: function() {
+ this.unlock();
+ },
+
+ onLockMenuClick: function() {
+ this.lock();
+ },
+
+ getMenuItems: function(locked) {
+ var me = this,
+ unlockText = me.unlockText,
+ lockText = me.lockText,
+
+ unlockCls = 'xg-hmenu-unlock',
+ lockCls = 'xg-hmenu-lock',
+ unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me),
+ lockHandler = Ext.Function.bind(me.onLockMenuClick, me);
+
+
+ return function() {
+ var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
+ o.push('-',{
+ cls: unlockCls,
+ text: unlockText,
+ handler: unlockHandler,
+ disabled: !locked
+ });
+ o.push({
+ cls: lockCls,
+ text: lockText,
+ handler: lockHandler,
+ disabled: locked
+ });
+ return o;
+ };
+ },
+
+
+
+ lock: function(activeHd, toIdx) {
+ var me = this,
+ normalGrid = me.normalGrid,
+ lockedGrid = me.lockedGrid,
+ normalHCt = normalGrid.headerCt,
+ lockedHCt = lockedGrid.headerCt;
+
+ activeHd = activeHd || normalHCt.getMenu().activeHeader;
+
+
+
+ if (activeHd.flex) {
+ activeHd.width = activeHd.getWidth();
+ delete activeHd.flex;
+ }
+
+ normalHCt.remove(activeHd, false);
+ lockedHCt.suspendLayout = true;
+ if (Ext.isDefined(toIdx)) {
+ lockedHCt.insert(toIdx, activeHd);
+ } else {
+ lockedHCt.add(activeHd);
+ }
+ lockedHCt.suspendLayout = false;
+ me.syncLockedSection();
+ },
+
+ syncLockedSection: function() {
+ var me = this;
+ me.syncLockedWidth();
+ me.lockedGrid.getView().refresh();
+ me.normalGrid.getView().refresh();
+ },
+
+
+
+ syncLockedWidth: function() {
+ var me = this,
+ width = me.lockedGrid.headerCt.getFullWidth(true);
+ me.lockedGrid.setWidth(width);
+ },
+
+ onLockedHeaderResize: function() {
+ this.syncLockedWidth();
+ },
+
+ onLockedHeaderHide: function() {
+ this.syncLockedWidth();
+ },
+
+ onLockedHeaderShow: function() {
+ this.syncLockedWidth();
+ },
+
+ onLockedHeaderSortChange: function(headerCt, header, sortState) {
+ if (sortState) {
+
+
+ this.normalGrid.headerCt.clearOtherSortStates(null, true);
+ }
+ },
+
+ onNormalHeaderSortChange: function(headerCt, header, sortState) {
+ if (sortState) {
+
+
+ this.lockedGrid.headerCt.clearOtherSortStates(null, true);
+ }
+ },
+
+
+
+ unlock: function(activeHd, toIdx) {
+ var me = this,
+ normalGrid = me.normalGrid,
+ lockedGrid = me.lockedGrid,
+ normalHCt = normalGrid.headerCt,
+ lockedHCt = lockedGrid.headerCt;
+
+ if (!Ext.isDefined(toIdx)) {
+ toIdx = 0;
+ }
+ activeHd = activeHd || lockedHCt.getMenu().activeHeader;
+
+ lockedHCt.remove(activeHd, false);
+ me.syncLockedWidth();
+ me.lockedGrid.getView().refresh();
+ normalHCt.insert(toIdx, activeHd);
+ me.normalGrid.getView().refresh();
+ },
+
+
+ reconfigureLockable: function(store, columns) {
+ var me = this,
+ lockedGrid = me.lockedGrid,
+ normalGrid = me.normalGrid;
+
+ if (columns) {
+ lockedGrid.headerCt.removeAll();
+ normalGrid.headerCt.removeAll();
+
+ columns = me.processColumns(columns);
+ lockedGrid.setWidth(columns.lockedWidth);
+ lockedGrid.headerCt.add(columns.locked);
+ normalGrid.headerCt.add(columns.normal);
+ }
+
+ if (store) {
+ store = Ext.data.StoreManager.lookup(store);
+ me.store = store;
+ lockedGrid.bindStore(store);
+ normalGrid.bindStore(store);
+ } else {
+ lockedGrid.getView().refresh();
+ normalGrid.getView().refresh();
+ }
+ }
+});
+
+
+Ext.define('Ext.grid.Scroller', {
+ extend: 'Ext.Component',
+ alias: 'widget.gridscroller',
+ weight: 110,
+ cls: Ext.baseCSSPrefix + 'scroller',
+ focusable: false,
+
+ renderTpl: ['<div class="' + Ext.baseCSSPrefix + 'stretcher"></div>'],
+
+ initComponent: function() {
+ var me = this,
+ dock = me.dock,
+ cls = Ext.baseCSSPrefix + 'scroller-vertical',
+ sizeProp = 'width',
+
+
+
+
+
+ scrollbarWidth = Ext.getScrollBarWidth() + (Ext.isIE ? 1 : -1);
+
+ me.offsets = {bottom: 0};
+
+ if (dock === 'top' || dock === 'bottom') {
+ cls = Ext.baseCSSPrefix + 'scroller-horizontal';
+ sizeProp = 'height';
+ }
+ me[sizeProp] = scrollbarWidth;
+
+ me.cls += (' ' + cls);
+
+ Ext.applyIf(me.renderSelectors, {
+ stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher'
+ });
+ me.callParent();
+ },
+
+
+ afterRender: function() {
+ var me = this;
+ me.callParent();
+ me.ownerCt.on('afterlayout', me.onOwnerAfterLayout, me);
+ me.mon(me.el, 'scroll', me.onElScroll, me);
+ Ext.cache[me.el.id].skipGarbageCollection = true;
+ },
+
+ getSizeCalculation: function() {
+ var owner = this.getPanel(),
+ dock = this.dock,
+ elDom = this.el.dom,
+ width = 1,
+ height = 1,
+ view, tbl;
+
+ if (dock === 'top' || dock === 'bottom') {
+
+
+ var items = owner.query('tableview'),
+ center = items[1] || items[0];
+
+ if (!center) {
+ return false;
+ }
+
+
+
+ width = center.headerCt.getFullWidth();
+
+ if (Ext.isIEQuirks) {
+ width--;
+ }
+
+ width--;
+ } else {
+ view = owner.down('tableview:not([lockableInjected])');
+ if (!view) {
+ return false;
+ }
+ tbl = view.el;
+ if (!tbl) {
+ return false;
+ }
+
+
+
+ height = tbl.dom.scrollHeight;
+ }
+ if (isNaN(width)) {
+ width = 1;
+ }
+ if (isNaN(height)) {
+ height = 1;
+ }
+ return {
+ width: width,
+ height: height
+ };
+ },
+
+ invalidate: function(firstPass) {
+ if (!this.stretchEl || !this.ownerCt) {
+ return;
+ }
+ var size = this.getSizeCalculation(),
+ elDom = this.el.dom;
+ if (size) {
+ this.stretchEl.setSize(size);
+
+
+
+ elDom.scrollTop = elDom.scrollTop;