ext-all-debug.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:2341k
源码类别:

中间件编程

开发平台:

JavaScript

  1.         if(this.enableFont && !Ext.isSafari2){
  2.             this.fontSelect = tb.el.createChild({
  3.                 tag:'select',
  4.                 cls:'x-font-select',
  5.                 html: this.createFontOptions()
  6.             });
  7.             this.mon(this.fontSelect, 'change', function(){
  8.                 var font = this.fontSelect.dom.value;
  9.                 this.relayCmd('fontname', font);
  10.                 this.deferFocus();
  11.             }, this);
  12.             tb.add(
  13.                 this.fontSelect.dom,
  14.                 '-'
  15.             );
  16.         }
  17.         if(this.enableFormat){
  18.             tb.add(
  19.                 btn('bold'),
  20.                 btn('italic'),
  21.                 btn('underline')
  22.             );
  23.         }
  24.         if(this.enableFontSize){
  25.             tb.add(
  26.                 '-',
  27.                 btn('increasefontsize', false, this.adjustFont),
  28.                 btn('decreasefontsize', false, this.adjustFont)
  29.             );
  30.         }
  31.         if(this.enableColors){
  32.             tb.add(
  33.                 '-', {
  34.                     itemId:'forecolor',
  35.                     cls:'x-btn-icon',
  36.                     iconCls: 'x-edit-forecolor',
  37.                     clickEvent:'mousedown',
  38.                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
  39.                     tabIndex:-1,
  40.                     menu : new Ext.menu.ColorMenu({
  41.                         allowReselect: true,
  42.                         focus: Ext.emptyFn,
  43.                         value:'000000',
  44.                         plain:true,
  45.                         listeners: {
  46.                             scope: this,
  47.                             select: function(cp, color){
  48.                                 this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
  49.                                 this.deferFocus();
  50.                             }
  51.                         },
  52.                         clickEvent:'mousedown'
  53.                     })
  54.                 }, {
  55.                     itemId:'backcolor',
  56.                     cls:'x-btn-icon',
  57.                     iconCls: 'x-edit-backcolor',
  58.                     clickEvent:'mousedown',
  59.                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
  60.                     tabIndex:-1,
  61.                     menu : new Ext.menu.ColorMenu({
  62.                         focus: Ext.emptyFn,
  63.                         value:'FFFFFF',
  64.                         plain:true,
  65.                         allowReselect: true,
  66.                         listeners: {
  67.                             scope: this,
  68.                             select: function(cp, color){
  69.                                 if(Ext.isGecko){
  70.                                     this.execCmd('useCSS', false);
  71.                                     this.execCmd('hilitecolor', color);
  72.                                     this.execCmd('useCSS', true);
  73.                                     this.deferFocus();
  74.                                 }else{
  75.                                     this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
  76.                                     this.deferFocus();
  77.                                 }
  78.                             }
  79.                         },
  80.                         clickEvent:'mousedown'
  81.                     })
  82.                 }
  83.             );
  84.         }
  85.         if(this.enableAlignments){
  86.             tb.add(
  87.                 '-',
  88.                 btn('justifyleft'),
  89.                 btn('justifycenter'),
  90.                 btn('justifyright')
  91.             );
  92.         }
  93.         if(!Ext.isSafari2){
  94.             if(this.enableLinks){
  95.                 tb.add(
  96.                     '-',
  97.                     btn('createlink', false, this.createLink)
  98.                 );
  99.             }
  100.             if(this.enableLists){
  101.                 tb.add(
  102.                     '-',
  103.                     btn('insertorderedlist'),
  104.                     btn('insertunorderedlist')
  105.                 );
  106.             }
  107.             if(this.enableSourceEdit){
  108.                 tb.add(
  109.                     '-',
  110.                     btn('sourceedit', true, function(btn){
  111.                         this.toggleSourceEdit(!this.sourceEditMode);
  112.                     })
  113.                 );
  114.             }
  115.         }
  116.         this.tb = tb;
  117.     },
  118.     /**
  119.      * Protected method that will not generally be called directly. It
  120.      * is called when the editor initializes the iframe with HTML contents. Override this method if you
  121.      * want to change the initialization markup of the iframe (e.g. to add stylesheets).
  122.      */
  123.     getDocMarkup : function(){
  124.         return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';
  125.     },
  126.     // private
  127.     getEditorBody : function(){
  128.         return this.doc.body || this.doc.documentElement;
  129.     },
  130.     // private
  131.     getDoc : function(){
  132.         return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
  133.     },
  134.     // private
  135.     getWin : function(){
  136.         return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
  137.     },
  138.     // private
  139.     onRender : function(ct, position){
  140.         Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
  141.         this.el.dom.style.border = '0 none';
  142.         this.el.dom.setAttribute('tabIndex', -1);
  143.         this.el.addClass('x-hidden');
  144.         if(Ext.isIE){ // fix IE 1px bogus margin
  145.             this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
  146.         }
  147.         this.wrap = this.el.wrap({
  148.             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
  149.         });
  150.         this.createToolbar(this);
  151.         this.disableItems(true);
  152.         // is this needed?
  153.         // this.tb.doLayout();
  154.         this.createIFrame();
  155.         if(!this.width){
  156.             var sz = this.el.getSize();
  157.             this.setSize(sz.width, this.height || sz.height);
  158.         }
  159.     },
  160.     createIFrame: function(){
  161.         var iframe = document.createElement('iframe');
  162.         iframe.name = Ext.id();
  163.         iframe.frameBorder = '0';
  164.         iframe.src = Ext.isIE ? Ext.SSL_SECURE_URL : "javascript:;";
  165.         this.wrap.dom.appendChild(iframe);
  166.         this.iframe = iframe;
  167.         this.monitorTask = Ext.TaskMgr.start({
  168.             run: this.checkDesignMode,
  169.             scope: this,
  170.             interval:100
  171.         });
  172.     },
  173.     initFrame : function(){
  174.         Ext.TaskMgr.stop(this.monitorTask);
  175.         this.doc = this.getDoc();
  176.         this.win = this.getWin();
  177.         this.doc.open();
  178.         this.doc.write(this.getDocMarkup());
  179.         this.doc.close();
  180.         var task = { // must defer to wait for browser to be ready
  181.             run : function(){
  182.                 if(this.doc.body || this.doc.readyState == 'complete'){
  183.                     Ext.TaskMgr.stop(task);
  184.                     this.doc.designMode="on";
  185.                     this.initEditor.defer(10, this);
  186.                 }
  187.             },
  188.             interval : 10,
  189.             duration:10000,
  190.             scope: this
  191.         };
  192.         Ext.TaskMgr.start(task);
  193.     },
  194.     checkDesignMode : function(){
  195.         if(this.wrap && this.wrap.dom.offsetWidth){
  196.             var doc = this.getDoc();
  197.             if(!doc){
  198.                 return;
  199.             }
  200.             if(!doc.editorInitialized || String(doc.designMode).toLowerCase() != 'on'){
  201.                 this.initFrame();
  202.             }
  203.         }
  204.     },
  205.     
  206.     disableItems: function(disabled){
  207.         if(this.fontSelect){
  208.             this.fontSelect.dom.disabled = disabled;
  209.         }
  210.         this.tb.items.each(function(item){
  211.             if(item.itemId != 'sourceedit'){
  212.                 item.setDisabled(disabled);
  213.             }
  214.         });
  215.     },
  216.     // private
  217.     onResize : function(w, h){
  218.         Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
  219.         if(this.el && this.iframe){
  220.             if(typeof w == 'number'){
  221.                 var aw = w - this.wrap.getFrameWidth('lr');
  222.                 this.el.setWidth(this.adjustWidth('textarea', aw));
  223.                 this.tb.setWidth(aw);
  224.                 this.iframe.style.width = Math.max(aw, 0) + 'px';
  225.             }
  226.             if(typeof h == 'number'){
  227.                 var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
  228.                 this.el.setHeight(this.adjustWidth('textarea', ah));
  229.                 this.iframe.style.height = Math.max(ah, 0) + 'px';
  230.                 if(this.doc){
  231.                     this.getEditorBody().style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
  232.                 }
  233.             }
  234.         }
  235.     },
  236.     /**
  237.      * Toggles the editor between standard and source edit mode.
  238.      * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
  239.      */
  240.     toggleSourceEdit : function(sourceEditMode){
  241.         if(sourceEditMode === undefined){
  242.             sourceEditMode = !this.sourceEditMode;
  243.         }
  244.         this.sourceEditMode = sourceEditMode === true;
  245.         var btn = this.tb.items.get('sourceedit');
  246.         if(btn.pressed !== this.sourceEditMode){
  247.             btn.toggle(this.sourceEditMode);
  248.             if(!btn.xtbHidden){
  249.                 return;
  250.             }
  251.         }
  252.         if(this.sourceEditMode){
  253.             this.disableItems(true);
  254.             this.syncValue();
  255.             this.iframe.className = 'x-hidden';
  256.             this.el.removeClass('x-hidden');
  257.             this.el.dom.removeAttribute('tabIndex');
  258.             this.el.focus();
  259.         }else{
  260.             if(this.initialized){
  261.                 this.disableItems(false);
  262.             }
  263.             this.pushValue();
  264.             this.iframe.className = '';
  265.             this.el.addClass('x-hidden');
  266.             this.el.dom.setAttribute('tabIndex', -1);
  267.             this.deferFocus();
  268.         }
  269.         var lastSize = this.lastSize;
  270.         if(lastSize){
  271.             delete this.lastSize;
  272.             this.setSize(lastSize);
  273.         }
  274.         this.fireEvent('editmodechange', this, this.sourceEditMode);
  275.     },
  276.     // private used internally
  277.     createLink : function(){
  278.         var url = prompt(this.createLinkText, this.defaultLinkValue);
  279.         if(url && url != 'http:/'+'/'){
  280.             this.relayCmd('createlink', url);
  281.         }
  282.     },
  283.     // private (for BoxComponent)
  284.     adjustSize : Ext.BoxComponent.prototype.adjustSize,
  285.     // private (for BoxComponent)
  286.     getResizeEl : function(){
  287.         return this.wrap;
  288.     },
  289.     // private (for BoxComponent)
  290.     getPositionEl : function(){
  291.         return this.wrap;
  292.     },
  293.     // private
  294.     initEvents : function(){
  295.         this.originalValue = this.getValue();
  296.     },
  297.     /**
  298.      * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
  299.      * @method
  300.      */
  301.     markInvalid : Ext.emptyFn,
  302.     
  303.     /**
  304.      * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
  305.      * @method
  306.      */
  307.     clearInvalid : Ext.emptyFn,
  308.     // docs inherit from Field
  309.     setValue : function(v){
  310.         Ext.form.HtmlEditor.superclass.setValue.call(this, v);
  311.         this.pushValue();
  312.         return this;
  313.     },
  314.     /**
  315.      * Protected method that will not generally be called directly. If you need/want
  316.      * custom HTML cleanup, this is the method you should override.
  317.      * @param {String} html The HTML to be cleaned
  318.      * @return {String} The cleaned HTML
  319.      */
  320.     cleanHtml : function(html){
  321.         html = String(html);
  322.         if(html.length > 5){
  323.             if(Ext.isWebKit){ // strip safari nonsense
  324.                 html = html.replace(/sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
  325.             }
  326.         }
  327.         if(html == this.defaultValue){
  328.             html = '';
  329.         }
  330.         return html;
  331.     },
  332.     /**
  333.      * Protected method that will not generally be called directly. Syncs the contents
  334.      * of the editor iframe with the textarea.
  335.      */
  336.     syncValue : function(){
  337.         if(this.initialized){
  338.             var bd = this.getEditorBody();
  339.             var html = bd.innerHTML;
  340.             if(Ext.isWebKit){
  341.                 var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
  342.                 var m = bs.match(/text-align:(.*?);/i);
  343.                 if(m && m[1]){
  344.                     html = '<div style="'+m[0]+'">' + html + '</div>';
  345.                 }
  346.             }
  347.             html = this.cleanHtml(html);
  348.             if(this.fireEvent('beforesync', this, html) !== false){
  349.                 this.el.dom.value = html;
  350.                 this.fireEvent('sync', this, html);
  351.             }
  352.         }
  353.     },
  354.     
  355.     //docs inherit from Field
  356.     getValue : function() {
  357.         this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
  358.         return Ext.form.HtmlEditor.superclass.getValue.call(this);
  359.     },
  360.     /**
  361.      * Protected method that will not generally be called directly. Pushes the value of the textarea
  362.      * into the iframe editor.
  363.      */
  364.     pushValue : function(){
  365.         if(this.initialized){
  366.             var v = this.el.dom.value;
  367.             if(!this.activated && v.length < 1){
  368.                 v = this.defaultValue;
  369.             }
  370.             if(this.fireEvent('beforepush', this, v) !== false){
  371.                 this.getEditorBody().innerHTML = v;
  372.                 if(Ext.isGecko){
  373.                     // Gecko hack, see: https://bugzilla.mozilla.org/show_bug.cgi?id=232791#c8
  374.                     var d = this.doc,
  375.                         mode = d.designMode.toLowerCase();
  376.                     
  377.                     d.designMode = mode.toggle('on', 'off');
  378.                     d.designMode = mode;
  379.                 }
  380.                 this.fireEvent('push', this, v);
  381.             }
  382.         }
  383.     },
  384.     // private
  385.     deferFocus : function(){
  386.         this.focus.defer(10, this);
  387.     },
  388.     // docs inherit from Field
  389.     focus : function(){
  390.         if(this.win && !this.sourceEditMode){
  391.             this.win.focus();
  392.         }else{
  393.             this.el.focus();
  394.         }
  395.     },
  396.     // private
  397.     initEditor : function(){
  398.         //Destroying the component during/before initEditor can cause issues.
  399.         try{
  400.             var dbody = this.getEditorBody();
  401.             var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
  402.             ss['background-attachment'] = 'fixed'; // w3c
  403.             dbody.bgProperties = 'fixed'; // ie
  404.             Ext.DomHelper.applyStyles(dbody, ss);
  405.             if(this.doc){
  406.                 try{
  407.                     Ext.EventManager.removeAll(this.doc);
  408.                 }catch(e){}
  409.             }
  410.             this.doc = this.getDoc();
  411.             Ext.EventManager.on(this.doc, {
  412.                 'mousedown': this.onEditorEvent,
  413.                 'dblclick': this.onEditorEvent,
  414.                 'click': this.onEditorEvent,
  415.                 'keyup': this.onEditorEvent,
  416.                 buffer:100,
  417.                 scope: this
  418.             });
  419.             if(Ext.isGecko){
  420.                 Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);
  421.             }
  422.             if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
  423.                 Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
  424.             }
  425.             this.initialized = true;
  426.             this.fireEvent('initialize', this);
  427.             this.doc.editorInitialized = true;
  428.             this.pushValue();
  429.         }catch(e){}
  430.     },
  431.     // private
  432.     onDestroy : function(){
  433.         if(this.monitorTask){
  434.             Ext.TaskMgr.stop(this.monitorTask);
  435.         }
  436.         if(this.rendered){
  437.             Ext.destroy(this.tb);
  438.             if(this.wrap){
  439.                 this.wrap.dom.innerHTML = '';
  440.                 this.wrap.remove();
  441.             }
  442.         }
  443.         if(this.el){
  444.             this.el.removeAllListeners();
  445.             this.el.remove();
  446.         }
  447.  
  448.         if(this.doc){
  449.             try{
  450.                 Ext.EventManager.removeAll(this.doc);
  451.                 for (var prop in this.doc){
  452.                    delete this.doc[prop];
  453.                 }
  454.             }catch(e){}
  455.         }
  456.         this.purgeListeners();
  457.     },
  458.     // private
  459.     onFirstFocus : function(){
  460.         this.activated = true;
  461.         this.disableItems(false);
  462.         if(Ext.isGecko){ // prevent silly gecko errors
  463.             this.win.focus();
  464.             var s = this.win.getSelection();
  465.             if(!s.focusNode || s.focusNode.nodeType != 3){
  466.                 var r = s.getRangeAt(0);
  467.                 r.selectNodeContents(this.getEditorBody());
  468.                 r.collapse(true);
  469.                 this.deferFocus();
  470.             }
  471.             try{
  472.                 this.execCmd('useCSS', true);
  473.                 this.execCmd('styleWithCSS', false);
  474.             }catch(e){}
  475.         }
  476.         this.fireEvent('activate', this);
  477.     },
  478.     // private
  479.     adjustFont: function(btn){
  480.         var adjust = btn.itemId == 'increasefontsize' ? 1 : -1;
  481.         var v = parseInt(this.doc.queryCommandValue('FontSize') || 2, 10);
  482.         if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
  483.             // Safari 3 values
  484.             // 1 = 10px, 2 = 13px, 3 = 16px, 4 = 18px, 5 = 24px, 6 = 32px
  485.             if(v <= 10){
  486.                 v = 1 + adjust;
  487.             }else if(v <= 13){
  488.                 v = 2 + adjust;
  489.             }else if(v <= 16){
  490.                 v = 3 + adjust;
  491.             }else if(v <= 18){
  492.                 v = 4 + adjust;
  493.             }else if(v <= 24){
  494.                 v = 5 + adjust;
  495.             }else {
  496.                 v = 6 + adjust;
  497.             }
  498.             v = v.constrain(1, 6);
  499.         }else{
  500.             if(Ext.isSafari){ // safari
  501.                 adjust *= 2;
  502.             }
  503.             v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
  504.         }
  505.         this.execCmd('FontSize', v);
  506.     },
  507.     // private
  508.     onEditorEvent : function(e){
  509.         this.updateToolbar();
  510.     },
  511.     /**
  512.      * Protected method that will not generally be called directly. It triggers
  513.      * a toolbar update by reading the markup state of the current selection in the editor.
  514.      */
  515.     updateToolbar: function(){
  516.         if(!this.activated){
  517.             this.onFirstFocus();
  518.             return;
  519.         }
  520.         var btns = this.tb.items.map, doc = this.doc;
  521.         if(this.enableFont && !Ext.isSafari2){
  522.             var name = (this.doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
  523.             if(name != this.fontSelect.dom.value){
  524.                 this.fontSelect.dom.value = name;
  525.             }
  526.         }
  527.         if(this.enableFormat){
  528.             btns.bold.toggle(doc.queryCommandState('bold'));
  529.             btns.italic.toggle(doc.queryCommandState('italic'));
  530.             btns.underline.toggle(doc.queryCommandState('underline'));
  531.         }
  532.         if(this.enableAlignments){
  533.             btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
  534.             btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
  535.             btns.justifyright.toggle(doc.queryCommandState('justifyright'));
  536.         }
  537.         if(!Ext.isSafari2 && this.enableLists){
  538.             btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
  539.             btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
  540.         }
  541.         
  542.         Ext.menu.MenuMgr.hideAll();
  543.         this.syncValue();
  544.     },
  545.     // private
  546.     relayBtnCmd : function(btn){
  547.         this.relayCmd(btn.itemId);
  548.     },
  549.     /**
  550.      * Executes a Midas editor command on the editor document and performs necessary focus and
  551.      * toolbar updates. <b>This should only be called after the editor is initialized.</b>
  552.      * @param {String} cmd The Midas command
  553.      * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
  554.      */
  555.     relayCmd : function(cmd, value){
  556.         (function(){
  557.             this.focus();
  558.             this.execCmd(cmd, value);
  559.             this.updateToolbar();
  560.         }).defer(10, this);
  561.     },
  562.     /**
  563.      * Executes a Midas editor command directly on the editor document.
  564.      * For visual commands, you should use {@link #relayCmd} instead.
  565.      * <b>This should only be called after the editor is initialized.</b>
  566.      * @param {String} cmd The Midas command
  567.      * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
  568.      */
  569.     execCmd : function(cmd, value){
  570.         this.doc.execCommand(cmd, false, value === undefined ? null : value);
  571.         this.syncValue();
  572.     },
  573.     // private
  574.     applyCommand : function(e){
  575.         if(e.ctrlKey){
  576.             var c = e.getCharCode(), cmd;
  577.             if(c > 0){
  578.                 c = String.fromCharCode(c);
  579.                 switch(c){
  580.                     case 'b':
  581.                         cmd = 'bold';
  582.                     break;
  583.                     case 'i':
  584.                         cmd = 'italic';
  585.                     break;
  586.                     case 'u':
  587.                         cmd = 'underline';
  588.                     break;
  589.                 }
  590.                 if(cmd){
  591.                     this.win.focus();
  592.                     this.execCmd(cmd);
  593.                     this.deferFocus();
  594.                     e.preventDefault();
  595.                 }
  596.             }
  597.         }
  598.     },
  599.     /**
  600.      * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
  601.      * to insert text.
  602.      * @param {String} text
  603.      */
  604.     insertAtCursor : function(text){
  605.         if(!this.activated){
  606.             return;
  607.         }
  608.         if(Ext.isIE){
  609.             this.win.focus();
  610.             var r = this.doc.selection.createRange();
  611.             if(r){
  612.                 r.collapse(true);
  613.                 r.pasteHTML(text);
  614.                 this.syncValue();
  615.                 this.deferFocus();
  616.             }
  617.         }else if(Ext.isGecko || Ext.isOpera){
  618.             this.win.focus();
  619.             this.execCmd('InsertHTML', text);
  620.             this.deferFocus();
  621.         }else if(Ext.isWebKit){
  622.             this.execCmd('InsertText', text);
  623.             this.deferFocus();
  624.         }
  625.     },
  626.     // private
  627.     fixKeys : function(){ // load time branching for fastest keydown performance
  628.         if(Ext.isIE){
  629.             return function(e){
  630.                 var k = e.getKey(), r;
  631.                 if(k == e.TAB){
  632.                     e.stopEvent();
  633.                     r = this.doc.selection.createRange();
  634.                     if(r){
  635.                         r.collapse(true);
  636.                         r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
  637.                         this.deferFocus();
  638.                     }
  639.                 }else if(k == e.ENTER){
  640.                     r = this.doc.selection.createRange();
  641.                     if(r){
  642.                         var target = r.parentElement();
  643.                         if(!target || target.tagName.toLowerCase() != 'li'){
  644.                             e.stopEvent();
  645.                             r.pasteHTML('<br />');
  646.                             r.collapse(false);
  647.                             r.select();
  648.                         }
  649.                     }
  650.                 }
  651.             };
  652.         }else if(Ext.isOpera){
  653.             return function(e){
  654.                 var k = e.getKey();
  655.                 if(k == e.TAB){
  656.                     e.stopEvent();
  657.                     this.win.focus();
  658.                     this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
  659.                     this.deferFocus();
  660.                 }
  661.             };
  662.         }else if(Ext.isWebKit){
  663.             return function(e){
  664.                 var k = e.getKey();
  665.                 if(k == e.TAB){
  666.                     e.stopEvent();
  667.                     this.execCmd('InsertText','t');
  668.                     this.deferFocus();
  669.                 }
  670.              };
  671.         }
  672.     }(),
  673.     /**
  674.      * Returns the editor's toolbar. <b>This is only available after the editor has been rendered.</b>
  675.      * @return {Ext.Toolbar}
  676.      */
  677.     getToolbar : function(){
  678.         return this.tb;
  679.     },
  680.     /**
  681.      * Object collection of toolbar tooltips for the buttons in the editor. The key
  682.      * is the command id associated with that button and the value is a valid QuickTips object.
  683.      * For example:
  684. <pre><code>
  685. {
  686.     bold : {
  687.         title: 'Bold (Ctrl+B)',
  688.         text: 'Make the selected text bold.',
  689.         cls: 'x-html-editor-tip'
  690.     },
  691.     italic : {
  692.         title: 'Italic (Ctrl+I)',
  693.         text: 'Make the selected text italic.',
  694.         cls: 'x-html-editor-tip'
  695.     },
  696.     ...
  697. </code></pre>
  698.     * @type Object
  699.      */
  700.     buttonTips : {
  701.         bold : {
  702.             title: 'Bold (Ctrl+B)',
  703.             text: 'Make the selected text bold.',
  704.             cls: 'x-html-editor-tip'
  705.         },
  706.         italic : {
  707.             title: 'Italic (Ctrl+I)',
  708.             text: 'Make the selected text italic.',
  709.             cls: 'x-html-editor-tip'
  710.         },
  711.         underline : {
  712.             title: 'Underline (Ctrl+U)',
  713.             text: 'Underline the selected text.',
  714.             cls: 'x-html-editor-tip'
  715.         },
  716.         increasefontsize : {
  717.             title: 'Grow Text',
  718.             text: 'Increase the font size.',
  719.             cls: 'x-html-editor-tip'
  720.         },
  721.         decreasefontsize : {
  722.             title: 'Shrink Text',
  723.             text: 'Decrease the font size.',
  724.             cls: 'x-html-editor-tip'
  725.         },
  726.         backcolor : {
  727.             title: 'Text Highlight Color',
  728.             text: 'Change the background color of the selected text.',
  729.             cls: 'x-html-editor-tip'
  730.         },
  731.         forecolor : {
  732.             title: 'Font Color',
  733.             text: 'Change the color of the selected text.',
  734.             cls: 'x-html-editor-tip'
  735.         },
  736.         justifyleft : {
  737.             title: 'Align Text Left',
  738.             text: 'Align text to the left.',
  739.             cls: 'x-html-editor-tip'
  740.         },
  741.         justifycenter : {
  742.             title: 'Center Text',
  743.             text: 'Center text in the editor.',
  744.             cls: 'x-html-editor-tip'
  745.         },
  746.         justifyright : {
  747.             title: 'Align Text Right',
  748.             text: 'Align text to the right.',
  749.             cls: 'x-html-editor-tip'
  750.         },
  751.         insertunorderedlist : {
  752.             title: 'Bullet List',
  753.             text: 'Start a bulleted list.',
  754.             cls: 'x-html-editor-tip'
  755.         },
  756.         insertorderedlist : {
  757.             title: 'Numbered List',
  758.             text: 'Start a numbered list.',
  759.             cls: 'x-html-editor-tip'
  760.         },
  761.         createlink : {
  762.             title: 'Hyperlink',
  763.             text: 'Make the selected text a hyperlink.',
  764.             cls: 'x-html-editor-tip'
  765.         },
  766.         sourceedit : {
  767.             title: 'Source Edit',
  768.             text: 'Switch to source editing mode.',
  769.             cls: 'x-html-editor-tip'
  770.         }
  771.     }
  772.     // hide stuff that is not compatible
  773.     /**
  774.      * @event blur
  775.      * @hide
  776.      */
  777.     /**
  778.      * @event change
  779.      * @hide
  780.      */
  781.     /**
  782.      * @event focus
  783.      * @hide
  784.      */
  785.     /**
  786.      * @event specialkey
  787.      * @hide
  788.      */
  789.     /**
  790.      * @cfg {String} fieldClass @hide
  791.      */
  792.     /**
  793.      * @cfg {String} focusClass @hide
  794.      */
  795.     /**
  796.      * @cfg {String} autoCreate @hide
  797.      */
  798.     /**
  799.      * @cfg {String} inputType @hide
  800.      */
  801.     /**
  802.      * @cfg {String} invalidClass @hide
  803.      */
  804.     /**
  805.      * @cfg {String} invalidText @hide
  806.      */
  807.     /**
  808.      * @cfg {String} msgFx @hide
  809.      */
  810.     /**
  811.      * @cfg {String} validateOnBlur @hide
  812.      */
  813.     /**
  814.      * @cfg {Boolean} allowDomMove  @hide
  815.      */
  816.     /**
  817.      * @cfg {String} applyTo @hide
  818.      */
  819.     /**
  820.      * @cfg {String} autoHeight  @hide
  821.      */
  822.     /**
  823.      * @cfg {String} autoWidth  @hide
  824.      */
  825.     /**
  826.      * @cfg {String} cls  @hide
  827.      */
  828.     /**
  829.      * @cfg {String} disabled  @hide
  830.      */
  831.     /**
  832.      * @cfg {String} disabledClass  @hide
  833.      */
  834.     /**
  835.      * @cfg {String} msgTarget  @hide
  836.      */
  837.     /**
  838.      * @cfg {String} readOnly  @hide
  839.      */
  840.     /**
  841.      * @cfg {String} style  @hide
  842.      */
  843.     /**
  844.      * @cfg {String} validationDelay  @hide
  845.      */
  846.     /**
  847.      * @cfg {String} validationEvent  @hide
  848.      */
  849.     /**
  850.      * @cfg {String} tabIndex  @hide
  851.      */
  852.     /**
  853.      * @property disabled
  854.      * @hide
  855.      */
  856.     /**
  857.      * @method applyToMarkup
  858.      * @hide
  859.      */
  860.     /**
  861.      * @method disable
  862.      * @hide
  863.      */
  864.     /**
  865.      * @method enable
  866.      * @hide
  867.      */
  868.     /**
  869.      * @method validate
  870.      * @hide
  871.      */
  872.     /**
  873.      * @event valid
  874.      * @hide
  875.      */
  876.     /**
  877.      * @method setDisabled
  878.      * @hide
  879.      */
  880.     /**
  881.      * @cfg keys
  882.      * @hide
  883.      */
  884. });
  885. Ext.reg('htmleditor', Ext.form.HtmlEditor);/**
  886.  * @class Ext.form.TimeField
  887.  * @extends Ext.form.ComboBox
  888.  * Provides a time input field with a time dropdown and automatic time validation.  Example usage:
  889.  * <pre><code>
  890. new Ext.form.TimeField({
  891.     minValue: '9:00 AM',
  892.     maxValue: '6:00 PM',
  893.     increment: 30
  894. });
  895. </code></pre>
  896.  * @constructor
  897.  * Create a new TimeField
  898.  * @param {Object} config
  899.  * @xtype timefield
  900.  */
  901. Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
  902.     /**
  903.      * @cfg {Date/String} minValue
  904.      * The minimum allowed time. Can be either a Javascript date object with a valid time value or a string 
  905.      * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to null).
  906.      */
  907.     minValue : null,
  908.     /**
  909.      * @cfg {Date/String} maxValue
  910.      * The maximum allowed time. Can be either a Javascript date object with a valid time value or a string 
  911.      * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to null).
  912.      */
  913.     maxValue : null,
  914.     /**
  915.      * @cfg {String} minText
  916.      * The error text to display when the date in the cell is before minValue (defaults to
  917.      * 'The time in this field must be equal to or after {0}').
  918.      */
  919.     minText : "The time in this field must be equal to or after {0}",
  920.     /**
  921.      * @cfg {String} maxText
  922.      * The error text to display when the time is after maxValue (defaults to
  923.      * 'The time in this field must be equal to or before {0}').
  924.      */
  925.     maxText : "The time in this field must be equal to or before {0}",
  926.     /**
  927.      * @cfg {String} invalidText
  928.      * The error text to display when the time in the field is invalid (defaults to
  929.      * '{value} is not a valid time').
  930.      */
  931.     invalidText : "{0} is not a valid time",
  932.     /**
  933.      * @cfg {String} format
  934.      * The default time format string which can be overriden for localization support.  The format must be
  935.      * valid according to {@link Date#parseDate} (defaults to 'g:i A', e.g., '3:15 PM').  For 24-hour time
  936.      * format try 'H:i' instead.
  937.      */
  938.     format : "g:i A",
  939.     /**
  940.      * @cfg {String} altFormats
  941.      * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
  942.      * format (defaults to 'g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H').
  943.      */
  944.     altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H",
  945.     /**
  946.      * @cfg {Number} increment
  947.      * The number of minutes between each time value in the list (defaults to 15).
  948.      */
  949.     increment: 15,
  950.     // private override
  951.     mode: 'local',
  952.     // private override
  953.     triggerAction: 'all',
  954.     // private override
  955.     typeAhead: false,
  956.     
  957.     // private - This is the date to use when generating time values in the absence of either minValue
  958.     // or maxValue.  Using the current date causes DST issues on DST boundary dates, so this is an 
  959.     // arbitrary "safe" date that can be any date aside from DST boundary dates.
  960.     initDate: '1/1/2008',
  961.     // private
  962.     initComponent : function(){
  963.         if(typeof this.minValue == "string"){
  964.             this.minValue = this.parseDate(this.minValue);
  965.         }
  966.         if(typeof this.maxValue == "string"){
  967.             this.maxValue = this.parseDate(this.maxValue);
  968.         }
  969.         if(!this.store){
  970.             var min = this.parseDate(this.minValue) || new Date(this.initDate).clearTime();
  971.             var max = this.parseDate(this.maxValue) || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1);
  972.             var times = [];
  973.             while(min <= max){
  974.                 times.push(min.dateFormat(this.format));
  975.                 min = min.add('mi', this.increment);
  976.             }
  977.             this.store = times;
  978.         }
  979.         Ext.form.TimeField.superclass.initComponent.call(this);
  980.     },
  981.     // inherited docs
  982.     getValue : function(){
  983.         var v = Ext.form.TimeField.superclass.getValue.call(this);
  984.         return this.formatDate(this.parseDate(v)) || '';
  985.     },
  986.     // inherited docs
  987.     setValue : function(value){
  988.         return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
  989.     },
  990.     // private overrides
  991.     validateValue : Ext.form.DateField.prototype.validateValue,
  992.     parseDate : Ext.form.DateField.prototype.parseDate,
  993.     formatDate : Ext.form.DateField.prototype.formatDate,
  994.     // private
  995.     beforeBlur : function(){
  996.         var v = this.parseDate(this.getRawValue());
  997.         if(v){
  998.             this.setValue(v.dateFormat(this.format));
  999.         }
  1000.         Ext.form.TimeField.superclass.beforeBlur.call(this);
  1001.     }
  1002.     /**
  1003.      * @cfg {Boolean} grow @hide
  1004.      */
  1005.     /**
  1006.      * @cfg {Number} growMin @hide
  1007.      */
  1008.     /**
  1009.      * @cfg {Number} growMax @hide
  1010.      */
  1011.     /**
  1012.      * @hide
  1013.      * @method autoSize
  1014.      */
  1015. });
  1016. Ext.reg('timefield', Ext.form.TimeField);/**  * @class Ext.form.Label  * @extends Ext.BoxComponent  * Basic Label field.  * @constructor  * Creates a new Label  * @param {Ext.Element/String/Object} config The configuration options.  If an element is passed, it is set as the internal  * element and its id used as the component id.  If a string is passed, it is assumed to be the id of an existing element  * and is used as the component id.  Otherwise, it is assumed to be a standard config object and is applied to the component.  * @xtype label  */ Ext.form.Label = Ext.extend(Ext.BoxComponent, {     /**      * @cfg {String} text The plain text to display within the label (defaults to ''). If you need to include HTML      * tags within the label's innerHTML, use the {@link #html} config instead.      */     /**      * @cfg {String} forId The id of the input element to which this label will be bound via the standard HTML 'for'      * attribute. If not specified, the attribute will not be added to the label.      */     /**      * @cfg {String} html An HTML fragment that will be used as the label's innerHTML (defaults to '').      * Note that if {@link #text} is specified it will take precedence and this value will be ignored.      */     // private     onRender : function(ct, position){         if(!this.el){             this.el = document.createElement('label');             this.el.id = this.getId();             this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');             if(this.forId){                 this.el.setAttribute('for', this.forId);             }         }         Ext.form.Label.superclass.onRender.call(this, ct, position);     },     /**      * Updates the label's innerHTML with the specified string.      * @param {String} text The new label text      * @param {Boolean} encode (optional) False to skip HTML-encoding the text when rendering it      * to the label (defaults to true which encodes the value). This might be useful if you want to include      * tags in the label's innerHTML rather than rendering them as string literals per the default logic.      * @return {Label} this      */     setText : function(t, encode){         var e = encode === false;         this[!e ? 'text' : 'html'] = t;         delete this[e ? 'text' : 'html'];         if(this.rendered){             this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;         }         return this;     } }); Ext.reg('label', Ext.form.Label);/**  * @class Ext.form.Action  * <p>The subclasses of this class provide actions to perform upon {@link Ext.form.BasicForm Form}s.</p>  * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when  * the Form needs to perform an action such as submit or load. The Configuration options  * listed for this class are set through the Form's action methods: {@link Ext.form.BasicForm#submit submit},  * {@link Ext.form.BasicForm#load load} and {@link Ext.form.BasicForm#doAction doAction}</p>  * <p>The instance of Action which performed the action is passed to the success  * and failure callbacks of the Form's action methods ({@link Ext.form.BasicForm#submit submit},  * {@link Ext.form.BasicForm#load load} and {@link Ext.form.BasicForm#doAction doAction}),  * and to the {@link Ext.form.BasicForm#actioncomplete actioncomplete} and  * {@link Ext.form.BasicForm#actionfailed actionfailed} event handlers.</p>  */ Ext.form.Action = function(form, options){     this.form = form;     this.options = options || {}; }; /**  * Failure type returned when client side validation of the Form fails  * thus aborting a submit action. Client side validation is performed unless  * {@link #clientValidation} is explicitly set to <tt>false</tt>.  * @type {String}  * @static  */ Ext.form.Action.CLIENT_INVALID = 'client'; /**  * <p>Failure type returned when server side processing fails and the {@link #result}'s  * <tt style="font-weight:bold">success</tt> property is set to <tt>false</tt>.</p>  * <p>In the case of a form submission, field-specific error messages may be returned in the  * {@link #result}'s <tt style="font-weight:bold">errors</tt> property.</p>  * @type {String}  * @static  */ Ext.form.Action.SERVER_INVALID = 'server'; /**  * Failure type returned when a communication error happens when attempting  * to send a request to the remote server. The {@link #response} may be examined to  * provide further information.  * @type {String}  * @static  */ Ext.form.Action.CONNECT_FAILURE = 'connect'; /**  * Failure type returned when the response's <tt style="font-weight:bold">success</tt>  * property is set to <tt>false</tt>, or no field values are returned in the response's  * <tt style="font-weight:bold">data</tt> property.  * @type {String}  * @static  */ Ext.form.Action.LOAD_FAILURE = 'load'; Ext.form.Action.prototype = { /**  * @cfg {String} url The URL that the Action is to invoke.  */ /**  * @cfg {Boolean} reset When set to <tt><b>true</b></tt>, causes the Form to be  * {@link Ext.form.BasicForm.reset reset} on Action success. If specified, this happens  * <b>before</b> the {@link #success} callback is called and before the Form's  * {@link Ext.form.BasicForm.actioncomplete actioncomplete} event fires.  */ /**  * @cfg {String} method The HTTP method to use to access the requested URL. Defaults to the  * {@link Ext.form.BasicForm}'s method, or if that is not specified, the underlying DOM form's method.  */ /**  * @cfg {Mixed} params <p>Extra parameter values to pass. These are added to the Form's  * {@link Ext.form.BasicForm#baseParams} and passed to the specified URL along with the Form's  * input fields.</p>  * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>  */ /**  * @cfg {Number} timeout The number of seconds to wait for a server response before  * failing with the {@link #failureType} as {@link #Action.CONNECT_FAILURE}. If not specified,  * defaults to the configured <tt>{@link Ext.form.BasicForm#timeout timeout}</tt> of the  * {@link Ext.form.BasicForm form}.  */ /**  * @cfg {Function} success The function to call when a valid success return packet is recieved.  * The function is passed the following parameters:<ul class="mdetail-params">  * <li><b>form</b> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>  * <li><b>action</b> : Ext.form.Action<div class="sub-desc">The Action class. The {@link #result}  * property of this object may be examined to perform custom postprocessing.</div></li>  * </ul>  */ /**  * @cfg {Function} failure The function to call when a failure packet was recieved, or when an  * error ocurred in the Ajax communication.  * The function is passed the following parameters:<ul class="mdetail-params">  * <li><b>form</b> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>  * <li><b>action</b> : Ext.form.Action<div class="sub-desc">The Action class. If an Ajax  * error ocurred, the failure type will be in {@link #failureType}. The {@link #result}  * property of this object may be examined to perform custom postprocessing.</div></li>  * </ul>  */ /**  * @cfg {Object} scope The scope in which to call the callback functions (The <tt>this</tt> reference  * for the callback functions).  */ /**  * @cfg {String} waitMsg The message to be displayed by a call to {@link Ext.MessageBox#wait}  * during the time the action is being processed.  */ /**  * @cfg {String} waitTitle The title to be displayed by a call to {@link Ext.MessageBox#wait}  * during the time the action is being processed.  */ /**  * The type of action this Action instance performs.  * Currently only "submit" and "load" are supported.  * @type {String}  */     type : 'default', /**  * The type of failure detected will be one of these: {@link #CLIENT_INVALID},  * {@link #SERVER_INVALID}, {@link #CONNECT_FAILURE}, or {@link #LOAD_FAILURE}.  Usage:  * <pre><code> var fp = new Ext.form.FormPanel({ ... buttons: [{     text: 'Save',     formBind: true,     handler: function(){         if(fp.getForm().isValid()){             fp.getForm().submit({                 url: 'form-submit.php',                 waitMsg: 'Submitting your data...',                 success: function(form, action){                     // server responded with success = true                     var result = action.{@link #result};                 },                 failure: function(form, action){                     if (action.{@link #failureType} === Ext.form.Action.{@link #CONNECT_FAILURE}) {                         Ext.Msg.alert('Error',                             'Status:'+action.{@link #response}.status+': '+                             action.{@link #response}.statusText);                     }                     if (action.failureType === Ext.form.Action.{@link #SERVER_INVALID}){                         // server responded with success = false                         Ext.Msg.alert('Invalid', action.{@link #result}.errormsg);                     }                 }             });         }     } },{     text: 'Reset',     handler: function(){         fp.getForm().reset();     } }]  * </code></pre>  * @property failureType  * @type {String}  */  /**  * The XMLHttpRequest object used to perform the action.  * @property response  * @type {Object}  */  /**  * The decoded response object containing a boolean <tt style="font-weight:bold">success</tt> property and  * other, action-specific properties.  * @property result  * @type {Object}  */     // interface method     run : function(options){     },     // interface method     success : function(response){     },     // interface method     handleResponse : function(response){     },     // default connection failure     failure : function(response){         this.response = response;         this.failureType = Ext.form.Action.CONNECT_FAILURE;         this.form.afterAction(this, false);     },     // private     // shared code among all Actions to validate that there was a response     // with either responseText or responseXml     processResponse : function(response){         this.response = response;         if(!response.responseText && !response.responseXML){             return true;         }         this.result = this.handleResponse(response);         return this.result;     },     // utility functions used internally     getUrl : function(appendParams){         var url = this.options.url || this.form.url || this.form.el.dom.action;         if(appendParams){             var p = this.getParams();             if(p){                 url = Ext.urlAppend(url, p);             }         }         return url;     },     // private     getMethod : function(){         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();     },     // private     getParams : function(){         var bp = this.form.baseParams;         var p = this.options.params;         if(p){             if(typeof p == "object"){                 p = Ext.urlEncode(Ext.applyIf(p, bp));             }else if(typeof p == 'string' && bp){                 p += '&' + Ext.urlEncode(bp);             }         }else if(bp){             p = Ext.urlEncode(bp);         }         return p;     },     // private     createCallback : function(opts){         var opts = opts || {};         return {             success: this.success,             failure: this.failure,             scope: this,             timeout: (opts.timeout*1000) || (this.form.timeout*1000),             upload: this.form.fileUpload ? this.success : undefined         };     } }; /**  * @class Ext.form.Action.Submit  * @extends Ext.form.Action  * <p>A class which handles submission of data from {@link Ext.form.BasicForm Form}s  * and processes the returned response.</p>  * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when  * {@link Ext.form.BasicForm#submit submit}ting.</p>  * <p><u><b>Response Packet Criteria</b></u></p>  * <p>A response packet may contain:  * <div class="mdetail-params"><ul>  * <li><b><code>success</code></b> property : Boolean  * <div class="sub-desc">The <code>success</code> property is required.</div></li>  * <li><b><code>errors</code></b> property : Object  * <div class="sub-desc"><div class="sub-desc">The <code>errors</code> property,  * which is optional, contains error messages for invalid fields.</div></li>  * </ul></div>  * <p><u><b>JSON Packets</b></u></p>  * <p>By default, response packets are assumed to be JSON, so a typical response  * packet may look like this:</p><pre><code> {     success: false,     errors: {         clientCode: "Client not found",         portOfLoading: "This field must not be null"     } }</code></pre>  * <p>Other data may be placed into the response for processing by the {@link Ext.form.BasicForm}'s callback  * or event handler methods. The object decoded from this JSON is available in the  * {@link Ext.form.Action#result result} property.</p>  * <p>Alternatively, if an {@link #errorReader} is specified as an {@link Ext.data.XmlReader XmlReader}:</p><pre><code>     errorReader: new Ext.data.XmlReader({             record : 'field',             success: '@success'         }, [             'id', 'msg'         ]     ) </code></pre>  * <p>then the results may be sent back in XML format:</p><pre><code> &lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;message success="false"&gt; &lt;errors&gt;     &lt;field&gt;         &lt;id&gt;clientCode&lt;/id&gt;         &lt;msg&gt;&lt;![CDATA[Code not found. &lt;br /&gt;&lt;i&gt;This is a test validation message from the server &lt;/i&gt;]]&gt;&lt;/msg&gt;     &lt;/field&gt;     &lt;field&gt;         &lt;id&gt;portOfLoading&lt;/id&gt;         &lt;msg&gt;&lt;![CDATA[Port not found. &lt;br /&gt;&lt;i&gt;This is a test validation message from the server &lt;/i&gt;]]&gt;&lt;/msg&gt;     &lt;/field&gt; &lt;/errors&gt; &lt;/message&gt; </code></pre>  * <p>Other elements may be placed into the response XML for processing by the {@link Ext.form.BasicForm}'s callback  * or event handler methods. The XML document is available in the {@link #errorReader}'s {@link Ext.data.XmlReader#xmlData xmlData} property.</p>  */ Ext.form.Action.Submit = function(form, options){     Ext.form.Action.Submit.superclass.constructor.call(this, form, options); }; Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {     /**      * @cfg {Ext.data.DataReader} errorReader <p><b>Optional. JSON is interpreted with      * no need for an errorReader.</b></p>      * <p>A Reader which reads a single record from the returned data. The DataReader's      * <b>success</b> property specifies how submission success is determined. The Record's      * data provides the error messages to apply to any invalid form Fields.</p>      */     /**      * @cfg {boolean} clientValidation Determines whether a Form's fields are validated      * in a final call to {@link Ext.form.BasicForm#isValid isValid} prior to submission.      * Pass <tt>false</tt> in the Form's submit options to prevent this. If not defined, pre-submission field validation      * is performed.      */     type : 'submit',     // private     run : function(){         var o = this.options;         var method = this.getMethod();         var isGet = method == 'GET';         if(o.clientValidation === false || this.form.isValid()){             Ext.Ajax.request(Ext.apply(this.createCallback(o), {                 form:this.form.el.dom,                 url:this.getUrl(isGet),                 method: method,                 headers: o.headers,                 params:!isGet ? this.getParams() : null,                 isUpload: this.form.fileUpload             }));         }else if (o.clientValidation !== false){ // client validation failed             this.failureType = Ext.form.Action.CLIENT_INVALID;             this.form.afterAction(this, false);         }     },     // private     success : function(response){         var result = this.processResponse(response);         if(result === true || result.success){             this.form.afterAction(this, true);             return;         }         if(result.errors){             this.form.markInvalid(result.errors);             this.failureType = Ext.form.Action.SERVER_INVALID;         }         this.form.afterAction(this, false);     },     // private     handleResponse : function(response){         if(this.form.errorReader){             var rs = this.form.errorReader.read(response);             var errors = [];             if(rs.records){                 for(var i = 0, len = rs.records.length; i < len; i++) {                     var r = rs.records[i];                     errors[i] = r.data;                 }             }             if(errors.length < 1){                 errors = null;             }             return {                 success : rs.success,                 errors : errors             };         }         return Ext.decode(response.responseText);     } }); /**  * @class Ext.form.Action.Load  * @extends Ext.form.Action  * <p>A class which handles loading of data from a server into the Fields of an {@link Ext.form.BasicForm}.</p>  * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when  * {@link Ext.form.BasicForm#load load}ing.</p>  * <p><u><b>Response Packet Criteria</b></u></p>  * <p>A response packet <b>must</b> contain:  * <div class="mdetail-params"><ul>  * <li><b><code>success</code></b> property : Boolean</li>  * <li><b><code>data</code></b> property : Object</li>  * <div class="sub-desc">The <code>data</code> property contains the values of Fields to load.  * The individual value object for each Field is passed to the Field's  * {@link Ext.form.Field#setValue setValue} method.</div></li>  * </ul></div>  * <p><u><b>JSON Packets</b></u></p>  * <p>By default, response packets are assumed to be JSON, so for the following form load call:<pre><code> var myFormPanel = new Ext.form.FormPanel({     title: 'Client and routing info',     items: [{         fieldLabel: 'Client',         name: 'clientName'     }, {         fieldLabel: 'Port of loading',         name: 'portOfLoading'     }, {         fieldLabel: 'Port of discharge',         name: 'portOfDischarge'     }] }); myFormPanel.{@link Ext.form.FormPanel#getForm getForm}().{@link Ext.form.BasicForm#load load}({     url: '/getRoutingInfo.php',     params: {         consignmentRef: myConsignmentRef     },     failure: function(form, action() {         Ext.Msg.alert("Load failed", action.result.errorMessage);     } }); </code></pre>  * a <b>success response</b> packet may look like this:</p><pre><code> {     success: true,     data: {         clientName: "Fred. Olsen Lines",         portOfLoading: "FXT",         portOfDischarge: "OSL"     } }</code></pre>  * while a <b>failure response</b> packet may look like this:</p><pre><code> {     success: false,     errorMessage: "Consignment reference not found" }</code></pre>  * <p>Other data may be placed into the response for processing the {@link Ext.form.BasicForm Form}'s  * callback or event handler methods. The object decoded from this JSON is available in the  * {@link Ext.form.Action#result result} property.</p>  */ Ext.form.Action.Load = function(form, options){     Ext.form.Action.Load.superclass.constructor.call(this, form, options);     this.reader = this.form.reader; }; Ext.extend(Ext.form.Action.Load, Ext.form.Action, {     // private     type : 'load',     // private     run : function(){         Ext.Ajax.request(Ext.apply(                 this.createCallback(this.options), {                     method:this.getMethod(),                     url:this.getUrl(false),                     headers: this.options.headers,                     params:this.getParams()         }));     },     // private     success : function(response){         var result = this.processResponse(response);         if(result === true || !result.success || !result.data){             this.failureType = Ext.form.Action.LOAD_FAILURE;             this.form.afterAction(this, false);             return;         }         this.form.clearInvalid();         this.form.setValues(result.data);         this.form.afterAction(this, true);     },     // private     handleResponse : function(response){         if(this.form.reader){             var rs = this.form.reader.read(response);             var data = rs.records && rs.records[0] ? rs.records[0].data : null;             return {                 success : rs.success,                 data : data             };         }         return Ext.decode(response.responseText);     } }); /**  * @class Ext.form.Action.DirectLoad  * @extends Ext.form.Action.Load  * Provides Ext.direct support for loading form data. This example illustrates usage  * of Ext.Direct to load a submit a form through Ext.Direct.  * <pre><code> var myFormPanel = new Ext.form.FormPanel({     // configs for FormPanel     title: 'Basic Information',     border: false,     padding: 10,     buttons:[{         text: 'Submit',         handler: function(){             basicInfo.getForm().submit({                 params: {                     uid: 5                 }             });         }     }],          // configs apply to child items     defaults: {anchor: '100%'},     defaultType: 'textfield',     items: [         // form fields go here     ],          // configs for BasicForm     api: {         load: Profile.getBasicInfo,         // The server-side must mark the submit handler as a 'formHandler'         submit: Profile.updateBasicInfo     },         paramOrder: ['uid'] }); // load the form myFormPanel.getForm().load({     params: {         uid: 5     } });  * </code></pre>  */ Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {     constructor: function(form, opts) {                 Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);     },     type: 'directload',          run : function(){         var args = this.getParams();         args.push(this.success, this);                         this.form.api.load.apply(window, args);     },          getParams: function() {         var buf = [], o = {};         var bp = this.form.baseParams;         var p = this.options.params;         Ext.apply(o, p, bp);         var paramOrder = this.form.paramOrder;         if(paramOrder){             for(var i = 0, len = paramOrder.length; i < len; i++){                 buf.push(o[paramOrder[i]]);             }         }else if(this.form.paramsAsHash){             buf.push(o);         }         return buf;     },     // Direct actions have already been processed and therefore     // we can directly set the result; Direct Actions do not have     // a this.response property.     processResponse: function(result) {         this.result = result;         return result;               } }); /**  * @class Ext.form.Action.DirectSubmit  * @extends Ext.form.Action.Submit  * Provides Ext.direct support for submitting form data.  * See {@link Ext.form.Action.DirectLoad}.  */ Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {     constructor: function(form, opts) {         Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);     },     type: 'directsubmit',     // override of Submit     run : function(){         var o = this.options;         if(o.clientValidation === false || this.form.isValid()){             // tag on any additional params to be posted in the             // form scope             this.success.params = this.getParams();             this.form.api.submit(this.form.el.dom, this.success, this);         }else if (o.clientValidation !== false){ // client validation failed             this.failureType = Ext.form.Action.CLIENT_INVALID;             this.form.afterAction(this, false);         }     },          getParams: function() {         var o = {};         var bp = this.form.baseParams;         var p = this.options.params;         Ext.apply(o, p, bp);         return o;     },         // Direct actions have already been processed and therefore     // we can directly set the result; Direct Actions do not have     // a this.response property.     processResponse: function(result) {         this.result = result;         return result;               } }); Ext.form.Action.ACTION_TYPES = {     'load' : Ext.form.Action.Load,     'submit' : Ext.form.Action.Submit,     'directload': Ext.form.Action.DirectLoad,     'directsubmit': Ext.form.Action.DirectSubmit }; /**  * @class Ext.form.VTypes  * <p>This is a singleton object which contains a set of commonly used field validation functions.  * The validations provided are basic and intended to be easily customizable and extended.</p>  * <p>To add custom VTypes specify the <code>{@link Ext.form.TextField#vtype vtype}</code> validation  * test function, and optionally specify any corresponding error text to display and any keystroke  * filtering mask to apply. For example:</p>  * <pre><code> // custom Vtype for vtype:'time' var timeTest = /^([1-9]|1[0-9]):([0-5][0-9])(s[a|p]m)$/i; Ext.apply(Ext.form.VTypes, {     //  vtype validation function     time: function(val, field) {         return timeTest.test(val);     },     // vtype Text property: The error text to display when the validation function returns false     timeText: 'Not a valid time.  Must be in the format "12:34 PM".',     // vtype Mask property: The keystroke filter mask     timeMask: /[ds:amp]/i });  * </code></pre>  * Another example:   * <pre><code> // custom Vtype for vtype:'IPAddress' Ext.apply(Ext.form.VTypes, {     IPAddress:  function(v) {         return /^d{1,3}.d{1,3}.d{1,3}.d{1,3}$/.test(v);     },     IPAddressText: 'Must be a numeric IP address',     IPAddressMask: /[d.]/i });  * </code></pre>  * @singleton  */ Ext.form.VTypes = function(){     // closure these in so they are only created once.     var alpha = /^[a-zA-Z_]+$/;     var alphanum = /^[a-zA-Z0-9_]+$/;     var email = /^(w+)([-+.][w]+)*@(w[-w]*.){1,5}([A-Za-z]){2,4}$/;     var url = /(((https?)|(ftp))://([-w]+.)+w{2,3}(/[%-w]+(.w{2,})?)*(([w-.?\/+@&#;`~=%!]*)(.w{2,})?)*/?)/i;     // All these messages and functions are configurable     return {         /**          * The function used to validate email addresses.  Note that this is a very basic validation -- complete          * validation per the email RFC specifications is very complex and beyond the scope of this class, although          * this function can be overridden if a more comprehensive validation scheme is desired.  See the validation          * section of the <a href="http://en.wikipedia.org/wiki/E-mail_address">Wikipedia article on email addresses</a>           * for additional information.  This implementation is intended to validate the following emails:<tt>          * 'barney@example.de', 'barney.rubble@example.com', 'barney-rubble@example.coop', 'barney+rubble@example.com'          * </tt>.          * @param {String} value The email address          * @return {Boolean} true if the RegExp test passed, and false if not.          */         'email' : function(v){             return email.test(v);         },         /**          * The error text to display when the email validation function returns false.  Defaults to:          * <tt>'This field should be an e-mail address in the format "user@example.com"'</tt>          * @type String          */         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',         /**          * The keystroke filter mask to be applied on email input.  See the {@link #email} method for           * information about more complex email validation. Defaults to:          * <tt>/[a-z0-9_.-@]/i</tt>          * @type RegExp          */         'emailMask' : /[a-z0-9_.-@]/i,         /**          * The function used to validate URLs          * @param {String} value The URL          * @return {Boolean} true if the RegExp test passed, and false if not.          */         'url' : function(v){             return url.test(v);         },         /**          * The error text to display when the url validation function returns false.  Defaults to:          * <tt>'This field should be a URL in the format "http:/'+'/www.example.com"'</tt>          * @type String          */         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',                  /**          * The function used to validate alpha values          * @param {String} value The value          * @return {Boolean} true if the RegExp test passed, and false if not.          */         'alpha' : function(v){             return alpha.test(v);         },         /**          * The error text to display when the alpha validation function returns false.  Defaults to:          * <tt>'This field should only contain letters and _'</tt>          * @type String          */         'alphaText' : 'This field should only contain letters and _',         /**          * The keystroke filter mask to be applied on alpha input.  Defaults to:          * <tt>/[a-z_]/i</tt>          * @type RegExp          */         'alphaMask' : /[a-z_]/i,         /**          * The function used to validate alphanumeric values          * @param {String} value The value          * @return {Boolean} true if the RegExp test passed, and false if not.          */         'alphanum' : function(v){             return alphanum.test(v);         },         /**          * The error text to display when the alphanumeric validation function returns false.  Defaults to:          * <tt>'This field should only contain letters, numbers and _'</tt>          * @type String          */         'alphanumText' : 'This field should only contain letters, numbers and _',         /**          * The keystroke filter mask to be applied on alphanumeric input.  Defaults to:          * <tt>/[a-z0-9_]/i</tt>          * @type RegExp          */         'alphanumMask' : /[a-z0-9_]/i     }; }();/**
  1017.  * @class Ext.grid.GridPanel
  1018.  * @extends Ext.Panel
  1019.  * <p>This class represents the primary interface of a component based grid control to represent data
  1020.  * in a tabular format of rows and columns. The GridPanel is composed of the following:</p>
  1021.  * <div class="mdetail-params"><ul>
  1022.  * <li><b>{@link Ext.data.Store Store}</b> : The Model holding the data records (rows)
  1023.  * <div class="sub-desc"></div></li>
  1024.  * <li><b>{@link Ext.grid.ColumnModel Column model}</b> : Column makeup
  1025.  * <div class="sub-desc"></div></li>
  1026.  * <li><b>{@link Ext.grid.GridView View}</b> : Encapsulates the user interface 
  1027.  * <div class="sub-desc"></div></li>
  1028.  * <li><b>{@link Ext.grid.AbstractSelectionModel selection model}</b> : Selection behavior 
  1029.  * <div class="sub-desc"></div></li>
  1030.  * </ul></div>
  1031.  * <p>Example usage:</p>
  1032.  * <pre><code>
  1033. var grid = new Ext.grid.GridPanel({
  1034.     {@link #store}: new (@link Ext.data.Store}({
  1035.         {@link Ext.data.Store#autoDestroy autoDestroy}: true,
  1036.         {@link Ext.data.Store#reader reader}: reader,
  1037.         {@link Ext.data.Store#data data}: xg.dummyData
  1038.     }),
  1039.     {@link #columns}: [
  1040.         {id: 'company', header: 'Company', width: 200, sortable: true, dataIndex: 'company'},
  1041.         {header: 'Price', width: 120, sortable: true, renderer: Ext.util.Format.usMoney, dataIndex: 'price'},
  1042.         {header: 'Change', width: 120, sortable: true, dataIndex: 'change'},
  1043.         {header: '% Change', width: 120, sortable: true, dataIndex: 'pctChange'},
  1044.         // instead of specifying renderer: Ext.util.Format.dateRenderer('m/d/Y') use xtype
  1045.         {header: 'Last Updated', width: 135, sortable: true, dataIndex: 'lastChange', xtype: 'datecolumn', format: 'M d, Y'}
  1046.     ],
  1047.     {@link #viewConfig}: {
  1048.         {@link Ext.grid.GridView#forceFit forceFit}: true,
  1049. //      Return CSS class to apply to rows depending upon data values
  1050.         {@link Ext.grid.GridView#getRowClass getRowClass}: function(record, index) {
  1051.             var c = record.{@link Ext.data.Record#get get}('change');
  1052.             if (c < 0) {
  1053.                 return 'price-fall';
  1054.             } else if (c > 0) {
  1055.                 return 'price-rise';
  1056.             }
  1057.         }
  1058.     },
  1059.     {@link #sm}: new Ext.grid.RowSelectionModel({singleSelect:true}),
  1060.     width: 600,
  1061.     height: 300,
  1062.     frame: true,
  1063.     title: 'Framed with Row Selection and Horizontal Scrolling',
  1064.     iconCls: 'icon-grid'
  1065. });
  1066.  * </code></pre>
  1067.  * <p><b><u>Notes:</u></b></p>
  1068.  * <div class="mdetail-params"><ul>
  1069.  * <li>Although this class inherits many configuration options from base classes, some of them
  1070.  * (such as autoScroll, autoWidth, layout, items, etc) are not used by this class, and will
  1071.  * have no effect.</li>
  1072.  * <li>A grid <b>requires</b> a width in which to scroll its columns, and a height in which to
  1073.  * scroll its rows. These dimensions can either be set explicitly through the
  1074.  * <tt>{@link Ext.BoxComponent#height height}</tt> and <tt>{@link Ext.BoxComponent#width width}</tt>
  1075.  * configuration options or implicitly set by using the grid as a child item of a
  1076.  * {@link Ext.Container Container} which will have a {@link Ext.Container#layout layout manager}
  1077.  * provide the sizing of its child items (for example the Container of the Grid may specify
  1078.  * <tt>{@link Ext.Container#layout layout}:'fit'</tt>).</li>
  1079.  * <li>To access the data in a Grid, it is necessary to use the data model encapsulated
  1080.  * by the {@link #store Store}. See the {@link #cellclick} event for more details.</li>
  1081.  * </ul></div>
  1082.  * @constructor
  1083.  * @param {Object} config The config object
  1084.  * @xtype grid
  1085.  */
  1086. Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
  1087.     /**
  1088.      * @cfg {String} autoExpandColumn
  1089.      * <p>The <tt>{@link Ext.grid.Column#id id}</tt> of a {@link Ext.grid.Column column} in
  1090.      * this grid that should expand to fill unused space. This value specified here can not
  1091.      * be <tt>0</tt>.</p>
  1092.      * <br><p><b>Note</b>: If the Grid's {@link Ext.grid.GridView view} is configured with
  1093.      * <tt>{@link Ext.grid.GridView#forceFit forceFit}=true</tt> the <tt>autoExpandColumn</tt>
  1094.      * is ignored. See {@link Ext.grid.Column}.<tt>{@link Ext.grid.Column#width width}</tt>
  1095.      * for additional details.</p>
  1096.      * <p>See <tt>{@link #autoExpandMax}</tt> and <tt>{@link #autoExpandMin}</tt> also.</p>
  1097.      */
  1098.     autoExpandColumn : false,
  1099.     /**
  1100.      * @cfg {Number} autoExpandMax The maximum width the <tt>{@link #autoExpandColumn}</tt>
  1101.      * can have (if enabled). Defaults to <tt>1000</tt>.
  1102.      */
  1103.     autoExpandMax : 1000,
  1104.     /**
  1105.      * @cfg {Number} autoExpandMin The minimum width the <tt>{@link #autoExpandColumn}</tt>
  1106.      * can have (if enabled). Defaults to <tt>50</tt>.
  1107.      */
  1108.     autoExpandMin : 50,
  1109.     /**
  1110.      * @cfg {Boolean} columnLines <tt>true</tt> to add css for column separation lines.
  1111.      * Default is <tt>false</tt>.
  1112.      */
  1113.     columnLines : false,
  1114.     /**
  1115.      * @cfg {Object} cm Shorthand for <tt>{@link #colModel}</tt>.
  1116.      */
  1117.     /**
  1118.      * @cfg {Object} colModel The {@link Ext.grid.ColumnModel} to use when rendering the grid (required).
  1119.      */
  1120.     /**
  1121.      * @cfg {Array} columns An array of {@link Ext.grid.Column columns} to auto create a
  1122.      * {@link Ext.grid.ColumnModel}.  The ColumnModel may be explicitly created via the
  1123.      * <tt>{@link #colModel}</tt> configuration property.
  1124.      */
  1125.     /**
  1126.      * @cfg {String} ddGroup The DD group this GridPanel belongs to. Defaults to <tt>'GridDD'</tt> if not specified.
  1127.      */
  1128.     /**
  1129.      * @cfg {String} ddText
  1130.      * Configures the text in the drag proxy.  Defaults to:
  1131.      * <pre><code>
  1132.      * ddText : '{0} selected row{1}'
  1133.      * </code></pre>
  1134.      * <tt>{0}</tt> is replaced with the number of selected rows.
  1135.      */
  1136.     ddText : '{0} selected row{1}',
  1137.     /**
  1138.      * @cfg {Boolean} deferRowRender <P>Defaults to <tt>true</tt> to enable deferred row rendering.</p>
  1139.      * <p>This allows the GridPanel to be initially rendered empty, with the expensive update of the row
  1140.      * structure deferred so that layouts with GridPanels appear more quickly.</p>
  1141.      */
  1142.     deferRowRender : true,
  1143.     /**
  1144.      * @cfg {Boolean} disableSelection <p><tt>true</tt> to disable selections in the grid. Defaults to <tt>false</tt>.</p>
  1145.      * <p>Ignored if a {@link #selModel SelectionModel} is specified.</p>
  1146.      */
  1147.     /**
  1148.      * @cfg {Boolean} enableColumnResize <tt>false</tt> to turn off column resizing for the whole grid. Defaults to <tt>true</tt>.
  1149.      */
  1150.     /**
  1151.      * @cfg {Boolean} enableColumnHide Defaults to <tt>true</tt> to enable hiding of columns with the header context menu.
  1152.      */
  1153.     enableColumnHide : true,
  1154.     /**
  1155.      * @cfg {Boolean} enableColumnMove Defaults to <tt>true</tt> to enable drag and drop reorder of columns. <tt>false</tt>
  1156.      * to turn off column reordering via drag drop.
  1157.      */
  1158.     enableColumnMove : true,
  1159.     /**
  1160.      * @cfg {Boolean} enableDragDrop <p>Enables dragging of the selected rows of the GridPanel. Defaults to <tt>false</tt>.</p>
  1161.      * <p>Setting this to <b><tt>true</tt></b> causes this GridPanel's {@link #getView GridView} to
  1162.      * create an instance of {@link Ext.grid.GridDragZone}. <b>Note</b>: this is available only <b>after</b>
  1163.      * the Grid has been rendered as the GridView's <tt>{@link Ext.grid.GridView#dragZone dragZone}</tt>
  1164.      * property.</p>
  1165.      * <p>A cooperating {@link Ext.dd.DropZone DropZone} must be created who's implementations of
  1166.      * {@link Ext.dd.DropZone#onNodeEnter onNodeEnter}, {@link Ext.dd.DropZone#onNodeOver onNodeOver},
  1167.      * {@link Ext.dd.DropZone#onNodeOut onNodeOut} and {@link Ext.dd.DropZone#onNodeDrop onNodeDrop} are able
  1168.      * to process the {@link Ext.grid.GridDragZone#getDragData data} which is provided.</p>
  1169.      */
  1170.     enableDragDrop : false,
  1171.     /**
  1172.      * @cfg {Boolean} enableHdMenu Defaults to <tt>true</tt> to enable the drop down button for menu in the headers.
  1173.      */
  1174.     enableHdMenu : true,
  1175.     /**
  1176.      * @cfg {Boolean} hideHeaders True to hide the grid's header. Defaults to <code>false</code>.
  1177.      */
  1178.     /**
  1179.      * @cfg {Object} loadMask An {@link Ext.LoadMask} config or true to mask the grid while
  1180.      * loading. Defaults to <code>false</code>.
  1181.      */
  1182.     loadMask : false,
  1183.     /**
  1184.      * @cfg {Number} maxHeight Sets the maximum height of the grid - ignored if <tt>autoHeight</tt> is not on.
  1185.      */
  1186.     /**
  1187.      * @cfg {Number} minColumnWidth The minimum width a column can be resized to. Defaults to <tt>25</tt>.
  1188.      */
  1189.     minColumnWidth : 25,
  1190.     /**
  1191.      * @cfg {Object} sm Shorthand for <tt>{@link #selModel}</tt>.
  1192.      */
  1193.     /**
  1194.      * @cfg {Object} selModel Any subclass of {@link Ext.grid.AbstractSelectionModel} that will provide
  1195.      * the selection model for the grid (defaults to {@link Ext.grid.RowSelectionModel} if not specified).
  1196.      */
  1197.     /**
  1198.      * @cfg {Ext.data.Store} store The {@link Ext.data.Store} the grid should use as its data source (required).
  1199.      */
  1200.     /**
  1201.      * @cfg {Boolean} stripeRows <tt>true</tt> to stripe the rows. Default is <tt>false</tt>.
  1202.      * <p>This causes the CSS class <tt><b>x-grid3-row-alt</b></tt> to be added to alternate rows of
  1203.      * the grid. A default CSS rule is provided which sets a background colour, but you can override this
  1204.      * with a rule which either overrides the <b>background-color</b> style using the '!important'
  1205.      * modifier, or which uses a CSS selector of higher specificity.</p>
  1206.      */
  1207.     stripeRows : false,
  1208.     /**
  1209.      * @cfg {Boolean} trackMouseOver True to highlight rows when the mouse is over. Default is <tt>true</tt>
  1210.      * for GridPanel, but <tt>false</tt> for EditorGridPanel.
  1211.      */
  1212.     trackMouseOver : true,
  1213.     /**
  1214.      * @cfg {Array} stateEvents
  1215.      * An array of events that, when fired, should trigger this component to save its state.
  1216.      * Defaults to:<pre><code>
  1217.      * stateEvents: ['columnmove', 'columnresize', 'sortchange']
  1218.      * </code></pre>
  1219.      * <p>These can be any types of events supported by this component, including browser or
  1220.      * custom events (e.g., <tt>['click', 'customerchange']</tt>).</p>
  1221.      * <p>See {@link Ext.Component#stateful} for an explanation of saving and restoring
  1222.      * Component state.</p>
  1223.      */
  1224.     stateEvents : ['columnmove', 'columnresize', 'sortchange'],
  1225.     /**
  1226.      * @cfg {Object} view The {@link Ext.grid.GridView} used by the grid. This can be set
  1227.      * before a call to {@link Ext.Component#render render()}.
  1228.      */
  1229.     view : null,
  1230.     /**
  1231.      * @cfg {Object} viewConfig A config object that will be applied to the grid's UI view.  Any of
  1232.      * the config options available for {@link Ext.grid.GridView} can be specified here. This option
  1233.      * is ignored if <tt>{@link #view}</tt> is specified.
  1234.      */
  1235.     // private
  1236.     rendered : false,
  1237.     // private
  1238.     viewReady : false,
  1239.     // private
  1240.     initComponent : function(){
  1241.         Ext.grid.GridPanel.superclass.initComponent.call(this);
  1242.         if(this.columnLines){
  1243.             this.cls = (this.cls || '') + ' x-grid-with-col-lines';
  1244.         }
  1245.         // override any provided value since it isn't valid
  1246.         // and is causing too many bug reports ;)
  1247.         this.autoScroll = false;
  1248.         this.autoWidth = false;
  1249.         if(Ext.isArray(this.columns)){
  1250.             this.colModel = new Ext.grid.ColumnModel(this.columns);
  1251.             delete this.columns;
  1252.         }
  1253.         // check and correct shorthanded configs
  1254.         if(this.ds){
  1255.             this.store = this.ds;
  1256.             delete this.ds;
  1257.         }
  1258.         if(this.cm){
  1259.             this.colModel = this.cm;
  1260.             delete this.cm;
  1261.         }
  1262.         if(this.sm){
  1263.             this.selModel = this.sm;
  1264.             delete this.sm;
  1265.         }
  1266.         this.store = Ext.StoreMgr.lookup(this.store);
  1267.         this.addEvents(
  1268.             // raw events
  1269.             /**
  1270.              * @event click
  1271.              * The raw click event for the entire grid.
  1272.              * @param {Ext.EventObject} e
  1273.              */
  1274.             'click',
  1275.             /**
  1276.              * @event dblclick
  1277.              * The raw dblclick event for the entire grid.
  1278.              * @param {Ext.EventObject} e
  1279.              */
  1280.             'dblclick',
  1281.             /**
  1282.              * @event contextmenu
  1283.              * The raw contextmenu event for the entire grid.
  1284.              * @param {Ext.EventObject} e
  1285.              */
  1286.             'contextmenu',
  1287.             /**
  1288.              * @event mousedown
  1289.              * The raw mousedown event for the entire grid.
  1290.              * @param {Ext.EventObject} e
  1291.              */
  1292.             'mousedown',
  1293.             /**
  1294.              * @event mouseup
  1295.              * The raw mouseup event for the entire grid.
  1296.              * @param {Ext.EventObject} e
  1297.              */
  1298.             'mouseup',
  1299.             /**
  1300.              * @event mouseover
  1301.              * The raw mouseover event for the entire grid.
  1302.              * @param {Ext.EventObject} e
  1303.              */
  1304.             'mouseover',
  1305.             /**
  1306.              * @event mouseout
  1307.              * The raw mouseout event for the entire grid.
  1308.              * @param {Ext.EventObject} e
  1309.              */
  1310.             'mouseout',
  1311.             /**
  1312.              * @event keypress
  1313.              * The raw keypress event for the entire grid.
  1314.              * @param {Ext.EventObject} e
  1315.              */
  1316.             'keypress',
  1317.             /**
  1318.              * @event keydown
  1319.              * The raw keydown event for the entire grid.
  1320.              * @param {Ext.EventObject} e
  1321.              */
  1322.             'keydown',
  1323.             // custom events
  1324.             /**
  1325.              * @event cellmousedown
  1326.              * Fires before a cell is clicked
  1327.              * @param {Grid} this
  1328.              * @param {Number} rowIndex
  1329.              * @param {Number} columnIndex
  1330.              * @param {Ext.EventObject} e
  1331.              */
  1332.             'cellmousedown',
  1333.             /**
  1334.              * @event rowmousedown
  1335.              * Fires before a row is clicked
  1336.              * @param {Grid} this
  1337.              * @param {Number} rowIndex
  1338.              * @param {Ext.EventObject} e
  1339.              */
  1340.             'rowmousedown',
  1341.             /**
  1342.              * @event headermousedown
  1343.              * Fires before a header is clicked
  1344.              * @param {Grid} this
  1345.              * @param {Number} columnIndex
  1346.              * @param {Ext.EventObject} e
  1347.              */
  1348.             'headermousedown',
  1349.             /**
  1350.              * @event cellclick
  1351.              * Fires when a cell is clicked.
  1352.              * The data for the cell is drawn from the {@link Ext.data.Record Record}
  1353.              * for this row. To access the data in the listener function use the
  1354.              * following technique:
  1355.              * <pre><code>
  1356. function(grid, rowIndex, columnIndex, e) {
  1357.     var record = grid.getStore().getAt(rowIndex);  // Get the Record
  1358.     var fieldName = grid.getColumnModel().getDataIndex(columnIndex); // Get field name
  1359.     var data = record.get(fieldName);
  1360. }
  1361. </code></pre>
  1362.              * @param {Grid} this
  1363.              * @param {Number} rowIndex
  1364.              * @param {Number} columnIndex
  1365.              * @param {Ext.EventObject} e
  1366.              */
  1367.             'cellclick',
  1368.             /**
  1369.              * @event celldblclick
  1370.              * Fires when a cell is double clicked
  1371.              * @param {Grid} this
  1372.              * @param {Number} rowIndex
  1373.              * @param {Number} columnIndex
  1374.              * @param {Ext.EventObject} e
  1375.              */
  1376.             'celldblclick',
  1377.             /**
  1378.              * @event rowclick
  1379.              * Fires when a row is clicked
  1380.              * @param {Grid} this
  1381.              * @param {Number} rowIndex
  1382.              * @param {Ext.EventObject} e
  1383.              */
  1384.             'rowclick',
  1385.             /**
  1386.              * @event rowdblclick
  1387.              * Fires when a row is double clicked
  1388.              * @param {Grid} this
  1389.              * @param {Number} rowIndex
  1390.              * @param {Ext.EventObject} e
  1391.              */
  1392.             'rowdblclick',
  1393.             /**
  1394.              * @event headerclick
  1395.              * Fires when a header is clicked
  1396.              * @param {Grid} this
  1397.              * @param {Number} columnIndex
  1398.              * @param {Ext.EventObject} e
  1399.              */
  1400.             'headerclick',
  1401.             /**
  1402.              * @event headerdblclick
  1403.              * Fires when a header cell is double clicked
  1404.              * @param {Grid} this
  1405.              * @param {Number} columnIndex
  1406.              * @param {Ext.EventObject} e
  1407.              */
  1408.             'headerdblclick',
  1409.             /**
  1410.              * @event rowcontextmenu
  1411.              * Fires when a row is right clicked
  1412.              * @param {Grid} this
  1413.              * @param {Number} rowIndex
  1414.              * @param {Ext.EventObject} e
  1415.              */
  1416.             'rowcontextmenu',
  1417.             /**
  1418.              * @event cellcontextmenu
  1419.              * Fires when a cell is right clicked
  1420.              * @param {Grid} this
  1421.              * @param {Number} rowIndex
  1422.              * @param {Number} cellIndex
  1423.              * @param {Ext.EventObject} e
  1424.              */
  1425.             'cellcontextmenu',
  1426.             /**
  1427.              * @event headercontextmenu
  1428.              * Fires when a header is right clicked
  1429.              * @param {Grid} this
  1430.              * @param {Number} columnIndex
  1431.              * @param {Ext.EventObject} e
  1432.              */
  1433.             'headercontextmenu',
  1434.             /**
  1435.              * @event bodyscroll
  1436.              * Fires when the body element is scrolled
  1437.              * @param {Number} scrollLeft
  1438.              * @param {Number} scrollTop
  1439.              */
  1440.             'bodyscroll',
  1441.             /**
  1442.              * @event columnresize
  1443.              * Fires when the user resizes a column
  1444.              * @param {Number} columnIndex
  1445.              * @param {Number} newSize
  1446.              */
  1447.             'columnresize',
  1448.             /**
  1449.              * @event columnmove
  1450.              * Fires when the user moves a column
  1451.              * @param {Number} oldIndex
  1452.              * @param {Number} newIndex
  1453.              */
  1454.             'columnmove',
  1455.             /**
  1456.              * @event sortchange
  1457.              * Fires when the grid's store sort changes
  1458.              * @param {Grid} this
  1459.              * @param {Object} sortInfo An object with the keys field and direction
  1460.              */
  1461.             'sortchange',
  1462.             /**
  1463.              * @event reconfigure
  1464.              * Fires when the grid is reconfigured with a new store and/or column model.
  1465.              * @param {Grid} this
  1466.              * @param {Ext.data.Store} store The new store
  1467.              * @param {Ext.grid.ColumnModel} colModel The new column model
  1468.              */
  1469.             'reconfigure'
  1470.         );
  1471.     },
  1472.     // private
  1473.     onRender : function(ct, position){
  1474.         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
  1475.         var c = this.body;
  1476.         this.el.addClass('x-grid-panel');
  1477.         var view = this.getView();
  1478.         view.init(this);
  1479.         this.mon(c, {
  1480.             mousedown: this.onMouseDown,
  1481.             click: this.onClick,
  1482.             dblclick: this.onDblClick,
  1483.             contextmenu: this.onContextMenu,
  1484.             keydown: this.onKeyDown,
  1485.             scope: this
  1486.         });
  1487.         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress']);
  1488.         this.getSelectionModel().init(this);
  1489.         this.view.render();
  1490.     },
  1491.     // private
  1492.     initEvents : function(){
  1493.         Ext.grid.GridPanel.superclass.initEvents.call(this);
  1494.         if(this.loadMask){
  1495.             this.loadMask = new Ext.LoadMask(this.bwrap,
  1496.                     Ext.apply({store:this.store}, this.loadMask));
  1497.         }
  1498.     },
  1499.     initStateEvents : function(){
  1500.         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
  1501.         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
  1502.     },
  1503.     applyState : function(state){
  1504.         var cm = this.colModel;
  1505.         var cs = state.columns;
  1506.         if(cs){
  1507.             for(var i = 0, len = cs.length; i < len; i++){
  1508.                 var s = cs[i];
  1509.                 var c = cm.getColumnById(s.id);
  1510.                 if(c){
  1511.                     c.hidden = s.hidden;
  1512.                     c.width = s.width;
  1513.                     var oldIndex = cm.getIndexById(s.id);
  1514.                     if(oldIndex != i){
  1515.                         cm.moveColumn(oldIndex, i);
  1516.                     }
  1517.                 }
  1518.             }
  1519.         }
  1520.         if(state.sort && this.store){
  1521.             this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);
  1522.         }
  1523.         delete state.columns;
  1524.         delete state.sort;
  1525.         Ext.grid.GridPanel.superclass.applyState.call(this, state);
  1526.     },
  1527.     getState : function(){
  1528.         var o = {columns: []};
  1529.         for(var i = 0, c; (c = this.colModel.config[i]); i++){
  1530.             o.columns[i] = {
  1531.                 id: c.id,
  1532.                 width: c.width
  1533.             };
  1534.             if(c.hidden){
  1535.                 o.columns[i].hidden = true;
  1536.             }
  1537.         }
  1538.         if(this.store){
  1539.             var ss = this.store.getSortState();
  1540.             if(ss){
  1541.                 o.sort = ss;
  1542.             }
  1543.         }
  1544.         return o;
  1545.     },
  1546.     // private
  1547.     afterRender : function(){