roojs-ui.js
[roojs1] / roojs-debug.js
index 956e8e8..f71e67f 100644 (file)
@@ -1237,6 +1237,7 @@ Date.createParser = function(format) {
         + "y = d.getFullYear();\n"
         + "m = d.getMonth();\n"
         + "d = d.getDate();\n"
+        + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
         + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
         + "if (results && results.length > 0) {";
     var regex = "";
@@ -8970,7 +8971,7 @@ if(opt.anim.isAnimated()){
          */
         mask : function(msg, msgCls)
         {
-            if(this.getStyle("position") == "static"){
+            if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
                 this.setStyle("position", "relative");
             }
             if(!this._mask){
@@ -9001,7 +9002,9 @@ if(opt.anim.isAnimated()){
                 }
                 var mm = this._maskMsg;
                 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
-                mm.dom.firstChild.innerHTML = msg;
+                if (mm.dom.firstChild) { // weird IE issue?
+                    mm.dom.firstChild.innerHTML = msg;
+                }
                 mm.setDisplayed(true);
                 mm.center(this);
                 mm.setStyle('z-index', z + 102);
@@ -15203,7 +15206,7 @@ Roo.extend(Roo.Component, Roo.util.Observable, {
         * Whether the component can move the Dom node when rendering (defaults to true).
         */
     allowDomMove : true,
-    /** @cfg {String} hideMode
+    /** @cfg {String} hideMode (display|visibility)
      * How this component should hidden. Supported values are
      * "visibility" (css visibility), "offsets" (negative offset position) and
      * "display" (css display) - defaults to "display".
@@ -15937,18 +15940,18 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
         
         el = el || false;
         var hp = this.parent ? 1 : 0;
-        Roo.log(this);
+        Roo.debug &&  Roo.log(this);
         
         if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
             // if parent is a '#.....' string, then let's use that..
             var ename = this.parent.substr(1);
             this.parent = false;
-            Roo.log(ename);
+            Roo.debug && Roo.log(ename);
             switch (ename) {
                 case 'bootstrap-body' :
                     if (typeof(Roo.bootstrap.Body) != 'undefined') {
                         this.parent = { el :  new  Roo.bootstrap.Body() };
-                        Roo.log("setting el to doc body");
+                        Roo.debug && Roo.log("setting el to doc body");
                          
                     } else {
                         throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
@@ -15964,12 +15967,14 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
                 
             
             if (!el && !this.parent) {
-                Roo.log("Warning - element can not be found :#" + ename );
+                Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
                 return;
             }
         }
-        Roo.log("EL:");Roo.log(el);
-        Roo.log("this.parent.el:");Roo.log(this.parent.el);
+        Roo.debug && Roo.log("EL:");
+        Roo.debug && Roo.log(el);
+        Roo.debug && Roo.log("this.parent.el:");
+        Roo.debug && Roo.log(this.parent.el);
         
         var tree = this._tree ? this._tree() : this.tree();
 
@@ -15986,7 +15991,7 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
         
         if (!this.parent) {
             
-            Roo.log("no parent - creating one");
+            Roo.debug && Roo.log("no parent - creating one");
             
             el = el ? Roo.get(el) : false;     
             
@@ -16008,11 +16013,11 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
             }
         }
         
-               if (!this.parent.el) {
-                       // probably an old style ctor, which has been disabled.
-                       return;
-                       
-               }
+        if (!this.parent.el) {
+                // probably an old style ctor, which has been disabled.
+                return;
+
+        }
                // The 'tree' method is  '_tree now' 
             
         tree.region = tree.region || this.region;
@@ -16027,7 +16032,7 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
         
         this.panel = this.el;
         this.layout = this.panel.layout;
-               this.parentLayout = this.parent.layout  || false;  
+        this.parentLayout = this.parent.layout  || false;  
          
     }
     
@@ -16179,7 +16184,7 @@ Roo.apply(Roo.XComponent, {
             try { 
                 obj.parent = this.toObject(opar);
             } catch(e) {
-                Roo.log("parent:toObject failed: " + e.toString());
+                Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
                 return;
             }
             
@@ -16198,7 +16203,7 @@ Roo.apply(Roo.XComponent, {
                 return;
             }
             if (obj.parent.constructor != Roo.XComponent) {
-                Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
+                Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
             }
             if (!obj.parent.modules) {
                 obj.parent.modules = new Roo.util.MixedCollection(false, 
@@ -22689,7 +22694,7 @@ Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
          */
         this.o = o;
         var s = this.meta, Record = this.recordType,
-            f = Record.prototype.fields, fi = f.items, fl = f.length;
+            f = Record ? Record.prototype.fields : null, fi = f ? f.items : [], fl = f ? f.length : 0;
 
 //      Generate extraction functions for the totalProperty, the root, the id, and for each field
         if (!this.ef) {
@@ -22703,7 +22708,7 @@ Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
                if (s.id) {
                        var g = this.getJsonAccessor(s.id);
                        this.getId = function(rec) {
-                               var r = g(rec);
+                               var r = g(rec);  
                                return (r === undefined || r === "") ? null : r;
                        };
                } else {
@@ -22731,30 +22736,30 @@ Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
             }
         }
         var records = [];
-           for(var i = 0; i < c; i++){
-                   var n = root[i];
-               var values = {};
-               var id = this.getId(n);
-               for(var j = 0; j < fl; j++){
-                   f = fi[j];
-                var v = this.ef[j](n);
-                if (!f.convert) {
-                    Roo.log('missing convert for ' + f.name);
-                    Roo.log(f);
-                    continue;
-                }
-                values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
-               }
-               var record = new Record(values, id);
-               record.json = n;
-               records[i] = record;
-           }
-           return {
+        for(var i = 0; i < c; i++){
+                var n = root[i];
+            var values = {};
+            var id = this.getId(n);
+            for(var j = 0; j < fl; j++){
+                f = fi[j];
+            var v = this.ef[j](n);
+            if (!f.convert) {
+                Roo.log('missing convert for ' + f.name);
+                Roo.log(f);
+                continue;
+            }
+            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
+            }
+            var record = new Record(values, id);
+            record.json = n;
+            records[i] = record;
+        }
+        return {
             raw : o,
-               success : success,
-               records : records,
-               totalRecords : totalRecords
-           };
+            success : success,
+            records : records,
+            totalRecords : totalRecords
+        };
     }
 });/*
  * Based on:
@@ -24853,6 +24858,8 @@ Roo.SplitBar.BOTTOM = 4;
  */
 Roo.View = function(config, depreciated_tpl, depreciated_config){
     
+    this.parent = false;
+    
     if (typeof(depreciated_tpl) == 'undefined') {
         // new way.. - universal constructor.
         Roo.apply(this, config);
@@ -24876,10 +24883,7 @@ Roo.View = function(config, depreciated_tpl, depreciated_config){
     
     
     this.tpl.compile();
-   
-  
     
-     
     /** @private */
     this.addEvents({
         /**
@@ -25030,6 +25034,11 @@ Roo.extend(Roo.View, Roo.util.Observable, {
      */
     toggleSelect : false,
     
+    /**
+     * @cfg {Boolean} tickable - selecting 
+     */
+    tickable : false,
+    
     /**
      * Returns the element this view is bound to.
      * @return {Roo.Element}
@@ -25078,10 +25087,26 @@ Roo.extend(Roo.View, Roo.util.Observable, {
         for(var i = 0, len = records.length; i < len; i++){
             var data = this.prepareData(records[i].data, i, records[i]);
             this.fireEvent("preparedata", this, data, i, records[i]);
+            
+            var d = Roo.apply({}, data);
+            
+            if(this.tickable){
+                Roo.apply(d, {'roo-id' : Roo.id()});
+                
+                var _this = this;
+            
+                Roo.each(this.parent.item, function(item){
+                    if(item[_this.parent.valueField] != data[_this.parent.valueField]){
+                        return;
+                    }
+                    Roo.apply(d, {'roo-data-checked' : 'checked'});
+                });
+            }
+            
             html[html.length] = Roo.util.Format.trim(
                 this.dataName ?
-                    t.applySubtemplate(this.dataName, data, this.store.meta) :
-                    t.apply(data)
+                    t.applySubtemplate(this.dataName, d, this.store.meta) :
+                    t.apply(d)
             );
         }
         
@@ -25288,7 +25313,11 @@ Roo.extend(Roo.View, Roo.util.Observable, {
                 this.select(item, this.multiSelect && e.ctrlKey);
                 this.lastSelection = item;
             }
-            e.preventDefault();
+            
+            if(!this.tickable){
+                e.preventDefault();
+            }
+            
         }
         return true;
     },
@@ -25373,6 +25402,7 @@ Roo.extend(Roo.View, Roo.util.Observable, {
         if(!keepExisting){
             this.clearSelections(true);
         }
+        
         if(this.fireEvent("beforeselect", this, node, this.selections) !== false){
             Roo.fly(node).addClass(this.selectedClass);
             this.selections.push(node);
@@ -27829,7 +27859,8 @@ Roo.extend(Roo.Button, Roo.util.Observable, {
     },
 
     // private
-    onClick : function(e){
+    onClick : function(e)
+    {
         if(e){
             e.preventDefault();
         }
@@ -28488,12 +28519,28 @@ Roo.Toolbar.prototype = {
  * @param {HTMLElement} el 
  */
 Roo.Toolbar.Item = function(el){
+    var cfg = {};
+    if (typeof (el.xtype) != 'undefined') {
+        cfg = el;
+        el = cfg.el;
+    }
+    
     this.el = Roo.getDom(el);
     this.id = Roo.id(this.el);
     this.hidden = false;
+    
+    this.addEvents({
+         /**
+            * @event render
+            * Fires when the button is rendered
+            * @param {Button} this
+            */
+        'render': true
+    });
+    Roo.Toolbar.Item.superclass.constructor.call(this,cfg);
 };
-
-Roo.Toolbar.Item.prototype = {
+Roo.extend(Roo.Toolbar.Item, Roo.util.Observable, {
+//Roo.Toolbar.Item.prototype = {
     
     /**
      * Get this item's HTML Element
@@ -28505,8 +28552,11 @@ Roo.Toolbar.Item.prototype = {
 
     // private
     render : function(td){
-        this.td = td;
+        
+         this.td = td;
         td.appendChild(this.el);
+        
+        this.fireEvent('render', this);
     },
     
     /**
@@ -28568,7 +28618,7 @@ Roo.Toolbar.Item.prototype = {
         this.disabled = false;
         this.el.disabled = false;
     }
-};
+});
 
 
 /**
@@ -28578,10 +28628,15 @@ Roo.Toolbar.Item.prototype = {
  * @constructor
  * Creates a new Separator
  */
-Roo.Toolbar.Separator = function(){
+Roo.Toolbar.Separator = function(cfg){
+    
     var s = document.createElement("span");
     s.className = "ytb-sep";
-    Roo.Toolbar.Separator.superclass.constructor.call(this, s);
+    if (cfg) {
+        cfg.el = s;
+    }
+    
+    Roo.Toolbar.Separator.superclass.constructor.call(this, cfg || s);
 };
 Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
     enable:Roo.emptyFn,
@@ -28596,10 +28651,13 @@ Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
  * @constructor
  * Creates a new Spacer
  */
-Roo.Toolbar.Spacer = function(){
+Roo.Toolbar.Spacer = function(cfg){
     var s = document.createElement("div");
     s.className = "ytb-spacer";
-    Roo.Toolbar.Spacer.superclass.constructor.call(this, s);
+    if (cfg) {
+        cfg.el = s;
+    }
+    Roo.Toolbar.Spacer.superclass.constructor.call(this, cfg || s);
 };
 Roo.extend(Roo.Toolbar.Spacer, Roo.Toolbar.Item, {
     enable:Roo.emptyFn,
@@ -28630,16 +28688,25 @@ Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
  * Creates a new TextItem
  * @param {String} text
  */
-Roo.Toolbar.TextItem = function(text){
-    if (typeof(text) == 'object') {
-        text = text.text;
+Roo.Toolbar.TextItem = function(cfg){
+    var  text = cfg || "";
+    if (typeof(cfg) == 'object') {
+        text = cfg.text || "";
+    }  else {
+        cfg = null;
     }
     var s = document.createElement("span");
     s.className = "ytb-text";
     s.innerHTML = text;
-    Roo.Toolbar.TextItem.superclass.constructor.call(this, s);
+    if (cfg) {
+        cfg.el  = s;
+    }
+    
+    Roo.Toolbar.TextItem.superclass.constructor.call(this, cfg ||  s);
 };
 Roo.extend(Roo.Toolbar.TextItem, Roo.Toolbar.Item, {
+    
+     
     enable:Roo.emptyFn,
     disable:Roo.emptyFn,
     focus:Roo.emptyFn
@@ -37809,12 +37876,14 @@ Roo.extend(Roo.form.TextField, Roo.form.Field,  {
             return;
         }
         
-        if(isSelectAll){ // backspace and delete key
+        if(isSelectAll && event.getCharCode() > 31){ // backspace and delete key
             
             event.preventDefault();
             // this is very hacky as keydown always get's upper case.
-            //
+            
             var cc = String.fromCharCode(event.getCharCode());
+            
+            
             this.setValue( event.shiftKey ?  cc : cc.toLowerCase());
             
         }
@@ -39809,9 +39878,8 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
     getValue : function(){
         if(this.valueField){
             return typeof this.value != 'undefined' ? this.value : '';
-        }else{
-            return Roo.form.ComboBox.superclass.getValue.call(this);
         }
+        return Roo.form.ComboBox.superclass.getValue.call(this);
     },
 
     /**
@@ -40288,6 +40356,13 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
 Roo.form.ComboBoxArray = function(config)
 {
     this.addEvents({
+        /**
+         * @event beforeremove
+         * Fires before remove the value from the list
+            * @param {Roo.form.ComboBoxArray} _self This combo box array
+             * @param {Roo.form.ComboBoxArray.Item} item removed item
+            */
+        'beforeremove' : true,
         /**
          * @event remove
          * Fires when remove the value from the list
@@ -40559,7 +40634,7 @@ Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
             }, this) 
              
         }
-        if (typeof(v) == 'object') {
+        if (typeof(v) == 'object' ) {
             // then let's assume it's an array of objects..
             Roo.each(v, function(l) {
                 this.addItem(l);
@@ -40709,12 +40784,19 @@ Roo.extend(Roo.form.ComboBoxArray.Item, Roo.BoxComponent, {
    
     remove : function()
     {
-        this.cb.items.remove(this);
-        this.el.child('img').un('click', this.remove, this);
-        this.el.remove();
-        this.cb.updateHiddenEl();
+        if(this.cb.disabled){
+            return;
+        }
+        
+        if(false !== this.cb.fireEvent('beforeremove', this.cb, this)){
+            this.cb.items.remove(this);
+            this.el.child('img').un('click', this.remove, this);
+            this.el.remove();
+            this.cb.updateHiddenEl();
+
+            this.cb.fireEvent('remove', this.cb, this);
+        }
         
-        this.cb.fireEvent('remove', this.cb, this);
     }
 });/*
  * Based on:
@@ -40864,6 +40946,9 @@ Roo.extend(Roo.form.Checkbox, Roo.form.Field,  {
 
        // private
     onClick : function(){ 
+        if (this.disabled) {
+            return;
+        }
         this.setChecked(!this.checked);
 
         //if(this.el.dom.checked != this.checked){
@@ -41015,6 +41100,8 @@ Roo.HtmlEditorCore = function(config){
     
     
     Roo.HtmlEditorCore.superclass.constructor.call(this, config);
+    
+    
     this.addEvents({
         /**
          * @event initialize
@@ -41067,7 +41154,14 @@ Roo.HtmlEditorCore = function(config){
          */
         editorevent: true
     });
-     
+    
+    // at this point this.owner is set, so we can start working out the whitelisted / blacklisted elements
+    
+    // defaults : white / black...
+    this.applyBlacklists();
+    
+    
+    
 };
 
 
@@ -41115,6 +41209,9 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     
     clearUp: true,
     
+    // blacklist + whitelisted elements..
+    black: false,
+    white: false,
      
     
 
@@ -41379,11 +41476,18 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             this.doc = iframe.contentWindow.document;
             this.win = iframe.contentWindow;
         } else {
-            if (!Roo.get(this.frameId)) {
+//            if (!Roo.get(this.frameId)) {
+//                return;
+//            }
+//            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
+//            this.win = Roo.get(this.frameId).dom.contentWindow;
+            
+            if (!Roo.get(this.frameId) && !iframe.contentDocument) {
                 return;
             }
+            
             this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
-            this.win = Roo.get(this.frameId).dom.contentWindow;
+            this.win = (iframe.contentWindow || Roo.get(this.frameId).dom.contentWindow);
         }
     },
     
@@ -41985,8 +42089,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             // clean up silly Windows -- stuff?
             return; 
         }
+        var lcname = node.tagName.toLowerCase();
+        // we ignore whitelists... ?? = not really the way to go, but we probably have not got a full
+        // whitelist of tags..
         
-        if (Roo.HtmlEditorCore.black.indexOf(node.tagName.toLowerCase()) > -1 && this.clearUp) {
+        if (this.black.indexOf(lcname) > -1 && this.clearUp ) {
             // remove node.
             node.parentNode.removeChild(node);
             return;
@@ -42036,15 +42143,15 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             
         }
         
+        var cwhite = this.cwhite;
+        var cblack = this.cblack;
+            
         function cleanStyle(n,v)
         {
             if (v.match(/expression/)) { //XSS?? should we even bother..
                 node.removeAttribute(n);
                 return;
             }
-            var cwhite = typeof(ed.cwhite) == 'undefined' ? Roo.HtmlEditorCore.cwhite : ed.cwhite;
-            var cblack = typeof(ed.cblack) == 'undefined' ? Roo.HtmlEditorCore.cblack : ed.cblack;
-            
             
             var parts = v.split(/;/);
             var clean = [];
@@ -42057,7 +42164,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 var l = p.split(':').shift().replace(/\s+/g,'');
                 l = l.replace(/^\s+/g,'').replace(/\s+$/g,'');
                 
-                if ( cblack.indexOf(l) > -1) {
+                if ( cwhite.length && cblack.indexOf(l) > -1) {
 //                    Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
                     //node.removeAttribute(n);
                     return true;
@@ -42225,107 +42332,201 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     },
     domToHTML : function(currentElement, depth, nopadtext) {
         
-            depth = depth || 0;
-            nopadtext = nopadtext || false;
+        depth = depth || 0;
+        nopadtext = nopadtext || false;
+    
+        if (!currentElement) {
+            return this.domToHTML(this.doc.body);
+        }
         
-            if (!currentElement) {
-                return this.domToHTML(this.doc.body);
-            }
-            
-            //Roo.log(currentElement);
-            var j;
-            var allText = false;
-            var nodeName = currentElement.nodeName;
-            var tagName = Roo.util.Format.htmlEncode(currentElement.tagName);
-            
-            if  (nodeName == '#text') {
-                return currentElement.nodeValue;
-            }
-            
+        //Roo.log(currentElement);
+        var j;
+        var allText = false;
+        var nodeName = currentElement.nodeName;
+        var tagName = Roo.util.Format.htmlEncode(currentElement.tagName);
+        
+        if  (nodeName == '#text') {
             
-            var ret = '';
-            if (nodeName != 'BODY') {
-                 
-                var i = 0;
-                // Prints the node tagName, such as <A>, <IMG>, etc
-                if (tagName) {
-                    var attr = [];
-                    for(i = 0; i < currentElement.attributes.length;i++) {
-                        // quoting?
-                        var aname = currentElement.attributes.item(i).name;
-                        if (!currentElement.attributes.item(i).value.length) {
-                            continue;
-                        }
-                        attr.push(aname + '="' + Roo.util.Format.htmlEncode(currentElement.attributes.item(i).value) + '"' );
+            return nopadtext ? currentElement.nodeValue : currentElement.nodeValue.trim();
+        }
+        
+        
+        var ret = '';
+        if (nodeName != 'BODY') {
+             
+            var i = 0;
+            // Prints the node tagName, such as <A>, <IMG>, etc
+            if (tagName) {
+                var attr = [];
+                for(i = 0; i < currentElement.attributes.length;i++) {
+                    // quoting?
+                    var aname = currentElement.attributes.item(i).name;
+                    if (!currentElement.attributes.item(i).value.length) {
+                        continue;
                     }
-                    
-                    ret = "<"+currentElement.tagName+ ( attr.length ? (' ' + attr.join(' ') ) : '') + ">";
-                } 
-                else {
-                    
-                    // eack
+                    attr.push(aname + '="' + Roo.util.Format.htmlEncode(currentElement.attributes.item(i).value) + '"' );
                 }
-            } else {
-                tagName = false;
-            }
-            if (['IMG', 'BR', 'HR', 'INPUT'].indexOf(tagName) > -1) {
-                return ret;
+                
+                ret = "<"+currentElement.tagName+ ( attr.length ? (' ' + attr.join(' ') ) : '') + ">";
+            } 
+            else {
+                
+                // eack
             }
-            if (['PRE', 'TEXTAREA', 'TD', 'A', 'SPAN'].indexOf(tagName) > -1) { // or code?
-                nopadtext = true;
+        } else {
+            tagName = false;
+        }
+        if (['IMG', 'BR', 'HR', 'INPUT'].indexOf(tagName) > -1) {
+            return ret;
+        }
+        if (['PRE', 'TEXTAREA', 'TD', 'A', 'SPAN'].indexOf(tagName) > -1) { // or code?
+            nopadtext = true;
+        }
+        
+        
+        // Traverse the tree
+        i = 0;
+        var currentElementChild = currentElement.childNodes.item(i);
+        var allText = true;
+        var innerHTML  = '';
+        lastnode = '';
+        while (currentElementChild) {
+            // Formatting code (indent the tree so it looks nice on the screen)
+            var nopad = nopadtext;
+            if (lastnode == 'SPAN') {
+                nopad  = true;
             }
-            
-            
-            // Traverse the tree
-            i = 0;
-            var currentElementChild = currentElement.childNodes.item(i);
-            var allText = true;
-            var innerHTML  = '';
-            lastnode = '';
-            while (currentElementChild) {
-                // Formatting code (indent the tree so it looks nice on the screen)
-                var nopad = nopadtext;
-                if (lastnode == 'SPAN') {
-                    nopad  = true;
-                }
-                // text
-                if  (currentElementChild.nodeName == '#text') {
-                    var toadd = Roo.util.Format.htmlEncode(currentElementChild.nodeValue);
-                    if (!nopad && toadd.length > 80) {
-                        innerHTML  += "\n" + (new Array( depth + 1 )).join( "  "  );
-                    }
-                    innerHTML  += toadd;
-                    
-                    i++;
-                    currentElementChild = currentElement.childNodes.item(i);
-                    lastNode = '';
-                    continue;
+            // text
+            if  (currentElementChild.nodeName == '#text') {
+                var toadd = Roo.util.Format.htmlEncode(currentElementChild.nodeValue);
+                toadd = nopadtext ? toadd : toadd.trim();
+                if (!nopad && toadd.length > 80) {
+                    innerHTML  += "\n" + (new Array( depth + 1 )).join( "  "  );
                 }
-                allText = false;
+                innerHTML  += toadd;
                 
-                innerHTML  += nopad ? '' : "\n" + (new Array( depth + 1 )).join( "  "  );
-                    
-                // Recursively traverse the tree structure of the child node
-                innerHTML   += this.domToHTML(currentElementChild, depth+1, nopadtext);
-                lastnode = currentElementChild.nodeName;
                 i++;
-                currentElementChild=currentElement.childNodes.item(i);
+                currentElementChild = currentElement.childNodes.item(i);
+                lastNode = '';
+                continue;
             }
+            allText = false;
             
-            ret += innerHTML;
+            innerHTML  += nopad ? '' : "\n" + (new Array( depth + 1 )).join( "  "  );
+                
+            // Recursively traverse the tree structure of the child node
+            innerHTML   += this.domToHTML(currentElementChild, depth+1, nopadtext);
+            lastnode = currentElementChild.nodeName;
+            i++;
+            currentElementChild=currentElement.childNodes.item(i);
+        }
+        
+        ret += innerHTML;
+        
+        if (!allText) {
+                // The remaining code is mostly for formatting the tree
+            ret+= nopadtext ? '' : "\n" + (new Array( depth  )).join( "  "  );
+        }
+        
+        
+        if (tagName) {
+            ret+= "</"+tagName+">";
+        }
+        return ret;
+        
+    },
+        
+    applyBlacklists : function()
+    {
+        var w = typeof(this.owner.white) != 'undefined' && this.owner.white ? this.owner.white  : [];
+        var b = typeof(this.owner.black) != 'undefined' && this.owner.black ? this.owner.black :  [];
+        
+        this.white = [];
+        this.black = [];
+        Roo.each(Roo.HtmlEditorCore.white, function(tag) {
+            if (b.indexOf(tag) > -1) {
+                return;
+            }
+            this.white.push(tag);
             
-            if (!allText) {
-                    // The remaining code is mostly for formatting the tree
-                ret+= nopadtext ? '' : "\n" + (new Array( depth  )).join( "  "  );
+        }, this);
+        
+        Roo.each(w, function(tag) {
+            if (b.indexOf(tag) > -1) {
+                return;
+            }
+            if (this.white.indexOf(tag) > -1) {
+                return;
             }
+            this.white.push(tag);
             
+        }, this);
+        
+        
+        Roo.each(Roo.HtmlEditorCore.black, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
+            }
+            this.black.push(tag);
             
-            if (tagName) {
-                ret+= "</"+tagName+">";
+        }, this);
+        
+        Roo.each(b, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
             }
-            return ret;
+            if (this.black.indexOf(tag) > -1) {
+                return;
+            }
+            this.black.push(tag);
             
-        }
+        }, this);
+        
+        
+        w = typeof(this.owner.cwhite) != 'undefined' && this.owner.cwhite ? this.owner.cwhite  : [];
+        b = typeof(this.owner.cblack) != 'undefined' && this.owner.cblack ? this.owner.cblack :  [];
+        
+        this.cwhite = [];
+        this.cblack = [];
+        Roo.each(Roo.HtmlEditorCore.cwhite, function(tag) {
+            if (b.indexOf(tag) > -1) {
+                return;
+            }
+            this.cwhite.push(tag);
+            
+        }, this);
+        
+        Roo.each(w, function(tag) {
+            if (b.indexOf(tag) > -1) {
+                return;
+            }
+            if (this.cwhite.indexOf(tag) > -1) {
+                return;
+            }
+            this.cwhite.push(tag);
+            
+        }, this);
+        
+        
+        Roo.each(Roo.HtmlEditorCore.cblack, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
+            }
+            this.cblack.push(tag);
+            
+        }, this);
+        
+        Roo.each(b, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
+            }
+            if (this.cblack.indexOf(tag) > -1) {
+                return;
+            }
+            this.cblack.push(tag);
+            
+        }, this);
+    }
     
     // hide stuff that is not compatible
     /**
@@ -42508,6 +42709,29 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
      */
     stylesheets: false,
     
+    
+     /**
+     * @cfg {Array} blacklist of css styles style attributes (blacklist overrides whitelist)
+     * 
+     */
+    cblack: false,
+    /**
+     * @cfg {Array} whitelist of css styles style attributes (blacklist overrides whitelist)
+     * 
+     */
+    cwhite: false,
+    
+     /**
+     * @cfg {Array} blacklist of html tags - in addition to standard blacklist.
+     * 
+     */
+    black: false,
+    /**
+     * @cfg {Array} whitelist of html tags - in addition to statndard whitelist
+     * 
+     */
+    white: false,
+    
     // id of frame..
     frameId: false,
     
@@ -42521,6 +42745,8 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
     iframePad:3,
     hideMode:'offsets',
     
+    actionMode : 'container', // defaults to hiding it...
+    
     defaultAutoCreate : { // modified by initCompnoent..
         tag: "textarea",
         style:"width:500px;height:300px;",
@@ -42676,6 +42902,126 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
             // should trigger onReize..
         }
         
+        this.keyNav = new Roo.KeyNav(this.el, {
+            
+            "tab" : function(e){
+                e.preventDefault();
+                
+                var value = this.getValue();
+                
+                var start = this.el.dom.selectionStart;
+                var end = this.el.dom.selectionEnd;
+                
+                if(!e.shiftKey){
+                    
+                    this.setValue(value.substring(0, start) + "\t" + value.substring(end));
+                    this.el.dom.setSelectionRange(end + 1, end + 1);
+                    return;
+                }
+                
+                var f = value.substring(0, start).split("\t");
+                
+                if(f.pop().length != 0){
+                    return;
+                }
+                
+                this.setValue(f.join("\t") + value.substring(end));
+                this.el.dom.setSelectionRange(start - 1, start - 1);
+                
+            },
+            
+            "home" : function(e){
+                e.preventDefault();
+                
+                var curr = this.el.dom.selectionStart;
+                var lines = this.getValue().split("\n");
+                
+                if(!lines.length){
+                    return;
+                }
+                
+                if(e.ctrlKey){
+                    this.el.dom.setSelectionRange(0, 0);
+                    return;
+                }
+                
+                var pos = 0;
+                
+                for (var i = 0; i < lines.length;i++) {
+                    pos += lines[i].length;
+                    
+                    if(i != 0){
+                        pos += 1;
+                    }
+                    
+                    if(pos < curr){
+                        continue;
+                    }
+                    
+                    pos -= lines[i].length;
+                    
+                    break;
+                }
+                
+                if(!e.shiftKey){
+                    this.el.dom.setSelectionRange(pos, pos);
+                    return;
+                }
+                
+                this.el.dom.selectionStart = pos;
+                this.el.dom.selectionEnd = curr;
+            },
+            
+            "end" : function(e){
+                e.preventDefault();
+                
+                var curr = this.el.dom.selectionStart;
+                var lines = this.getValue().split("\n");
+                
+                if(!lines.length){
+                    return;
+                }
+                
+                if(e.ctrlKey){
+                    this.el.dom.setSelectionRange(this.getValue().length, this.getValue().length);
+                    return;
+                }
+                
+                var pos = 0;
+                
+                for (var i = 0; i < lines.length;i++) {
+                    
+                    pos += lines[i].length;
+                    
+                    if(i != 0){
+                        pos += 1;
+                    }
+                    
+                    if(pos < curr){
+                        continue;
+                    }
+                    
+                    break;
+                }
+                
+                if(!e.shiftKey){
+                    this.el.dom.setSelectionRange(pos, pos);
+                    return;
+                }
+                
+                this.el.dom.selectionStart = curr;
+                this.el.dom.selectionEnd = pos;
+            },
+
+            scope : this,
+
+            doRelay : function(foo, bar, hname){
+                return Roo.KeyNav.prototype.doRelay.apply(this, arguments);
+            },
+
+            forceKeyDown: true
+        });
+        
 //        if(this.autosave && this.w){
 //            this.autoSaveFn = setInterval(this.autosave, 1000);
 //        }
@@ -42684,7 +43030,6 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
     // private
     onResize : function(w, h)
     {
-        //Roo.log('resize: ' +w + ',' + h );
         Roo.form.HtmlEditor.superclass.onResize.apply(this, arguments);
         var ew = false;
         var eh = false;
@@ -42710,6 +43055,7 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
                 
                 var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
                 ah -= 5; // knock a few pixes off for look..
+                Roo.log(ah);
                 this.el.setHeight(this.adjustWidth('textarea', ah));
                 var eh = ah;
             }
@@ -42736,6 +43082,14 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
             this.el.removeClass('x-hidden');
             this.el.dom.removeAttribute('tabIndex');
             this.el.focus();
+            
+            for (var i = 0; i < this.toolbars.length; i++) {
+                if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){
+                    this.toolbars[i].tb.hide();
+                    this.toolbars[i].footer.hide();
+                }
+            }
+            
         }else{
             Roo.log('editor - hiding textarea');
 //            Roo.log('out')
@@ -42744,10 +43098,20 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
             
             this.el.addClass('x-hidden');
             this.el.dom.setAttribute('tabIndex', -1);
+            
+            for (var i = 0; i < this.toolbars.length; i++) {
+                if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){
+                    this.toolbars[i].tb.show();
+                    this.toolbars[i].footer.show();
+                }
+            }
+            
             //this.deferFocus();
         }
-         
+        
         this.setSize(this.wrap.getSize());
+        this.onResize(this.wrap.getSize().width, this.wrap.getSize().height);
+        
         this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
     },
  
@@ -54821,7 +55185,8 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
     /**
      * @cfg {Function} renderer (Optional) A function used to generate HTML markup for a cell
      * given the cell's data value. See {@link #setRenderer}. If not specified, the
-     * default renderer uses the raw data value.
+     * default renderer uses the raw data value. If an object is returned (bootstrap only)
+     * then it is treated as a Roo Component object instance, and it is rendered after the initial row is rendered
      */
        /**
      * @cfg {Roo.grid.GridEditor} editor (Optional) For grid editors - returns the grid editor 
@@ -54829,7 +55194,9 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
     /**
      * @cfg {String} align (Optional) Set the CSS text-align property of the column.  Defaults to undefined.
      */
-
+    /**
+     * @cfg {String} cursor (Optional)
+     */
     /**
      * Returns the id of the column at the specified index.
      * @param {Number} index The column index