sync
[roojs1] / roojs-debug.js
index 0c1a5eb..1cda431 100644 (file)
@@ -4667,6 +4667,7 @@ Roo.Template.prototype = {
      * @return {String} The HTML fragment
      */
     applyTemplate : function(values){
+        Roo.log(["applyTemplate", values]);
         try {
            
             if(this.compiled){
@@ -6073,10 +6074,10 @@ Roo.util.Observable.releaseCapture = function(o){
             var ls = this.listeners, scope, len = ls.length;
             if(len > 0){
                 this.firing = true;
-                var args = Array.prototype.slice.call(arguments, 0);
+               var args = Array.prototype.slice.call(arguments, 0);                
                 for(var i = 0; i < len; i++){
-                    var l = ls[i];
-                    if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
+                   var l = ls[i];
+                    if(l.fireFn.apply(l.scope||this.obj||window, args) === false){
                         this.firing = false;
                         return false;
                     }
@@ -11659,7 +11660,9 @@ Roo.extend(Roo.data.Connection, Roo.util.Observable, {
                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
                 p = '';
             }
+            Roo.lib.Ajax.useDefaultHeader = typeof(o.headers) == 'undefined' || typeof(o.headers['Content-Type']) == 'undefined';
             this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
+            Roo.lib.Ajax.useDefaultHeader == true;
             return this.transId;
         }else{
             Roo.callback(o.callback, o.scope, [o, null, null]);
@@ -13299,6 +13302,9 @@ mc.add(otherEl);
  * @return {Object} The item associated with the passed key.
  */
     item : function(key){
+        if (key === 'length') {
+            return null;
+        }
         var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
         return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
     },
@@ -15433,7 +15439,7 @@ Roo.extend(Roo.Component, Roo.util.Observable, {
     /**
      * @cfg {String} actionMode 
      * which property holds the element that used for  hide() / show() / disable() / enable()
-     * default is 'el' 
+     * default is 'el' for forms you probably want to set this to fieldEl 
      */
     actionMode : "el",
 
@@ -16800,10 +16806,86 @@ Roo.Markdown.toHtml = function(text) {
 //
 (function() {
     
+     /**
+         * eval:var:escape
+         * eval:var:unescape
+         * eval:var:replace
+         */
+      
+    /**
+     * Helpers
+     */
+    
+    var escape = function (html, encode) {
+      return html
+        .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
+        .replace(/</g, '&lt;')
+        .replace(/>/g, '&gt;')
+        .replace(/"/g, '&quot;')
+        .replace(/'/g, '&#39;');
+    }
+    
+    var unescape = function (html) {
+        // explicitly match decimal, hex, and named HTML entities 
+      return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
+        n = n.toLowerCase();
+        if (n === 'colon') { return ':'; }
+        if (n.charAt(0) === '#') {
+          return n.charAt(1) === 'x'
+            ? String.fromCharCode(parseInt(n.substring(2), 16))
+            : String.fromCharCode(+n.substring(1));
+        }
+        return '';
+      });
+    }
+    
+    var replace = function (regex, opt) {
+      regex = regex.source;
+      opt = opt || '';
+      return function self(name, val) {
+        if (!name) { return new RegExp(regex, opt); }
+        val = val.source || val;
+        val = val.replace(/(^|[^\[])\^/g, '$1');
+        regex = regex.replace(name, val);
+        return self;
+      };
+    }
+
+
+         /**
+         * eval:var:noop
+    */
+    var noop = function () {}
+    noop.exec = noop;
+    
+         /**
+         * eval:var:merge
+    */
+    var merge = function (obj) {
+      var i = 1
+        , target
+        , key;
+    
+      for (; i < arguments.length; i++) {
+        target = arguments[i];
+        for (key in target) {
+          if (Object.prototype.hasOwnProperty.call(target, key)) {
+            obj[key] = target[key];
+          }
+        }
+      }
+    
+      return obj;
+    }
+    
+    
     /**
      * Block-Level Grammar
      */
     
+    
+    
+    
     var block = {
       newline: /^\n+/,
       code: /^( {4}[^\n]+\n*)+/,
@@ -16893,7 +16975,7 @@ Roo.Markdown.toHtml = function(text) {
      * Block Lexer
      */
     
-    function Lexer(options) {
+    var Lexer = function (options) {
       this.tokens = [];
       this.tokens.links = {};
       this.options = options || marked.defaults;
@@ -17311,7 +17393,7 @@ Roo.Markdown.toHtml = function(text) {
      * Inline Lexer & Compiler
      */
     
-    function InlineLexer(links, options) {
+    var InlineLexer  = function (links, options) {
       this.options = options || marked.defaults;
       this.links = links;
       this.rules = inline.normal;
@@ -17551,7 +17633,11 @@ Roo.Markdown.toHtml = function(text) {
      * Renderer
      */
     
-    function Renderer(options) {
+     /**
+         * eval:var:Renderer
+    */
+    
+    var Renderer   = function (options) {
       this.options = options || {};
     }
     
@@ -17700,8 +17786,11 @@ Roo.Markdown.toHtml = function(text) {
     /**
      * Parsing & Compiling
      */
+         /**
+         * eval:var:Parser
+    */
     
-    function Parser(options) {
+    var Parser= function (options) {
       this.tokens = [];
       this.token = null;
       this.options = options || marked.defaults;
@@ -17876,72 +17965,15 @@ Roo.Markdown.toHtml = function(text) {
         }
       }
     };
-    
-    /**
-     * Helpers
-     */
-    
-    function escape(html, encode) {
-      return html
-        .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
-        .replace(/</g, '&lt;')
-        .replace(/>/g, '&gt;')
-        .replace(/"/g, '&quot;')
-        .replace(/'/g, '&#39;');
-    }
-    
-    function unescape(html) {
-        // explicitly match decimal, hex, and named HTML entities 
-      return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
-        n = n.toLowerCase();
-        if (n === 'colon') { return ':'; }
-        if (n.charAt(0) === '#') {
-          return n.charAt(1) === 'x'
-            ? String.fromCharCode(parseInt(n.substring(2), 16))
-            : String.fromCharCode(+n.substring(1));
-        }
-        return '';
-      });
-    }
-    
-    function replace(regex, opt) {
-      regex = regex.source;
-      opt = opt || '';
-      return function self(name, val) {
-        if (!name) { return new RegExp(regex, opt); }
-        val = val.source || val;
-        val = val.replace(/(^|[^\[])\^/g, '$1');
-        regex = regex.replace(name, val);
-        return self;
-      };
-    }
-    
-    function noop() {}
-    noop.exec = noop;
-    
-    function merge(obj) {
-      var i = 1
-        , target
-        , key;
-    
-      for (; i < arguments.length; i++) {
-        target = arguments[i];
-        for (key in target) {
-          if (Object.prototype.hasOwnProperty.call(target, key)) {
-            obj[key] = target[key];
-          }
-        }
-      }
-    
-      return obj;
-    }
-    
+  
     
     /**
      * Marked
      */
-    
-    function marked(src, opt, callback) {
+         /**
+         * eval:var:marked
+    */
+    var marked = function (src, opt, callback) {
       if (callback || typeof opt === 'function') {
         if (!callback) {
           callback = opt;
@@ -17962,7 +17994,9 @@ Roo.Markdown.toHtml = function(text) {
         }
     
         pending = tokens.length;
-    
+         /**
+         * eval:var:done
+    */
         var done = function(err) {
           if (err) {
             opt.highlight = highlight;
@@ -21095,8 +21129,8 @@ Roo.dd.DDTarget = function(id, sGroup, config) {
     if (id) {
         this.initTarget(id, sGroup, config);
     }
-    if (config.listeners || config.events) { 
-       Roo.dd.DragDrop.superclass.constructor.call(this,  { 
+    if (config && (config.listeners || config.events)) { 
+        Roo.dd.DragDrop.superclass.constructor.call(this,  { 
             listeners : config.listeners || {}, 
             events : config.events || {} 
         });    
@@ -23235,6 +23269,16 @@ Roo.extend(Roo.data.Store, Roo.util.Observable, {
         var r = this.reader.readRecords(o);
         this.loadRecords(r, {add: append}, true);
     },
+    
+     /**
+     * using 'cn' the nested child reader read the child array into it's child stores.
+     * @param {Object} rec The record with a 'children array
+     */
+    loadDataFromChildren : function(rec)
+    {
+        this.loadData(this.reader.toLoadData(rec));
+    },
+    
 
     /**
      * Gets the number of cached records.
@@ -23539,14 +23583,16 @@ Roo.extend(Roo.data.Store, Roo.util.Observable, {
  * Small helper class to make creating Stores from Array data easier.
  * @cfg {Number} id The array index of the record id. Leave blank to auto generate ids.
  * @cfg {Array} fields An array of field definition objects, or field name strings.
+ * @cfg {Object} an existing reader (eg. copied from another store)
  * @cfg {Array} data The multi-dimensional array of data
  * @constructor
  * @param {Object} config
  */
-Roo.data.SimpleStore = function(config){
+Roo.data.SimpleStore = function(config)
+{
     Roo.data.SimpleStore.superclass.constructor.call(this, {
         isLocal : true,
-        reader: new Roo.data.ArrayReader({
+        reader: typeof(config.reader) != 'undefined' ? config.reader : new Roo.data.ArrayReader({
                 id: config.id
             },
             Roo.data.Record.create(config.fields)
@@ -23723,6 +23769,9 @@ Roo.data.DataReader = function(meta, recordType){
 };
 
 Roo.data.DataReader.prototype = {
+    
+    
+    readerType : 'Data',
      /**
      * Create an empty record
      * @param {Object} data (optional) - overlay some values
@@ -23743,6 +23792,7 @@ Roo.data.DataReader.prototype = {
         return new this.recordType(Roo.apply(da, d));
     }
     
+    
 };/*
  * Based on:
  * Ext JS Library 1.1.1
@@ -24281,6 +24331,8 @@ Roo.data.JsonReader = function(meta, recordType){
 };
 Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
     
+    readerType : 'Json',
+    
     /**
      * @prop {Boolean} metaFromRemote  - if the meta data was loaded from the remote source.
      * Used by Store query builder to append _requestMeta to params.
@@ -24422,6 +24474,14 @@ Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
             records : records,
             totalRecords : totalRecords
         };
+    },
+    // used when loading children.. @see loadDataFromChildren
+    toLoadData: function(rec)
+    {
+       // expect rec just to be an array.. eg [a,b,c, [...] << cn ]
+       var data = typeof(rec.data.cn) == 'undefined' ? [] : rec.data.cn;
+       return { data : data, total : data.length };
+       
     }
 });/*
  * Based on:
@@ -24492,6 +24552,9 @@ Roo.data.XmlReader = function(meta, recordType){
     Roo.data.XmlReader.superclass.constructor.call(this, meta, recordType||meta.fields);
 };
 Roo.extend(Roo.data.XmlReader, Roo.data.DataReader, {
+    
+    readerType : 'Xml',
+    
     /**
      * This method is only used by a DataProxy which has retrieved data from a remote server.
         * @param {Object} response The XHR object which contains the parsed XML document.  The response is expected
@@ -24603,44 +24666,54 @@ var myReader = new Roo.data.ArrayReader({
  * 
  * created using {@link Roo.data.Record#create}.
  */
-Roo.data.ArrayReader = function(meta, recordType){
-    
-     
+Roo.data.ArrayReader = function(meta, recordType)
+{    
     Roo.data.ArrayReader.superclass.constructor.call(this, meta, recordType||meta.fields);
 };
 
 Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
-    /**
+    
+      /**
      * Create a data block containing Roo.data.Records from an XML document.
      * @param {Object} o An Array of row objects which represents the dataset.
      * @return {Object} A data block which is used by an {@link Roo.data.Store} object as
      * a cache of Roo.data.Records.
      */
-    readRecords : function(o){
+    readRecords : function(o)
+    {
         var sid = this.meta ? this.meta.id : null;
        var recordType = this.recordType, fields = recordType.prototype.fields;
        var records = [];
        var root = o;
-           for(var i = 0; i < root.length; i++){
-                   var n = root[i];
-               var values = {};
-               var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
-               for(var j = 0, jlen = fields.length; j < jlen; j++){
-                var f = fields.items[j];
-                var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
-                var v = n[k] !== undefined ? n[k] : f.defaultValue;
-                v = f.convert(v);
-                values[f.name] = v;
-            }
-               var record = new recordType(values, id);
-               record.json = n;
-               records[records.length] = record;
+       for(var i = 0; i < root.length; i++){
+               var n = root[i];
+           var values = {};
+           var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
+           for(var j = 0, jlen = fields.length; j < jlen; j++){
+               var f = fields.items[j];
+               var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
+               var v = n[k] !== undefined ? n[k] : f.defaultValue;
+               v = f.convert(v);
+               values[f.name] = v;
            }
-           return {
-               records : records,
-               totalRecords : records.length
-           };
+           var record = new recordType(values, id);
+           record.json = n;
+           records[records.length] = record;
+       }
+       return {
+           records : records,
+           totalRecords : records.length
+       };
+    },
+    // used when loading children.. @see loadDataFromChildren
+    toLoadData: function(rec)
+    {
+       // expect rec just to be an array.. eg [a,b,c, [...] << cn ]
+       return typeof(rec.data.cn) == 'undefined' ? [] : rec.data.cn;
+       
     }
+    
+    
 });/*
  * Based on:
  * Ext JS Library 1.1.1
@@ -25002,6 +25075,7 @@ Roo.extend(Roo.data.Node, Roo.util.Observable, {
         }else if(arguments.length > 1){
             multi = arguments;
         }
+        
         // if passed an array or multiple args do them one by one
         if(multi){
             for(var i = 0, len = multi.length; i < len; i++) {
@@ -25020,6 +25094,7 @@ Roo.extend(Roo.data.Node, Roo.util.Observable, {
                 }
                 oldParent.removeChild(node);
             }
+            
             index = this.childNodes.length;
             if(index == 0){
                 this.setFirstChild(node);
@@ -25037,6 +25112,9 @@ Roo.extend(Roo.data.Node, Roo.util.Observable, {
             this.setLastChild(node);
             node.setOwnerTree(this.getOwnerTree());
             this.fireEvent("append", this.ownerTree, this, node, index);
+            if(this.ownerTree) {
+                this.ownerTree.fireEvent("appendnode", this, node, index);
+            }
             if(oldParent){
                 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
             }
@@ -34274,7 +34352,15 @@ Roo.tree.TreePanel = function(el, config){
         * </ul>
         * @param {Object} dragOverEvent
         */
-       "nodedragover" : true
+       "nodedragover" : true,
+       /**
+        * @event appendnode
+        * Fires when append node to the tree
+        * @param {Roo.tree.TreePanel} this
+        * @param {Roo.tree.TreeNode} node
+        * @param {Number} index The index of the newly appended node
+        */
+       "appendnode" : true
         
     });
     if(this.singleExpand){
@@ -35135,7 +35221,8 @@ Roo.extend(Roo.tree.TreeNode, Roo.data.Node, {
                 this.renderChildren();
             }
             this.expanded = true;
-            if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
+            
+            if(!this.isHiddenRoot() && (this.getOwnerTree() && this.getOwnerTree().animate && anim !== false) || anim){
                 this.ui.animExpand(function(){
                     this.fireEvent("expand", this);
                     if(typeof callback == "function"){
@@ -35586,7 +35673,7 @@ Roo.tree.TreeNodeUI.prototype = {
             this.addClass("x-tree-node-disabled");
         }
         var ot = this.node.getOwnerTree();
-        var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
+        var dd = ot ? (ot.enableDD || ot.enableDrag || ot.enableDrop) : false;
         if(dd && (!this.node.isRoot || ot.rootVisible)){
             Roo.dd.Registry.register(this.elNode, {
                 node: this.node,
@@ -35829,11 +35916,11 @@ Roo.tree.TreeNodeUI.prototype = {
         // add some indent caching, this helps performance when rendering a large tree
         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
         var t = n.getOwnerTree();
-        var txt = t.renderer ? t.renderer(n.attributes) : Roo.util.Format.htmlEncode(n.text);
+        var txt = t && t.renderer ? t.renderer(n.attributes) : Roo.util.Format.htmlEncode(n.text);
         if (typeof(n.attributes.html) != 'undefined') {
             txt = n.attributes.html;
         }
-        var tip = t.rendererTip ? t.rendererTip(n.attributes) : txt;
+        var tip = t && t.rendererTip ? t.rendererTip(n.attributes) : txt;
         var cb = typeof a.checked == 'boolean';
         var href = a.href ? a.href : Roo.isGecko ? "" : "#";
         var buf = ['<li class="x-tree-node"><div class="x-tree-node-el ', a.cls,'">',
@@ -39427,6 +39514,10 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
      * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
      */
     selectOnFocus : false,
+    /**
+     * @cfg {Boolean} allowLeadingSpace True to prevent the stripping of leading white space 
+     */    
+    allowLeadingSpace : false,
     /**
      * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
      */
@@ -39471,8 +39562,11 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
         
         if(this.selectOnFocus){
             this.on("focus", this.preFocus, this);
-            
         }
+       if (!this.allowLeadingSpace) {
+           this.on('blur', this.cleanLeadingSpace, this);
+       }
+       
         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
             this.el.on("keypress", this.filterKeys, this);
         }
@@ -39508,7 +39602,15 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
             this.autoSize();
         }
     },
-
+    // private - clean the leading white space
+    cleanLeadingSpace : function(e)
+    {
+        if ( this.inputType == 'file') {
+            return;
+        }
+        
+        this.setValue((this.getValue() + '').replace(/^\s+/,''));
+    },
     /**
      * Resets the current field value to the originally-loaded value and clears any validation messages.
      *  
@@ -39516,9 +39618,7 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
     reset : function(){
         Roo.form.TextField.superclass.reset.call(this);
        
-    },
-
-    
+    }, 
     // private
     preFocus : function(){
         
@@ -40270,7 +40370,8 @@ Roo.extend(Roo.form.NumberField, Roo.form.TextField,  {
 * Create a new DateField
 * @param {Object} config
  */
-Roo.form.DateField = function(config){
+Roo.form.DateField = function(config)
+{
     Roo.form.DateField.superclass.constructor.call(this, config);
     
       this.addEvents({
@@ -40618,7 +40719,13 @@ dateField.setValue('2006-5-4');
         
         return String(this.getValue()) !== String(this.startValue);
         
+    },
+    // @overide
+    cleanLeadingSpace : function(e)
+    {
+       return;
     }
+    
 });/*
  * Based on:
  * Ext JS Library 1.1.1
@@ -41331,9 +41438,11 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
     // element that contains real text value.. (when hidden is used..)
      
     // private
-    onRender : function(ct, position){
+    onRender : function(ct, position)
+    {
         Roo.form.ComboBox.superclass.onRender.call(this, ct, position);
-        if(this.hiddenName){
+        
+       if(this.hiddenName){
             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id:  (this.hiddenId||this.hiddenName)},
                     'before', true);
             this.hiddenField.value =
@@ -41345,6 +41454,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
              
              
         }
+       
         if(Roo.isGecko){
             this.el.dom.setAttribute('autocomplete', 'off');
         }
@@ -41405,7 +41515,9 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         }
 
         this.view = new Roo.View(this.innerList, this.tpl, {
-            singleSelect:true, store: this.store, selectedClass: this.selectedClass
+            singleSelect:true,
+           store: this.store,
+           selectedClass: this.selectedClass
         });
 
         this.view.on('click', this.onViewClick, this);
@@ -42092,7 +42204,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         this.view.select(match);
         var sn = Roo.get(this.view.getSelectedNodes()[0]);
         sn.scrollIntoView(sn.dom.parentNode, false);
-    }
+    } 
 
     /** 
     * @cfg {Boolean} grow 
@@ -42227,7 +42339,7 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
         
         // give fake names to child combo;
         this.combo.hiddenName = this.hiddenName ? (this.hiddenName+'-subcombo') : this.hiddenName;
-        this.combo.name = this.name? (this.name+'-subcombo') : this.name;
+        this.combo.name = this.name ? (this.name+'-subcombo') : this.name;
         
         this.combo = Roo.factory(this.combo, Roo.form);
         this.combo.onRender(ct, position);
@@ -42348,6 +42460,7 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
     {
         var valueField = this.combo.valueField;
         var displayField = this.combo.displayField;
+       
         if (this.items.indexOfKey(rec[valueField]) > -1) {
             //console.log("GOT " + rec.data.id);
             return;
@@ -42379,7 +42492,6 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
         
         this.items.each(function(f) {
             ar.push(f.data[idField]);
-           
         });
         this.hiddenEl.dom.value = ar.join(',');
         this.validate();
@@ -42405,11 +42517,9 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
     },
     setValue: function(v) // not a valid action - must use addItems..
     {
-         
-        this.reset();
-        
-        
         
+        this.reset();
+         
         if (this.store.isLocal && (typeof(v) == 'string')) {
             // then we can use the store to find the values..
             // comma seperated at present.. this needs to allow JSON based encoding..
@@ -42593,6 +42703,434 @@ Roo.extend(Roo.form.ComboBoxArray.Item, Roo.BoxComponent, {
         }
         
     }
+});/*
+ * RooJS Library 1.1.1
+ * Copyright(c) 2008-2011  Alan Knowles
+ *
+ * License - LGPL
+ */
+
+/**
+ * @class Roo.form.ComboNested
+ * @extends Roo.form.ComboBox
+ * A combobox for that allows selection of nested items in a list,
+ * eg.
+ *
+ *  Book
+ *    -> red
+ *    -> green
+ *  Table
+ *    -> square
+ *      ->red
+ *      ->green
+ *    -> rectangle
+ *      ->green
+ *      
+ * 
+ * @constructor
+ * Create a new ComboNested
+ * @param {Object} config Configuration options
+ */
+Roo.form.ComboNested = function(config){
+    Roo.form.ComboCheck.superclass.constructor.call(this, config);
+    // should verify some data...
+    // like
+    // hiddenName = required..
+    // displayField = required
+    // valudField == required
+    var req= [ 'hiddenName', 'displayField', 'valueField' ];
+    var _t = this;
+    Roo.each(req, function(e) {
+        if ((typeof(_t[e]) == 'undefined' ) || !_t[e].length) {
+            throw "Roo.form.ComboNested : missing value for: " + e;
+        }
+    });
+     
+    
+};
+
+Roo.extend(Roo.form.ComboNested, Roo.form.ComboBox, {
+   
+    /*
+     * @config {Number} max Number of columns to show
+     */
+    
+    maxColumns : 3,
+   
+    list : null, // the outermost div..
+    innerLists : null, // the
+    views : null,
+    stores : null,
+    // private
+    loadingChildren : false,
+    
+    onRender : function(ct, position)
+    {
+        Roo.form.ComboBox.superclass.onRender.call(this, ct, position); // skip parent call - got to above..
+        
+        if(this.hiddenName){
+            this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id:  (this.hiddenId||this.hiddenName)},
+                    'before', true);
+            this.hiddenField.value =
+                this.hiddenValue !== undefined ? this.hiddenValue :
+                this.value !== undefined ? this.value : '';
+
+            // prevent input submission
+            this.el.dom.removeAttribute('name');
+             
+             
+        }
+       
+        if(Roo.isGecko){
+            this.el.dom.setAttribute('autocomplete', 'off');
+        }
+
+        var cls = 'x-combo-list';
+
+        this.list = new Roo.Layer({
+            shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
+        });
+
+        var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
+        this.list.setWidth(lw);
+        this.list.swallowEvent('mousewheel');
+        this.assetHeight = 0;
+
+        if(this.title){
+            this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
+            this.assetHeight += this.header.getHeight();
+        }
+        this.innerLists = [];
+        this.views = [];
+        this.stores = [];
+        for (var i =0 ; i < this.maxColumns; i++) {
+            this.onRenderList( cls, i);
+        }
+        
+        // always needs footer, as we are going to have an 'OK' button.
+        this.footer = this.list.createChild({cls:cls+'-ft'});
+        this.pageTb = new Roo.Toolbar(this.footer);  
+        var _this = this;
+        this.pageTb.add(  {
+            
+            text: 'Done',
+            handler: function()
+            {
+                _this.collapse();
+            }
+        });
+        
+        if ( this.allowBlank && !this.disableClear) {
+            
+            this.pageTb.add(new Roo.Toolbar.Fill(), {
+                cls: 'x-btn-icon x-btn-clear',
+                text: '&#160;',
+                handler: function()
+                {
+                    _this.collapse();
+                    _this.clearValue();
+                    _this.onSelect(false, -1);
+                }
+            });
+        }
+        if (this.footer) {
+            this.assetHeight += this.footer.getHeight();
+        }
+        
+    },
+    onRenderList : function (  cls, i)
+    {
+        
+        var lw = Math.floor(
+                ((this.listWidth * this.maxColumns || Math.max(this.wrap.getWidth(), this.minListWidth)) - this.list.getFrameWidth('lr')) / this.maxColumns
+        );
+        
+        this.list.setWidth(lw); // default to '1'
+
+        var il = this.innerLists[i] = this.list.createChild({cls:cls+'-inner'});
+        //il.on('mouseover', this.onViewOver, this, { list:  i });
+        //il.on('mousemove', this.onViewMove, this, { list:  i });
+        il.setWidth(lw);
+        il.setStyle({ 'overflow-x' : 'hidden'});
+
+        if(!this.tpl){
+            this.tpl = new Roo.Template({
+                html :  '<div class="'+cls+'-item '+cls+'-item-{cn:this.isEmpty}">{' + this.displayField + '}</div>',
+                isEmpty: function (value, allValues) {
+                    //Roo.log(value);
+                    var dl = typeof(value.data) != 'undefined' ? value.data.length : value.length; ///json is a nested response..
+                    return dl ? 'has-children' : 'no-children'
+                }
+            });
+        }
+        
+        var store  = this.store;
+        if (i > 0) {
+            store  = new Roo.data.SimpleStore({
+                //fields : this.store.reader.meta.fields,
+                reader : this.store.reader,
+                data : [ ]
+            });
+        }
+        this.stores[i]  = store;
+                  
+        var view = this.views[i] = new Roo.View(
+            il,
+            this.tpl,
+            {
+                singleSelect:true,
+                store: store,
+                selectedClass: this.selectedClass
+            }
+        );
+        view.getEl().setWidth(lw);
+        view.getEl().setStyle({
+            position: i < 1 ? 'relative' : 'absolute',
+            top: 0,
+            left: (i * lw ) + 'px',
+            display : i > 0 ? 'none' : 'block'
+        });
+        view.on('selectionchange', this.onSelectChange.createDelegate(this, {list : i }, true));
+        view.on('dblclick', this.onDoubleClick.createDelegate(this, {list : i }, true));
+        //view.on('click', this.onViewClick, this, { list : i });
+
+        store.on('beforeload', this.onBeforeLoad, this);
+        store.on('load',  this.onLoad, this, { list  : i});
+        store.on('loadexception', this.onLoadException, this);
+
+        // hide the other vies..
+        
+        
+        
+    },
+      
+    restrictHeight : function()
+    {
+        var mh = 0;
+        Roo.each(this.innerLists, function(il,i) {
+            var el = this.views[i].getEl();
+            el.dom.style.height = '';
+            var inner = el.dom;
+            var h = Math.max(il.clientHeight, il.offsetHeight, il.scrollHeight);
+            // only adjust heights on other ones..
+            mh = Math.max(h, mh);
+            if (i < 1) {
+                
+                el.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
+                il.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
+               
+            }
+            
+            
+        }, this);
+        
+        this.list.beginUpdate();
+        this.list.setHeight(mh+this.list.getFrameWidth('tb')+this.assetHeight);
+        this.list.alignTo(this.el, this.listAlign);
+        this.list.endUpdate();
+        
+    },
+     
+    
+    // -- store handlers..
+    // private
+    onBeforeLoad : function()
+    {
+        if(!this.hasFocus){
+            return;
+        }
+        this.innerLists[0].update(this.loadingText ?
+               '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
+        this.restrictHeight();
+        this.selectedIndex = -1;
+    },
+    // private
+    onLoad : function(a,b,c,d)
+    {
+        if (!this.loadingChildren) {
+            // then we are loading the top level. - hide the children
+            for (var i = 1;i < this.views.length; i++) {
+                this.views[i].getEl().setStyle({ display : 'none' });
+            }
+            var lw = Math.floor(
+                ((this.listWidth * this.maxColumns || Math.max(this.wrap.getWidth(), this.minListWidth)) - this.list.getFrameWidth('lr')) / this.maxColumns
+            );
+        
+             this.list.setWidth(lw); // default to '1'
+
+            
+        }
+        if(!this.hasFocus){
+            return;
+        }
+        
+        if(this.store.getCount() > 0) {
+            this.expand();
+            this.restrictHeight();   
+        } else {
+            this.onEmptyResults();
+        }
+        
+        if (!this.loadingChildren) {
+            this.selectActive();
+        }
+        /*
+        this.stores[1].loadData([]);
+        this.stores[2].loadData([]);
+        this.views
+        */    
+    
+        //this.el.focus();
+    },
+    
+    
+    // private
+    onLoadException : function()
+    {
+        this.collapse();
+        Roo.log(this.store.reader.jsonData);
+        if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
+            Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
+        }
+        
+        
+    },
+    // no cleaning of leading spaces on blur here.
+    cleanLeadingSpace : function(e) { },
+    
+
+    onSelectChange : function (view, sels, opts )
+    {
+        var ix = view.getSelectedIndexes();
+         
+        if (opts.list > this.maxColumns - 2) {
+            if (view.store.getCount()<  1) {
+                this.views[opts.list ].getEl().setStyle({ display :   'none' });
+
+            } else  {
+                if (ix.length) {
+                    // used to clear ?? but if we are loading unselected 
+                    this.setFromData(view.store.getAt(ix[0]).data);
+                }
+                
+            }
+            
+            return;
+        }
+        
+        if (!ix.length) {
+            // this get's fired when trigger opens..
+           // this.setFromData({});
+            var str = this.stores[opts.list+1];
+            str.data.clear(); // removeall wihtout the fire events..
+            return;
+        }
+        
+        var rec = view.store.getAt(ix[0]);
+         
+        this.setFromData(rec.data);
+        this.fireEvent('select', this, rec, ix[0]);
+        
+        var lw = Math.floor(
+             (
+                (this.listWidth * this.maxColumns || Math.max(this.wrap.getWidth(), this.minListWidth)) - this.list.getFrameWidth('lr')
+             ) / this.maxColumns
+        );
+        this.loadingChildren = true;
+        this.stores[opts.list+1].loadDataFromChildren( rec );
+        this.loadingChildren = false;
+        var dl = this.stores[opts.list+1]. getTotalCount();
+        
+        this.views[opts.list+1].getEl().setHeight( this.innerLists[0].getHeight());
+        
+        this.views[opts.list+1].getEl().setStyle({ display : dl ? 'block' : 'none' });
+        for (var i = opts.list+2; i < this.views.length;i++) {
+            this.views[i].getEl().setStyle({ display : 'none' });
+        }
+        
+        this.innerLists[opts.list+1].setHeight( this.innerLists[0].getHeight());
+        this.list.setWidth(lw * (opts.list + (dl ? 2 : 1)));
+        
+        if (this.isLoading) {
+           // this.selectActive(opts.list);
+        }
+         
+    },
+    
+    
+    
+    
+    onDoubleClick : function()
+    {
+        this.collapse(); //??
+    },
+    
+     
+    
+    
+    
+    // private
+    recordToStack : function(store, prop, value, stack)
+    {
+        var cstore = new Roo.data.SimpleStore({
+            //fields : this.store.reader.meta.fields, // we need array reader.. for
+            reader : this.store.reader,
+            data : [ ]
+        });
+        var _this = this;
+        var record  = false;
+        var srec = false;
+        if(store.getCount() < 1){
+            return false;
+        }
+        store.each(function(r){
+            if(r.data[prop] == value){
+                record = r;
+            srec = r;
+                return false;
+            }
+            if (r.data.cn && r.data.cn.length) {
+                cstore.loadDataFromChildren( r);
+                var cret = _this.recordToStack(cstore, prop, value, stack);
+                if (cret !== false) {
+                    record = cret;
+                    srec = r;
+                    return false;
+                }
+            }
+             
+            return true;
+        });
+        if (record == false) {
+            return false
+        }
+        stack.unshift(srec);
+        return record;
+    },
+    
+    /*
+     * find the stack of stores that match our value.
+     *
+     * 
+     */
+    
+    selectActive : function ()
+    {
+       // if store is not loaded, then we will need to wait for that to happen first.
+        var stack = [];
+        this.recordToStack(this.store, this.valueField, this.getValue(), stack);
+        for (var i = 0; i < stack.length; i++ ) {
+            this.views[i].select(stack[i].store.indexOf(stack[i]), false, false );
+        }
+       
+    }
+       
+        
+    
+    
+    
+    
 });/*
  * Based on:
  * Ext JS Library 1.1.1
@@ -43216,17 +43754,32 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             html = this.cleanHtml(html);
             // fix up the special chars.. normaly like back quotes in word...
             // however we do not want to do this with chinese..
-            html = html.replace(/([\x80-\uffff])/g, function (a, b) {
-                var cc = b.charCodeAt();
-                if (
+            html = html.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0080-\uFFFF]/g, function(match) {
+                
+                var cc = match.charCodeAt();
+
+                // Get the character value, handling surrogate pairs
+                if (match.length == 2) {
+                    // It's a surrogate pair, calculate the Unicode code point
+                    var high = match.charCodeAt(0) - 0xD800;
+                    var low  = match.charCodeAt(1) - 0xDC00;
+                    cc = (high * 0x400) + low + 0x10000;
+                }  else if (
                     (cc >= 0x4E00 && cc < 0xA000 ) ||
                     (cc >= 0x3400 && cc < 0x4E00 ) ||
                     (cc >= 0xf900 && cc < 0xfb00 )
                 ) {
-                        return b;
-                }
-                return "&#"+cc+";" 
+                        return match;
+                }  
+         
+                // No, use a numeric entity. Here we brazenly (and possibly mistakenly)
+                return "&#" + cc + ";";
+                
+                
             });
+            
+            
+             
             if(this.owner.fireEvent('beforesync', this, html) !== false){
                 this.el.dom.value = html;
                 this.owner.fireEvent('sync', this, html);
@@ -43410,7 +43963,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     insertTag : function(tg)
     {
         // could be a bit smarter... -> wrap the current selected tRoo..
-        if (tg.toLowerCase() == 'span' || tg.toLowerCase() == 'code') {
+        if (tg.toLowerCase() == 'span' ||
+            tg.toLowerCase() == 'code' ||
+            tg.toLowerCase() == 'sup' ||
+            tg.toLowerCase() == 'sub' 
+            ) {
             
             range = this.createRange(this.getSelection());
             var wrappingNode = this.doc.createElement(tg.toLowerCase());
@@ -43906,6 +44463,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
         
+        // spans with no attributes - just remove them..
+        if ((!node.attributes || !node.attributes.length) && lcname == 'span') { 
+            remove_keep_children = true;
+        }
+        
         // remove <a name=....> as rendering on yahoo mailer is borked with this.
         // this will have to be flaged elsewhere - perhaps ablack=name... on the mailer..
         
@@ -43926,6 +44488,10 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         }
         
         if (!node.attributes || !node.attributes.length) {
+            
+          
+            
+            
             this.cleanUpChildren(node);
             return;
         }
@@ -44022,11 +44588,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             
             if (a.name == 'class') {
                 if (a.value.match(/^Mso/)) {
-                    node.className = '';
+                    node.removeAttribute('class');
                 }
                 
                 if (a.value.match(/^body$/)) {
-                    node.className = '';
+                    node.removeAttribute('class');
                 }
                 continue;
             }
@@ -44047,12 +44613,29 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
      */
     cleanWord : function(node)
     {
-        
-        
         if (!node) {
             this.cleanWord(this.doc.body);
             return;
         }
+        
+        if(
+                node.nodeName == 'SPAN' &&
+                !node.hasAttributes() &&
+                node.childNodes.length == 1 &&
+                node.firstChild.nodeName == "#text"  
+        ) {
+            var textNode = node.firstChild;
+            node.removeChild(textNode);
+            if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
+                node.parentNode.insertBefore(node.ownerDocument.createTextNode(" "), node);
+            }
+            node.parentNode.insertBefore(textNode, node);
+            if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
+                node.parentNode.insertBefore(node.ownerDocument.createTextNode(" ") , node);
+            }
+            node.parentNode.removeChild(node);
+        }
+        
         if (node.nodeName == "#text") {
             // clean up silly Windows -- stuff?
             return; 
@@ -44067,16 +44650,20 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             node.parentNode.removeChild(node);
             return;
         }
-        
+        //Roo.log(node.tagName);
         // remove - but keep children..
-        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|font)/)) {
+        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)) {
+            //Roo.log('-- removed');
             while (node.childNodes.length) {
                 var cn = node.childNodes[0];
                 node.removeChild(cn);
                 node.parentNode.insertBefore(cn, node);
+                // move node to parent - and clean it..
+                this.cleanWord(cn);
             }
             node.parentNode.removeChild(node);
-            this.iterateChildren(node, this.cleanWord);
+            /// no need to iterate chidlren = it's got none..
+            //this.iterateChildren(node, this.cleanWord);
             return;
         }
         // clean styles
@@ -45316,7 +45903,8 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarStandard.prototype,  {
         ["h1"],["h2"],["h3"],["h4"],["h5"],["h6"], 
         ["pre"],[ "code"], 
         ["abbr"],[ "acronym"],[ "address"],[ "cite"],[ "samp"],[ "var"],
-        ['div'],['span']
+        ['div'],['span'],
+        ['sup'],['sub']
     ],
     
     cleanStyles : [
@@ -45618,8 +46206,9 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarStandard.prototype,  {
                     
                     var c = Roo.get(editorcore.doc.body);
                     c.select('[class]').each(function(s) {
-                        s.dom.className = '';
+                        s.dom.removeAttribute('class');
                     });
+                    editorcore.cleanWord();
                     editorcore.syncValue();
                 },
                 tabIndex:-1
@@ -46811,6 +47400,8 @@ Roo.form.BasicForm = function(el, config){
         this.initEl(el);
     }
     Roo.form.BasicForm.superclass.constructor.call(this);
+    
+    Roo.form.BasicForm.popover.apply();
 };
 
 Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
@@ -46881,6 +47472,16 @@ Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
      * @type Boolean
      */
     disableMask : false,
+    
+    /**
+     * @cfg {Boolean} errorMask (true|false) default false
+     */
+    errorMask : false,
+    
+    /**
+     * @cfg {Number} maskOffset Default 100
+     */
+    maskOffset : 100,
 
     // private
     initEl : function(el){
@@ -46901,11 +47502,23 @@ Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
      */
     isValid : function(){
         var valid = true;
+        var target = false;
         this.items.each(function(f){
-           if(!f.validate()){
-               valid = false;
-           }
+            if(f.validate()){
+                return;
+            }
+            
+            valid = false;
+                
+            if(!target && f.el.isVisible(true)){
+                target = f;
+            }
         });
+        
+        if(this.errorMask && !valid){
+            Roo.form.BasicForm.popover.mask(this, target);
+        }
+        
         return valid;
     },
 
@@ -47253,7 +47866,7 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
                 
         return this;
     },
-
     /**
      * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
      * they are returned as an array.
@@ -47268,6 +47881,23 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
             }, this);
         }
         
+        // use formdata
+        if (typeof(FormData) != 'undefined' && asString !== true) {
+            // this relies on a 'recent' version of chrome apparently...
+            try {
+                var fd = (new FormData(this.el.dom)).entries();
+                var ret = {};
+                var ent = fd.next();
+                while (!ent.done) {
+                    ret[ent.value[0]] = ent.value[1]; // not sure how this will handle duplicates..
+                    ent = fd.next();
+                };
+                return ret;
+            } catch(e) {
+                
+            }
+            
+        }
         
         
         var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
@@ -47423,7 +48053,153 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
 });
 
 // back compat
-Roo.BasicForm = Roo.form.BasicForm;/*
+Roo.BasicForm = Roo.form.BasicForm;
+
+Roo.apply(Roo.form.BasicForm, {
+    
+    popover : {
+        
+        padding : 5,
+        
+        isApplied : false,
+        
+        isMasked : false,
+        
+        form : false,
+        
+        target : false,
+        
+        intervalID : false,
+        
+        maskEl : false,
+        
+        apply : function()
+        {
+            if(this.isApplied){
+                return;
+            }
+            
+            this.maskEl = {
+                top : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-top-mask" }, true),
+                left : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-left-mask" }, true),
+                bottom : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-bottom-mask" }, true),
+                right : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-right-mask" }, true)
+            };
+            
+            this.maskEl.top.enableDisplayMode("block");
+            this.maskEl.left.enableDisplayMode("block");
+            this.maskEl.bottom.enableDisplayMode("block");
+            this.maskEl.right.enableDisplayMode("block");
+            
+            Roo.get(document.body).on('click', function(){
+                this.unmask();
+            }, this);
+            
+            Roo.get(document.body).on('touchstart', function(){
+                this.unmask();
+            }, this);
+            
+            this.isApplied = true
+        },
+        
+        mask : function(form, target)
+        {
+            this.form = form;
+            
+            this.target = target;
+            
+            if(!this.form.errorMask || !target.el){
+                return;
+            }
+            
+            var scrollable = this.target.el.findScrollableParent() || this.target.el.findParent('div.x-layout-active-content', 100, true) || Roo.get(document.body);
+            
+            var ot = this.target.el.calcOffsetsTo(scrollable);
+            
+            var scrollTo = ot[1] - this.form.maskOffset;
+            
+            scrollTo = Math.min(scrollTo, scrollable.dom.scrollHeight);
+            
+            scrollable.scrollTo('top', scrollTo);
+            
+            var el = this.target.wrap || this.target.el;
+            
+            var box = el.getBox();
+            
+            this.maskEl.top.setStyle('position', 'absolute');
+            this.maskEl.top.setStyle('z-index', 10000);
+            this.maskEl.top.setSize(Roo.lib.Dom.getDocumentWidth(), box.y - this.padding);
+            this.maskEl.top.setLeft(0);
+            this.maskEl.top.setTop(0);
+            this.maskEl.top.show();
+            
+            this.maskEl.left.setStyle('position', 'absolute');
+            this.maskEl.left.setStyle('z-index', 10000);
+            this.maskEl.left.setSize(box.x - this.padding, box.height + this.padding * 2);
+            this.maskEl.left.setLeft(0);
+            this.maskEl.left.setTop(box.y - this.padding);
+            this.maskEl.left.show();
+
+            this.maskEl.bottom.setStyle('position', 'absolute');
+            this.maskEl.bottom.setStyle('z-index', 10000);
+            this.maskEl.bottom.setSize(Roo.lib.Dom.getDocumentWidth(), Roo.lib.Dom.getDocumentHeight() - box.bottom - this.padding);
+            this.maskEl.bottom.setLeft(0);
+            this.maskEl.bottom.setTop(box.bottom + this.padding);
+            this.maskEl.bottom.show();
+
+            this.maskEl.right.setStyle('position', 'absolute');
+            this.maskEl.right.setStyle('z-index', 10000);
+            this.maskEl.right.setSize(Roo.lib.Dom.getDocumentWidth() - box.right - this.padding, box.height + this.padding * 2);
+            this.maskEl.right.setLeft(box.right + this.padding);
+            this.maskEl.right.setTop(box.y - this.padding);
+            this.maskEl.right.show();
+
+            this.intervalID = window.setInterval(function() {
+                Roo.form.BasicForm.popover.unmask();
+            }, 10000);
+
+            window.onwheel = function(){ return false;};
+            
+            (function(){ this.isMasked = true; }).defer(500, this);
+            
+        },
+        
+        unmask : function()
+        {
+            if(!this.isApplied || !this.isMasked || !this.form || !this.target || !this.form.errorMask){
+                return;
+            }
+            
+            this.maskEl.top.setStyle('position', 'absolute');
+            this.maskEl.top.setSize(0, 0).setXY([0, 0]);
+            this.maskEl.top.hide();
+
+            this.maskEl.left.setStyle('position', 'absolute');
+            this.maskEl.left.setSize(0, 0).setXY([0, 0]);
+            this.maskEl.left.hide();
+
+            this.maskEl.bottom.setStyle('position', 'absolute');
+            this.maskEl.bottom.setSize(0, 0).setXY([0, 0]);
+            this.maskEl.bottom.hide();
+
+            this.maskEl.right.setStyle('position', 'absolute');
+            this.maskEl.right.setSize(0, 0).setXY([0, 0]);
+            this.maskEl.right.hide();
+            
+            window.onwheel = function(){ return true;};
+            
+            if(this.intervalID){
+                window.clearInterval(this.intervalID);
+                this.intervalID = false;
+            }
+            
+            this.isMasked = false;
+            
+        }
+        
+    }
+    
+});/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -47491,8 +48267,6 @@ Roo.form.Form = function(config){
     
     Roo.each(xitems, this.addxtype, this);
     
-    
-    
 };
 
 Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
@@ -52372,7 +53146,7 @@ Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
      * Collapses this region.
      * @param {Boolean} skipAnim (optional) true to collapse the element without animation (if animate is true)
      */
-    collapse : function(skipAnim, skipCheck = false){
+    collapse : function(skipAnim, skipCheck){
         if(this.collapsed) {
             return;
         }
@@ -54693,12 +55467,12 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
         return this;
     },
 
-       /**
-        * Reconfigures the grid to use a different Store and Column Model.
-        * The View will be bound to the new objects and refreshed.
-        * @param {Roo.data.Store} dataSource The new {@link Roo.data.Store} object
-        * @param {Roo.grid.ColumnModel} The new {@link Roo.grid.ColumnModel} object
-        */
+    /**
+     * Reconfigures the grid to use a different Store and Column Model.
+     * The View will be bound to the new objects and refreshed.
+     * @param {Roo.data.Store} dataSource The new {@link Roo.data.Store} object
+     * @param {Roo.grid.ColumnModel} The new {@link Roo.grid.ColumnModel} object
+     */
     reconfigure : function(dataSource, colModel){
         if(this.loadMask){
             this.loadMask.destroy();
@@ -54710,7 +55484,41 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
         this.colModel = colModel;
         this.view.refresh(true);
     },
-
+    /**
+     * addColumns
+     * Add's a column, default at the end..
+     
+     * @param {int} position to add (default end)
+     * @param {Array} of objects of column configuration see {@link Roo.grid.ColumnModel} 
+     */
+    addColumns : function(pos, ar)
+    {
+        
+        for (var i =0;i< ar.length;i++) {
+            var cfg = ar[i];
+            cfg.id = typeof(cfg.id) == 'undefined' ? Roo.id() : cfg.id; // don't normally use this..
+            this.cm.lookup[cfg.id] = cfg;
+        }
+        
+        
+        if (typeof(pos) == 'undefined' || pos >= this.cm.config.length) {
+            pos = this.cm.config.length; //this.cm.config.push(cfg);
+        } 
+        pos = Math.max(0,pos);
+        ar.unshift(0);
+        ar.unshift(pos);
+        this.cm.config.splice.apply(this.cm.config, ar);
+        
+        
+        
+        this.view.generateRules(this.cm);
+        this.view.refresh(true);
+        
+    },
+    
+    
+    
+    
     // private
     onKeyDown : function(e){
         this.fireEvent("keydown", e);