comment out row/cell selection requirement for cellclick - no idea why that was done...
[roojs1] / roojs-debug.js
index 2109150..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,11 +4693,18 @@ 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 {
@@ -4726,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);
@@ -4745,7 +4788,7 @@ Roo.Template.prototype = {
      */
     set : function(html, compile){
         this.html = html;
-        this.compiled = null;
+        this.compiled = false;
         if(compile){
             this.compile();
         }
@@ -5023,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;
             }
         }
@@ -5041,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];
 
@@ -5145,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"){
@@ -5906,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);
         }
     },
@@ -6256,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);
@@ -6314,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(){
@@ -7099,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;
         }
@@ -7121,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
@@ -7626,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;
@@ -7655,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){
@@ -7669,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;
@@ -7699,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;
         },
 
@@ -8180,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;
         },
 
@@ -8203,6 +8324,7 @@ if(opt.anim.isAnimated()){
          */
         removeAllListeners : function(){
             E.purgeElement(this.dom);
+            this.listeners = {};
             return this;
         },
 
@@ -8212,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
@@ -8560,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){
@@ -8601,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;
@@ -9315,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
@@ -9328,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'));
@@ -11616,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')){
@@ -11625,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){
@@ -11802,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,
@@ -11826,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;
  
          
@@ -13899,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 = {
@@ -14414,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.
@@ -15737,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.
@@ -22502,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
@@ -22516,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
@@ -22530,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
@@ -25139,35 +25336,35 @@ Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
     readRecords : function(o)
     {
         var sid = this.meta ? this.meta.id : null;
-       var recordType = this.recordType, fields = recordType.prototype.fields;
-       var records = [];
-       var root = o;
-       for(var i = 0; i < root.length; i++){
-               var n = root[i];
-           var values = {};
-           var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
-           for(var j = 0, jlen = fields.length; j < jlen; j++){
-               var f = fields.items[j];
-               var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
-               var v = n[k] !== undefined ? n[k] : f.defaultValue;
-               v = f.convert(v);
-               values[f.name] = v;
-           }
-           var record = new recordType(values, id);
-           record.json = n;
-           records[records.length] = record;
-       }
-       return {
-           records : records,
-           totalRecords : records.length
-       };
+        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
+        };
     },
     // 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;
-       
+        // expect rec just to be an array.. eg [a,b,c, [...] << cn ]
+        return typeof(rec.data.cn) == 'undefined' ? [] : rec.data.cn;
+        
     }
     
     
@@ -38288,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 : '',
     
@@ -43595,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">' +
@@ -44524,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);
             
@@ -45157,8 +45358,8 @@ Roo.HtmlEditorCore.cblack= [
 
 
 Roo.HtmlEditorCore.swapCodes   =[ 
-    [    8211, "--" ], 
-    [    8212, "--" ], 
+    [    8211, "&#8211;" ], 
+    [    8212, "&#8212;" ], 
     [    8216,  "'" ],  
     [    8217, "'" ],  
     [    8220, '"' ],  
@@ -47537,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
@@ -51385,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();
@@ -54131,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.
@@ -54168,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;
@@ -55319,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.
@@ -55355,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?)
     */
     
     /**
@@ -55429,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
@@ -55739,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(){
@@ -55751,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.
@@ -56671,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");
@@ -57666,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;
@@ -57925,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.. 
@@ -57946,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();
@@ -58021,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]);
+       
     }
 
     /**
@@ -58186,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
      */
@@ -58512,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)