ext-all-debug.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:1167k
源码类别:

JavaScript

开发平台:

JavaScript

  1.     
  2.     b4Drag: function(e) {
  3.         this.setDragElPos(e.getPageX(),
  4.                             e.getPageY());
  5.     },
  6.     toString: function() {
  7.         return ("DD " + this.id);
  8.     }
  9.     
  10.     
  11.     
  12.     
  13. });
  14. Ext.dd.DDProxy = function(id, sGroup, config) {
  15.     if (id) {
  16.         this.init(id, sGroup, config);
  17.         this.initFrame();
  18.     }
  19. };
  20. Ext.dd.DDProxy.dragElId = "ygddfdiv";
  21. Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
  22.     
  23.     resizeFrame: true,
  24.     
  25.     centerFrame: false,
  26.     
  27.     createFrame: function() {
  28.         var self = this;
  29.         var body = document.body;
  30.         if (!body || !body.firstChild) {
  31.             setTimeout( function() { self.createFrame(); }, 50 );
  32.             return;
  33.         }
  34.         var div = this.getDragEl();
  35.         if (!div) {
  36.             div    = document.createElement("div");
  37.             div.id = this.dragElId;
  38.             var s  = div.style;
  39.             s.position   = "absolute";
  40.             s.visibility = "hidden";
  41.             s.cursor     = "move";
  42.             s.border     = "2px solid #aaa";
  43.             s.zIndex     = 999;
  44.             
  45.             
  46.             
  47.             body.insertBefore(div, body.firstChild);
  48.         }
  49.     },
  50.     
  51.     initFrame: function() {
  52.         this.createFrame();
  53.     },
  54.     applyConfig: function() {
  55.         Ext.dd.DDProxy.superclass.applyConfig.call(this);
  56.         this.resizeFrame = (this.config.resizeFrame !== false);
  57.         this.centerFrame = (this.config.centerFrame);
  58.         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
  59.     },
  60.     
  61.     showFrame: function(iPageX, iPageY) {
  62.         var el = this.getEl();
  63.         var dragEl = this.getDragEl();
  64.         var s = dragEl.style;
  65.         this._resizeProxy();
  66.         if (this.centerFrame) {
  67.             this.setDelta( Math.round(parseInt(s.width,  10)/2),
  68.                            Math.round(parseInt(s.height, 10)/2) );
  69.         }
  70.         this.setDragElPos(iPageX, iPageY);
  71.         Ext.fly(dragEl).show();
  72.     },
  73.     
  74.     _resizeProxy: function() {
  75.         if (this.resizeFrame) {
  76.             var el = this.getEl();
  77.             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
  78.         }
  79.     },
  80.     
  81.     b4MouseDown: function(e) {
  82.         var x = e.getPageX();
  83.         var y = e.getPageY();
  84.         this.autoOffset(x, y);
  85.         this.setDragElPos(x, y);
  86.     },
  87.     
  88.     b4StartDrag: function(x, y) {
  89.         
  90.         this.showFrame(x, y);
  91.     },
  92.     
  93.     b4EndDrag: function(e) {
  94.         Ext.fly(this.getDragEl()).hide();
  95.     },
  96.     
  97.     
  98.     
  99.     endDrag: function(e) {
  100.         var lel = this.getEl();
  101.         var del = this.getDragEl();
  102.         
  103.         del.style.visibility = "";
  104.         this.beforeMove();
  105.         
  106.         
  107.         lel.style.visibility = "hidden";
  108.         Ext.dd.DDM.moveToEl(lel, del);
  109.         del.style.visibility = "hidden";
  110.         lel.style.visibility = "";
  111.         this.afterDrag();
  112.     },
  113.     beforeMove : function(){
  114.     },
  115.     afterDrag : function(){
  116.     },
  117.     toString: function() {
  118.         return ("DDProxy " + this.id);
  119.     }
  120. });
  121. Ext.dd.DDTarget = function(id, sGroup, config) {
  122.     if (id) {
  123.         this.initTarget(id, sGroup, config);
  124.     }
  125. };
  126. Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
  127.     
  128.     getDragEl: Ext.emptyFn,
  129.     
  130.     isValidHandleChild: Ext.emptyFn,
  131.     
  132.     startDrag: Ext.emptyFn,
  133.     
  134.     endDrag: Ext.emptyFn,
  135.     
  136.     onDrag: Ext.emptyFn,
  137.     
  138.     onDragDrop: Ext.emptyFn,
  139.     
  140.     onDragEnter: Ext.emptyFn,
  141.     
  142.     onDragOut: Ext.emptyFn,
  143.     
  144.     onDragOver: Ext.emptyFn,
  145.     
  146.     onInvalidDrop: Ext.emptyFn,
  147.     
  148.     onMouseDown: Ext.emptyFn,
  149.     
  150.     onMouseUp: Ext.emptyFn,
  151.     
  152.     setXConstraint: Ext.emptyFn,
  153.     
  154.     setYConstraint: Ext.emptyFn,
  155.     
  156.     resetConstraints: Ext.emptyFn,
  157.     
  158.     clearConstraints: Ext.emptyFn,
  159.     
  160.     clearTicks: Ext.emptyFn,
  161.     
  162.     setInitPosition: Ext.emptyFn,
  163.     
  164.     setDragElId: Ext.emptyFn,
  165.     
  166.     setHandleElId: Ext.emptyFn,
  167.     
  168.     setOuterHandleElId: Ext.emptyFn,
  169.     
  170.     addInvalidHandleClass: Ext.emptyFn,
  171.     
  172.     addInvalidHandleId: Ext.emptyFn,
  173.     
  174.     addInvalidHandleType: Ext.emptyFn,
  175.     
  176.     removeInvalidHandleClass: Ext.emptyFn,
  177.     
  178.     removeInvalidHandleId: Ext.emptyFn,
  179.     
  180.     removeInvalidHandleType: Ext.emptyFn,
  181.     toString: function() {
  182.         return ("DDTarget " + this.id);
  183.     }
  184. });
  185. Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {
  186.     
  187.     active: false,
  188.     
  189.     tolerance: 5,
  190.     
  191.     autoStart: false,
  192.     
  193.     constructor : function(config){
  194.         Ext.apply(this, config);
  195.     this.addEvents(
  196.         
  197.         'mousedown',
  198.         
  199.         'mouseup',
  200.         
  201.         'mousemove',
  202.         
  203.         'dragstart',
  204.         
  205.         'dragend',
  206.         
  207.         'drag'
  208.     );
  209.     this.dragRegion = new Ext.lib.Region(0,0,0,0);
  210.     if(this.el){
  211.         this.initEl(this.el);
  212.     }
  213.         Ext.dd.DragTracker.superclass.constructor.call(this, config);
  214.     },
  215.     initEl: function(el){
  216.         this.el = Ext.get(el);
  217.         el.on('mousedown', this.onMouseDown, this,
  218.                 this.delegate ? {delegate: this.delegate} : undefined);
  219.     },
  220.     destroy : function(){
  221.         this.el.un('mousedown', this.onMouseDown, this);
  222.     },
  223.     onMouseDown: function(e, target){
  224.         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
  225.             this.startXY = this.lastXY = e.getXY();
  226.             this.dragTarget = this.delegate ? target : this.el.dom;
  227.             if(this.preventDefault !== false){
  228.                 e.preventDefault();
  229.             }
  230.             var doc = Ext.getDoc();
  231.             doc.on('mouseup', this.onMouseUp, this);
  232.             doc.on('mousemove', this.onMouseMove, this);
  233.             doc.on('selectstart', this.stopSelect, this);
  234.             if(this.autoStart){
  235.                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
  236.             }
  237.         }
  238.     },
  239.     onMouseMove: function(e, target){
  240.         
  241.         if(this.active && Ext.isIE && !e.browserEvent.button){
  242.             e.preventDefault();
  243.             this.onMouseUp(e);
  244.             return;
  245.         }
  246.         e.preventDefault();
  247.         var xy = e.getXY(), s = this.startXY;
  248.         this.lastXY = xy;
  249.         if(!this.active){
  250.             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
  251.                 this.triggerStart();
  252.             }else{
  253.                 return;
  254.             }
  255.         }
  256.         this.fireEvent('mousemove', this, e);
  257.         this.onDrag(e);
  258.         this.fireEvent('drag', this, e);
  259.     },
  260.     onMouseUp: function(e){
  261.         var doc = Ext.getDoc();
  262.         doc.un('mousemove', this.onMouseMove, this);
  263.         doc.un('mouseup', this.onMouseUp, this);
  264.         doc.un('selectstart', this.stopSelect, this);
  265.         e.preventDefault();
  266.         this.clearStart();
  267.         var wasActive = this.active;
  268.         this.active = false;
  269.         delete this.elRegion;
  270.         this.fireEvent('mouseup', this, e);
  271.         if(wasActive){
  272.             this.onEnd(e);
  273.             this.fireEvent('dragend', this, e);
  274.         }
  275.     },
  276.     triggerStart: function(isTimer){
  277.         this.clearStart();
  278.         this.active = true;
  279.         this.onStart(this.startXY);
  280.         this.fireEvent('dragstart', this, this.startXY);
  281.     },
  282.     clearStart : function(){
  283.         if(this.timer){
  284.             clearTimeout(this.timer);
  285.             delete this.timer;
  286.         }
  287.     },
  288.     stopSelect : function(e){
  289.         e.stopEvent();
  290.         return false;
  291.     },
  292.     onBeforeStart : function(e){
  293.     },
  294.     onStart : function(xy){
  295.     },
  296.     onDrag : function(e){
  297.     },
  298.     onEnd : function(e){
  299.     },
  300.     getDragTarget : function(){
  301.         return this.dragTarget;
  302.     },
  303.     getDragCt : function(){
  304.         return this.el;
  305.     },
  306.     getXY : function(constrain){
  307.         return constrain ?
  308.                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
  309.     },
  310.     getOffset : function(constrain){
  311.         var xy = this.getXY(constrain);
  312.         var s = this.startXY;
  313.         return [s[0]-xy[0], s[1]-xy[1]];
  314.     },
  315.     constrainModes: {
  316.         'point' : function(xy){
  317.             if(!this.elRegion){
  318.                 this.elRegion = this.getDragCt().getRegion();
  319.             }
  320.             var dr = this.dragRegion;
  321.             dr.left = xy[0];
  322.             dr.top = xy[1];
  323.             dr.right = xy[0];
  324.             dr.bottom = xy[1];
  325.             dr.constrainTo(this.elRegion);
  326.             return [dr.left, dr.top];
  327.         }
  328.     }
  329. });
  330. Ext.dd.ScrollManager = function(){
  331.     var ddm = Ext.dd.DragDropMgr;
  332.     var els = {};
  333.     var dragEl = null;
  334.     var proc = {};
  335.     
  336.     var onStop = function(e){
  337.         dragEl = null;
  338.         clearProc();
  339.     };
  340.     
  341.     var triggerRefresh = function(){
  342.         if(ddm.dragCurrent){
  343.              ddm.refreshCache(ddm.dragCurrent.groups);
  344.         }
  345.     };
  346.     
  347.     var doScroll = function(){
  348.         if(ddm.dragCurrent){
  349.             var dds = Ext.dd.ScrollManager;
  350.             var inc = proc.el.ddScrollConfig ?
  351.                       proc.el.ddScrollConfig.increment : dds.increment;
  352.             if(!dds.animate){
  353.                 if(proc.el.scroll(proc.dir, inc)){
  354.                     triggerRefresh();
  355.                 }
  356.             }else{
  357.                 proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
  358.             }
  359.         }
  360.     };
  361.     
  362.     var clearProc = function(){
  363.         if(proc.id){
  364.             clearInterval(proc.id);
  365.         }
  366.         proc.id = 0;
  367.         proc.el = null;
  368.         proc.dir = "";
  369.     };
  370.     
  371.     var startProc = function(el, dir){
  372.         clearProc();
  373.         proc.el = el;
  374.         proc.dir = dir;
  375.         var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
  376.                 el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
  377.         proc.id = setInterval(doScroll, freq);
  378.     };
  379.     
  380.     var onFire = function(e, isDrop){
  381.         if(isDrop || !ddm.dragCurrent){ return; }
  382.         var dds = Ext.dd.ScrollManager;
  383.         if(!dragEl || dragEl != ddm.dragCurrent){
  384.             dragEl = ddm.dragCurrent;
  385.             
  386.             dds.refreshCache();
  387.         }
  388.         
  389.         var xy = Ext.lib.Event.getXY(e);
  390.         var pt = new Ext.lib.Point(xy[0], xy[1]);
  391.         for(var id in els){
  392.             var el = els[id], r = el._region;
  393.             var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
  394.             if(r && r.contains(pt) && el.isScrollable()){
  395.                 if(r.bottom - pt.y <= c.vthresh){
  396.                     if(proc.el != el){
  397.                         startProc(el, "down");
  398.                     }
  399.                     return;
  400.                 }else if(r.right - pt.x <= c.hthresh){
  401.                     if(proc.el != el){
  402.                         startProc(el, "left");
  403.                     }
  404.                     return;
  405.                 }else if(pt.y - r.top <= c.vthresh){
  406.                     if(proc.el != el){
  407.                         startProc(el, "up");
  408.                     }
  409.                     return;
  410.                 }else if(pt.x - r.left <= c.hthresh){
  411.                     if(proc.el != el){
  412.                         startProc(el, "right");
  413.                     }
  414.                     return;
  415.                 }
  416.             }
  417.         }
  418.         clearProc();
  419.     };
  420.     
  421.     ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
  422.     ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
  423.     
  424.     return {
  425.         
  426.         register : function(el){
  427.             if(Ext.isArray(el)){
  428.                 for(var i = 0, len = el.length; i < len; i++) {
  429.                  this.register(el[i]);
  430.                 }
  431.             }else{
  432.                 el = Ext.get(el);
  433.                 els[el.id] = el;
  434.             }
  435.         },
  436.         
  437.         
  438.         unregister : function(el){
  439.             if(Ext.isArray(el)){
  440.                 for(var i = 0, len = el.length; i < len; i++) {
  441.                  this.unregister(el[i]);
  442.                 }
  443.             }else{
  444.                 el = Ext.get(el);
  445.                 delete els[el.id];
  446.             }
  447.         },
  448.         
  449.         
  450.         vthresh : 25,
  451.         
  452.         hthresh : 25,
  453.         
  454.         increment : 100,
  455.         
  456.         
  457.         frequency : 500,
  458.         
  459.         
  460.         animate: true,
  461.         
  462.         
  463.         animDuration: .4,
  464.         
  465.         
  466.         refreshCache : function(){
  467.             for(var id in els){
  468.                 if(typeof els[id] == 'object'){ 
  469.                     els[id]._region = els[id].getRegion();
  470.                 }
  471.             }
  472.         }
  473.     };
  474. }();
  475. Ext.dd.Registry = function(){
  476.     var elements = {}; 
  477.     var handles = {}; 
  478.     var autoIdSeed = 0;
  479.     var getId = function(el, autogen){
  480.         if(typeof el == "string"){
  481.             return el;
  482.         }
  483.         var id = el.id;
  484.         if(!id && autogen !== false){
  485.             id = "extdd-" + (++autoIdSeed);
  486.             el.id = id;
  487.         }
  488.         return id;
  489.     };
  490.     
  491.     return {
  492.     
  493.         register : function(el, data){
  494.             data = data || {};
  495.             if(typeof el == "string"){
  496.                 el = document.getElementById(el);
  497.             }
  498.             data.ddel = el;
  499.             elements[getId(el)] = data;
  500.             if(data.isHandle !== false){
  501.                 handles[data.ddel.id] = data;
  502.             }
  503.             if(data.handles){
  504.                 var hs = data.handles;
  505.                 for(var i = 0, len = hs.length; i < len; i++){
  506.                  handles[getId(hs[i])] = data;
  507.                 }
  508.             }
  509.         },
  510.     
  511.         unregister : function(el){
  512.             var id = getId(el, false);
  513.             var data = elements[id];
  514.             if(data){
  515.                 delete elements[id];
  516.                 if(data.handles){
  517.                     var hs = data.handles;
  518.                     for(var i = 0, len = hs.length; i < len; i++){
  519.                      delete handles[getId(hs[i], false)];
  520.                     }
  521.                 }
  522.             }
  523.         },
  524.     
  525.         getHandle : function(id){
  526.             if(typeof id != "string"){ 
  527.                 id = id.id;
  528.             }
  529.             return handles[id];
  530.         },
  531.     
  532.         getHandleFromEvent : function(e){
  533.             var t = Ext.lib.Event.getTarget(e);
  534.             return t ? handles[t.id] : null;
  535.         },
  536.     
  537.         getTarget : function(id){
  538.             if(typeof id != "string"){ 
  539.                 id = id.id;
  540.             }
  541.             return elements[id];
  542.         },
  543.     
  544.         getTargetFromEvent : function(e){
  545.             var t = Ext.lib.Event.getTarget(e);
  546.             return t ? elements[t.id] || handles[t.id] : null;
  547.         }
  548.     };
  549. }();
  550. Ext.dd.StatusProxy = function(config){
  551.     Ext.apply(this, config);
  552.     this.id = this.id || Ext.id();
  553.     this.el = new Ext.Layer({
  554.         dh: {
  555.             id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
  556.                 {tag: "div", cls: "x-dd-drop-icon"},
  557.                 {tag: "div", cls: "x-dd-drag-ghost"}
  558.             ]
  559.         }, 
  560.         shadow: !config || config.shadow !== false
  561.     });
  562.     this.ghost = Ext.get(this.el.dom.childNodes[1]);
  563.     this.dropStatus = this.dropNotAllowed;
  564. };
  565. Ext.dd.StatusProxy.prototype = {
  566.     
  567.     dropAllowed : "x-dd-drop-ok",
  568.     
  569.     dropNotAllowed : "x-dd-drop-nodrop",
  570.     
  571.     setStatus : function(cssClass){
  572.         cssClass = cssClass || this.dropNotAllowed;
  573.         if(this.dropStatus != cssClass){
  574.             this.el.replaceClass(this.dropStatus, cssClass);
  575.             this.dropStatus = cssClass;
  576.         }
  577.     },
  578.     
  579.     reset : function(clearGhost){
  580.         this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
  581.         this.dropStatus = this.dropNotAllowed;
  582.         if(clearGhost){
  583.             this.ghost.update("");
  584.         }
  585.     },
  586.     
  587.     update : function(html){
  588.         if(typeof html == "string"){
  589.             this.ghost.update(html);
  590.         }else{
  591.             this.ghost.update("");
  592.             html.style.margin = "0";
  593.             this.ghost.dom.appendChild(html);
  594.         }
  595.         var el = this.ghost.dom.firstChild; 
  596.         if(el){
  597.             Ext.fly(el).setStyle('float', 'none');
  598.         }
  599.     },
  600.     
  601.     getEl : function(){
  602.         return this.el;
  603.     },
  604.     
  605.     getGhost : function(){
  606.         return this.ghost;
  607.     },
  608.     
  609.     hide : function(clear){
  610.         this.el.hide();
  611.         if(clear){
  612.             this.reset(true);
  613.         }
  614.     },
  615.     
  616.     stop : function(){
  617.         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
  618.             this.anim.stop();
  619.         }
  620.     },
  621.     
  622.     show : function(){
  623.         this.el.show();
  624.     },
  625.     
  626.     sync : function(){
  627.         this.el.sync();
  628.     },
  629.     
  630.     repair : function(xy, callback, scope){
  631.         this.callback = callback;
  632.         this.scope = scope;
  633.         if(xy && this.animRepair !== false){
  634.             this.el.addClass("x-dd-drag-repair");
  635.             this.el.hideUnders(true);
  636.             this.anim = this.el.shift({
  637.                 duration: this.repairDuration || .5,
  638.                 easing: 'easeOut',
  639.                 xy: xy,
  640.                 stopFx: true,
  641.                 callback: this.afterRepair,
  642.                 scope: this
  643.             });
  644.         }else{
  645.             this.afterRepair();
  646.         }
  647.     },
  648.     
  649.     afterRepair : function(){
  650.         this.hide(true);
  651.         if(typeof this.callback == "function"){
  652.             this.callback.call(this.scope || this);
  653.         }
  654.         this.callback = null;
  655.         this.scope = null;
  656.     },
  657.     
  658.     destroy: function(){
  659.         Ext.destroy(this.ghost, this.el);    
  660.     }
  661. };
  662. Ext.dd.DragSource = function(el, config){
  663.     this.el = Ext.get(el);
  664.     if(!this.dragData){
  665.         this.dragData = {};
  666.     }
  667.     
  668.     Ext.apply(this, config);
  669.     
  670.     if(!this.proxy){
  671.         this.proxy = new Ext.dd.StatusProxy();
  672.     }
  673.     Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
  674.           {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
  675.     
  676.     this.dragging = false;
  677. };
  678. Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
  679.     
  680.     
  681.     dropAllowed : "x-dd-drop-ok",
  682.     
  683.     dropNotAllowed : "x-dd-drop-nodrop",
  684.     
  685.     getDragData : function(e){
  686.         return this.dragData;
  687.     },
  688.     
  689.     onDragEnter : function(e, id){
  690.         var target = Ext.dd.DragDropMgr.getDDById(id);
  691.         this.cachedTarget = target;
  692.         if(this.beforeDragEnter(target, e, id) !== false){
  693.             if(target.isNotifyTarget){
  694.                 var status = target.notifyEnter(this, e, this.dragData);
  695.                 this.proxy.setStatus(status);
  696.             }else{
  697.                 this.proxy.setStatus(this.dropAllowed);
  698.             }
  699.             
  700.             if(this.afterDragEnter){
  701.                 
  702.                 this.afterDragEnter(target, e, id);
  703.             }
  704.         }
  705.     },
  706.     
  707.     beforeDragEnter : function(target, e, id){
  708.         return true;
  709.     },
  710.     
  711.     alignElWithMouse: function() {
  712.         Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
  713.         this.proxy.sync();
  714.     },
  715.     
  716.     onDragOver : function(e, id){
  717.         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
  718.         if(this.beforeDragOver(target, e, id) !== false){
  719.             if(target.isNotifyTarget){
  720.                 var status = target.notifyOver(this, e, this.dragData);
  721.                 this.proxy.setStatus(status);
  722.             }
  723.             if(this.afterDragOver){
  724.                 
  725.                 this.afterDragOver(target, e, id);
  726.             }
  727.         }
  728.     },
  729.     
  730.     beforeDragOver : function(target, e, id){
  731.         return true;
  732.     },
  733.     
  734.     onDragOut : function(e, id){
  735.         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
  736.         if(this.beforeDragOut(target, e, id) !== false){
  737.             if(target.isNotifyTarget){
  738.                 target.notifyOut(this, e, this.dragData);
  739.             }
  740.             this.proxy.reset();
  741.             if(this.afterDragOut){
  742.                 
  743.                 this.afterDragOut(target, e, id);
  744.             }
  745.         }
  746.         this.cachedTarget = null;
  747.     },
  748.     
  749.     beforeDragOut : function(target, e, id){
  750.         return true;
  751.     },
  752.     
  753.     
  754.     onDragDrop : function(e, id){
  755.         var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
  756.         if(this.beforeDragDrop(target, e, id) !== false){
  757.             if(target.isNotifyTarget){
  758.                 if(target.notifyDrop(this, e, this.dragData)){ 
  759.                     this.onValidDrop(target, e, id);
  760.                 }else{
  761.                     this.onInvalidDrop(target, e, id);
  762.                 }
  763.             }else{
  764.                 this.onValidDrop(target, e, id);
  765.             }
  766.             
  767.             if(this.afterDragDrop){
  768.                 
  769.                 this.afterDragDrop(target, e, id);
  770.             }
  771.         }
  772.         delete this.cachedTarget;
  773.     },
  774.     
  775.     beforeDragDrop : function(target, e, id){
  776.         return true;
  777.     },
  778.     
  779.     onValidDrop : function(target, e, id){
  780.         this.hideProxy();
  781.         if(this.afterValidDrop){
  782.             
  783.             this.afterValidDrop(target, e, id);
  784.         }
  785.     },
  786.     
  787.     getRepairXY : function(e, data){
  788.         return this.el.getXY();  
  789.     },
  790.     
  791.     onInvalidDrop : function(target, e, id){
  792.         this.beforeInvalidDrop(target, e, id);
  793.         if(this.cachedTarget){
  794.             if(this.cachedTarget.isNotifyTarget){
  795.                 this.cachedTarget.notifyOut(this, e, this.dragData);
  796.             }
  797.             this.cacheTarget = null;
  798.         }
  799.         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
  800.         if(this.afterInvalidDrop){
  801.             
  802.             this.afterInvalidDrop(e, id);
  803.         }
  804.     },
  805.     
  806.     afterRepair : function(){
  807.         if(Ext.enableFx){
  808.             this.el.highlight(this.hlColor || "c3daf9");
  809.         }
  810.         this.dragging = false;
  811.     },
  812.     
  813.     beforeInvalidDrop : function(target, e, id){
  814.         return true;
  815.     },
  816.     
  817.     handleMouseDown : function(e){
  818.         if(this.dragging) {
  819.             return;
  820.         }
  821.         var data = this.getDragData(e);
  822.         if(data && this.onBeforeDrag(data, e) !== false){
  823.             this.dragData = data;
  824.             this.proxy.stop();
  825.             Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
  826.         } 
  827.     },
  828.     
  829.     onBeforeDrag : function(data, e){
  830.         return true;
  831.     },
  832.     
  833.     onStartDrag : Ext.emptyFn,
  834.     
  835.     startDrag : function(x, y){
  836.         this.proxy.reset();
  837.         this.dragging = true;
  838.         this.proxy.update("");
  839.         this.onInitDrag(x, y);
  840.         this.proxy.show();
  841.     },
  842.     
  843.     onInitDrag : function(x, y){
  844.         var clone = this.el.dom.cloneNode(true);
  845.         clone.id = Ext.id(); 
  846.         this.proxy.update(clone);
  847.         this.onStartDrag(x, y);
  848.         return true;
  849.     },
  850.     
  851.     getProxy : function(){
  852.         return this.proxy;  
  853.     },
  854.     
  855.     hideProxy : function(){
  856.         this.proxy.hide();  
  857.         this.proxy.reset(true);
  858.         this.dragging = false;
  859.     },
  860.     
  861.     triggerCacheRefresh : function(){
  862.         Ext.dd.DDM.refreshCache(this.groups);
  863.     },
  864.     
  865.     b4EndDrag: function(e) {
  866.     },
  867.     
  868.     endDrag : function(e){
  869.         this.onEndDrag(this.dragData, e);
  870.     },
  871.     
  872.     onEndDrag : function(data, e){
  873.     },
  874.     
  875.     
  876.     autoOffset : function(x, y) {
  877.         this.setDelta(-12, -20);
  878.     },
  879.     
  880.     destroy: function(){
  881.         Ext.dd.DragSource.superclass.destroy.call(this);
  882.         Ext.destroy(this.proxy);
  883.     }
  884. });
  885. Ext.dd.DropTarget = function(el, config){
  886.     this.el = Ext.get(el);
  887.     
  888.     Ext.apply(this, config);
  889.     
  890.     if(this.containerScroll){
  891.         Ext.dd.ScrollManager.register(this.el);
  892.     }
  893.     
  894.     Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
  895.           {isTarget: true});
  896. };
  897. Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
  898.     
  899.     
  900.     
  901.     dropAllowed : "x-dd-drop-ok",
  902.     
  903.     dropNotAllowed : "x-dd-drop-nodrop",
  904.     
  905.     isTarget : true,
  906.     
  907.     isNotifyTarget : true,
  908.     
  909.     notifyEnter : function(dd, e, data){
  910.         if(this.overClass){
  911.             this.el.addClass(this.overClass);
  912.         }
  913.         return this.dropAllowed;
  914.     },
  915.     
  916.     notifyOver : function(dd, e, data){
  917.         return this.dropAllowed;
  918.     },
  919.     
  920.     notifyOut : function(dd, e, data){
  921.         if(this.overClass){
  922.             this.el.removeClass(this.overClass);
  923.         }
  924.     },
  925.     
  926.     notifyDrop : function(dd, e, data){
  927.         return false;
  928.     }
  929. });
  930. Ext.dd.DragZone = function(el, config){
  931.     Ext.dd.DragZone.superclass.constructor.call(this, el, config);
  932.     if(this.containerScroll){
  933.         Ext.dd.ScrollManager.register(this.el);
  934.     }
  935. };
  936. Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
  937.     
  938.     
  939.     
  940.     
  941.     getDragData : function(e){
  942.         return Ext.dd.Registry.getHandleFromEvent(e);
  943.     },
  944.     
  945.     
  946.     onInitDrag : function(x, y){
  947.         this.proxy.update(this.dragData.ddel.cloneNode(true));
  948.         this.onStartDrag(x, y);
  949.         return true;
  950.     },
  951.     
  952.     
  953.     afterRepair : function(){
  954.         if(Ext.enableFx){
  955.             Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
  956.         }
  957.         this.dragging = false;
  958.     },
  959.     
  960.     getRepairXY : function(e){
  961.         return Ext.Element.fly(this.dragData.ddel).getXY();  
  962.     }
  963. });
  964. Ext.dd.DropZone = function(el, config){
  965.     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
  966. };
  967. Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
  968.     
  969.     getTargetFromEvent : function(e){
  970.         return Ext.dd.Registry.getTargetFromEvent(e);
  971.     },
  972.     
  973.     onNodeEnter : function(n, dd, e, data){
  974.         
  975.     },
  976.     
  977.     onNodeOver : function(n, dd, e, data){
  978.         return this.dropAllowed;
  979.     },
  980.     
  981.     onNodeOut : function(n, dd, e, data){
  982.         
  983.     },
  984.     
  985.     onNodeDrop : function(n, dd, e, data){
  986.         return false;
  987.     },
  988.     
  989.     onContainerOver : function(dd, e, data){
  990.         return this.dropNotAllowed;
  991.     },
  992.     
  993.     onContainerDrop : function(dd, e, data){
  994.         return false;
  995.     },
  996.     
  997.     notifyEnter : function(dd, e, data){
  998.         return this.dropNotAllowed;
  999.     },
  1000.     
  1001.     notifyOver : function(dd, e, data){
  1002.         var n = this.getTargetFromEvent(e);
  1003.         if(!n){ 
  1004.             if(this.lastOverNode){
  1005.                 this.onNodeOut(this.lastOverNode, dd, e, data);
  1006.                 this.lastOverNode = null;
  1007.             }
  1008.             return this.onContainerOver(dd, e, data);
  1009.         }
  1010.         if(this.lastOverNode != n){
  1011.             if(this.lastOverNode){
  1012.                 this.onNodeOut(this.lastOverNode, dd, e, data);
  1013.             }
  1014.             this.onNodeEnter(n, dd, e, data);
  1015.             this.lastOverNode = n;
  1016.         }
  1017.         return this.onNodeOver(n, dd, e, data);
  1018.     },
  1019.     
  1020.     notifyOut : function(dd, e, data){
  1021.         if(this.lastOverNode){
  1022.             this.onNodeOut(this.lastOverNode, dd, e, data);
  1023.             this.lastOverNode = null;
  1024.         }
  1025.     },
  1026.     
  1027.     notifyDrop : function(dd, e, data){
  1028.         if(this.lastOverNode){
  1029.             this.onNodeOut(this.lastOverNode, dd, e, data);
  1030.             this.lastOverNode = null;
  1031.         }
  1032.         var n = this.getTargetFromEvent(e);
  1033.         return n ?
  1034.             this.onNodeDrop(n, dd, e, data) :
  1035.             this.onContainerDrop(dd, e, data);
  1036.     },
  1037.     
  1038.     triggerCacheRefresh : function(){
  1039.         Ext.dd.DDM.refreshCache(this.groups);
  1040.     }  
  1041. });
  1042. Ext.Element.addMethods({
  1043.     
  1044.     initDD : function(group, config, overrides){
  1045.         var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
  1046.         return Ext.apply(dd, overrides);
  1047.     },
  1048.     
  1049.     initDDProxy : function(group, config, overrides){
  1050.         var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
  1051.         return Ext.apply(dd, overrides);
  1052.     },
  1053.     
  1054.     initDDTarget : function(group, config, overrides){
  1055.         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
  1056.         return Ext.apply(dd, overrides);
  1057.     }
  1058. });
  1059. Ext.data.Api = (function() {
  1060.     
  1061.     
  1062.     
  1063.     
  1064.     var validActions = {};
  1065.     return {
  1066.         
  1067.         actions : {
  1068.             create  : 'create',
  1069.             read    : 'read',
  1070.             update  : 'update',
  1071.             destroy : 'destroy'
  1072.         },
  1073.         
  1074.         restActions : {
  1075.             create  : 'POST',
  1076.             read    : 'GET',
  1077.             update  : 'PUT',
  1078.             destroy : 'DELETE'
  1079.         },
  1080.         
  1081.         isAction : function(action) {
  1082.             return (Ext.data.Api.actions[action]) ? true : false;
  1083.         },
  1084.         
  1085.         getVerb : function(name) {
  1086.             if (validActions[name]) {
  1087.                 return validActions[name];  
  1088.             }
  1089.             for (var verb in this.actions) {
  1090.                 if (this.actions[verb] === name) {
  1091.                     validActions[name] = verb;
  1092.                     break;
  1093.                 }
  1094.             }
  1095.             return (validActions[name] !== undefined) ? validActions[name] : null;
  1096.         },
  1097.         
  1098.         isValid : function(api){
  1099.             var invalid = [];
  1100.             var crud = this.actions; 
  1101.             for (var action in api) {
  1102.                 if (!(action in crud)) {
  1103.                     invalid.push(action);
  1104.                 }
  1105.             }
  1106.             return (!invalid.length) ? true : invalid;
  1107.         },
  1108.         
  1109.         hasUniqueUrl : function(proxy, verb) {
  1110.             var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
  1111.             var unique = true;
  1112.             for (var action in proxy.api) {
  1113.                 if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
  1114.                     break;
  1115.                 }
  1116.             }
  1117.             return unique;
  1118.         },
  1119.         
  1120.         prepare : function(proxy) {
  1121.             if (!proxy.api) {
  1122.                 proxy.api = {}; 
  1123.             }
  1124.             for (var verb in this.actions) {
  1125.                 var action = this.actions[verb];
  1126.                 proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
  1127.                 if (typeof(proxy.api[action]) == 'string') {
  1128.                     proxy.api[action] = {
  1129.                         url: proxy.api[action],
  1130.                         method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
  1131.                     };
  1132.                 }
  1133.             }
  1134.         },
  1135.         
  1136.         restify : function(proxy) {
  1137.             proxy.restful = true;
  1138.             for (var verb in this.restActions) {
  1139.                 proxy.api[this.actions[verb]].method = this.restActions[verb];
  1140.             }
  1141.             
  1142.             
  1143.             proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
  1144.                 var reader = o.reader;
  1145.                 var res = new Ext.data.Response({
  1146.                     action: action,
  1147.                     raw: response
  1148.                 });
  1149.                 switch (response.status) {
  1150.                     case 200:   
  1151.                         return true;
  1152.                         break;
  1153.                     case 201:   
  1154.                         res.success = true;
  1155.                         break;
  1156.                     case 204:  
  1157.                         res.success = true;
  1158.                         res.data = null;
  1159.                         break;
  1160.                     default:
  1161.                         return true;
  1162.                         break;
  1163.                 }
  1164.                 if (res.success === true) {
  1165.                     this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
  1166.                 } else {
  1167.                     this.fireEvent('exception', this, 'remote', action, o, res, rs);
  1168.                 }
  1169.                 o.request.callback.call(o.request.scope, res.data, res, res.success);
  1170.                 return false;   
  1171.             }, proxy);
  1172.         }
  1173.     };
  1174. })();
  1175. Ext.data.Response = function(params, response) {
  1176.     Ext.apply(this, params, {
  1177.         raw: response
  1178.     });
  1179. };
  1180. Ext.data.Response.prototype = {
  1181.     message : null,
  1182.     success : false,
  1183.     status : null,
  1184.     root : null,
  1185.     raw : null,
  1186.     getMessage : function() {
  1187.         return this.message;
  1188.     },
  1189.     getSuccess : function() {
  1190.         return this.success;
  1191.     },
  1192.     getStatus : function() {
  1193.         return this.status
  1194.     },
  1195.     getRoot : function() {
  1196.         return this.root;
  1197.     },
  1198.     getRawResponse : function() {
  1199.         return this.raw;
  1200.     }
  1201. };
  1202. Ext.data.Api.Error = Ext.extend(Ext.Error, {
  1203.     constructor : function(message, arg) {
  1204.         this.arg = arg;
  1205.         Ext.Error.call(this, message);
  1206.     },
  1207.     name: 'Ext.data.Api'
  1208. });
  1209. Ext.apply(Ext.data.Api.Error.prototype, {
  1210.     lang: {
  1211.         'action-url-undefined': 'No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
  1212.         'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
  1213.         'invalid-url': 'Invalid url.  Please review your proxy configuration.',
  1214.         'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
  1215.     }
  1216. });
  1217. Ext.data.SortTypes = {
  1218.     
  1219.     none : function(s){
  1220.         return s;
  1221.     },
  1222.     
  1223.     
  1224.     stripTagsRE : /</?[^>]+>/gi,
  1225.     
  1226.     
  1227.     asText : function(s){
  1228.         return String(s).replace(this.stripTagsRE, "");
  1229.     },
  1230.     
  1231.     
  1232.     asUCText : function(s){
  1233.         return String(s).toUpperCase().replace(this.stripTagsRE, "");
  1234.     },
  1235.     
  1236.     
  1237.     asUCString : function(s) {
  1238.      return String(s).toUpperCase();
  1239.     },
  1240.     
  1241.     
  1242.     asDate : function(s) {
  1243.         if(!s){
  1244.             return 0;
  1245.         }
  1246.         if(Ext.isDate(s)){
  1247.             return s.getTime();
  1248.         }
  1249.      return Date.parse(String(s));
  1250.     },
  1251.     
  1252.     
  1253.     asFloat : function(s) {
  1254.      var val = parseFloat(String(s).replace(/,/g, ""));
  1255.      return isNaN(val) ? 0 : val;
  1256.     },
  1257.     
  1258.     
  1259.     asInt : function(s) {
  1260.         var val = parseInt(String(s).replace(/,/g, ""), 10);
  1261.         return isNaN(val) ? 0 : val;
  1262.     }
  1263. };
  1264. Ext.data.Record = function(data, id){
  1265.     
  1266.     this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
  1267.     this.data = data || {};
  1268. };
  1269. Ext.data.Record.create = function(o){
  1270.     var f = Ext.extend(Ext.data.Record, {});
  1271.     var p = f.prototype;
  1272.     p.fields = new Ext.util.MixedCollection(false, function(field){
  1273.         return field.name;
  1274.     });
  1275.     for(var i = 0, len = o.length; i < len; i++){
  1276.         p.fields.add(new Ext.data.Field(o[i]));
  1277.     }
  1278.     f.getField = function(name){
  1279.         return p.fields.get(name);
  1280.     };
  1281.     return f;
  1282. };
  1283. Ext.data.Record.PREFIX = 'ext-record';
  1284. Ext.data.Record.AUTO_ID = 1;
  1285. Ext.data.Record.EDIT = 'edit';
  1286. Ext.data.Record.REJECT = 'reject';
  1287. Ext.data.Record.COMMIT = 'commit';
  1288. Ext.data.Record.id = function(rec) {
  1289.     rec.phantom = true;
  1290.     return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
  1291. };
  1292. Ext.data.Record.prototype = {
  1293.     
  1294.     
  1295.     
  1296.     
  1297.     
  1298.     
  1299.     dirty : false,
  1300.     editing : false,
  1301.     error : null,
  1302.     
  1303.     modified : null,
  1304.     
  1305.     phantom : false,
  1306.     
  1307.     join : function(store){
  1308.         
  1309.         this.store = store;
  1310.     },
  1311.     
  1312.     set : function(name, value){
  1313.         var encode = Ext.isPrimitive(value) ? String : Ext.encode;
  1314.         if(encode(this.data[name]) == encode(value)) {
  1315.             return;
  1316.         }        
  1317.         this.dirty = true;
  1318.         if(!this.modified){
  1319.             this.modified = {};
  1320.         }
  1321.         if(this.modified[name] === undefined){
  1322.             this.modified[name] = this.data[name];
  1323.         }
  1324.         this.data[name] = value;
  1325.         if(!this.editing){
  1326.             this.afterEdit();
  1327.         }
  1328.     },
  1329.     
  1330.     afterEdit : function(){
  1331.         if(this.store){
  1332.             this.store.afterEdit(this);
  1333.         }
  1334.     },
  1335.     
  1336.     afterReject : function(){
  1337.         if(this.store){
  1338.             this.store.afterReject(this);
  1339.         }
  1340.     },
  1341.     
  1342.     afterCommit : function(){
  1343.         if(this.store){
  1344.             this.store.afterCommit(this);
  1345.         }
  1346.     },
  1347.     
  1348.     get : function(name){
  1349.         return this.data[name];
  1350.     },
  1351.     
  1352.     beginEdit : function(){
  1353.         this.editing = true;
  1354.         this.modified = this.modified || {};
  1355.     },
  1356.     
  1357.     cancelEdit : function(){
  1358.         this.editing = false;
  1359.         delete this.modified;
  1360.     },
  1361.     
  1362.     endEdit : function(){
  1363.         this.editing = false;
  1364.         if(this.dirty){
  1365.             this.afterEdit();
  1366.         }
  1367.     },
  1368.     
  1369.     reject : function(silent){
  1370.         var m = this.modified;
  1371.         for(var n in m){
  1372.             if(typeof m[n] != "function"){
  1373.                 this.data[n] = m[n];
  1374.             }
  1375.         }
  1376.         this.dirty = false;
  1377.         delete this.modified;
  1378.         this.editing = false;
  1379.         if(silent !== true){
  1380.             this.afterReject();
  1381.         }
  1382.     },
  1383.     
  1384.     commit : function(silent){
  1385.         this.dirty = false;
  1386.         delete this.modified;
  1387.         this.editing = false;
  1388.         if(silent !== true){
  1389.             this.afterCommit();
  1390.         }
  1391.     },
  1392.     
  1393.     getChanges : function(){
  1394.         var m = this.modified, cs = {};
  1395.         for(var n in m){
  1396.             if(m.hasOwnProperty(n)){
  1397.                 cs[n] = this.data[n];
  1398.             }
  1399.         }
  1400.         return cs;
  1401.     },
  1402.     
  1403.     hasError : function(){
  1404.         return this.error !== null;
  1405.     },
  1406.     
  1407.     clearError : function(){
  1408.         this.error = null;
  1409.     },
  1410.     
  1411.     copy : function(newId) {
  1412.         return new this.constructor(Ext.apply({}, this.data), newId || this.id);
  1413.     },
  1414.     
  1415.     isModified : function(fieldName){
  1416.         return !!(this.modified && this.modified.hasOwnProperty(fieldName));
  1417.     },
  1418.     
  1419.     isValid : function() {
  1420.         return this.fields.find(function(f) {
  1421.             return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
  1422.         },this) ? false : true;
  1423.     },
  1424.     
  1425.     markDirty : function(){
  1426.         this.dirty = true;
  1427.         if(!this.modified){
  1428.             this.modified = {};
  1429.         }
  1430.         this.fields.each(function(f) {
  1431.             this.modified[f.name] = this.data[f.name];
  1432.         },this);
  1433.     }
  1434. };
  1435. Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
  1436.     
  1437.     
  1438.     register : function(){
  1439.         for(var i = 0, s; (s = arguments[i]); i++){
  1440.             this.add(s);
  1441.         }
  1442.     },
  1443.     
  1444.     unregister : function(){
  1445.         for(var i = 0, s; (s = arguments[i]); i++){
  1446.             this.remove(this.lookup(s));
  1447.         }
  1448.     },
  1449.     
  1450.     lookup : function(id){
  1451.         if(Ext.isArray(id)){
  1452.             var fields = ['field1'], expand = !Ext.isArray(id[0]);
  1453.             if(!expand){
  1454.                 for(var i = 2, len = id[0].length; i <= len; ++i){
  1455.                     fields.push('field' + i);
  1456.                 }
  1457.             }
  1458.             return new Ext.data.ArrayStore({
  1459.                 fields: fields,
  1460.                 data: id,
  1461.                 expandData: expand,
  1462.                 autoDestroy: true,
  1463.                 autoCreated: true
  1464.             });
  1465.         }
  1466.         return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
  1467.     },
  1468.     
  1469.     getKey : function(o){
  1470.          return o.storeId;
  1471.     }
  1472. });
  1473. Ext.data.Store = Ext.extend(Ext.util.Observable, {
  1474.     
  1475.     
  1476.     
  1477.     
  1478.     
  1479.     
  1480.     
  1481.     writer : undefined,
  1482.     
  1483.     
  1484.     
  1485.     remoteSort : false,
  1486.     
  1487.     autoDestroy : false,
  1488.     
  1489.     pruneModifiedRecords : false,
  1490.     
  1491.     lastOptions : null,
  1492.     
  1493.     autoSave : true,
  1494.     
  1495.     batch : true,
  1496.     
  1497.     restful: false,
  1498.     
  1499.     paramNames : undefined,
  1500.     
  1501.     defaultParamNames : {
  1502.         start : 'start',
  1503.         limit : 'limit',
  1504.         sort : 'sort',
  1505.         dir : 'dir'
  1506.     },
  1507.     
  1508.     batchKey : '_ext_batch_',
  1509.     constructor : function(config){
  1510.         this.data = new Ext.util.MixedCollection(false);
  1511.         this.data.getKey = function(o){
  1512.             return o.id;
  1513.         };
  1514.         
  1515.         this.baseParams = {};
  1516.         
  1517.         this.removed = [];
  1518.         if(config && config.data){
  1519.             this.inlineData = config.data;
  1520.             delete config.data;
  1521.         }
  1522.         Ext.apply(this, config);
  1523.         this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
  1524.         if((this.url || this.api) && !this.proxy){
  1525.             this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
  1526.         }
  1527.         
  1528.         if (this.restful === true && this.proxy) {
  1529.             
  1530.             
  1531.             this.batch = false;
  1532.             Ext.data.Api.restify(this.proxy);
  1533.         }
  1534.         if(this.reader){ 
  1535.             if(!this.recordType){
  1536.                 this.recordType = this.reader.recordType;
  1537.             }
  1538.             if(this.reader.onMetaChange){
  1539.                 this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
  1540.             }
  1541.             if (this.writer) { 
  1542.                 if (this.writer instanceof(Ext.data.DataWriter) === false) {    
  1543.                     this.writer = this.buildWriter(this.writer);
  1544.                 }
  1545.                 this.writer.meta = this.reader.meta;
  1546.                 this.pruneModifiedRecords = true;
  1547.             }
  1548.         }
  1549.         
  1550.         if(this.recordType){
  1551.             
  1552.             this.fields = this.recordType.prototype.fields;
  1553.         }
  1554.         this.modified = [];
  1555.         this.addEvents(
  1556.             
  1557.             'datachanged',
  1558.             
  1559.             'metachange',
  1560.             
  1561.             'add',
  1562.             
  1563.             'remove',
  1564.             
  1565.             'update',
  1566.             
  1567.             'clear',
  1568.             
  1569.             'exception',
  1570.             
  1571.             'beforeload',
  1572.             
  1573.             'load',
  1574.             
  1575.             'loadexception',
  1576.             
  1577.             'beforewrite',
  1578.             
  1579.             'write',
  1580.             
  1581.             'beforesave',
  1582.             
  1583.             'save'
  1584.         );
  1585.         if(this.proxy){
  1586.             
  1587.             this.relayEvents(this.proxy,  ['loadexception', 'exception']);
  1588.         }
  1589.         
  1590.         if (this.writer) {
  1591.             this.on({
  1592.                 scope: this,
  1593.                 add: this.createRecords,
  1594.                 remove: this.destroyRecord,
  1595.                 update: this.updateRecord,
  1596.                 clear: this.onClear
  1597.             });
  1598.         }
  1599.         this.sortToggle = {};
  1600.         if(this.sortField){
  1601.             this.setDefaultSort(this.sortField, this.sortDir);
  1602.         }else if(this.sortInfo){
  1603.             this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
  1604.         }
  1605.         Ext.data.Store.superclass.constructor.call(this);
  1606.         if(this.id){
  1607.             this.storeId = this.id;
  1608.             delete this.id;
  1609.         }
  1610.         if(this.storeId){
  1611.             Ext.StoreMgr.register(this);
  1612.         }
  1613.         if(this.inlineData){
  1614.             this.loadData(this.inlineData);
  1615.             delete this.inlineData;
  1616.         }else if(this.autoLoad){
  1617.             this.load.defer(10, this, [
  1618.                 typeof this.autoLoad == 'object' ?
  1619.                     this.autoLoad : undefined]);
  1620.         }
  1621.         
  1622.         this.batchCounter = 0;
  1623.         this.batches = {};
  1624.     },
  1625.     
  1626.     buildWriter : function(config) {
  1627.         var klass = undefined;
  1628.         type = (config.format || 'json').toLowerCase();
  1629.         switch (type) {
  1630.             case 'json':
  1631.                 klass = Ext.data.JsonWriter;
  1632.                 break;
  1633.             case 'xml':
  1634.                 klass = Ext.data.XmlWriter;
  1635.                 break;
  1636.             default:
  1637.                 klass = Ext.data.JsonWriter;
  1638.         }
  1639.         return new klass(config);
  1640.     },
  1641.     
  1642.     destroy : function(){
  1643.         if(!this.isDestroyed){
  1644.             if(this.storeId){
  1645.                 Ext.StoreMgr.unregister(this);
  1646.             }
  1647.             this.clearData();
  1648.             this.data = null;
  1649.             Ext.destroy(this.proxy);
  1650.             this.reader = this.writer = null;
  1651.             this.purgeListeners();
  1652.             this.isDestroyed = true;
  1653.         }
  1654.     },
  1655.     
  1656.     add : function(records){
  1657.         records = [].concat(records);
  1658.         if(records.length < 1){
  1659.             return;
  1660.         }
  1661.         for(var i = 0, len = records.length; i < len; i++){
  1662.             records[i].join(this);
  1663.         }
  1664.         var index = this.data.length;
  1665.         this.data.addAll(records);
  1666.         if(this.snapshot){
  1667.             this.snapshot.addAll(records);
  1668.         }
  1669.         this.fireEvent('add', this, records, index);
  1670.     },
  1671.     
  1672.     addSorted : function(record){
  1673.         var index = this.findInsertIndex(record);
  1674.         this.insert(index, record);
  1675.     },
  1676.     
  1677.     remove : function(record){
  1678.         if(Ext.isArray(record)){
  1679.             Ext.each(record, function(r){
  1680.                 this.remove(r);
  1681.             }, this);
  1682.         }
  1683.         var index = this.data.indexOf(record);
  1684.         if(index > -1){
  1685.             record.join(null);
  1686.             this.data.removeAt(index);
  1687.         }
  1688.         if(this.pruneModifiedRecords){
  1689.             this.modified.remove(record);
  1690.         }
  1691.         if(this.snapshot){
  1692.             this.snapshot.remove(record);
  1693.         }
  1694.         if(index > -1){
  1695.             this.fireEvent('remove', this, record, index);
  1696.         }
  1697.     },
  1698.     
  1699.     removeAt : function(index){
  1700.         this.remove(this.getAt(index));
  1701.     },
  1702.     
  1703.     removeAll : function(silent){
  1704.         var items = [];
  1705.         this.each(function(rec){
  1706.             items.push(rec);
  1707.         });
  1708.         this.clearData();
  1709.         if(this.snapshot){
  1710.             this.snapshot.clear();
  1711.         }
  1712.         if(this.pruneModifiedRecords){
  1713.             this.modified = [];
  1714.         }
  1715.         if (silent !== true) {  
  1716.             this.fireEvent('clear', this, items);
  1717.         }
  1718.     },
  1719.     
  1720.     onClear: function(store, records){
  1721.         Ext.each(records, function(rec, index){
  1722.             this.destroyRecord(this, rec, index);
  1723.         }, this);
  1724.     },
  1725.     
  1726.     insert : function(index, records){
  1727.         records = [].concat(records);
  1728.         for(var i = 0, len = records.length; i < len; i++){
  1729.             this.data.insert(index, records[i]);
  1730.             records[i].join(this);
  1731.         }
  1732.         if(this.snapshot){
  1733.             this.snapshot.addAll(records);
  1734.         }
  1735.         this.fireEvent('add', this, records, index);
  1736.     },
  1737.     
  1738.     indexOf : function(record){
  1739.         return this.data.indexOf(record);
  1740.     },
  1741.     
  1742.     indexOfId : function(id){
  1743.         return this.data.indexOfKey(id);
  1744.     },
  1745.     
  1746.     getById : function(id){
  1747.         return (this.snapshot || this.data).key(id);
  1748.     },
  1749.     
  1750.     getAt : function(index){
  1751.         return this.data.itemAt(index);
  1752.     },
  1753.     
  1754.     getRange : function(start, end){
  1755.         return this.data.getRange(start, end);
  1756.     },
  1757.     
  1758.     storeOptions : function(o){
  1759.         o = Ext.apply({}, o);
  1760.         delete o.callback;
  1761.         delete o.scope;
  1762.         this.lastOptions = o;
  1763.     },
  1764.     
  1765.     clearData: function(){
  1766.         this.data.each(function(rec) {
  1767.             rec.join(null);
  1768.         });
  1769.         this.data.clear();
  1770.     },
  1771.     
  1772.     load : function(options) {
  1773.         options = options || {};
  1774.         this.storeOptions(options);
  1775.         if(this.sortInfo && this.remoteSort){
  1776.             var pn = this.paramNames;
  1777.             options.params = options.params || {};
  1778.             options.params[pn.sort] = this.sortInfo.field;
  1779.             options.params[pn.dir] = this.sortInfo.direction;
  1780.         }
  1781.         try {
  1782.             return this.execute('read', null, options); 
  1783.         } catch(e) {
  1784.             this.handleException(e);
  1785.             return false;
  1786.         }
  1787.     },
  1788.     
  1789.     updateRecord : function(store, record, action) {
  1790.         if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
  1791.             this.save();
  1792.         }
  1793.     },
  1794.     
  1795.     createRecords : function(store, rs, index) {
  1796.         for (var i = 0, len = rs.length; i < len; i++) {
  1797.             if (rs[i].phantom && rs[i].isValid()) {
  1798.                 rs[i].markDirty();  
  1799.                 this.modified.push(rs[i]);  
  1800.             }
  1801.         }
  1802.         if (this.autoSave === true) {
  1803.             this.save();
  1804.         }
  1805.     },
  1806.     
  1807.     destroyRecord : function(store, record, index) {
  1808.         if (this.modified.indexOf(record) != -1) {  
  1809.             this.modified.remove(record);
  1810.         }
  1811.         if (!record.phantom) {
  1812.             this.removed.push(record);
  1813.             
  1814.             
  1815.             
  1816.             record.lastIndex = index;
  1817.             if (this.autoSave === true) {
  1818.                 this.save();
  1819.             }
  1820.         }
  1821.     },
  1822.     
  1823.     execute : function(action, rs, options,  batch) {
  1824.         
  1825.         if (!Ext.data.Api.isAction(action)) {
  1826.             throw new Ext.data.Api.Error('execute', action);
  1827.         }
  1828.         
  1829.         options = Ext.applyIf(options||{}, {
  1830.             params: {}
  1831.         });
  1832.         if(batch !== undefined){
  1833.             this.addToBatch(batch);
  1834.         }
  1835.         
  1836.         
  1837.         var doRequest = true;
  1838.         if (action === 'read') {
  1839.             Ext.applyIf(options.params, this.baseParams);
  1840.             doRequest = this.fireEvent('beforeload', this, options);
  1841.         }
  1842.         else {
  1843.             
  1844.             
  1845.             if (this.writer.listful === true && this.restful !== true) {
  1846.                 rs = (Ext.isArray(rs)) ? rs : [rs];
  1847.             }
  1848.             
  1849.             else if (Ext.isArray(rs) && rs.length == 1) {
  1850.                 rs = rs.shift();
  1851.             }
  1852.             
  1853.             if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
  1854.                 this.writer.apply(options.params, this.baseParams, action, rs);
  1855.             }
  1856.         }
  1857.         if (doRequest !== false) {
  1858.             
  1859.             if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
  1860.                 options.params.xaction = action;    
  1861.             }
  1862.             
  1863.             
  1864.             
  1865.             
  1866.             
  1867.             this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
  1868.         }
  1869.         return doRequest;
  1870.     },
  1871.     
  1872.     save : function() {
  1873.         if (!this.writer) {
  1874.             throw new Ext.data.Store.Error('writer-undefined');
  1875.         }
  1876.         var queue = [],
  1877.             len,
  1878.             trans,
  1879.             batch,
  1880.             data = {};
  1881.         
  1882.         if(this.removed.length){
  1883.             queue.push(['destroy', this.removed]);
  1884.         }
  1885.         
  1886.         var rs = [].concat(this.getModifiedRecords());
  1887.         if(rs.length){
  1888.             
  1889.             var phantoms = [];
  1890.             for(var i = rs.length-1; i >= 0; i--){
  1891.                 if(rs[i].phantom === true){
  1892.                     var rec = rs.splice(i, 1).shift();
  1893.                     if(rec.isValid()){
  1894.                         phantoms.push(rec);
  1895.                     }
  1896.                 }else if(!rs[i].isValid()){ 
  1897.                     rs.splice(i,1);
  1898.                 }
  1899.             }
  1900.             
  1901.             if(phantoms.length){
  1902.                 queue.push(['create', phantoms]);
  1903.             }
  1904.             
  1905.             if(rs.length){
  1906.                 queue.push(['update', rs]);
  1907.             }
  1908.         }
  1909.         len = queue.length;
  1910.         if(len){
  1911.             batch = ++this.batchCounter;
  1912.             for(var i = 0; i < len; ++i){
  1913.                 trans = queue[i];
  1914.                 data[trans[0]] = trans[1];
  1915.             }
  1916.             if(this.fireEvent('beforesave', this, data) !== false){
  1917.                 for(var i = 0; i < len; ++i){
  1918.                     trans = queue[i];
  1919.                     this.doTransaction(trans[0], trans[1], batch);
  1920.                 }
  1921.                 return batch;
  1922.             }
  1923.         }
  1924.         return -1;
  1925.     },
  1926.     
  1927.     doTransaction : function(action, rs, batch) {
  1928.         function transaction(records) {
  1929.             try{
  1930.                 this.execute(action, records, undefined, batch);
  1931.             }catch (e){
  1932.                 this.handleException(e);
  1933.             }
  1934.         }
  1935.         if(this.batch === false){
  1936.             for(var i = 0, len = rs.length; i < len; i++){
  1937.                 transaction.call(this, rs[i]);
  1938.             }
  1939.         }else{
  1940.             transaction.call(this, rs);
  1941.         }
  1942.     },
  1943.     
  1944.     addToBatch : function(batch){
  1945.         var b = this.batches,
  1946.             key = this.batchKey + batch,
  1947.             o = b[key];
  1948.         if(!o){
  1949.             b[key] = o = {
  1950.                 id: batch,
  1951.                 count: 0,
  1952.                 data: {}
  1953.             }
  1954.         }
  1955.         ++o.count;
  1956.     },
  1957.     removeFromBatch : function(batch, action, data){
  1958.         var b = this.batches,
  1959.             key = this.batchKey + batch,
  1960.             o = b[key],
  1961.             data,
  1962.             arr;
  1963.         if(o){
  1964.             arr = o.data[action] || [];
  1965.             o.data[action] = arr.concat(data);
  1966.             if(o.count === 1){
  1967.                 data = o.data;
  1968.                 delete b[key];
  1969.                 this.fireEvent('save', this, batch, data);
  1970.             }else{
  1971.                 --o.count;
  1972.             }
  1973.         }
  1974.     },
  1975.     
  1976.     
  1977.     createCallback : function(action, rs, batch) {
  1978.         var actions = Ext.data.Api.actions;
  1979.         return (action == 'read') ? this.loadRecords : function(data, response, success) {
  1980.             
  1981.             this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
  1982.             
  1983.             if (success === true) {
  1984.                 this.fireEvent('write', this, action, data, response, rs);
  1985.             }
  1986.             this.removeFromBatch(batch, action, data);
  1987.         };
  1988.     },
  1989.     
  1990.     
  1991.     
  1992.     clearModified : function(rs) {
  1993.         if (Ext.isArray(rs)) {
  1994.             for (var n=rs.length-1;n>=0;n--) {
  1995.                 this.modified.splice(this.modified.indexOf(rs[n]), 1);
  1996.             }
  1997.         } else {
  1998.             this.modified.splice(this.modified.indexOf(rs), 1);
  1999.         }
  2000.     },
  2001.     
  2002.     reMap : function(record) {
  2003.         if (Ext.isArray(record)) {
  2004.             for (var i = 0, len = record.length; i < len; i++) {
  2005.                 this.reMap(record[i]);
  2006.             }
  2007.         } else {
  2008.             delete this.data.map[record._phid];
  2009.             this.data.map[record.id] = record;
  2010.             var index = this.data.keys.indexOf(record._phid);
  2011.             this.data.keys.splice(index, 1, record.id);
  2012.             delete record._phid;
  2013.         }
  2014.     },
  2015.     
  2016.     onCreateRecords : function(success, rs, data) {
  2017.         if (success === true) {
  2018.             try {
  2019.                 this.reader.realize(rs, data);
  2020.                 this.reMap(rs);
  2021.             }
  2022.             catch (e) {
  2023.                 this.handleException(e);
  2024.                 if (Ext.isArray(rs)) {
  2025.                     
  2026.                     this.onCreateRecords(success, rs, data);
  2027.                 }
  2028.             }
  2029.         }
  2030.     },
  2031.     
  2032.     onUpdateRecords : function(success, rs, data) {
  2033.         if (success === true) {
  2034.             try {
  2035.                 this.reader.update(rs, data);
  2036.             } catch (e) {
  2037.                 this.handleException(e);
  2038.                 if (Ext.isArray(rs)) {
  2039.                     
  2040.                     this.onUpdateRecords(success, rs, data);
  2041.                 }
  2042.             }
  2043.         }
  2044.     },
  2045.     
  2046.     onDestroyRecords : function(success, rs, data) {
  2047.         
  2048.         rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
  2049.         for (var i=0,len=rs.length;i<len;i++) {
  2050.             this.removed.splice(this.removed.indexOf(rs[i]), 1);
  2051.         }
  2052.         if (success === false) {
  2053.             
  2054.             
  2055.             for (i=rs.length-1;i>=0;i--) {
  2056.                 this.insert(rs[i].lastIndex, rs[i]);    
  2057.             }
  2058.         }
  2059.     },
  2060.     
  2061.     handleException : function(e) {
  2062.         
  2063.         Ext.handleError(e);
  2064.     },
  2065.     
  2066.     reload : function(options){
  2067.         this.load(Ext.applyIf(options||{}, this.lastOptions));
  2068.     },
  2069.     
  2070.     
  2071.     loadRecords : function(o, options, success){
  2072.         if (this.isDestroyed === true) {
  2073.             return;
  2074.         }
  2075.         if(!o || success === false){
  2076.             if(success !== false){
  2077.                 this.fireEvent('load', this, [], options);
  2078.             }
  2079.             if(options.callback){
  2080.                 options.callback.call(options.scope || this, [], options, false, o);
  2081.             }
  2082.             return;
  2083.         }
  2084.         var r = o.records, t = o.totalRecords || r.length;
  2085.         if(!options || options.add !== true){
  2086.             if(this.pruneModifiedRecords){
  2087.                 this.modified = [];
  2088.             }
  2089.             for(var i = 0, len = r.length; i < len; i++){
  2090.                 r[i].join(this);
  2091.             }
  2092.             if(this.snapshot){
  2093.                 this.data = this.snapshot;
  2094.                 delete this.snapshot;
  2095.             }
  2096.             this.clearData();
  2097.             this.data.addAll(r);
  2098.             this.totalLength = t;
  2099.             this.applySort();
  2100.             this.fireEvent('datachanged', this);
  2101.         }else{
  2102.             this.totalLength = Math.max(t, this.data.length+r.length);
  2103.             this.add(r);
  2104.         }
  2105.         this.fireEvent('load', this, r, options);
  2106.         if(options.callback){
  2107.             options.callback.call(options.scope || this, r, options, true);
  2108.         }
  2109.     },
  2110.     
  2111.     loadData : function(o, append){
  2112.         var r = this.reader.readRecords(o);
  2113.         this.loadRecords(r, {add: append}, true);
  2114.     },
  2115.     
  2116.     getCount : function(){
  2117.         return this.data.length || 0;
  2118.     },
  2119.     
  2120.     getTotalCount : function(){
  2121.         return this.totalLength || 0;
  2122.     },
  2123.     
  2124.     getSortState : function(){
  2125.         return this.sortInfo;
  2126.     },
  2127.     
  2128.     applySort : function(){
  2129.         if(this.sortInfo && !this.remoteSort){
  2130.             var s = this.sortInfo, f = s.field;
  2131.             this.sortData(f, s.direction);
  2132.         }
  2133.     },
  2134.     
  2135.     sortData : function(f, direction){
  2136.         direction = direction || 'ASC';
  2137.         var st = this.fields.get(f).sortType;
  2138.         var fn = function(r1, r2){
  2139.             var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
  2140.             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
  2141.         };
  2142.         this.data.sort(direction, fn);
  2143.         if(this.snapshot && this.snapshot != this.data){
  2144.             this.snapshot.sort(direction, fn);
  2145.         }
  2146.     },
  2147.     
  2148.     setDefaultSort : function(field, dir){
  2149.         dir = dir ? dir.toUpperCase() : 'ASC';
  2150.         this.sortInfo = {field: field, direction: dir};
  2151.         this.sortToggle[field] = dir;
  2152.     },
  2153.     
  2154.     sort : function(fieldName, dir){
  2155.         var f = this.fields.get(fieldName);
  2156.         if(!f){
  2157.             return false;
  2158.         }
  2159.         if(!dir){
  2160.             if(this.sortInfo && this.sortInfo.field == f.name){ 
  2161.                 dir = (this.sortToggle[f.name] || 'ASC').toggle('ASC', 'DESC');
  2162.             }else{
  2163.                 dir = f.sortDir;
  2164.             }
  2165.         }
  2166.         var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
  2167.         var si = (this.sortInfo) ? this.sortInfo : null;
  2168.         this.sortToggle[f.name] = dir;
  2169.         this.sortInfo = {field: f.name, direction: dir};
  2170.         if(!this.remoteSort){
  2171.             this.applySort();
  2172.             this.fireEvent('datachanged', this);
  2173.         }else{
  2174.             if (!this.load(this.lastOptions)) {
  2175.                 if (st) {
  2176.                     this.sortToggle[f.name] = st;
  2177.                 }
  2178.                 if (si) {
  2179.                     this.sortInfo = si;
  2180.                 }
  2181.             }
  2182.         }
  2183.     },
  2184.     
  2185.     each : function(fn, scope){
  2186.         this.data.each(fn, scope);
  2187.     },
  2188.     
  2189.     getModifiedRecords : function(){
  2190.         return this.modified;
  2191.     },
  2192.     
  2193.     createFilterFn : function(property, value, anyMatch, caseSensitive){
  2194.         if(Ext.isEmpty(value, false)){
  2195.             return false;
  2196.         }
  2197.         value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
  2198.         return function(r){
  2199.             return value.test(r.data[property]);
  2200.         };
  2201.     },
  2202.     
  2203.     sum : function(property, start, end){
  2204.         var rs = this.data.items, v = 0;
  2205.         start = start || 0;
  2206.         end = (end || end === 0) ? end : rs.length-1;
  2207.         for(var i = start; i <= end; i++){
  2208.             v += (rs[i].data[property] || 0);
  2209.         }
  2210.         return v;
  2211.     },
  2212.     
  2213.     filter : function(property, value, anyMatch, caseSensitive){
  2214.         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
  2215.         return fn ? this.filterBy(fn) : this.clearFilter();
  2216.     },
  2217.     
  2218.     filterBy : function(fn, scope){
  2219.         this.snapshot = this.snapshot || this.data;
  2220.         this.data = this.queryBy(fn, scope||this);
  2221.         this.fireEvent('datachanged', this);
  2222.     },
  2223.     
  2224.     query : function(property, value, anyMatch, caseSensitive){
  2225.         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
  2226.         return fn ? this.queryBy(fn) : this.data.clone();
  2227.     },
  2228.     
  2229.     queryBy : function(fn, scope){
  2230.         var data = this.snapshot || this.data;
  2231.         return data.filterBy(fn, scope||this);
  2232.     },
  2233.     
  2234.     find : function(property, value, start, anyMatch, caseSensitive){
  2235.         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
  2236.         return fn ? this.data.findIndexBy(fn, null, start) : -1;
  2237.     },
  2238.     
  2239.     findExact: function(property, value, start){
  2240.         return this.data.findIndexBy(function(rec){
  2241.             return rec.get(property) === value;
  2242.         }, this, start);
  2243.     },
  2244.     
  2245.     findBy : function(fn, scope, start){
  2246.         return this.data.findIndexBy(fn, scope, start);
  2247.     },
  2248.     
  2249.     collect : function(dataIndex, allowNull, bypassFilter){
  2250.         var d = (bypassFilter === true && this.snapshot) ?
  2251.                 this.snapshot.items : this.data.items;
  2252.         var v, sv, r = [], l = {};
  2253.         for(var i = 0, len = d.length; i < len; i++){
  2254.             v = d[i].data[dataIndex];
  2255.             sv = String(v);
  2256.             if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
  2257.                 l[sv] = true;
  2258.                 r[r.length] = v;
  2259.             }
  2260.         }
  2261.         return r;
  2262.     },
  2263.     
  2264.     clearFilter : function(suppressEvent){
  2265.         if(this.isFiltered()){
  2266.             this.data = this.snapshot;
  2267.             delete this.snapshot;
  2268.             if(suppressEvent !== true){
  2269.                 this.fireEvent('datachanged', this);
  2270.             }
  2271.         }
  2272.     },
  2273.     
  2274.     isFiltered : function(){
  2275.         return this.snapshot && this.snapshot != this.data;
  2276.     },
  2277.     
  2278.     afterEdit : function(record){
  2279.         if(this.modified.indexOf(record) == -1){
  2280.             this.modified.push(record);
  2281.         }
  2282.         this.fireEvent('update', this, record, Ext.data.Record.EDIT);
  2283.     },
  2284.     
  2285.     afterReject : function(record){
  2286.         this.modified.remove(record);
  2287.         this.fireEvent('update', this, record, Ext.data.Record.REJECT);
  2288.     },
  2289.     
  2290.     afterCommit : function(record){
  2291.         this.modified.remove(record);
  2292.         this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
  2293.     },
  2294.     
  2295.     commitChanges : function(){
  2296.         var m = this.modified.slice(0);
  2297.         this.modified = [];
  2298.         for(var i = 0, len = m.length; i < len; i++){
  2299.             m[i].commit();
  2300.         }
  2301.     },
  2302.     
  2303.     rejectChanges : function(){
  2304.         var m = this.modified.slice(0);
  2305.         this.modified = [];
  2306.         for(var i = 0, len = m.length; i < len; i++){
  2307.             m[i].reject();
  2308.         }
  2309.         var m = this.removed.slice(0).reverse();
  2310.         this.removed = [];
  2311.         for(var i = 0, len = m.length; i < len; i++){
  2312.             this.insert(m[i].lastIndex||0, m[i]);
  2313.             m[i].reject();
  2314.         }
  2315.     },
  2316.     
  2317.     onMetaChange : function(meta){
  2318.         this.recordType = this.reader.recordType;
  2319.         this.fields = this.recordType.prototype.fields;
  2320.         delete this.snapshot;
  2321.         if(this.reader.meta.sortInfo){
  2322.             this.sortInfo = this.reader.meta.sortInfo;
  2323.         }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
  2324.             delete this.sortInfo;
  2325.         }
  2326.         if(this.writer){
  2327.             this.writer.meta = this.reader.meta;
  2328.         }
  2329.         this.modified = [];
  2330.         this.fireEvent('metachange', this, this.reader.meta);
  2331.     },
  2332.     
  2333.     findInsertIndex : function(record){
  2334.         this.suspendEvents();
  2335.         var data = this.data.clone();
  2336.         this.data.add(record);
  2337.         this.applySort();
  2338.         var index = this.data.indexOf(record);
  2339.         this.data = data;
  2340.         this.resumeEvents();
  2341.         return index;
  2342.     },
  2343.     
  2344.     setBaseParam : function (name, value){
  2345.         this.baseParams = this.baseParams || {};
  2346.         this.baseParams[name] = value;
  2347.     }
  2348. });
  2349. Ext.reg('store', Ext.data.Store);
  2350. Ext.data.Store.Error = Ext.extend(Ext.Error, {
  2351.     name: 'Ext.data.Store'
  2352. });
  2353. Ext.apply(Ext.data.Store.Error.prototype, {
  2354.     lang: {
  2355.         'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
  2356.     }
  2357. });
  2358. Ext.data.Field = function(config){
  2359.     if(typeof config == "string"){
  2360.         config = {name: config};
  2361.     }
  2362.     Ext.apply(this, config);
  2363.     if(!this.type){
  2364.         this.type = "auto";
  2365.     }
  2366.     var st = Ext.data.SortTypes;
  2367.     
  2368.     if(typeof this.sortType == "string"){
  2369.         this.sortType = st[this.sortType];
  2370.     }
  2371.     
  2372.     if(!this.sortType){
  2373.         switch(this.type){
  2374.             case "string":
  2375.                 this.sortType = st.asUCString;
  2376.                 break;
  2377.             case "date":
  2378.                 this.sortType = st.asDate;
  2379.                 break;
  2380.             default:
  2381.                 this.sortType = st.none;
  2382.         }
  2383.     }
  2384.     
  2385.     var stripRe = /[$,%]/g;
  2386.     
  2387.     
  2388.     if(!this.convert){
  2389.         var cv, dateFormat = this.dateFormat;
  2390.         switch(this.type){
  2391.             case "":
  2392.             case "auto":
  2393.             case undefined:
  2394.                 cv = function(v){ return v; };
  2395.                 break;
  2396.             case "string":
  2397.                 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
  2398.                 break;
  2399.             case "int":
  2400.                 cv = function(v){
  2401.                     return v !== undefined && v !== null && v !== '' ?
  2402.                         parseInt(String(v).replace(stripRe, ""), 10) : '';
  2403.                     };
  2404.                 break;
  2405.             case "float":
  2406.                 cv = function(v){
  2407.                     return v !== undefined && v !== null && v !== '' ?
  2408.                         parseFloat(String(v).replace(stripRe, ""), 10) : '';
  2409.                     };
  2410.                 break;
  2411.             case "bool":
  2412.                 cv = function(v){ return v === true || v === "true" || v == 1; };
  2413.                 break;
  2414.             case "date":
  2415.                 cv = function(v){
  2416.                     if(!v){
  2417.                         return '';
  2418.                     }
  2419.                     if(Ext.isDate(v)){
  2420.                         return v;
  2421.                     }
  2422.                     if(dateFormat){
  2423.                         if(dateFormat == "timestamp"){
  2424.                             return new Date(v*1000);
  2425.                         }
  2426.                         if(dateFormat == "time"){
  2427.                             return new Date(parseInt(v, 10));
  2428.                         }
  2429.                         return Date.parseDate(v, dateFormat);
  2430.                     }
  2431.                     var parsed = Date.parse(v);
  2432.                     return parsed ? new Date(parsed) : null;
  2433.                 };
  2434.                 break;
  2435.             default:
  2436.                 cv = function(v){ return v; };
  2437.                 break;
  2438.         }
  2439.         this.convert = cv;
  2440.     }
  2441. };
  2442. Ext.data.Field.prototype = {
  2443.     
  2444.     
  2445.     
  2446.     
  2447.     dateFormat: null,
  2448.     
  2449.     defaultValue: "",
  2450.     
  2451.     mapping: null,
  2452.     
  2453.     sortType : null,
  2454.     
  2455.     sortDir : "ASC",
  2456.     
  2457.     allowBlank : true
  2458. };
  2459. Ext.data.DataReader = function(meta, recordType){
  2460.     
  2461.     this.meta = meta;
  2462.     
  2463.     this.recordType = Ext.isArray(recordType) ?
  2464.         Ext.data.Record.create(recordType) : recordType;
  2465.     
  2466.     if (this.recordType){
  2467.         this.buildExtractors();
  2468.     }
  2469. };
  2470. Ext.data.DataReader.prototype = {
  2471.     
  2472.     
  2473.     getTotal: Ext.emptyFn,
  2474.     
  2475.     getRoot: Ext.emptyFn,
  2476.     
  2477.     getMessage: Ext.emptyFn,
  2478.     
  2479.     getSuccess: Ext.emptyFn,
  2480.     
  2481.     getId: Ext.emptyFn,
  2482.     
  2483.     buildExtractors : Ext.emptyFn,
  2484.     
  2485.     extractData : Ext.emptyFn,
  2486.     
  2487.     extractValues : Ext.emptyFn,
  2488.     
  2489.     realize: function(rs, data){
  2490.         if (Ext.isArray(rs)) {
  2491.             for (var i = rs.length - 1; i >= 0; i--) {
  2492.                 
  2493.                 if (Ext.isArray(data)) {
  2494.                     this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
  2495.                 }
  2496.                 else {
  2497.                     
  2498.                     
  2499.                     this.realize(rs.splice(i,1).shift(), data);
  2500.                 }
  2501.             }
  2502.         }
  2503.         else {
  2504.             
  2505.             if (Ext.isArray(data) && data.length == 1) {
  2506.                 data = data.shift();
  2507.             }
  2508.             if (!this.isData(data)) {
  2509.                 
  2510.                 
  2511.                 throw new Ext.data.DataReader.Error('realize', rs);
  2512.             }
  2513.             rs.phantom = false; 
  2514.             rs._phid = rs.id;  
  2515.             rs.id = this.getId(data);
  2516.             rs.fields.each(function(f) {
  2517.                 if (data[f.name] !== f.defaultValue) {
  2518.                     rs.data[f.name] = data[f.name];
  2519.                 }
  2520.             });
  2521.             rs.commit();
  2522.         }
  2523.     },
  2524.     
  2525.     update : function(rs, data) {
  2526.         if (Ext.isArray(rs)) {
  2527.             for (var i=rs.length-1; i >= 0; i--) {
  2528.                 if (Ext.isArray(data)) {
  2529.                     this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
  2530.                 }
  2531.                 else {
  2532.                     
  2533.                     
  2534.                     this.update(rs.splice(i,1).shift(), data);
  2535.                 }
  2536.             }
  2537.         }
  2538.         else {
  2539.             
  2540.             if (Ext.isArray(data) && data.length == 1) {
  2541.                 data = data.shift();
  2542.             }
  2543.             if (this.isData(data)) {
  2544.                 rs.fields.each(function(f) {
  2545.                     if (data[f.name] !== f.defaultValue) {
  2546.                         rs.data[f.name] = data[f.name];
  2547.                     }
  2548.                 });
  2549.             }
  2550.             rs.commit();
  2551.         }
  2552.     },
  2553.     
  2554.     extractData : function(root, returnRecords) {
  2555.         
  2556.         var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
  2557.         var rs = [];
  2558.         
  2559.         
  2560.         if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
  2561.             root = [root];
  2562.         }
  2563.         var f       = this.recordType.prototype.fields,
  2564.             fi      = f.items,
  2565.             fl      = f.length,
  2566.             rs      = [];
  2567.         if (returnRecords === true) {
  2568.             var Record = this.recordType;
  2569.             for (var i = 0; i < root.length; i++) {
  2570.                 var n = root[i];
  2571.                 var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
  2572.                 record[rawName] = n;    
  2573.                 rs.push(record);
  2574.             }
  2575.         }
  2576.         else {
  2577.             for (var i = 0; i < root.length; i++) {
  2578.                 var data = this.extractValues(root[i], fi, fl);
  2579.                 data[this.meta.idProperty] = this.getId(root[i]);
  2580.                 rs.push(data);
  2581.             }
  2582.         }
  2583.         return rs;
  2584.     },
  2585.     
  2586.     isData : function(data) {
  2587.         return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
  2588.     },
  2589.     
  2590.     onMetaChange : function(meta){
  2591.         delete this.ef;
  2592.         this.meta = meta;
  2593.         this.recordType = Ext.data.Record.create(meta.fields);
  2594.         this.buildExtractors();
  2595.     }
  2596. };
  2597. Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
  2598.     constructor : function(message, arg) {
  2599.         this.arg = arg;
  2600.         Ext.Error.call(this, message);
  2601.     },
  2602.     name: 'Ext.data.DataReader'
  2603. });
  2604. Ext.apply(Ext.data.DataReader.Error.prototype, {
  2605.     lang : {
  2606.         'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
  2607.         'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
  2608.         'invalid-response': "#readResponse received an invalid response from the server."
  2609.     }
  2610. });
  2611. Ext.data.DataWriter = function(config){
  2612.     Ext.apply(this, config);
  2613. };
  2614. Ext.data.DataWriter.prototype = {
  2615.     
  2616.     writeAllFields : false,
  2617.     
  2618.     listful : false,    
  2619.     
  2620.     apply : function(params, baseParams, action, rs) {
  2621.         var data    = [],
  2622.         renderer    = action + 'Record';
  2623.         
  2624.         if (Ext.isArray(rs)) {
  2625.             Ext.each(rs, function(rec){
  2626.                 data.push(this[renderer](rec));
  2627.             }, this);
  2628.         }
  2629.         else if (rs instanceof Ext.data.Record) {
  2630.             data = this[renderer](rs);
  2631.         }
  2632.         this.render(params, baseParams, data);
  2633.     },
  2634.     
  2635.     render : Ext.emptyFn,
  2636.     
  2637.     updateRecord : Ext.emptyFn,
  2638.     
  2639.     createRecord : Ext.emptyFn,
  2640.     
  2641.     destroyRecord : Ext.emptyFn,
  2642.     
  2643.     toHash : function(rec, config) {
  2644.         var map = rec.fields.map,
  2645.             data = {},
  2646.             raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
  2647.             m;
  2648.         Ext.iterate(raw, function(prop, value){
  2649.             if((m = map[prop])){
  2650.                 data[m.mapping ? m.mapping : m.name] = value;
  2651.             }
  2652.         });
  2653.         
  2654.         
  2655.         
  2656.         if (rec.phantom) {
  2657.             if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
  2658.                 delete data[this.meta.idProperty];
  2659.             }
  2660.         } else {
  2661.             data[this.meta.idProperty] = rec.id
  2662.         }
  2663.         return data;
  2664.     },
  2665.     
  2666.     toArray : function(data) {
  2667.         var fields = [];
  2668.         Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
  2669.         return fields;
  2670.     }
  2671. };
  2672. Ext.data.DataProxy = function(conn){
  2673.     
  2674.     
  2675.     conn = conn || {};
  2676.     
  2677.     
  2678.     
  2679.     this.api     = conn.api;
  2680.     this.url     = conn.url;
  2681.     this.restful = conn.restful;
  2682.     this.listeners = conn.listeners;
  2683.     
  2684.     this.prettyUrls = conn.prettyUrls;
  2685.     
  2686.     this.addEvents(
  2687.         
  2688.         'exception',
  2689.         
  2690.         'beforeload',
  2691.         
  2692.         'load',
  2693.         
  2694.         'loadexception',
  2695.         
  2696.         'beforewrite',
  2697.         
  2698.         'write'
  2699.     );
  2700.     Ext.data.DataProxy.superclass.constructor.call(this);
  2701.     
  2702.     try {
  2703.         Ext.data.Api.prepare(this);
  2704.     } catch (e) {
  2705.         if (e instanceof Ext.data.Api.Error) {
  2706.             e.toConsole();
  2707.         }
  2708.     }
  2709.     
  2710.     Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
  2711. };
  2712. Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
  2713.     
  2714.     restful: false,
  2715.     
  2716.     setApi : function() {
  2717.         if (arguments.length == 1) {
  2718.             var valid = Ext.data.Api.isValid(arguments[0]);
  2719.             if (valid === true) {
  2720.                 this.api = arguments[0];
  2721.             }
  2722.             else {
  2723.                 throw new Ext.data.Api.Error('invalid', valid);
  2724.             }
  2725.         }
  2726.         else if (arguments.length == 2) {
  2727.             if (!Ext.data.Api.isAction(arguments[0])) {
  2728.                 throw new Ext.data.Api.Error('invalid', arguments[0]);
  2729.             }
  2730.             this.api[arguments[0]] = arguments[1];
  2731.         }
  2732.         Ext.data.Api.prepare(this);
  2733.     },
  2734.     
  2735.     isApiAction : function(action) {
  2736.         return (this.api[action]) ? true : false;
  2737.     },
  2738.     
  2739.     request : function(action, rs, params, reader, callback, scope, options) {
  2740.         if (!this.api[action] && !this.load) {
  2741.             throw new Ext.data.DataProxy.Error('action-undefined', action);
  2742.         }
  2743.         params = params || {};
  2744.         if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
  2745.             this.doRequest.apply(this, arguments);
  2746.         }
  2747.         else {
  2748.             callback.call(scope || this, null, options, false);
  2749.         }
  2750.     },
  2751.     
  2752.     load : null,
  2753.     
  2754.     doRequest : function(action, rs, params, reader, callback, scope, options) {
  2755.         
  2756.         
  2757.         
  2758.         this.load(params, reader, callback, scope, options);
  2759.     },
  2760.     
  2761.     onRead : Ext.emptyFn,
  2762.     
  2763.     onWrite : Ext.emptyFn,
  2764.     
  2765.     buildUrl : function(action, record) {
  2766.         record = record || null;
  2767.         
  2768.         
  2769.         
  2770.         var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
  2771.         if (!url) {
  2772.             throw new Ext.data.Api.Error('invalid-url', action);
  2773.         }
  2774.         
  2775.         
  2776.         
  2777.         
  2778.         
  2779.         
  2780.         var provides = null;
  2781.         var m = url.match(/(.*)(.json|.xml|.html)$/);
  2782.         if (m) {
  2783.             provides = m[2];    
  2784.             url      = m[1];    
  2785.         }
  2786.         
  2787.         if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
  2788.             url += '/' + record.id;
  2789.         }
  2790.         return (provides === null) ? url : url + provides;
  2791.     },
  2792.     
  2793.     destroy: function(){
  2794.         this.purgeListeners();
  2795.     }
  2796. });
  2797. Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
  2798. Ext.util.Observable.call(Ext.data.DataProxy);
  2799. Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
  2800.     constructor : function(message, arg) {
  2801.         this.arg = arg;
  2802.         Ext.Error.call(this, message);
  2803.     },
  2804.     name: 'Ext.data.DataProxy'
  2805. });
  2806. Ext.apply(Ext.data.DataProxy.Error.prototype, {
  2807.     lang: {
  2808.         'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
  2809.         'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
  2810.     }
  2811. });
  2812. Ext.data.Request = function(params) {
  2813.     Ext.apply(this, params);
  2814. };
  2815. Ext.data.Request.prototype = {
  2816.     
  2817.     action : undefined,
  2818.     
  2819.     rs : undefined,
  2820.     
  2821.     params: undefined,
  2822.     
  2823.     callback : Ext.emptyFn,
  2824.     
  2825.     scope : undefined,
  2826.     
  2827.     reader : undefined
  2828. };
  2829. Ext.data.Response = function(params) {
  2830.     Ext.apply(this, params);
  2831. };
  2832. Ext.data.Response.prototype = {
  2833.     
  2834.     action: undefined,
  2835.     
  2836.     success : undefined,
  2837.     
  2838.     message : undefined,
  2839.     
  2840.     data: undefined,
  2841.     
  2842.     raw: undefined,
  2843.     
  2844.     records: undefined
  2845. };
  2846. Ext.data.ScriptTagProxy = function(config){
  2847.     Ext.apply(this, config);
  2848.     Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
  2849.     this.head = document.getElementsByTagName("head")[0];
  2850.     
  2851. };
  2852. Ext.data.ScriptTagProxy.TRANS_ID = 1000;
  2853. Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
  2854.     
  2855.     
  2856.     timeout : 30000,
  2857.     
  2858.     callbackParam : "callback",
  2859.     
  2860.     nocache : true,
  2861.     
  2862.     doRequest : function(action, rs, params, reader, callback, scope, arg) {
  2863.         var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
  2864.         var url = this.buildUrl(action, rs);
  2865.         if (!url) {
  2866.             throw new Ext.data.Api.Error('invalid-url', url);
  2867.         }
  2868.         url = Ext.urlAppend(url, p);
  2869.         if(this.nocache){
  2870.             url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
  2871.         }
  2872.         var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
  2873.         var trans = {
  2874.             id : transId,
  2875.             action: action,
  2876.             cb : "stcCallback"+transId,
  2877.             scriptId : "stcScript"+transId,
  2878.             params : params,
  2879.             arg : arg,
  2880.             url : url,
  2881.             callback : callback,
  2882.             scope : scope,
  2883.             reader : reader
  2884.         };
  2885.         window[trans.cb] = this.createCallback(action, rs, trans);
  2886.         url += String.format("&{0}={1}", this.callbackParam, trans.cb);
  2887.         if(this.autoAbort !== false){
  2888.             this.abort();
  2889.         }
  2890.         trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
  2891.         var script = document.createElement("script");
  2892.         script.setAttribute("src", url);
  2893.         script.setAttribute("type", "text/javascript");
  2894.         script.setAttribute("id", trans.scriptId);
  2895.         this.head.appendChild(script);
  2896.         this.trans = trans;
  2897.     },
  2898.     
  2899.     createCallback : function(action, rs, trans) {
  2900.         var self = this;
  2901.         return function(res) {
  2902.             self.trans = false;
  2903.             self.destroyTrans(trans, true);
  2904.             if (action === Ext.data.Api.actions.read) {
  2905.                 self.onRead.call(self, action, trans, res);
  2906.             } else {
  2907.                 self.onWrite.call(self, action, trans, res, rs);
  2908.             }
  2909.         };
  2910.     },
  2911.     
  2912.     onRead : function(action, trans, res) {
  2913.         var result;
  2914.         try {
  2915.             result = trans.reader.readRecords(res);
  2916.         }catch(e){
  2917.             
  2918.             this.fireEvent("loadexception", this, trans, res, e);
  2919.             this.fireEvent('exception', this, 'response', action, trans, res, e);
  2920.             trans.callback.call(trans.scope||window, null, trans.arg, false);
  2921.             return;
  2922.         }
  2923.         if (result.success === false) {
  2924.             
  2925.             this.fireEvent('loadexception', this, trans, res);
  2926.             this.fireEvent('exception', this, 'remote', action, trans, res, null);
  2927.         } else {
  2928.             this.fireEvent("load", this, res, trans.arg);
  2929.         }
  2930.         trans.callback.call(trans.scope||window, result, trans.arg, result.success);
  2931.     },
  2932.     
  2933.     onWrite : function(action, trans, response, rs) {
  2934.         var reader = trans.reader;
  2935.         try {
  2936.             
  2937.             var res = reader.readResponse(action, response);
  2938.         } catch (e) {
  2939.             this.fireEvent('exception', this, 'response', action, trans, res, e);
  2940.             trans.callback.call(trans.scope||window, null, res, false);
  2941.             return;
  2942.         }
  2943.         if(!res.success === true){
  2944.             this.fireEvent('exception', this, 'remote', action, trans, res, rs);
  2945.             trans.callback.call(trans.scope||window, null, res, false);
  2946.             return;
  2947.         }
  2948.         this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
  2949.         trans.callback.call(trans.scope||window, res.data, res, true);
  2950.     },
  2951.     
  2952.     isLoading : function(){
  2953.         return this.trans ? true : false;
  2954.     },
  2955.     
  2956.     abort : function(){
  2957.         if(this.isLoading()){
  2958.             this.destroyTrans(this.trans);
  2959.         }
  2960.     },
  2961.     
  2962.     destroyTrans : function(trans, isLoaded){
  2963.         this.head.removeChild(document.getElementById(trans.scriptId));
  2964.         clearTimeout(trans.timeoutId);
  2965.         if(isLoaded){
  2966.             window[trans.cb] = undefined;
  2967.             try{
  2968.                 delete window[trans.cb];
  2969.             }catch(e){}
  2970.         }else{
  2971.             
  2972.             window[trans.cb] = function(){
  2973.                 window[trans.cb] = undefined;
  2974.                 try{
  2975.                     delete window[trans.cb];
  2976.                 }catch(e){}
  2977.             };
  2978.         }
  2979.     },
  2980.     
  2981.     handleFailure : function(trans){
  2982.         this.trans = false;
  2983.         this.destroyTrans(trans, false);
  2984.         if (trans.action === Ext.data.Api.actions.read) {
  2985.             
  2986.             this.fireEvent("loadexception", this, null, trans.arg);
  2987.         }
  2988.         this.fireEvent('exception', this, 'response', trans.action, {
  2989.             response: null,
  2990.             options: trans.arg
  2991.         });
  2992.         trans.callback.call(trans.scope||window, null, trans.arg, false);
  2993.     },
  2994.     
  2995.     destroy: function(){
  2996.         this.abort();
  2997.         Ext.data.ScriptTagProxy.superclass.destroy.call(this);
  2998.     }
  2999. });
  3000. Ext.data.HttpProxy = function(conn){
  3001.     Ext.data.HttpProxy.superclass.constructor.call(this, conn);
  3002.     
  3003.     this.conn = conn;
  3004.     
  3005.     
  3006.     
  3007.     
  3008.     this.conn.url = null;
  3009.     this.useAjax = !conn || !conn.events;
  3010.     
  3011.     var actions = Ext.data.Api.actions;
  3012.     this.activeRequest = {};
  3013.     for (var verb in actions) {
  3014.         this.activeRequest[actions[verb]] = undefined;
  3015.     }
  3016. };
  3017. Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
  3018.     
  3019.     getConnection : function() {
  3020.         return this.useAjax ? Ext.Ajax : this.conn;
  3021.     },
  3022.     
  3023.     setUrl : function(url, makePermanent) {
  3024.         this.conn.url = url;
  3025.         if (makePermanent === true) {
  3026.             this.url = url;
  3027.             this.api = null;
  3028.             Ext.data.Api.prepare(this);
  3029.         }
  3030.     },
  3031.     
  3032.     doRequest : function(action, rs, params, reader, cb, scope, arg) {
  3033.         var  o = {
  3034.             method: (this.api[action]) ? this.api[action]['method'] : undefined,
  3035.             request: {
  3036.                 callback : cb,
  3037.                 scope : scope,
  3038.                 arg : arg
  3039.             },
  3040.             reader: reader,
  3041.             callback : this.createCallback(action, rs),
  3042.             scope: this
  3043.         };
  3044.         
  3045.         
  3046.         if (params.jsonData) {
  3047.             o.jsonData = params.jsonData;
  3048.         } else if (params.xmlData) {
  3049.             o.xmlData = params.xmlData;
  3050.         } else {
  3051.             o.params = params || {};
  3052.         }
  3053.         
  3054.         
  3055.         
  3056.         this.conn.url = this.buildUrl(action, rs);
  3057.         if(this.useAjax){
  3058.             Ext.applyIf(o, this.conn);
  3059.             
  3060.             if (this.activeRequest[action]) {
  3061.                 
  3062.                 
  3063.                 
  3064.                 
  3065.                 
  3066.             }
  3067.             this.activeRequest[action] = Ext.Ajax.request(o);
  3068.         }else{
  3069.             this.conn.request(o);
  3070.         }
  3071.         
  3072.         this.conn.url = null;
  3073.     },
  3074.     
  3075.     createCallback : function(action, rs) {
  3076.         return function(o, success, response) {
  3077.             this.activeRequest[action] = undefined;
  3078.             if (!success) {
  3079.                 if (action === Ext.data.Api.actions.read) {
  3080.                     
  3081.                     
  3082.                     this.fireEvent('loadexception', this, o, response);
  3083.                 }
  3084.                 this.fireEvent('exception', this, 'response', action, o, response);
  3085.                 o.request.callback.call(o.request.scope, null, o.request.arg, false);
  3086.                 return;
  3087.             }
  3088.             if (action === Ext.data.Api.actions.read) {
  3089.                 this.onRead(action, o, response);
  3090.             } else {
  3091.                 this.onWrite(action, o, response, rs);
  3092.             }
  3093.         }
  3094.     },
  3095.     
  3096.     onRead : function(action, o, response) {
  3097.         var result;
  3098.         try {
  3099.             result = o.reader.read(response);
  3100.         }catch(e){
  3101.             
  3102.             
  3103.             this.fireEvent('loadexception', this, o, response, e);
  3104.             this.fireEvent('exception', this, 'response', action, o, response, e);
  3105.             o.request.callback.call(o.request.scope, null, o.request.arg, false);
  3106.             return;
  3107.         }
  3108.         if (result.success === false) {
  3109.             
  3110.             
  3111.             this.fireEvent('loadexception', this, o, response);
  3112.             
  3113.             var res = o.reader.readResponse(action, response);
  3114.             this.fireEvent('exception', this, 'remote', action, o, res, null);
  3115.         }
  3116.         else {
  3117.             this.fireEvent('load', this, o, o.request.arg);
  3118.         }
  3119.         
  3120.         
  3121.         
  3122.         o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
  3123.     },
  3124.     
  3125.     onWrite : function(action, o, response, rs) {
  3126.         var reader = o.reader;
  3127.         var res;
  3128.         try {
  3129.             res = reader.readResponse(action, response);
  3130.         } catch (e) {
  3131.             this.fireEvent('exception', this, 'response', action, o, response, e);
  3132.             o.request.callback.call(o.request.scope, null, o.request.arg, false);
  3133.             return;
  3134.         }
  3135.         if (res.success === false) {
  3136.             this.fireEvent('exception', this, 'remote', action, o, res, rs);
  3137.         } else {
  3138.             this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
  3139.         }
  3140.         
  3141.         
  3142.         
  3143.         o.request.callback.call(o.request.scope, res.data, res, res.success);
  3144.     },
  3145.     
  3146.     destroy: function(){
  3147.         if(!this.useAjax){
  3148.             this.conn.abort();
  3149.         }else if(this.activeRequest){
  3150.             var actions = Ext.data.Api.actions;
  3151.             for (var verb in actions) {
  3152.                 if(this.activeRequest[actions[verb]]){
  3153.                     Ext.Ajax.abort(this.activeRequest[actions[verb]]);
  3154.                 }
  3155.             }
  3156.         }
  3157.         Ext.data.HttpProxy.superclass.destroy.call(this);
  3158.     }
  3159. });
  3160. Ext.data.MemoryProxy = function(data){
  3161.     
  3162.     var api = {};
  3163.     api[Ext.data.Api.actions.read] = true;
  3164.     Ext.data.MemoryProxy.superclass.constructor.call(this, {
  3165.         api: api
  3166.     });
  3167.     this.data = data;
  3168. };
  3169. Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
  3170.     
  3171.        
  3172.     doRequest : function(action, rs, params, reader, callback, scope, arg) {
  3173.         
  3174.         params = params || {};
  3175.         var result;
  3176.         try {
  3177.             result = reader.readRecords(this.data);
  3178.         }catch(e){
  3179.             
  3180.             this.fireEvent("loadexception", this, null, arg, e);
  3181.             this.fireEvent('exception', this, 'response', action, arg, null, e);
  3182.             callback.call(scope, null, arg, false);
  3183.             return;
  3184.         }
  3185.         callback.call(scope, result, arg, true);
  3186.     }
  3187. });
  3188. Ext.data.JsonWriter = function(config) {
  3189.     Ext.data.JsonWriter.superclass.constructor.call(this, config);
  3190.     
  3191.     
  3192.     if (this.returnJson != undefined) {
  3193.         this.encode = this.returnJson;
  3194.     }
  3195. }
  3196. Ext.extend(Ext.data.JsonWriter, Ext.data.DataWriter, {
  3197.     
  3198.     returnJson : undefined,
  3199.     
  3200.     encode : true,
  3201.     
  3202.     render : function(params, baseParams, data) {
  3203.         if (this.encode === true) {
  3204.             
  3205.             Ext.apply(params, baseParams);
  3206.             params[this.meta.root] = Ext.encode(data);
  3207.         } else {
  3208.             
  3209.             var jdata = Ext.apply({}, baseParams);
  3210.             jdata[this.meta.root] = data;
  3211.             params.jsonData = jdata;
  3212.         }
  3213.     },
  3214.     
  3215.     createRecord : function(rec) {
  3216.        return this.toHash(rec);
  3217.     },
  3218.     
  3219.     updateRecord : function(rec) {
  3220.         return this.toHash(rec);
  3221.     },
  3222.     
  3223.     destroyRecord : function(rec) {
  3224.         return rec.id;
  3225.     }
  3226. });
  3227. Ext.data.JsonReader = function(meta, recordType){
  3228.     meta = meta || {};
  3229.     
  3230.     
  3231.     
  3232.     
  3233.     Ext.applyIf(meta, {
  3234.         idProperty: 'id',
  3235.         successProperty: 'success',
  3236.         totalProperty: 'total'
  3237.     });
  3238.     Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
  3239. };
  3240. Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
  3241.     
  3242.     
  3243.     read : function(response){
  3244.         var json = response.responseText;
  3245.         var o = Ext.decode(json);
  3246.         if(!o) {
  3247.             throw {message: 'JsonReader.read: Json object not found'};
  3248.         }
  3249.         return this.readRecords(o);
  3250.     },
  3251.     
  3252.     readResponse : function(action, response) {
  3253.         var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
  3254.         if(!o) {
  3255.             throw new Ext.data.JsonReader.Error('response');
  3256.         }
  3257.         var root = this.getRoot(o);
  3258.         if (action === Ext.data.Api.actions.create) {
  3259.             var def = Ext.isDefined(root);
  3260.             if (def && Ext.isEmpty(root)) {
  3261.                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
  3262.             }
  3263.             else if (!def) {
  3264.                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
  3265.             }
  3266.         }
  3267.         
  3268.         var res = new Ext.data.Response({
  3269.             action: action,
  3270.             success: this.getSuccess(o),
  3271.             data: (root) ? this.extractData(root, false) : [],
  3272.             message: this.getMessage(o),
  3273.             raw: o
  3274.         });
  3275.         
  3276.         if (Ext.isEmpty(res.success)) {
  3277.             throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
  3278.         }
  3279.         return res;
  3280.     },
  3281.     
  3282.     readRecords : function(o){
  3283.         
  3284.         this.jsonData = o;
  3285.         if(o.metaData){
  3286.             this.onMetaChange(o.metaData);
  3287.         }
  3288.         var s = this.meta, Record = this.recordType,
  3289.             f = Record.prototype.fields, fi = f.items, fl = f.length, v;
  3290.         var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
  3291.         if(s.totalProperty){
  3292.             v = parseInt(this.getTotal(o), 10);
  3293.             if(!isNaN(v)){
  3294.                 totalRecords = v;
  3295.             }
  3296.         }
  3297.         if(s.successProperty){
  3298.             v = this.getSuccess(o);
  3299.             if(v === false || v === 'false'){
  3300.                 success = false;
  3301.             }
  3302.         }
  3303.         
  3304.         return {
  3305.             success : success,
  3306.             records : this.extractData(root, true), 
  3307.             totalRecords : totalRecords
  3308.         };
  3309.     },
  3310.     
  3311.     buildExtractors : function() {
  3312.         if(this.ef){
  3313.             return;
  3314.         }
  3315.         var s = this.meta, Record = this.recordType,
  3316.             f = Record.prototype.fields, fi = f.items, fl = f.length;
  3317.         if(s.totalProperty) {
  3318.             this.getTotal = this.createAccessor(s.totalProperty);
  3319.         }
  3320.         if(s.successProperty) {
  3321.             this.getSuccess = this.createAccessor(s.successProperty);
  3322.         }
  3323.         if (s.messageProperty) {
  3324.             this.getMessage = this.createAccessor(s.messageProperty);
  3325.         }
  3326.         this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
  3327.         if (s.id || s.idProperty) {
  3328.             var g = this.createAccessor(s.id || s.idProperty);
  3329.             this.getId = function(rec) {
  3330.                 var r = g(rec);
  3331.                 return (r === undefined || r === '') ? null : r;
  3332.             };
  3333.         } else {
  3334.             this.getId = function(){return null;};
  3335.         }
  3336.         var ef = [];
  3337.         for(var i = 0; i < fl; i++){
  3338.             f = fi[i];
  3339.             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
  3340.             ef.push(this.createAccessor(map));
  3341.         }
  3342.         this.ef = ef;
  3343.     },
  3344.     
  3345.     simpleAccess : function(obj, subsc) {
  3346.         return obj[subsc];
  3347.     },
  3348.     
  3349.     createAccessor : function(){
  3350.         var re = /[[.]/;
  3351.         return function(expr) {
  3352.             try {
  3353.                 return(re.test(expr)) ?
  3354.                 new Function('obj', 'return obj.' + expr) :
  3355.                 function(obj){
  3356.                     return obj[expr];
  3357.                 };
  3358.             } catch(e){}
  3359.             return Ext.emptyFn;
  3360.         };
  3361.     }(),
  3362.     
  3363.     extractValues : function(data, items, len) {
  3364.         var f, values = {};
  3365.         for(var j = 0; j < len; j++){
  3366.             f = items[j];
  3367.             var v = this.ef[j](data);
  3368.             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
  3369.         }
  3370.         return values;
  3371.     }
  3372. });
  3373. Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
  3374.     constructor : function(message, arg) {
  3375.         this.arg = arg;
  3376.         Ext.Error.call(this, message);
  3377.     },
  3378.     name : 'Ext.data.JsonReader'
  3379. });
  3380. Ext.apply(Ext.data.JsonReader.Error.prototype, {
  3381.     lang: {
  3382.         'response': 'An error occurred while json-decoding your server response',
  3383.         'successProperty-response': 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
  3384.         'root-undefined-config': 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
  3385.         'idProperty-undefined' : 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
  3386.         'root-empty': 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
  3387.     }
  3388. });
  3389. Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
  3390.     
  3391.     
  3392.     
  3393.     
  3394.     readRecords : function(o){
  3395.         this.arrayData = o;
  3396.         var s = this.meta,
  3397.             sid = s ? Ext.num(s.idIndex, s.id) : null,
  3398.             recordType = this.recordType,
  3399.             fields = recordType.prototype.fields,
  3400.             records = [],
  3401.             v;
  3402.         var root = this.getRoot(o);
  3403.         for(var i = 0, len = root.length; i < len; i++) {
  3404.             var n = root[i],
  3405.                 values = {},
  3406.                 id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
  3407.             for(var j = 0, jlen = fields.length; j < jlen; j++) {
  3408.                 var f = fields.items[j],
  3409.                     k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
  3410.                 v = n[k] !== undefined ? n[k] : f.defaultValue;
  3411.                 v = f.convert(v, n);
  3412.                 values[f.name] = v;
  3413.             }
  3414.             var record = new recordType(values, id);
  3415.             record.json = n;
  3416.             records[records.length] = record;
  3417.         }
  3418.         var totalRecords = records.length;
  3419.         if(s.totalProperty) {
  3420.             v = parseInt(this.getTotal(o), 10);
  3421.             if(!isNaN(v)) {
  3422.                 totalRecords = v;
  3423.             }
  3424.         }
  3425.         return {
  3426.             records : records,
  3427.             totalRecords : totalRecords
  3428.         };
  3429.     }
  3430. });
  3431. Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
  3432.     
  3433.     constructor: function(config){
  3434.         Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
  3435.             reader: new Ext.data.ArrayReader(config)
  3436.         }));
  3437.     },
  3438.     loadData : function(data, append){
  3439.         if(this.expandData === true){
  3440.             var r = [];
  3441.             for(var i = 0, len = data.length; i < len; i++){
  3442.                 r[r.length] = [data[i]];
  3443.             }
  3444.             data = r;
  3445.         }
  3446.         Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
  3447.     }
  3448. });
  3449. Ext.reg('arraystore', Ext.data.ArrayStore);
  3450. Ext.data.SimpleStore = Ext.data.ArrayStore;
  3451. Ext.reg('simplestore', Ext.data.SimpleStore);
  3452. Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
  3453.     
  3454.     constructor: function(config){
  3455.         Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
  3456.             reader: new Ext.data.JsonReader(config)
  3457.         }));
  3458.     }
  3459. });
  3460. Ext.reg('jsonstore', Ext.data.JsonStore);
  3461. Ext.data.XmlWriter = function(params) {
  3462.     Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
  3463.     
  3464.     this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
  3465. };
  3466. Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
  3467.     
  3468.     documentRoot: 'xrequest',
  3469.     
  3470.     forceDocumentRoot: false,
  3471.     
  3472.     root: 'records',
  3473.     
  3474.     xmlVersion : '1.0',
  3475.     
  3476.     xmlEncoding: 'ISO-8859-15',
  3477.     
  3478.     
  3479.     tpl: '<tpl for="."><' + '?xml version="{version}" encoding="{encoding}"?' + '><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}</tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',
  3480.     
  3481.     render : function(params, baseParams, data) {
  3482.         baseParams = this.toArray(baseParams);
  3483.         params.xmlData = this.tpl.applyTemplate({
  3484.             version: this.xmlVersion,
  3485.             encoding: this.xmlEncoding,
  3486.             documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
  3487.             record: this.meta.record,
  3488.             root: this.root,
  3489.             baseParams: baseParams,
  3490.             records: (Ext.isArray(data[0])) ? data : [data]
  3491.         });
  3492.     },
  3493.     
  3494.     createRecord : function(rec) {
  3495.         return this.toArray(this.toHash(rec));
  3496.     },
  3497.     
  3498.     updateRecord : function(rec) {
  3499.         return this.toArray(this.toHash(rec));
  3500.     },
  3501.     
  3502.     destroyRecord : function(rec) {
  3503.         var data = {};
  3504.         data[this.meta.idProperty] = rec.id;
  3505.         return this.toArray(data);
  3506.     }
  3507. });
  3508. Ext.data.XmlReader = function(meta, recordType){
  3509.     meta = meta || {};
  3510.     
  3511.     Ext.applyIf(meta, {
  3512.         idProperty: meta.idProperty || meta.idPath || meta.id,
  3513.         successProperty: meta.successProperty || meta.success
  3514.     });
  3515.     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
  3516. };
  3517. Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
  3518.     
  3519.     read : function(response){
  3520.         var doc = response.responseXML;
  3521.         if(!doc) {
  3522.             throw {message: "XmlReader.read: XML Document not available"};
  3523.         }
  3524.         return this.readRecords(doc);
  3525.     },
  3526.     
  3527.     readRecords : function(doc){
  3528.         
  3529.         this.xmlData = doc;
  3530.         var root    = doc.documentElement || doc,
  3531.             q       = Ext.DomQuery,
  3532.             totalRecords = 0,
  3533.             success = true;
  3534.         if(this.meta.totalProperty){
  3535.             totalRecords = this.getTotal(root, 0);
  3536.         }
  3537.         if(this.meta.successProperty){
  3538.             success = this.getSuccess(root);
  3539.         }
  3540.         var records = this.extractData(q.select(this.meta.record, root), true); 
  3541.         
  3542.         return {
  3543.             success : success,
  3544.             records : records,
  3545.             totalRecords : totalRecords || records.length
  3546.         };
  3547.     },
  3548.     
  3549.     readResponse : function(action, response) {
  3550.         var q   = Ext.DomQuery,
  3551.         doc     = response.responseXML;
  3552.         
  3553.         var res = new Ext.data.Response({
  3554.             action: action,
  3555.             success : this.getSuccess(doc),
  3556.             message: this.getMessage(doc),
  3557.             data: this.extractData(q.select(this.meta.record, doc) || q.select(this.meta.root, doc), false),
  3558.             raw: doc
  3559.         });
  3560.         if (Ext.isEmpty(res.success)) {
  3561.             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
  3562.         }
  3563.         
  3564.         if (action === Ext.data.Api.actions.create) {
  3565.             var def = Ext.isDefined(res.data);
  3566.             if (def && Ext.isEmpty(res.data)) {
  3567.                 throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
  3568.             }
  3569.             else if (!def) {
  3570.                 throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
  3571.             }
  3572.         }
  3573.         return res;
  3574.     },
  3575.     getSuccess : function() {
  3576.         return true;
  3577.     },
  3578.     
  3579.     buildExtractors : function() {
  3580.         if(this.ef){
  3581.             return;
  3582.         }
  3583.         var s       = this.meta,
  3584.             Record  = this.recordType,
  3585.             f       = Record.prototype.fields,
  3586.             fi      = f.items,
  3587.             fl      = f.length;
  3588.         if(s.totalProperty) {
  3589.             this.getTotal = this.createAccessor(s.totalProperty);
  3590.         }
  3591.         if(s.successProperty) {
  3592.             this.getSuccess = this.createAccessor(s.successProperty);
  3593.         }
  3594.         if (s.messageProperty) {
  3595.             this.getMessage = this.createAccessor(s.messageProperty);
  3596.         }
  3597.         this.getRoot = function(res) {
  3598.             return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
  3599.         }
  3600.         if (s.idPath || s.idProperty) {
  3601.             var g = this.createAccessor(s.idPath || s.idProperty);
  3602.             this.getId = function(rec) {
  3603.                 var id = g(rec) || rec.id;
  3604.                 return (id === undefined || id === '') ? null : id;
  3605.             };
  3606.         } else {
  3607.             this.getId = function(){return null;};
  3608.         }
  3609.         var ef = [];
  3610.         for(var i = 0; i < fl; i++){
  3611.             f = fi[i];
  3612.             var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
  3613.             ef.push(this.createAccessor(map));
  3614.         }
  3615.         this.ef = ef;
  3616.     },
  3617.     
  3618.     createAccessor : function(){
  3619.         var q = Ext.DomQuery;
  3620.         return function(key) {
  3621.             switch(key) {
  3622.                 case this.meta.totalProperty:
  3623.                     return function(root, def){
  3624.                         return q.selectNumber(key, root, def);
  3625.                     }
  3626.                     break;
  3627.                 case this.meta.successProperty:
  3628.                     return function(root, def) {
  3629.                         var sv = q.selectValue(key, root, true);
  3630.                         var success = sv !== false && sv !== 'false';
  3631.                         return success;
  3632.                     }
  3633.                     break;
  3634.                 default:
  3635.                     return function(root, def) {
  3636.                         return q.selectValue(key, root, def);
  3637.                     }
  3638.                     break;
  3639.             }
  3640.         };
  3641.     }(),
  3642.     
  3643.     extractValues : function(data, items, len) {
  3644.         var f, values = {};
  3645.         for(var j = 0; j < len; j++){
  3646.             f = items[j];
  3647.             var v = this.ef[j](data);
  3648.             values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
  3649.         }
  3650.         return values;
  3651.     }
  3652. });
  3653. Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
  3654.     
  3655.     constructor: function(config){
  3656.         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
  3657.             reader: new Ext.data.XmlReader(config)
  3658.         }));
  3659.     }
  3660. });
  3661. Ext.reg('xmlstore', Ext.data.XmlStore);
  3662. Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
  3663.     
  3664.     
  3665.     constructor: function(config){
  3666.         Ext.data.GroupingStore.superclass.constructor.call(this, config);
  3667.         this.applyGroupField();
  3668.     },
  3669.     
  3670.     
  3671.     
  3672.     remoteGroup : false,
  3673.     
  3674.     groupOnSort:false,
  3675. groupDir : 'ASC',
  3676.     
  3677.     clearGrouping : function(){
  3678.         this.groupField = false;
  3679.         if(this.remoteGroup){
  3680.             if(this.baseParams){
  3681.                 delete this.baseParams.groupBy;
  3682.             }
  3683.             var lo = this.lastOptions;
  3684.             if(lo && lo.params){
  3685.                 delete lo.params.groupBy;
  3686.             }
  3687.             this.reload();
  3688.         }else{
  3689.             this.applySort();
  3690.             this.fireEvent('datachanged', this);
  3691.         }
  3692.     },
  3693.     
  3694.     groupBy : function(field, forceRegroup, direction){
  3695. direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
  3696.         if(this.groupField == field && this.groupDir == direction && !forceRegroup){
  3697.             return; 
  3698.         }
  3699.         this.groupField = field;
  3700. this.groupDir = direction;
  3701.         this.applyGroupField();
  3702.         if(this.groupOnSort){
  3703.             this.sort(field, direction);
  3704.             return;
  3705.         }
  3706.         if(this.remoteGroup){
  3707.             this.reload();
  3708.         }else{
  3709.             var si = this.sortInfo || {};
  3710.             if(si.field != field || si.direction != direction){
  3711.                 this.applySort();
  3712.             }else{
  3713.                 this.sortData(field, direction);
  3714.             }
  3715.             this.fireEvent('datachanged', this);
  3716.         }
  3717.     },
  3718.     
  3719.     
  3720.     applyGroupField: function(){
  3721.         if(this.remoteGroup){
  3722.             if(!this.baseParams){
  3723.                 this.baseParams = {};
  3724.             }
  3725.             this.baseParams.groupBy = this.groupField;
  3726.             this.baseParams.groupDir = this.groupDir;
  3727.         }
  3728.     },
  3729.     
  3730.     applySort : function(){
  3731.         Ext.data.GroupingStore.superclass.applySort.call(this);
  3732.         if(!this.groupOnSort && !this.remoteGroup){
  3733.             var gs = this.getGroupState();
  3734.             if(gs && (gs != this.sortInfo.field || this.groupDir != this.sortInfo.direction)){
  3735.                 this.sortData(this.groupField, this.groupDir);
  3736.             }
  3737.         }
  3738.     },
  3739.     
  3740.     applyGrouping : function(alwaysFireChange){
  3741.         if(this.groupField !== false){
  3742.             this.groupBy(this.groupField, true, this.groupDir);
  3743.             return true;
  3744.         }else{
  3745.             if(alwaysFireChange === true){
  3746.                 this.fireEvent('datachanged', this);
  3747.             }
  3748.             return false;
  3749.         }
  3750.     },
  3751.     
  3752.     getGroupState : function(){
  3753.         return this.groupOnSort && this.groupField !== false ?
  3754.                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
  3755.     }
  3756. });
  3757. Ext.reg('groupingstore', Ext.data.GroupingStore);
  3758. Ext.data.DirectProxy = function(config){
  3759.     Ext.apply(this, config);
  3760.     if(typeof this.paramOrder == 'string'){
  3761.         this.paramOrder = this.paramOrder.split(/[s,|]/);
  3762.     }
  3763.     Ext.data.DirectProxy.superclass.constructor.call(this, config);
  3764. };
  3765. Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
  3766.     
  3767.     paramOrder: undefined,
  3768.     
  3769.     paramsAsHash: true,
  3770.     
  3771.     directFn : undefined,
  3772.     
  3773.     doRequest : function(action, rs, params, reader, callback, scope, options) {
  3774.         var args = [],
  3775.             directFn = this.api[action] || this.directFn;
  3776.         switch (action) {
  3777.             case Ext.data.Api.actions.create:
  3778.                 args.push(params.jsonData);
  3779.                 break;
  3780.             case Ext.data.Api.actions.read:
  3781.                 
  3782.                 if(directFn.directCfg.method.len > 0){
  3783.                     if(this.paramOrder){
  3784.                         for(var i = 0, len = this.paramOrder.length; i < len; i++){
  3785.                             args.push(params[this.paramOrder[i]]);
  3786.                         }
  3787.                     }else if(this.paramsAsHash){
  3788.                         args.push(params);
  3789.                     }
  3790.                 }
  3791.                 break;
  3792.             case Ext.data.Api.actions.update:
  3793.                 args.push(params.jsonData);        
  3794.                 break;
  3795.             case Ext.data.Api.actions.destroy:
  3796.                 args.push(params.jsonData);        
  3797.                 break;
  3798.         }
  3799.         var trans = {
  3800.             params : params || {},
  3801.             request: {
  3802.                 callback : callback,
  3803.                 scope : scope,
  3804.                 arg : options
  3805.             },
  3806.             reader: reader
  3807.         };
  3808.         args.push(this.createCallback(action, rs, trans), this);
  3809.         directFn.apply(window, args);
  3810.     },
  3811.     
  3812.     createCallback : function(action, rs, trans) {
  3813.         return function(result, res) {
  3814.             if (!res.status) {
  3815.                 
  3816.                 if (action === Ext.data.Api.actions.read) {
  3817.                     this.fireEvent("loadexception", this, trans, res, null);
  3818.                 }
  3819.                 this.fireEvent('exception', this, 'remote', action, trans, res, null);
  3820.                 trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
  3821.                 return;
  3822.             }
  3823.             if (action === Ext.data.Api.actions.read) {
  3824.                 this.onRead(action, trans, result, res);
  3825.             } else {
  3826.                 this.onWrite(action, trans, result, res, rs);
  3827.             }
  3828.         };
  3829.     },
  3830.     
  3831.     onRead : function(action, trans, result, res) {
  3832.         var records;
  3833.         try {
  3834.             records = trans.reader.readRecords(result);
  3835.         }
  3836.         catch (ex) {
  3837.             
  3838.             this.fireEvent("loadexception", this, trans, res, ex);
  3839.             this.fireEvent('exception', this, 'response', action, trans, res, ex);
  3840.             trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
  3841.             return;
  3842.         }
  3843.         this.fireEvent("load", this, res, trans.request.arg);
  3844.         trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
  3845.     },
  3846.     
  3847.     onWrite : function(action, trans, result, res, rs) {
  3848.         var data = trans.reader.extractData(result, false);
  3849.         this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
  3850.         trans.request.callback.call(trans.request.scope, data, res, true);
  3851.     }
  3852. });
  3853. Ext.data.DirectStore = function(c){
  3854.     
  3855.     c.batchTransactions = false;
  3856.     Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
  3857.         proxy: (typeof(c.proxy) == 'undefined') ? new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')) : c.proxy,
  3858.         reader: (typeof(c.reader) == 'undefined' && typeof(c.fields) == 'object') ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
  3859.     }));
  3860. };
  3861. Ext.extend(Ext.data.DirectStore, Ext.data.Store, {});
  3862. Ext.reg('directstore', Ext.data.DirectStore);
  3863. Ext.Direct = Ext.extend(Ext.util.Observable, {
  3864.     
  3865.     
  3866.     exceptions: {
  3867.         TRANSPORT: 'xhr',
  3868.         PARSE: 'parse',
  3869.         LOGIN: 'login',
  3870.         SERVER: 'exception'
  3871.     },
  3872.     
  3873.     
  3874.     constructor: function(){
  3875.         this.addEvents(
  3876.             
  3877.             'event',
  3878.             
  3879.             'exception'
  3880.         );
  3881.         this.transactions = {};
  3882.         this.providers = {};
  3883.     },
  3884.     
  3885.     addProvider : function(provider){        
  3886.         var a = arguments;
  3887.         if(a.length > 1){
  3888.             for(var i = 0, len = a.length; i < len; i++){
  3889.                 this.addProvider(a[i]);
  3890.             }
  3891.             return;
  3892.         }
  3893.         
  3894.         
  3895.         if(!provider.events){
  3896.             provider = new Ext.Direct.PROVIDERS[provider.type](provider);
  3897.         }
  3898.         provider.id = provider.id || Ext.id();
  3899.         this.providers[provider.id] = provider;
  3900.         provider.on('data', this.onProviderData, this);
  3901.         provider.on('exception', this.onProviderException, this);
  3902.         if(!provider.isConnected()){
  3903.             provider.connect();
  3904.         }
  3905.         return provider;
  3906.     },
  3907.     
  3908.     getProvider : function(id){
  3909.         return this.providers[id];
  3910.     },
  3911.     removeProvider : function(id){
  3912.         var provider = id.id ? id : this.providers[id.id];
  3913.         provider.un('data', this.onProviderData, this);
  3914.         provider.un('exception', this.onProviderException, this);
  3915.         delete this.providers[provider.id];
  3916.         return provider;
  3917.     },
  3918.     addTransaction: function(t){
  3919.         this.transactions[t.tid] = t;
  3920.         return t;
  3921.     },
  3922.     removeTransaction: function(t){
  3923.         delete this.transactions[t.tid || t];
  3924.         return t;
  3925.     },
  3926.     getTransaction: function(tid){
  3927.         return this.transactions[tid.tid || tid];
  3928.     },
  3929.     onProviderData : function(provider, e){
  3930.         if(Ext.isArray(e)){
  3931.             for(var i = 0, len = e.length; i < len; i++){
  3932.                 this.onProviderData(provider, e[i]);
  3933.             }
  3934.             return;
  3935.         }
  3936.         if(e.name && e.name != 'event' && e.name != 'exception'){
  3937.             this.fireEvent(e.name, e);
  3938.         }else if(e.type == 'exception'){
  3939.             this.fireEvent('exception', e);
  3940.         }
  3941.         this.fireEvent('event', e, provider);
  3942.     },
  3943.     createEvent : function(response, extraProps){
  3944.         return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
  3945.     }
  3946. });
  3947. Ext.Direct = new Ext.Direct();
  3948. Ext.Direct.TID = 1;
  3949. Ext.Direct.PROVIDERS = {};
  3950. Ext.Direct.Transaction = function(config){
  3951.     Ext.apply(this, config);
  3952.     this.tid = ++Ext.Direct.TID;
  3953.     this.retryCount = 0;
  3954. };
  3955. Ext.Direct.Transaction.prototype = {
  3956.     send: function(){
  3957.         this.provider.queueTransaction(this);
  3958.     },
  3959.     retry: function(){
  3960.         this.retryCount++;
  3961.         this.send();
  3962.     },
  3963.     getProvider: function(){
  3964.         return this.provider;
  3965.     }
  3966. };Ext.Direct.Event = function(config){
  3967.     Ext.apply(this, config);
  3968. }
  3969. Ext.Direct.Event.prototype = {
  3970.     status: true,
  3971.     getData: function(){
  3972.         return this.data;
  3973.     }
  3974. };
  3975. Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
  3976.     type: 'rpc',
  3977.     getTransaction: function(){
  3978.         return this.transaction || Ext.Direct.getTransaction(this.tid);
  3979.     }
  3980. });
  3981. Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
  3982.     status: false,
  3983.     type: 'exception'
  3984. });
  3985. Ext.Direct.eventTypes = {
  3986.     'rpc':  Ext.Direct.RemotingEvent,
  3987.     'event':  Ext.Direct.Event,
  3988.     'exception':  Ext.Direct.ExceptionEvent
  3989. };
  3990. Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
  3991.     
  3992.         
  3993.         
  3994.     priority: 1,
  3995.         
  3996.  
  3997.     
  3998.     constructor : function(config){
  3999.         Ext.apply(this, config);
  4000.         this.addEvents(
  4001.                         
  4002.             'connect',
  4003.                         
  4004.             'disconnect',
  4005.                         
  4006.             'data',
  4007.