comment out row/cell selection requirement for cellclick - no idea why that was done...
[roojs1] / roojs-debug.js
index e956860..db55df5 100644 (file)
@@ -1015,8 +1015,34 @@ Roo.applyIf(Array.prototype, {
         }
 
         return res;
+    },
+    /**
+     * equals
+     * @param {Array} o The array to compare to
+     * @returns {Boolean} true if the same
+     */
+    equals : function(b)
+    {
+        // https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript
+       if (this === b) {
+           return true;
+        }
+       if (b == null) {
+           return false;
+       }
+       if (this.length !== b.length) {
+           return false;
+       }
+      
+       // sort?? a.sort().equals(b.sort());
+      
+       for (var i = 0; i < this.length; ++i) {
+           if (this[i] !== b[i]) {
+               return false;
+           }
+       }
+       return true;
     }
-    
 });
 
 
@@ -4652,6 +4678,12 @@ Roo.Template = function(cfg){
 };
 Roo.Template.prototype = {
     
+    /**
+     * @cfg {Function} onLoad Called after the template has been loaded and complied (usually from a remove source)
+     */
+    onLoad : false,
+    
+    
     /**
      * @cfg {String} url  The Url to load the template from. beware if you are loading from a url, the data may not be ready if you use it instantly..
      *                    it should be fixed so that template is observable...
@@ -4661,12 +4693,20 @@ Roo.Template.prototype = {
      * @cfg {String} html  The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
      */
     html : '',
+    
+    
+    compiled : false,
+    loaded : false,
     /**
      * Returns an HTML fragment of this template with the specified values applied.
      * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
      * @return {String} The HTML fragment
      */
+    
+   
+    
     applyTemplate : function(values){
+        //Roo.log(["applyTemplate", values]);
         try {
            
             if(this.compiled){
@@ -4725,9 +4765,13 @@ Roo.Template.prototype = {
             method : 'GET',
             success : function (response) {
                 _t.loading = false;
-                _t.html = response.responseText;
                 _t.url = false;
-                _t.compile();
+                
+                _t.set(response.responseText,true);
+                _t.loaded = true;
+                if (_t.onLoad) {
+                    _t.onLoad();
+                }
              },
             failure : function(response) {
                 Roo.log("Template failed to load from " + _t.url);
@@ -4744,7 +4788,7 @@ Roo.Template.prototype = {
      */
     set : function(html, compile){
         this.html = html;
-        this.compiled = null;
+        this.compiled = false;
         if(compile){
             this.compile();
         }
@@ -5022,7 +5066,11 @@ Roo.DomQuery = function(){
         }
         var r = [], ri = -1, cn;
         for(var i = 0, ci; ci = c[i]; i++){
-            if((' '+ci.className+' ').indexOf(v) != -1){
+           
+           
+            if((' '+
+               ( (ci instanceof SVGElement) ? ci.className.baseVal : ci.className)
+                +' ').indexOf(v) != -1){
                 r[++ri] = ci;
             }
         }
@@ -5040,7 +5088,7 @@ Roo.DomQuery = function(){
             return n.htmlFor;
         }
         if(attr == "class" || attr == "className"){
-            return n.className;
+           return (n instanceof SVGElement) ? n.className.baseVal : n.className;
         }
         return n.getAttribute(attr) || n[attr];
 
@@ -5144,7 +5192,7 @@ Roo.DomQuery = function(){
                 a = Roo.DomQuery.getStyle(ci, attr);
             }
             else if(attr == "class" || attr == "className"){
-                a = ci.className;
+                a = (ci instanceof SVGElement) ? ci.className.baseVal : ci.className;
             }else if(attr == "for"){
                 a = ci.htmlFor;
             }else if(attr == "href"){
@@ -5905,12 +5953,15 @@ Roo.util.Observable.prototype = {
     relayEvents : function(o, events){
         var createHandler = function(ename){
             return function(){
+                
                 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
             };
         };
         for(var i = 0, len = events.length; i < len; i++){
             var ename = events[i];
-            if(!this.events[ename]){ this.events[ename] = true; };
+            if(!this.events[ename]){
+               this.events[ename] = true;
+           };
             o.on(ename, createHandler(ename), this);
         }
     },
@@ -6073,10 +6124,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;
                     }
@@ -6255,8 +6306,10 @@ Roo.EventManager = function(){
         }
     }
     
+  
 
-    var listen = function(element, ename, opt, fn, scope){
+    var listen = function(element, ename, opt, fn, scope)
+    {
         var o = (!opt || typeof opt == "boolean") ? {} : opt;
         fn = fn || o.fn; scope = scope || o.scope;
         var el = Roo.getDom(element);
@@ -6313,7 +6366,9 @@ Roo.EventManager = function(){
         
         
          
-        E.on(el, ename, h);
+        E.on(el, ename, h); // this adds the actuall listener to the object..
+        
+        
         if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
             el.addEventListener("DOMMouseScroll", h, false);
             E.on(window, 'unload', function(){
@@ -7098,9 +7153,13 @@ if(opt.anim.isAnimated()){
  * @param {String/HTMLElement} element
  * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
  */
-    Roo.Element = function(element, forceNew){
+    Roo.Element = function(element, forceNew)
+    {
         var dom = typeof element == "string" ?
                 document.getElementById(element) : element;
+        
+        this.listeners = {};
+        
         if(!dom){ // invalid id/element
             return null;
         }
@@ -7120,18 +7179,22 @@ if(opt.anim.isAnimated()){
          * @type String
          */
         this.id = id || Roo.id(dom);
+        
+        return this; // assumed for cctor?
     };
 
     var El = Roo.Element;
 
     El.prototype = {
         /**
-         * The element's default display mode  (defaults to "")
+         * The element's default display mode  (defaults to "") 
          * @type String
          */
         originalDisplay : "",
 
-        visibilityMode : 1,
+        
+        // note this is overridden in BS version..
+        visibilityMode : 1, 
         /**
          * The default unit to append to CSS values where a unit isn't provided (defaults to px).
          * @type String
@@ -7625,7 +7688,11 @@ if(opt.anim.isAnimated()){
                 }
             }else{
                 if(className && !this.hasClass(className)){
-                    this.dom.className = this.dom.className + " " + className;
+                    if (this.dom instanceof SVGElement) {
+                        this.dom.className.baseVal =this.dom.className.baseVal  + " " + className;
+                    } else {
+                        this.dom.className = this.dom.className + " " + className;
+                    }
                 }
             }
             return this;
@@ -7654,7 +7721,9 @@ if(opt.anim.isAnimated()){
          * @return {Roo.Element} this
          */
         removeClass : function(className){
-            if(!className || !this.dom.className){
+            
+            var cn = this.dom instanceof SVGElement ? this.dom.className.baseVal : this.dom.className;
+            if(!className || !cn){
                 return this;
             }
             if(className instanceof Array){
@@ -7668,8 +7737,11 @@ if(opt.anim.isAnimated()){
                        re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
                        this.classReCache[className] = re;
                     }
-                    this.dom.className =
-                        this.dom.className.replace(re, " ");
+                    if (this.dom instanceof SVGElement) {
+                        this.dom.className.baseVal = cn.replace(re, " ");
+                    } else {
+                        this.dom.className = cn.replace(re, " ");
+                    }
                 }
             }
             return this;
@@ -7698,6 +7770,9 @@ if(opt.anim.isAnimated()){
          * @return {Boolean} True if the class exists, else false
          */
         hasClass : function(className){
+            if (this.dom instanceof SVGElement) {
+                return className && (' '+this.dom.className.baseVal +' ').indexOf(' '+className+' ') != -1; 
+            } 
             return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
         },
 
@@ -8179,20 +8254,67 @@ if(opt.anim.isAnimated()){
          * @param {Object} scope       (optional) The scope (this object) of the fn
          * @param {Object}   options   (optional)An object with standard {@link Roo.EventManager#addListener} options
          */
-        addListener : function(eventName, fn, scope, options){
-            if (this.dom) {
-                Roo.EventManager.on(this.dom,  eventName, fn, scope || this, options);
+        addListener : function(eventName, fn, scope, options)
+        {
+            if (eventName == 'dblclick') { // doublclick (touchstart) - faked on touch.
+                this.addListener('touchstart', this.onTapHandler, this);
             }
+            
+            // we need to handle a special case where dom element is a svg element.
+            // in this case we do not actua
+            if (!this.dom) {
+                return;
+            }
+            
+            if (this.dom instanceof SVGElement && !(this.dom instanceof SVGSVGElement)) {
+                if (typeof(this.listeners[eventName]) == 'undefined') {
+                    this.listeners[eventName] =  new Roo.util.Event(this, eventName);
+                }
+                this.listeners[eventName].addListener(fn, scope, options);
+                return;
+            }
+            
+                
+            Roo.EventManager.on(this.dom,  eventName, fn, scope || this, options);
+            
+            
         },
-
+        tapedTwice : false,
+        onTapHandler : function(event)
+        {
+            if(!this.tapedTwice) {
+                this.tapedTwice = true;
+                var s = this;
+                setTimeout( function() {
+                    s.tapedTwice = false;
+                }, 300 );
+                return;
+            }
+            event.preventDefault();
+            var revent = new MouseEvent('dblclick',  {
+                view: window,
+                bubbles: true,
+                cancelable: true
+            });
+             
+            this.dom.dispatchEvent(revent);
+            //action on double tap goes below
+             
+        }, 
         /**
          * Removes an event handler from this element
          * @param {String} eventName the type of event to remove
          * @param {Function} fn the method the event invokes
+         * @param {Function} scope (needed for svg fake listeners)
          * @return {Roo.Element} this
          */
-        removeListener : function(eventName, fn){
+        removeListener : function(eventName, fn, scope){
             Roo.EventManager.removeListener(this.dom,  eventName, fn);
+            if (typeof(this.listeners) == 'undefined'  || typeof(this.listeners[eventName]) == 'undefined') {
+                return this;
+            }
+            this.listeners[eventName].removeListener(fn, scope);
             return this;
         },
 
@@ -8202,6 +8324,7 @@ if(opt.anim.isAnimated()){
          */
         removeAllListeners : function(){
             E.purgeElement(this.dom);
+            this.listeners = {};
             return this;
         },
 
@@ -8211,6 +8334,7 @@ if(opt.anim.isAnimated()){
             });
         },
 
+        
         /**
          * Set the opacity of the element
          * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
@@ -8559,7 +8683,8 @@ if(opt.anim.isAnimated()){
          * @param {Array} offsets (optional) Offset the positioning by [x, y]
          * @return {Array} [x, y]
          */
-        getAlignToXY : function(el, p, o){
+        getAlignToXY : function(el, p, o)
+        {
             el = Roo.get(el);
             var d = this.dom;
             if(!el.dom){
@@ -8600,7 +8725,7 @@ if(opt.anim.isAnimated()){
                 //otherwise swap the aligned el to the opposite border of the target.
                 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
                var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
-               var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
+               var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t")  );
                var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
 
                var doc = document;
@@ -9314,7 +9439,7 @@ if(opt.anim.isAnimated()){
         /**
          * @private
          */
-      fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
+        fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
 
         /**
          * Sizes this element to its parent element's dimensions performing
@@ -9327,7 +9452,7 @@ if(opt.anim.isAnimated()){
           Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
           this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
           if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
-            return;
+            return this;
           }
           var p = Roo.get(targetParent || this.dom.parentNode);
           this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
@@ -11615,7 +11740,7 @@ Roo.extend(Roo.data.Connection, Roo.util.Observable, {
                 var enctype = form.getAttribute("enctype");
                 
                 if (o.formData) {
-                    return this.doFormDataUpload(o,p,url);
+                    return this.doFormDataUpload(o, url);
                 }
                 
                 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
@@ -11624,6 +11749,16 @@ Roo.extend(Roo.data.Connection, Roo.util.Observable, {
                 var f = Roo.lib.Ajax.serializeForm(form);
                 p = p ? (p + '&' + f) : f;
             }
+            
+            if (!o.form && o.formData) {
+                o.formData = o.formData === true ? new FormData() : o.formData;
+                for (var k in o.params) {
+                    o.formData.append(k,o.params[k]);
+                }
+                    
+                return this.doFormDataUpload(o, url);
+            }
+            
 
             var hs = o.headers;
             if(this.defaultHeaders){
@@ -11659,7 +11794,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]);
@@ -11799,11 +11936,17 @@ Roo.extend(Roo.data.Connection, Roo.util.Observable, {
     // this is a 'formdata version???'
     
     
-    doFormDataUpload : function(o, ps, url)
+    doFormDataUpload : function(o,  url)
     {
-        var form = Roo.getDom(o.form);
-        form.enctype = form.encoding = 'multipart/form-data';
-        var formData = o.formData === true ? new FormData(form) : o.formData;
+        var formData;
+        if (o.form) {
+            var form =  Roo.getDom(o.form);
+            form.enctype = form.encoding = 'multipart/form-data';
+            formData = o.formData === true ? new FormData(form) : o.formData;
+        } else {
+            formData = o.formData === true ? new FormData() : o.formData;
+        }
+        
       
         var cb = {
             success: this.handleResponse,
@@ -11823,7 +11966,7 @@ Roo.extend(Roo.data.Connection, Roo.util.Observable, {
 
         //Roo.lib.Ajax.defaultPostHeader = null;
         Roo.lib.Ajax.useDefaultHeader = false;
-        this.transId = Roo.lib.Ajax.request( "POST", url, cb, o.formData, o);
+        this.transId = Roo.lib.Ajax.request( "POST", url, cb,  formData, o);
         Roo.lib.Ajax.useDefaultHeader = true;
  
          
@@ -13299,6 +13442,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!
     },
@@ -13893,7 +14039,26 @@ Roo.util.Format = function(){
          */
         stripTags : function(v){
             return !v ? v : String(v).replace(this.stripTagsRE, "");
+        },
+        
+        /**
+         * Size in Mb,Gb etc.
+         * @param {Number} value The number to be formated
+         * @param {number} decimals how many decimal places
+         * @return {String} the formated string
+         */
+        size : function(value, decimals)
+        {
+            var sizes = ['b', 'k', 'M', 'G', 'T'];
+            if (value == 0) {
+                return 0;
+            }
+            var i = parseInt(Math.floor(Math.log(value) / Math.log(1024)));
+            return Roo.util.Format.number(value/ Math.pow(1024, i) ,decimals)   + sizes[i];
         }
+        
+        
+        
     };
 }();
 Roo.util.Format.defaults = {
@@ -14408,7 +14573,44 @@ Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
         this.el.removeClass(this.pressClass);
         this.fireEvent("mouseup", this);
     }
-});/*
+});/**
+ * @class Roo.util.Clipboard
+ * @static
+ * 
+ * Clipboard UTILS
+ * 
+ **/
+Roo.util.Clipboard = {
+    /**
+     * Writes a string to the clipboard - using the Clipboard API if https, otherwise using text area.
+     * @param {String} text to copy to clipboard
+     */
+    write : function(text) {
+        // navigator clipboard api needs a secure context (https)
+        if (navigator.clipboard && window.isSecureContext) {
+            // navigator clipboard api method'
+            navigator.clipboard.writeText(text);
+            return ;
+        } 
+        // text area method
+        var ta = document.createElement("textarea");
+        ta.value = text;
+        // make the textarea out of viewport
+        ta.style.position = "fixed";
+        ta.style.left = "-999999px";
+        ta.style.top = "-999999px";
+        document.body.appendChild(ta);
+        ta.focus();
+        ta.select();
+        document.execCommand('copy');
+        (function() {
+            ta.remove();
+        }).defer(100);
+        
+    }
+        
+}
+    /*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -15433,7 +15635,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",
 
@@ -15731,7 +15933,7 @@ Roo.extend(Roo.Component, Roo.util.Observable, {
  * @extends Roo.Component
  * Base class for any visual {@link Roo.Component} that uses a box container.  BoxComponent provides automatic box
  * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model.  All
- * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
+ * container classes should subclass BoxComponent so that they will work consistently when nested within other Roo
  * layout containers.
  * @constructor
  * @param {Roo.Element/String/Object} config The configuration options.
@@ -15998,6 +16200,463 @@ Roo.extend(Roo.BoxComponent, Roo.Component, {
         return {x : x, y: y};
     }
 });/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+ (function(){ 
+/**
+ * @class Roo.Layer
+ * @extends Roo.Element
+ * An extended {@link Roo.Element} object that supports a shadow and shim, constrain to viewport and
+ * automatic maintaining of shadow/shim positions.
+ * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
+ * @cfg {String/Boolean} shadow True to create a shadow element with default class "x-layer-shadow", or
+ * you can pass a string with a CSS class name. False turns off the shadow.
+ * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: "div", cls: "x-layer"}).
+ * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
+ * @cfg {String} cls CSS class to add to the element
+ * @cfg {Number} zindex Starting z-index (defaults to 11000)
+ * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 3)
+ * @constructor
+ * @param {Object} config An object with config options.
+ * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
+ */
+
+Roo.Layer = function(config, existingEl){
+    config = config || {};
+    var dh = Roo.DomHelper;
+    var cp = config.parentEl, pel = cp ? Roo.getDom(cp) : document.body;
+    if(existingEl){
+        this.dom = Roo.getDom(existingEl);
+    }
+    if(!this.dom){
+        var o = config.dh || {tag: "div", cls: "x-layer"};
+        this.dom = dh.append(pel, o);
+    }
+    if(config.cls){
+        this.addClass(config.cls);
+    }
+    this.constrain = config.constrain !== false;
+    this.visibilityMode = Roo.Element.VISIBILITY;
+    if(config.id){
+        this.id = this.dom.id = config.id;
+    }else{
+        this.id = Roo.id(this.dom);
+    }
+    this.zindex = config.zindex || this.getZIndex();
+    this.position("absolute", this.zindex);
+    if(config.shadow){
+        this.shadowOffset = config.shadowOffset || 4;
+        this.shadow = new Roo.Shadow({
+            offset : this.shadowOffset,
+            mode : config.shadow
+        });
+    }else{
+        this.shadowOffset = 0;
+    }
+    this.useShim = config.shim !== false && Roo.useShims;
+    this.useDisplay = config.useDisplay;
+    this.hide();
+};
+
+var supr = Roo.Element.prototype;
+
+// shims are shared among layer to keep from having 100 iframes
+var shims = [];
+
+Roo.extend(Roo.Layer, Roo.Element, {
+
+    getZIndex : function(){
+        return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
+    },
+
+    getShim : function(){
+        if(!this.useShim){
+            return null;
+        }
+        if(this.shim){
+            return this.shim;
+        }
+        var shim = shims.shift();
+        if(!shim){
+            shim = this.createShim();
+            shim.enableDisplayMode('block');
+            shim.dom.style.display = 'none';
+            shim.dom.style.visibility = 'visible';
+        }
+        var pn = this.dom.parentNode;
+        if(shim.dom.parentNode != pn){
+            pn.insertBefore(shim.dom, this.dom);
+        }
+        shim.setStyle('z-index', this.getZIndex()-2);
+        this.shim = shim;
+        return shim;
+    },
+
+    hideShim : function(){
+        if(this.shim){
+            this.shim.setDisplayed(false);
+            shims.push(this.shim);
+            delete this.shim;
+        }
+    },
+
+    disableShadow : function(){
+        if(this.shadow){
+            this.shadowDisabled = true;
+            this.shadow.hide();
+            this.lastShadowOffset = this.shadowOffset;
+            this.shadowOffset = 0;
+        }
+    },
+
+    enableShadow : function(show){
+        if(this.shadow){
+            this.shadowDisabled = false;
+            this.shadowOffset = this.lastShadowOffset;
+            delete this.lastShadowOffset;
+            if(show){
+                this.sync(true);
+            }
+        }
+    },
+
+    // private
+    // this code can execute repeatedly in milliseconds (i.e. during a drag) so
+    // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
+    sync : function(doShow){
+        var sw = this.shadow;
+        if(!this.updating && this.isVisible() && (sw || this.useShim)){
+            var sh = this.getShim();
+
+            var w = this.getWidth(),
+                h = this.getHeight();
+
+            var l = this.getLeft(true),
+                t = this.getTop(true);
+
+            if(sw && !this.shadowDisabled){
+                if(doShow && !sw.isVisible()){
+                    sw.show(this);
+                }else{
+                    sw.realign(l, t, w, h);
+                }
+                if(sh){
+                    if(doShow){
+                       sh.show();
+                    }
+                    // fit the shim behind the shadow, so it is shimmed too
+                    var a = sw.adjusts, s = sh.dom.style;
+                    s.left = (Math.min(l, l+a.l))+"px";
+                    s.top = (Math.min(t, t+a.t))+"px";
+                    s.width = (w+a.w)+"px";
+                    s.height = (h+a.h)+"px";
+                }
+            }else if(sh){
+                if(doShow){
+                   sh.show();
+                }
+                sh.setSize(w, h);
+                sh.setLeftTop(l, t);
+            }
+            
+        }
+    },
+
+    // private
+    destroy : function(){
+        this.hideShim();
+        if(this.shadow){
+            this.shadow.hide();
+        }
+        this.removeAllListeners();
+        var pn = this.dom.parentNode;
+        if(pn){
+            pn.removeChild(this.dom);
+        }
+        Roo.Element.uncache(this.id);
+    },
+
+    remove : function(){
+        this.destroy();
+    },
+
+    // private
+    beginUpdate : function(){
+        this.updating = true;
+    },
+
+    // private
+    endUpdate : function(){
+        this.updating = false;
+        this.sync(true);
+    },
+
+    // private
+    hideUnders : function(negOffset){
+        if(this.shadow){
+            this.shadow.hide();
+        }
+        this.hideShim();
+    },
+
+    // private
+    constrainXY : function(){
+        if(this.constrain){
+            var vw = Roo.lib.Dom.getViewWidth(),
+                vh = Roo.lib.Dom.getViewHeight();
+            var s = Roo.get(document).getScroll();
+
+            var xy = this.getXY();
+            var x = xy[0], y = xy[1];   
+            var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
+            // only move it if it needs it
+            var moved = false;
+            // first validate right/bottom
+            if((x + w) > vw+s.left){
+                x = vw - w - this.shadowOffset;
+                moved = true;
+            }
+            if((y + h) > vh+s.top){
+                y = vh - h - this.shadowOffset;
+                moved = true;
+            }
+            // then make sure top/left isn't negative
+            if(x < s.left){
+                x = s.left;
+                moved = true;
+            }
+            if(y < s.top){
+                y = s.top;
+                moved = true;
+            }
+            if(moved){
+                if(this.avoidY){
+                    var ay = this.avoidY;
+                    if(y <= ay && (y+h) >= ay){
+                        y = ay-h-5;   
+                    }
+                }
+                xy = [x, y];
+                this.storeXY(xy);
+                supr.setXY.call(this, xy);
+                this.sync();
+            }
+        }
+    },
+
+    isVisible : function(){
+        return this.visible;    
+    },
+
+    // private
+    showAction : function(){
+        this.visible = true; // track visibility to prevent getStyle calls
+        if(this.useDisplay === true){
+            this.setDisplayed("");
+        }else if(this.lastXY){
+            supr.setXY.call(this, this.lastXY);
+        }else if(this.lastLT){
+            supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
+        }
+    },
+
+    // private
+    hideAction : function(){
+        this.visible = false;
+        if(this.useDisplay === true){
+            this.setDisplayed(false);
+        }else{
+            this.setLeftTop(-10000,-10000);
+        }
+    },
+
+    // overridden Element method
+    setVisible : function(v, a, d, c, e){
+        if(v){
+            this.showAction();
+        }
+        if(a && v){
+            var cb = function(){
+                this.sync(true);
+                if(c){
+                    c();
+                }
+            }.createDelegate(this);
+            supr.setVisible.call(this, true, true, d, cb, e);
+        }else{
+            if(!v){
+                this.hideUnders(true);
+            }
+            var cb = c;
+            if(a){
+                cb = function(){
+                    this.hideAction();
+                    if(c){
+                        c();
+                    }
+                }.createDelegate(this);
+            }
+            supr.setVisible.call(this, v, a, d, cb, e);
+            if(v){
+                this.sync(true);
+            }else if(!a){
+                this.hideAction();
+            }
+        }
+    },
+
+    storeXY : function(xy){
+        delete this.lastLT;
+        this.lastXY = xy;
+    },
+
+    storeLeftTop : function(left, top){
+        delete this.lastXY;
+        this.lastLT = [left, top];
+    },
+
+    // private
+    beforeFx : function(){
+        this.beforeAction();
+        return Roo.Layer.superclass.beforeFx.apply(this, arguments);
+    },
+
+    // private
+    afterFx : function(){
+        Roo.Layer.superclass.afterFx.apply(this, arguments);
+        this.sync(this.isVisible());
+    },
+
+    // private
+    beforeAction : function(){
+        if(!this.updating && this.shadow){
+            this.shadow.hide();
+        }
+    },
+
+    // overridden Element method
+    setLeft : function(left){
+        this.storeLeftTop(left, this.getTop(true));
+        supr.setLeft.apply(this, arguments);
+        this.sync();
+    },
+
+    setTop : function(top){
+        this.storeLeftTop(this.getLeft(true), top);
+        supr.setTop.apply(this, arguments);
+        this.sync();
+    },
+
+    setLeftTop : function(left, top){
+        this.storeLeftTop(left, top);
+        supr.setLeftTop.apply(this, arguments);
+        this.sync();
+    },
+
+    setXY : function(xy, a, d, c, e){
+        this.fixDisplay();
+        this.beforeAction();
+        this.storeXY(xy);
+        var cb = this.createCB(c);
+        supr.setXY.call(this, xy, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+    },
+
+    // private
+    createCB : function(c){
+        var el = this;
+        return function(){
+            el.constrainXY();
+            el.sync(true);
+            if(c){
+                c();
+            }
+        };
+    },
+
+    // overridden Element method
+    setX : function(x, a, d, c, e){
+        this.setXY([x, this.getY()], a, d, c, e);
+    },
+
+    // overridden Element method
+    setY : function(y, a, d, c, e){
+        this.setXY([this.getX(), y], a, d, c, e);
+    },
+
+    // overridden Element method
+    setSize : function(w, h, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        supr.setSize.call(this, w, h, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+    },
+
+    // overridden Element method
+    setWidth : function(w, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        supr.setWidth.call(this, w, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+    },
+
+    // overridden Element method
+    setHeight : function(h, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        supr.setHeight.call(this, h, a, d, cb, e);
+        if(!a){
+            cb();
+        }
+    },
+
+    // overridden Element method
+    setBounds : function(x, y, w, h, a, d, c, e){
+        this.beforeAction();
+        var cb = this.createCB(c);
+        if(!a){
+            this.storeXY([x, y]);
+            supr.setXY.call(this, [x, y]);
+            supr.setSize.call(this, w, h, a, d, cb, e);
+            cb();
+        }else{
+            supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
+        }
+        return this;
+    },
+    
+    /**
+     * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
+     * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
+     * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
+     * @param {Number} zindex The new z-index to set
+     * @return {this} The Layer
+     */
+    setZIndex : function(zindex){
+        this.zindex = zindex;
+        this.setStyle("z-index", zindex + 2);
+        if(this.shadow){
+            this.shadow.setZIndex(zindex + 1);
+        }
+        if(this.shim){
+            this.shim.setStyle("z-index", zindex);
+        }
+    }
+});
+})();/*
  * Original code for Roojs - LGPL
  * <script type="text/javascript">
  */
@@ -16800,10 +17459,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 +17628,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 +18046,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 +18286,11 @@ Roo.Markdown.toHtml = function(text) {
      * Renderer
      */
     
-    function Renderer(options) {
+     /**
+         * eval:var:Renderer
+    */
+    
+    var Renderer   = function (options) {
       this.options = options || {};
     }
     
@@ -17700,8 +18439,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 +18618,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 +18647,9 @@ Roo.Markdown.toHtml = function(text) {
         }
     
         pending = tokens.length;
-    
+         /**
+         * eval:var:done
+    */
         var done = function(err) {
           if (err) {
             opt.highlight = highlight;
@@ -21095,8 +21782,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 || {} 
         });    
@@ -22011,7 +22698,7 @@ Roo.dd.DropTarget = function(el, config){
          * target.  This default implementation adds the CSS class specified by overClass (if any) to the drop element
          * and returns the dropAllowed config value.  This method should be overridden if drop validation is required.
          * 
-         * IMPORTANT : it should set this.overClass and this.dropAllowed
+         * IMPORTANT : it should set  this.valid to true|false
          * 
          * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
          * @param {Event} e The event
@@ -22025,7 +22712,7 @@ Roo.dd.DropTarget = function(el, config){
          * This method will be called on every mouse movement while the drag source is over the drop target.
          * This default implementation simply returns the dropAllowed config value.
          * 
-         * IMPORTANT : it should set this.dropAllowed
+         * IMPORTANT : it should set  this.valid to true|false
          * 
          * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
          * @param {Event} e The event
@@ -22039,6 +22726,7 @@ Roo.dd.DropTarget = function(el, config){
          * out of the target without dropping.  This default implementation simply removes the CSS class specified by
          * overClass (if any) from the drop element.
          * 
+         * 
          * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
          * @param {Event} e The event
          * @param {Object} data An object containing arbitrary data supplied by the drag source
@@ -23235,6 +23923,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 +24237,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 +24423,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 +24446,7 @@ Roo.data.DataReader.prototype = {
         return new this.recordType(Roo.apply(da, d));
     }
     
+    
 };/*
  * Based on:
  * Ext JS Library 1.1.1
@@ -24281,6 +24985,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 +25128,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 +25206,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 +25320,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 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;
-           }
-           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
@@ -25396,463 +26123,6 @@ Roo.extend(Roo.data.Node, Roo.util.Observable, {
  * Fork - LGPL
  * <script type="text/javascript">
  */
- (function(){ 
-/**
- * @class Roo.Layer
- * @extends Roo.Element
- * An extended {@link Roo.Element} object that supports a shadow and shim, constrain to viewport and
- * automatic maintaining of shadow/shim positions.
- * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
- * @cfg {String/Boolean} shadow True to create a shadow element with default class "x-layer-shadow", or
- * you can pass a string with a CSS class name. False turns off the shadow.
- * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: "div", cls: "x-layer"}).
- * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
- * @cfg {String} cls CSS class to add to the element
- * @cfg {Number} zindex Starting z-index (defaults to 11000)
- * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 3)
- * @constructor
- * @param {Object} config An object with config options.
- * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
- */
-
-Roo.Layer = function(config, existingEl){
-    config = config || {};
-    var dh = Roo.DomHelper;
-    var cp = config.parentEl, pel = cp ? Roo.getDom(cp) : document.body;
-    if(existingEl){
-        this.dom = Roo.getDom(existingEl);
-    }
-    if(!this.dom){
-        var o = config.dh || {tag: "div", cls: "x-layer"};
-        this.dom = dh.append(pel, o);
-    }
-    if(config.cls){
-        this.addClass(config.cls);
-    }
-    this.constrain = config.constrain !== false;
-    this.visibilityMode = Roo.Element.VISIBILITY;
-    if(config.id){
-        this.id = this.dom.id = config.id;
-    }else{
-        this.id = Roo.id(this.dom);
-    }
-    this.zindex = config.zindex || this.getZIndex();
-    this.position("absolute", this.zindex);
-    if(config.shadow){
-        this.shadowOffset = config.shadowOffset || 4;
-        this.shadow = new Roo.Shadow({
-            offset : this.shadowOffset,
-            mode : config.shadow
-        });
-    }else{
-        this.shadowOffset = 0;
-    }
-    this.useShim = config.shim !== false && Roo.useShims;
-    this.useDisplay = config.useDisplay;
-    this.hide();
-};
-
-var supr = Roo.Element.prototype;
-
-// shims are shared among layer to keep from having 100 iframes
-var shims = [];
-
-Roo.extend(Roo.Layer, Roo.Element, {
-
-    getZIndex : function(){
-        return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
-    },
-
-    getShim : function(){
-        if(!this.useShim){
-            return null;
-        }
-        if(this.shim){
-            return this.shim;
-        }
-        var shim = shims.shift();
-        if(!shim){
-            shim = this.createShim();
-            shim.enableDisplayMode('block');
-            shim.dom.style.display = 'none';
-            shim.dom.style.visibility = 'visible';
-        }
-        var pn = this.dom.parentNode;
-        if(shim.dom.parentNode != pn){
-            pn.insertBefore(shim.dom, this.dom);
-        }
-        shim.setStyle('z-index', this.getZIndex()-2);
-        this.shim = shim;
-        return shim;
-    },
-
-    hideShim : function(){
-        if(this.shim){
-            this.shim.setDisplayed(false);
-            shims.push(this.shim);
-            delete this.shim;
-        }
-    },
-
-    disableShadow : function(){
-        if(this.shadow){
-            this.shadowDisabled = true;
-            this.shadow.hide();
-            this.lastShadowOffset = this.shadowOffset;
-            this.shadowOffset = 0;
-        }
-    },
-
-    enableShadow : function(show){
-        if(this.shadow){
-            this.shadowDisabled = false;
-            this.shadowOffset = this.lastShadowOffset;
-            delete this.lastShadowOffset;
-            if(show){
-                this.sync(true);
-            }
-        }
-    },
-
-    // private
-    // this code can execute repeatedly in milliseconds (i.e. during a drag) so
-    // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
-    sync : function(doShow){
-        var sw = this.shadow;
-        if(!this.updating && this.isVisible() && (sw || this.useShim)){
-            var sh = this.getShim();
-
-            var w = this.getWidth(),
-                h = this.getHeight();
-
-            var l = this.getLeft(true),
-                t = this.getTop(true);
-
-            if(sw && !this.shadowDisabled){
-                if(doShow && !sw.isVisible()){
-                    sw.show(this);
-                }else{
-                    sw.realign(l, t, w, h);
-                }
-                if(sh){
-                    if(doShow){
-                       sh.show();
-                    }
-                    // fit the shim behind the shadow, so it is shimmed too
-                    var a = sw.adjusts, s = sh.dom.style;
-                    s.left = (Math.min(l, l+a.l))+"px";
-                    s.top = (Math.min(t, t+a.t))+"px";
-                    s.width = (w+a.w)+"px";
-                    s.height = (h+a.h)+"px";
-                }
-            }else if(sh){
-                if(doShow){
-                   sh.show();
-                }
-                sh.setSize(w, h);
-                sh.setLeftTop(l, t);
-            }
-            
-        }
-    },
-
-    // private
-    destroy : function(){
-        this.hideShim();
-        if(this.shadow){
-            this.shadow.hide();
-        }
-        this.removeAllListeners();
-        var pn = this.dom.parentNode;
-        if(pn){
-            pn.removeChild(this.dom);
-        }
-        Roo.Element.uncache(this.id);
-    },
-
-    remove : function(){
-        this.destroy();
-    },
-
-    // private
-    beginUpdate : function(){
-        this.updating = true;
-    },
-
-    // private
-    endUpdate : function(){
-        this.updating = false;
-        this.sync(true);
-    },
-
-    // private
-    hideUnders : function(negOffset){
-        if(this.shadow){
-            this.shadow.hide();
-        }
-        this.hideShim();
-    },
-
-    // private
-    constrainXY : function(){
-        if(this.constrain){
-            var vw = Roo.lib.Dom.getViewWidth(),
-                vh = Roo.lib.Dom.getViewHeight();
-            var s = Roo.get(document).getScroll();
-
-            var xy = this.getXY();
-            var x = xy[0], y = xy[1];   
-            var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
-            // only move it if it needs it
-            var moved = false;
-            // first validate right/bottom
-            if((x + w) > vw+s.left){
-                x = vw - w - this.shadowOffset;
-                moved = true;
-            }
-            if((y + h) > vh+s.top){
-                y = vh - h - this.shadowOffset;
-                moved = true;
-            }
-            // then make sure top/left isn't negative
-            if(x < s.left){
-                x = s.left;
-                moved = true;
-            }
-            if(y < s.top){
-                y = s.top;
-                moved = true;
-            }
-            if(moved){
-                if(this.avoidY){
-                    var ay = this.avoidY;
-                    if(y <= ay && (y+h) >= ay){
-                        y = ay-h-5;   
-                    }
-                }
-                xy = [x, y];
-                this.storeXY(xy);
-                supr.setXY.call(this, xy);
-                this.sync();
-            }
-        }
-    },
-
-    isVisible : function(){
-        return this.visible;    
-    },
-
-    // private
-    showAction : function(){
-        this.visible = true; // track visibility to prevent getStyle calls
-        if(this.useDisplay === true){
-            this.setDisplayed("");
-        }else if(this.lastXY){
-            supr.setXY.call(this, this.lastXY);
-        }else if(this.lastLT){
-            supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
-        }
-    },
-
-    // private
-    hideAction : function(){
-        this.visible = false;
-        if(this.useDisplay === true){
-            this.setDisplayed(false);
-        }else{
-            this.setLeftTop(-10000,-10000);
-        }
-    },
-
-    // overridden Element method
-    setVisible : function(v, a, d, c, e){
-        if(v){
-            this.showAction();
-        }
-        if(a && v){
-            var cb = function(){
-                this.sync(true);
-                if(c){
-                    c();
-                }
-            }.createDelegate(this);
-            supr.setVisible.call(this, true, true, d, cb, e);
-        }else{
-            if(!v){
-                this.hideUnders(true);
-            }
-            var cb = c;
-            if(a){
-                cb = function(){
-                    this.hideAction();
-                    if(c){
-                        c();
-                    }
-                }.createDelegate(this);
-            }
-            supr.setVisible.call(this, v, a, d, cb, e);
-            if(v){
-                this.sync(true);
-            }else if(!a){
-                this.hideAction();
-            }
-        }
-    },
-
-    storeXY : function(xy){
-        delete this.lastLT;
-        this.lastXY = xy;
-    },
-
-    storeLeftTop : function(left, top){
-        delete this.lastXY;
-        this.lastLT = [left, top];
-    },
-
-    // private
-    beforeFx : function(){
-        this.beforeAction();
-        return Roo.Layer.superclass.beforeFx.apply(this, arguments);
-    },
-
-    // private
-    afterFx : function(){
-        Roo.Layer.superclass.afterFx.apply(this, arguments);
-        this.sync(this.isVisible());
-    },
-
-    // private
-    beforeAction : function(){
-        if(!this.updating && this.shadow){
-            this.shadow.hide();
-        }
-    },
-
-    // overridden Element method
-    setLeft : function(left){
-        this.storeLeftTop(left, this.getTop(true));
-        supr.setLeft.apply(this, arguments);
-        this.sync();
-    },
-
-    setTop : function(top){
-        this.storeLeftTop(this.getLeft(true), top);
-        supr.setTop.apply(this, arguments);
-        this.sync();
-    },
-
-    setLeftTop : function(left, top){
-        this.storeLeftTop(left, top);
-        supr.setLeftTop.apply(this, arguments);
-        this.sync();
-    },
-
-    setXY : function(xy, a, d, c, e){
-        this.fixDisplay();
-        this.beforeAction();
-        this.storeXY(xy);
-        var cb = this.createCB(c);
-        supr.setXY.call(this, xy, a, d, cb, e);
-        if(!a){
-            cb();
-        }
-    },
-
-    // private
-    createCB : function(c){
-        var el = this;
-        return function(){
-            el.constrainXY();
-            el.sync(true);
-            if(c){
-                c();
-            }
-        };
-    },
-
-    // overridden Element method
-    setX : function(x, a, d, c, e){
-        this.setXY([x, this.getY()], a, d, c, e);
-    },
-
-    // overridden Element method
-    setY : function(y, a, d, c, e){
-        this.setXY([this.getX(), y], a, d, c, e);
-    },
-
-    // overridden Element method
-    setSize : function(w, h, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        supr.setSize.call(this, w, h, a, d, cb, e);
-        if(!a){
-            cb();
-        }
-    },
-
-    // overridden Element method
-    setWidth : function(w, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        supr.setWidth.call(this, w, a, d, cb, e);
-        if(!a){
-            cb();
-        }
-    },
-
-    // overridden Element method
-    setHeight : function(h, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        supr.setHeight.call(this, h, a, d, cb, e);
-        if(!a){
-            cb();
-        }
-    },
-
-    // overridden Element method
-    setBounds : function(x, y, w, h, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        if(!a){
-            this.storeXY([x, y]);
-            supr.setXY.call(this, [x, y]);
-            supr.setSize.call(this, w, h, a, d, cb, e);
-            cb();
-        }else{
-            supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
-        }
-        return this;
-    },
-    
-    /**
-     * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
-     * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
-     * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
-     * @param {Number} zindex The new z-index to set
-     * @return {this} The Layer
-     */
-    setZIndex : function(zindex){
-        this.zindex = zindex;
-        this.setStyle("z-index", zindex + 2);
-        if(this.shadow){
-            this.shadow.setZIndex(zindex + 1);
-        }
-        if(this.shim){
-            this.shim.setStyle("z-index", zindex);
-        }
-    }
-});
-})();/*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
 
 
 /**
@@ -30371,7 +30641,7 @@ Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
  * A simple class that renders text directly into a toolbar.
  * @constructor
  * Creates a new TextItem
- * @param {String} text
+ * @cfg {string} text 
  */
 Roo.Toolbar.TextItem = function(cfg){
     var  text = cfg || "";
@@ -38215,7 +38485,7 @@ Roo.menu.TextItem = function(cfg){
 
 Roo.extend(Roo.menu.TextItem, Roo.menu.BaseItem, {
     /**
-     * @cfg {Boolean} text Text to show on item.
+     * @cfg {String} text Text to show on item.
      */
     text : '',
     
@@ -38773,6 +39043,14 @@ Roo.extend(Roo.form.TextItem, Roo.BoxComponent,  {
             }
             this.el = ct.createChild(cfg, position);
         }
+    },
+    /*
+     * setHTML
+     * @param {String} html update the Contents of the element.
+     */
+    setHTML : function(html)
+    {
+        this.fieldEl.dom.innerHTML = html;
     }
     
 });/*
@@ -39532,7 +39810,11 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
     // private - clean the leading white space
     cleanLeadingSpace : function(e)
     {
-       this.setValue(this.getValue().replace(/^\s+/,''));
+        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.
@@ -40293,7 +40575,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({
@@ -40641,7 +40924,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
@@ -41354,9 +41643,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 =
@@ -41368,6 +41659,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
              
              
         }
+       
         if(Roo.isGecko){
             this.el.dom.setAttribute('autocomplete', 'off');
         }
@@ -41428,7 +41720,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);
@@ -42115,7 +42409,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 
@@ -42229,7 +42523,10 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
      * @cfg {String} hiddenName    The hidden name of the field, often contains an comma seperated list of names
      */
     hiddenName : false,
-    
+      /**
+     * @cfg {String} seperator    The value seperator normally ',' 
+     */
+    seperator : ',',
     
     // private the array of items that are displayed..
     items  : false,
@@ -42250,7 +42547,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);
@@ -42371,6 +42668,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;
@@ -42402,9 +42700,8 @@ 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.hiddenEl.dom.value = ar.join(this.seperator);
         this.validate();
     },
     
@@ -42428,17 +42725,15 @@ 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..
             this.hiddenEl.value  = v;
             var v_ar = [];
-            Roo.each(v.split(','), function(k) {
+            Roo.each(v.split(this.seperator), function(k) {
                 Roo.log("CHECK " + this.valueField + ',' + k);
                 var li = this.store.query(this.valueField, k);
                 if (!li.length) {
@@ -42455,7 +42750,13 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
         if (typeof(v) == 'object' ) {
             // then let's assume it's an array of objects..
             Roo.each(v, function(l) {
-                this.addItem(l);
+                var add = l;
+                if (typeof(l) == 'string') {
+                    add = {};
+                    add[this.valueField] = l;
+                    add[this.displayField] = l
+                }
+                this.addItem(add);
             }, this);
              
         }
@@ -42477,10 +42778,9 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
         dv = typeof(dv) != 'string' ? '' : dv;
         
         
-        var keys = kv.split(',');
-        var display = dv.split(',');
+        var keys = kv.split(this.seperator);
+        var display = dv.split(this.seperator);
         for (var i = 0 ; i < keys.length; i++) {
-            
             add = {};
             add[this.valueField] = keys[i];
             add[this.displayField] = display[i];
@@ -42528,7 +42828,7 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
             originalValue.push(d[i][this.valueField]);
         }
         
-        return String(this.getValue()) !== String(originalValue.join(','));
+        return String(this.getValue()) !== String(originalValue.join(this.seperator));
         
     }
     
@@ -42616,6 +42916,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
@@ -43064,10 +43792,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 st = '<style type="text/css">' +
                     'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
                    '</style>';
-        } else { 
-            st = '<style type="text/css">' +
-                    this.stylesheets +
-                '</style>';
+        } else {
+            for (var i in this.stylesheets) { 
+                st += '<link rel="stylesheet" href="' + this.stylesheets[i] +'" type="text/css">';
+            }
+            
         }
         
         st +=  '<style type="text/css">' +
@@ -43084,7 +43813,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             //<style type="text/css">' +
             //'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
             //'</style>' +
-            ' </head><body class="' +  cls + '"></body></html>';
+            ' </head><body contenteditable="true" data-enable-grammerly="true" class="' +  cls + '"></body></html>';
     },
 
     // private
@@ -43239,17 +43968,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);
@@ -43433,7 +44177,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());
@@ -43929,6 +44677,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..
         
@@ -43949,6 +44702,10 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         }
         
         if (!node.attributes || !node.attributes.length) {
+            
+          
+            
+            
             this.cleanUpChildren(node);
             return;
         }
@@ -43965,6 +44722,9 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             if (v.match(/^#/)) {
                 return;
             }
+            if (v.match(/^\{/)) { // allow template editing.
+                return;
+            }
 //            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
             node.removeAttribute(n);
             
@@ -44045,11 +44805,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;
             }
@@ -44107,16 +44867,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
@@ -44594,8 +45358,8 @@ Roo.HtmlEditorCore.cblack= [
 
 
 Roo.HtmlEditorCore.swapCodes   =[ 
-    [    8211, "--" ], 
-    [    8212, "--" ], 
+    [    8211, "&#8211;" ], 
+    [    8212, "&#8212;" ], 
     [    8216,  "'" ],  
     [    8217, "'" ],  
     [    8220, '"' ],  
@@ -45356,7 +46120,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 : [
@@ -45658,8 +46423,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
@@ -46972,7 +47738,26 @@ Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
         
         return valid;
     },
-
+    /**
+     * Returns array of invalid form fields.
+     * @return Array
+     */
+    
+    invalidFields : function()
+    {
+        var ret = [];
+        this.items.each(function(f){
+            if(f.validate()){
+                return;
+            }
+            ret.push(f);
+            
+        });
+        
+        return ret;
+    },
+    
+    
     /**
      * DEPRICATED Returns true if any fields in this form have changed since their original load. 
      * @return Boolean
@@ -47317,7 +48102,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.
@@ -47332,6 +48117,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);
@@ -50803,10 +51605,10 @@ Roo.DDView = function(container, tpl, config) {
     this.getEl().setStyle("outline", "0px none");
     this.getEl().unselectable();
     if (this.dragGroup) {
-               this.setDraggable(this.dragGroup.split(","));
+       this.setDraggable(this.dragGroup.split(","));
     }
     if (this.dropGroup) {
-               this.setDroppable(this.dropGroup.split(","));
+       this.setDroppable(this.dropGroup.split(","));
     }
     if (this.deletable) {
        this.setDeletable();
@@ -52580,7 +53382,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;
         }
@@ -53549,6 +54351,7 @@ Roo.LayoutStateManager.prototype = {
  * @cfg {String/Object} params  When used with {@link #url}, calls {@link #setUrl} with this value
  * @cfg {Boolean} loadOnce      When used with {@link #url}, calls {@link #setUrl} with this value
  * @cfg {String}    content        Raw content to fill content panel with (uses setContent on construction.)
+ * @cfg {String}    style  Extra style to add to the content panel 
 
  * @constructor
  * Create a new ContentPanel.
@@ -53586,6 +54389,8 @@ Roo.ContentPanel = function(el, config, content){
                         {tag: "div", cls: "x-layout-inactive-content", id: config.id||el}, true);
         }
     }
+    
+    
     this.closable = false;
     this.loaded = false;
     this.active = false;
@@ -54737,6 +55542,9 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
     /**
      * @cfg {String} ddGroup - drag drop group.
      */
+      /**
+     * @cfg {String} dragGroup - drag group (?? not sure if needed.)
+     */
 
     /**
      * @cfg {Number} minColumnWidth The minimum width a column can be resized to. Default is 25.
@@ -54773,6 +55581,9 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
 
     /**
     * @cfg {Boolean} enableDrag  True to enable drag of rows. Default is false. (double check if this is needed?)
+    */
+      /**
+    * @cfg {Boolean} enableDrop  True to enable drop of elements. Default is false. (double check if this is needed?)
     */
     
     /**
@@ -54847,6 +55658,15 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
     /**
     * @cfg {Number} maxHeight Sets the maximum height of the grid - ignored if autoHeight is not on.
     */
+    
+    
+    /**
+    * @cfg {String} ddText Configures the text is the drag proxy (defaults to "%0 selected row(s)").
+    * %0 is replaced with the number of selected rows.
+    */
+    ddText : "{0} selected row{1}",
+    
+    
     /**
      * Called once after all setup has been completed and the grid is ready to be rendered.
      * @return {Roo.grid.Grid} this
@@ -54901,12 +55721,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();
@@ -54918,7 +55738,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);
@@ -55123,11 +55977,17 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
     getView : function(){
         if(!this.view){
             this.view = new Roo.grid.GridView(this.viewConfig);
+           this.relayEvents(this.view, [
+               "beforerowremoved", "beforerowsinserted",
+               "beforerefresh", "rowremoved",
+               "rowsinserted", "rowupdated" ,"refresh"
+           ]);
         }
         return this.view;
     },
     /**
      * Called to get grid's drag proxy text, by default returns this.ddText.
+     * Override this to put something different in the dragged text.
      * @return {String}
      */
     getDragDropText : function(){
@@ -55135,12 +55995,7 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
         return String.format(this.ddText, count, count == 1 ? '' : 's');
     }
 });
-/**
- * Configures the text is the drag proxy (defaults to "%0 selected row(s)").
- * %0 is replaced with the number of selected rows.
- * @type String
- */
-Roo.grid.Grid.prototype.ddText = "{0} selected row{1}";/*
+/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -56055,7 +56910,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
                 );
         */
         if(ctop < stop){
-             c.scrollTop = ctop;
+            c.scrollTop = ctop;
             //Roo.log("set scrolltop to ctop DISABLE?");
         }else if(cbot > sbot){
             //Roo.log("set scrolltop to cbot-ch");
@@ -57050,7 +57905,8 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
         }
     },
 
-    layout : function(initialRender, is2ndPass){
+    layout : function(initialRender, is2ndPass)
+    {
         var g = this.grid;
         var auto = g.autoHeight;
         var scrollOffset = 16;
@@ -57309,7 +58165,12 @@ Roo.extend(Roo.grid.GridDragZone, Roo.dd.DragZone, {
             }
         
         }
+        if (sm.getSelections && sm.getSelections().length < 1) {
+            return false;
+        }
+        
         
+        // before it used to all dragging of unseleted... - now we dont do that.
         if(rowIndex !== false){
             
             // if editorgrid.. 
@@ -57330,14 +58191,14 @@ Roo.extend(Roo.grid.GridDragZone, Roo.dd.DragZone, {
                 grid: this.grid,
                 ddel: this.ddel,
                 rowIndex: rowIndex,
-                selections:sm.getSelections ? sm.getSelections() : (
-                    sm.getSelectedCell() ? [ this.grid.ds.getAt(sm.getSelectedCell()[0]) ] : []
-                )
+                selections: sm.getSelections ? sm.getSelections() : (
+                    sm.getSelectedCell() ? [ this.grid.ds.getAt(sm.getSelectedCell()[0]) ] : [])
             };
         }
         return false;
     },
-
+    
+    
     onInitDrag : function(e){
         var data = this.dragData;
         this.ddel.innerHTML = this.grid.getDragDropText();
@@ -57405,30 +58266,15 @@ Roo.grid.ColumnModel = function(config){
        /**
      * The config passed into the constructor
      */
-    this.config = config;
+    this.config = []; //config;
     this.lookup = {};
 
     // if no id, create one
     // if the column does not have a dataIndex mapping,
     // map it to the order it is in the config
     for(var i = 0, len = config.length; i < len; i++){
-        var c = config[i];
-        if(typeof c.dataIndex == "undefined"){
-            c.dataIndex = i;
-        }
-        if(typeof c.renderer == "string"){
-            c.renderer = Roo.util.Format[c.renderer];
-        }
-        if(typeof c.id == "undefined"){
-            c.id = Roo.id();
-        }
-        if(c.editor && c.editor.xtype){
-            c.editor  = Roo.factory(c.editor, Roo.grid);
-        }
-        if(c.editor && c.editor.isFormField){
-            c.editor = new Roo.grid.GridEditor(c.editor);
-        }
-        this.lookup[c.id] = c;
+       this.addColumn(config[i]);
+       
     }
 
     /**
@@ -57570,7 +58416,7 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
 
     
     /**
-     * Returns the column for a specified dataIndex.
+     * Returns the column Object for a specified dataIndex.
      * @param {String} dataIndex The column dataIndex
      * @return {Object|Boolean} the column or false if not found
      */
@@ -57896,7 +58742,35 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
      */
     setEditor : function(col, editor){
         this.config[col].editor = editor;
+    },
+    /**
+     * Add a column (experimental...) - defaults to adding to the end..
+     * @param {Object} config 
+    */
+    addColumn : function(c)
+    {
+    
+       var i = this.config.length;
+       this.config[i] = c;
+       
+       if(typeof c.dataIndex == "undefined"){
+            c.dataIndex = i;
+        }
+        if(typeof c.renderer == "string"){
+            c.renderer = Roo.util.Format[c.renderer];
+        }
+        if(typeof c.id == "undefined"){
+            c.id = Roo.id();
+        }
+        if(c.editor && c.editor.xtype){
+            c.editor  = Roo.factory(c.editor, Roo.grid);
+        }
+        if(c.editor && c.editor.isFormField){
+            c.editor = new Roo.grid.GridEditor(c.editor);
+        }
+        this.lookup[c.id] = c;
     }
+    
 });
 
 Roo.grid.ColumnModel.defaultRenderer = function(value)