Roo/bootstrap/dash/TabGroup.js
[roojs1] / roojs-bootstrap-debug.js
index dd4f942..8a77694 100644 (file)
@@ -956,6 +956,38 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
         }
         
         return cfg;
+    },
+    
+    titleEl : function()
+    {
+        if(!this.el || !this.panel.length || !this.header.length){
+            return;
+        }
+        
+        return this.el.select('.panel-title',true).first();
+    },
+    
+    setTitle : function(v)
+    {
+        var titleEl = this.titleEl();
+        
+        if(!titleEl){
+            return;
+        }
+        
+        titleEl.dom.innerHTML = v;
+    },
+    
+    getTitle : function()
+    {
+        
+        var titleEl = this.titleEl();
+        
+        if(!titleEl){
+            return '';
+        }
+        
+        return titleEl.dom.innerHTML;
     }
    
 });
@@ -1076,6 +1108,7 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
  * @cfg {String} href a tag href
  * @cfg {String} target (_self|_blank|_parent|_top) target for a href.
  * @cfg {String} html the content of the link.
+ * @cfg {Boolean} preventDefault (true | false) default false
 
  * 
  * @constructor
@@ -1101,6 +1134,7 @@ Roo.extend(Roo.bootstrap.Link, Roo.bootstrap.Component,  {
     
     href: false,
     target: false,
+    preventDefault: false,
 
     getAutoCreate : function(){
         
@@ -1130,6 +1164,9 @@ Roo.extend(Roo.bootstrap.Link, Roo.bootstrap.Component,  {
     
     onClick : function(e)
     {
+        if(this.preventDefault){
+            e.preventDefault();
+        }
         //Roo.log('img onclick');
         this.fireEvent('click', this, e);
     }
@@ -2823,7 +2860,8 @@ Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
     unmask : function()
     {
         this.maskEl.hide();
-    }
+    } 
+    
     
     
     
@@ -3234,11 +3272,19 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
         
     },
     
+    addItem : function(cfg)
+    {
+        var cn = new Roo.bootstrap.NavItem(cfg);
+        this.register(cn);
+        cn.parentId = this.id;
+        cn.onRender(this.el, null);
+        return cn;
+    },
     
     register : function(item)
     {
-       this.navItems.push( item);
-       item.navId = this.navId;
+        this.navItems.push( item);
+        item.navId = this.navId;
     
     },
     getNavItem: function(tabId)
@@ -3254,6 +3300,10 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
         });
         return ret;
     }
+    
+    
+    
+    
 });
 
  
@@ -3281,222 +3331,6 @@ Roo.apply(Roo.bootstrap.NavGroup, {
  * 
  */
 
-/**
- * @class Roo.bootstrap.Navbar.Item
- * @extends Roo.bootstrap.Component
- * Bootstrap Navbar.Button class
- * @cfg {String} href  link to
- * @cfg {String} html content of button
- * @cfg {String} badge text inside badge
- * @cfg {String} glyphicon name of glyphicon
- * @cfg {String} icon name of font awesome icon
- * @cfg {Boolean} active Is item active
- * @cfg {Boolean} preventDefault (true | false) default false
- * @cfg {String} tabId the tab that this item activates.
-  
- * @constructor
- * Create a new Navbar Button
- * @param {Object} config The config object
- */
-Roo.bootstrap.Navbar.Item = function(config){
-    Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
-    this.addEvents({
-        // raw events
-        /**
-         * @event click
-         * The raw click event for the entire grid.
-         * @param {Roo.EventObject} e
-         */
-        "click" : true,
-        /**
-           * @event changed
-           * Fires when the active item active state changes
-           * @param {Roo.bootstrap.Navbar.Item} this
-           * @param {boolean} state the new state
-            
-         */
-        'changed': true
-    });
-   
-};
-
-Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component,  {
-    
-    href: false,
-    html: '',
-    badge: '',
-    icon: false,
-    glyphicon: false,
-    active: false,
-    preventDefault : false,
-    tabId : false,
-    
-    getAutoCreate : function(){
-        
-        var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
-       
-        if (this.parent().parent().sidebar === true) {
-            cfg = {
-                tag: 'li',
-                cls: '',
-                cn: [
-                    {
-                    tag: 'p',
-                    cls: ''
-                    }
-                ]
-            }
-            
-            if (this.html) {
-                cfg.cn[0].html = this.html;
-            }
-            
-            if (this.active) {
-                this.cls += ' active';
-            }
-            
-            if (this.menu) {
-                cfg.cn[0].cls += ' dropdown-toggle';
-                cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
-            }
-            
-            if (this.href) {
-                cfg.cn[0].tag = 'a',
-                cfg.cn[0].href = this.href;
-            }
-            
-            if (this.glyphicon) {
-                cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
-            }
-                
-            if (this.icon) {
-                cfg.cn[0].html = '<i class="'+this.icon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
-            }
-            
-            return cfg;
-        }
-       
-        cfg = {
-            tag: 'li',
-                cls: 'nav-item'
-        }
-            
-        if (this.active) {
-            cfg.cls = typeof(cfg.cls) == 'undefined' ? 'active' : cfg.cls + ' active';
-        }
-            
-        cfg.cn = [
-            {
-                tag: 'p',
-                html: 'Text'
-            }
-        ];
-        
-        if (this.glyphicon) {
-            if(cfg.html){cfg.html = ' ' + this.html};
-            cfg.cn=[
-                {
-                    tag: 'span',
-                    cls: 'glyphicon glyphicon-' + this.glyphicon
-                }
-            ];
-        }
-        
-        cfg.cn[0].html = this.html || cfg.cn[0].html ;
-        
-        if (this.menu) {
-            cfg.cn[0].tag='a';
-            cfg.cn[0].href='#';
-            cfg.cn[0].html += " <span class='caret'></span>";
-        //}else if (!this.href) {
-        //    cfg.cn[0].tag='p';
-        //    cfg.cn[0].cls='navbar-text';
-        } else {
-            cfg.cn[0].tag='a';
-            cfg.cn[0].href=this.href||'#';
-            cfg.cn[0].html=this.html;
-        }
-        
-        if (this.badge !== '') {
-            
-            cfg.cn[0].cn=[
-            cfg.cn[0].html + ' ',
-            {
-                tag: 'span',
-                cls: 'badge',
-                html: this.badge
-            }
-            ];
-            cfg.cn[0].html=''
-        }
-        
-        if (this.icon) {
-            cfg.cn[0].html = '<i class="'+this.icon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
-        }
-        
-        return cfg;
-    },
-    initEvents: function() {
-       // Roo.log('init events?');
-       // Roo.log(this.el.dom);
-        this.el.select('a',true).on('click', this.onClick, this);
-        // at this point parent should be available..
-        this.parent().register(this);
-    },
-    
-    onClick : function(e)
-    {
-        if(this.preventDefault){
-            e.preventDefault();
-        }
-        
-        if (typeof (this.menu) != 'undefined') {
-            this.menu.parentType = this.xtype;
-            this.menu.triggerEl = this.el;
-            this.addxtype(Roo.apply({}, this.menu));
-        }
-        
-        if(this.fireEvent('click', this, e) === false){
-            return;
-        };
-        
-        if (['tabs','pills'].indexOf(this.parent().type)!==-1) {
-            if (typeof(this.parent().setActiveItem) !== 'undefined') {
-               this.parent().setActiveItem(this);
-           }
-           
-        } 
-    },
-    
-    isActive: function () {
-        return this.active
-    },
-    setActive : function(state, fire)
-    {
-        this.active = state;
-        if (!state ) {
-            this.el.removeClass('active');
-        } else if (!this.el.hasClass('active')) {
-            this.el.addClass('active');
-        }
-        if (fire) {
-            this.fireEvent('changed', this, state);
-        }
-       
-       
-    }
-     // this should not be here...
-});
-
- /*
- * - LGPL
- *
- * row
- * 
- */
-
 /**
  * @class Roo.bootstrap.NavItem
  * @extends Roo.bootstrap.Component
@@ -3508,8 +3342,11 @@ Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component,  {
  * @cfg {String} glyphicon name of glyphicon
  * @cfg {String} icon name of font awesome icon
  * @cfg {Boolean} active Is item active
+ * @cfg {Boolean} disabled Is item disabled
  * @cfg {Boolean} preventDefault (true | false) default false
  * @cfg {String} tabId the tab that this item activates.
+ * @cfg {String} tagtype (a|span) render as a href or span?
   
  * @constructor
  * Create a new Navbar Item
@@ -3547,6 +3384,8 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     active: false,
     preventDefault : false,
     tabId : false,
+    tagtype : 'a',
+    disabled : false,
     
     getAutoCreate : function(){
          
@@ -3555,7 +3394,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
             cls: 'nav-item',
             cn : [
                 {
-                    tag: 'a',
+                    tag: this.tagtype,
                     href : this.href || "#",
                     html: this.html || ''
                 }
@@ -3569,9 +3408,9 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
         // glyphicon and icon go before content..
         if (this.glyphicon || this.icon) {
              if (this.icon) {
-                cfg.cn[0].html = '<i class="'+this.icon+'"></i><span>' + cfg.cn[0].html + '</span>'
+                cfg.cn[0].html = '<i class="'+this.icon+'"></i> <span>' + cfg.cn[0].html + '</span>'
             } else {
-                cfg.cn[0].html = '<span class="glyphicon glyphicon-' + this.glyphicon + '"></span>'  + cfg.cn[0].html;
+                cfg.cn[0].html = '<span class="glyphicon glyphicon-' + this.glyphicon + '"></span> '  + cfg.cn[0].html;
             }
         }
         
@@ -3587,7 +3426,9 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
              
             cfg.cn[0].html += ' <span class="badge">' + this.badge + '</span>';
         }
-        
+        if (this.disabled) {
+            cfg.cls += ' disabled';
+        }
         
         
         return cfg;
@@ -3595,7 +3436,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     initEvents: function() {
        // Roo.log('init events?');
        // Roo.log(this.el.dom);
-       if (typeof (this.menu) != 'undefined') {
+        if (typeof (this.menu) != 'undefined') {
             this.menu.parentType = this.xtype;
             this.menu.triggerEl = this.el;
             this.addxtype(Roo.apply({}, this.menu));
@@ -3609,18 +3450,22 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     
     onClick : function(e)
     {
+         
         if(this.preventDefault){
             e.preventDefault();
         }
-        
+        if (this.disabled) {
+            return;
+        }
+        Roo.log("fire event clicked");
         if(this.fireEvent('click', this, e) === false){
             return;
         };
         
         if (['tabs','pills'].indexOf(this.parent().type)!==-1) {
-            if (typeof(this.parent().setActiveItem) !== 'undefined') {
-               this.parent().setActiveItem(this);
-           }
+            if (typeof(this.parent().setActiveItem) !== 'undefined') {
+                this.parent().setActiveItem(this);
+            }
            
            
            
@@ -3643,9 +3488,18 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
         }
        
        
-    }
+    },
      // this should not be here...
+    setDisabled : function(state)
+    {
+        this.disabled = state;
+        if (!state ) {
+            this.el.removeClass('disabled');
+        } else if (!this.el.hasClass('disabled')) {
+            this.el.addClass('disabled');
+        }
+        
+    }
 });
  
 
@@ -4010,1284 +3864,2035 @@ Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component,  {
 });
 
  /*
- * - LGPL
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
  *
- * table
- * 
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
  */
 
 /**
- * @class Roo.bootstrap.Table
- * @extends Roo.bootstrap.Component
- * Bootstrap Table class
- * @cfg {String} cls table class
- * @cfg {String} align (left|center|right) Specifies the alignment of a table according to surrounding text
- * @cfg {String} bgcolor Specifies the background color for a table
- * @cfg {Number} border Specifies whether the table cells should have borders or not
- * @cfg {Number} cellpadding Specifies the space between the cell wall and the cell content
- * @cfg {Number} cellspacing Specifies the space between cells
- * @cfg {String} frame Specifies which parts of the outside borders that should be visible
- * @cfg {String} rules Specifies which parts of the inside borders that should be visible
- * @cfg {String} sortable Specifies that the table should be sortable
- * @cfg {String} summary Specifies a summary of the content of a table
- * @cfg {Number} width Specifies the width of a table
- * 
- * @cfg {boolean} striped Should the rows be alternative striped
- * @cfg {boolean} bordered Add borders to the table
- * @cfg {boolean} hover Add hover highlighting
- * @cfg {boolean} condensed Format condensed
- * @cfg {boolean} responsive Format condensed
- * @cfg {Boolean} loadMask (true|false) default false
- *
+ * @class Roo.grid.ColumnModel
+ * @extends Roo.util.Observable
+ * This is the default implementation of a ColumnModel used by the Grid. It defines
+ * the columns in the grid.
+ * <br>Usage:<br>
+ <pre><code>
+ var colModel = new Roo.grid.ColumnModel([
+       {header: "Ticker", width: 60, sortable: true, locked: true},
+       {header: "Company Name", width: 150, sortable: true},
+       {header: "Market Cap.", width: 100, sortable: true},
+       {header: "$ Sales", width: 100, sortable: true, renderer: money},
+       {header: "Employees", width: 100, sortable: true, resizable: false}
+ ]);
+ </code></pre>
+ * <p>
  
- * 
+ * The config options listed for this class are options which may appear in each
+ * individual column definition.
+ * <br/>RooJS Fix - column id's are not sequential but use Roo.id() - fixes bugs with layouts.
  * @constructor
- * Create a new Table
- * @param {Object} config The config object
- */
+ * @param {Object} config An Array of column config objects. See this class's
+ * config objects for details.
+*/
+Roo.grid.ColumnModel = function(config){
+       /**
+     * The config passed into the constructor
+     */
+    this.config = config;
+    this.lookup = {};
 
-Roo.bootstrap.Table = function(config){
-    Roo.bootstrap.Table.superclass.constructor.call(this, config);
-    
-    if (this.sm) {
-        this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table);
-        this.sm = this.selModel;
-        this.sm.xmodule = this.xmodule || false;
-    }
-    if (this.cm && typeof(this.cm.config) == 'undefined') {
-        this.colModel = new Roo.bootstrap.Table.ColumnModel(this.cm);
-        this.cm = this.colModel;
-        this.cm.xmodule = this.xmodule || false;
-    }
-    if (this.store) {
-        this.store= Roo.factory(this.store, Roo.data);
-        this.ds = this.store;
-        this.ds.xmodule = this.xmodule || false;
-         
+    // 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;
     }
+
+    /**
+     * The width of columns which have no width specified (defaults to 100)
+     * @type Number
+     */
+    this.defaultWidth = 100;
+
+    /**
+     * Default sortable of columns which have no sortable specified (defaults to false)
+     * @type Boolean
+     */
+    this.defaultSortable = false;
+
+    this.addEvents({
+        /**
+            * @event widthchange
+            * Fires when the width of a column changes.
+            * @param {ColumnModel} this
+            * @param {Number} columnIndex The column index
+            * @param {Number} newWidth The new width
+            */
+           "widthchange": true,
+        /**
+            * @event headerchange
+            * Fires when the text of a header changes.
+            * @param {ColumnModel} this
+            * @param {Number} columnIndex The column index
+            * @param {Number} newText The new header text
+            */
+           "headerchange": true,
+        /**
+            * @event hiddenchange
+            * Fires when a column is hidden or "unhidden".
+            * @param {ColumnModel} this
+            * @param {Number} columnIndex The column index
+            * @param {Boolean} hidden true if hidden, false otherwise
+            */
+           "hiddenchange": true,
+           /**
+         * @event columnmoved
+         * Fires when a column is moved.
+         * @param {ColumnModel} this
+         * @param {Number} oldIndex
+         * @param {Number} newIndex
+         */
+        "columnmoved" : true,
+        /**
+         * @event columlockchange
+         * Fires when a column's locked state is changed
+         * @param {ColumnModel} this
+         * @param {Number} colIndex
+         * @param {Boolean} locked true if locked
+         */
+        "columnlockchange" : true
+    });
+    Roo.grid.ColumnModel.superclass.constructor.call(this);
 };
+Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
+    /**
+     * @cfg {String} header The header text to display in the Grid view.
+     */
+    /**
+     * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s
+     * {@link Roo.data.Record} definition from which to draw the column's value. If not
+     * specified, the column's index is used as an index into the Record's data Array.
+     */
+    /**
+     * @cfg {Number} width (Optional) The initial width in pixels of the column. Using this
+     * instead of {@link Roo.grid.Grid#autoSizeColumns} is more efficient.
+     */
+    /**
+     * @cfg {Boolean} sortable (Optional) True if sorting is to be allowed on this column.
+     * Defaults to the value of the {@link #defaultSortable} property.
+     * Whether local/remote sorting is used is specified in {@link Roo.data.Store#remoteSort}.
+     */
+    /**
+     * @cfg {Boolean} locked (Optional) True to lock the column in place while scrolling the Grid.  Defaults to false.
+     */
+    /**
+     * @cfg {Boolean} fixed (Optional) True if the column width cannot be changed.  Defaults to false.
+     */
+    /**
+     * @cfg {Boolean} resizable (Optional) False to disable column resizing. Defaults to true.
+     */
+    /**
+     * @cfg {Boolean} hidden (Optional) True to hide the column. Defaults to false.
+     */
+    /**
+     * @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.
+     */
+       /**
+     * @cfg {Roo.grid.GridEditor} editor (Optional) For grid editors - returns the grid editor 
+     */
+    /**
+     * @cfg {String} align (Optional) Set the CSS text-align property of the column.  Defaults to undefined.
+     */
+
+    /**
+     * Returns the id of the column at the specified index.
+     * @param {Number} index The column index
+     * @return {String} the id
+     */
+    getColumnId : function(index){
+        return this.config[index].id;
+    },
+
+    /**
+     * Returns the column for a specified id.
+     * @param {String} id The column id
+     * @return {Object} the column
+     */
+    getColumnById : function(id){
+        return this.lookup[id];
+    },
 
-Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     
-    cls: false,
-    align: false,
-    bgcolor: false,
-    border: false,
-    cellpadding: false,
-    cellspacing: false,
-    frame: false,
-    rules: false,
-    sortable: false,
-    summary: false,
-    width: false,
-    striped : false,
-    bordered: false,
-    hover:  false,
-    condensed : false,
-    responsive : false,
-    sm : false,
-    cm : false,
-    store : false,
-    loadMask : false,
+    /**
+     * Returns the column for a specified dataIndex.
+     * @param {String} dataIndex The column dataIndex
+     * @return {Object|Boolean} the column or false if not found
+     */
+    getColumnByDataIndex: function(dataIndex){
+        var index = this.findColumnIndex(dataIndex);
+        return index > -1 ? this.config[index] : false;
+    },
     
-    getAutoCreate : function(){
-        var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
-        
-        cfg = {
-            tag: 'table',
-            cls : 'table',
-            cn : []
-        }
-            
-        if (this.striped) {
-            cfg.cls += ' table-striped';
+    /**
+     * Returns the index for a specified column id.
+     * @param {String} id The column id
+     * @return {Number} the index, or -1 if not found
+     */
+    getIndexById : function(id){
+        for(var i = 0, len = this.config.length; i < len; i++){
+            if(this.config[i].id == id){
+                return i;
+            }
         }
-        if (this.hover) {
-            cfg.cls += ' table-hover';
+        return -1;
+    },
+    
+    /**
+     * Returns the index for a specified column dataIndex.
+     * @param {String} dataIndex The column dataIndex
+     * @return {Number} the index, or -1 if not found
+     */
+    
+    findColumnIndex : function(dataIndex){
+        for(var i = 0, len = this.config.length; i < len; i++){
+            if(this.config[i].dataIndex == dataIndex){
+                return i;
+            }
         }
-        if (this.bordered) {
-            cfg.cls += ' table-bordered';
+        return -1;
+    },
+    
+    
+    moveColumn : function(oldIndex, newIndex){
+        var c = this.config[oldIndex];
+        this.config.splice(oldIndex, 1);
+        this.config.splice(newIndex, 0, c);
+        this.dataMap = null;
+        this.fireEvent("columnmoved", this, oldIndex, newIndex);
+    },
+
+    isLocked : function(colIndex){
+        return this.config[colIndex].locked === true;
+    },
+
+    setLocked : function(colIndex, value, suppressEvent){
+        if(this.isLocked(colIndex) == value){
+            return;
         }
-        if (this.condensed) {
-            cfg.cls += ' table-condensed';
-        }
-        if (this.responsive) {
-            cfg.cls += ' table-responsive';
-        }
-        
-          
-        
-        
-        if (this.cls) {
-            cfg.cls+=  ' ' +this.cls;
-        }
-        
-        // this lot should be simplifed...
-        
-        if (this.align) {
-            cfg.align=this.align;
-        }
-        if (this.bgcolor) {
-            cfg.bgcolor=this.bgcolor;
-        }
-        if (this.border) {
-            cfg.border=this.border;
-        }
-        if (this.cellpadding) {
-            cfg.cellpadding=this.cellpadding;
-        }
-        if (this.cellspacing) {
-            cfg.cellspacing=this.cellspacing;
+        this.config[colIndex].locked = value;
+        if(!suppressEvent){
+            this.fireEvent("columnlockchange", this, colIndex, value);
         }
-        if (this.frame) {
-            cfg.frame=this.frame;
+    },
+
+    getTotalLockedWidth : function(){
+        var totalWidth = 0;
+        for(var i = 0; i < this.config.length; i++){
+            if(this.isLocked(i) && !this.isHidden(i)){
+                this.totalWidth += this.getColumnWidth(i);
+            }
         }
-        if (this.rules) {
-            cfg.rules=this.rules;
+        return totalWidth;
+    },
+
+    getLockedCount : function(){
+        for(var i = 0, len = this.config.length; i < len; i++){
+            if(!this.isLocked(i)){
+                return i;
+            }
         }
-        if (this.sortable) {
-            cfg.sortable=this.sortable;
+    },
+
+    /**
+     * Returns the number of columns.
+     * @return {Number}
+     */
+    getColumnCount : function(visibleOnly){
+        if(visibleOnly === true){
+            var c = 0;
+            for(var i = 0, len = this.config.length; i < len; i++){
+                if(!this.isHidden(i)){
+                    c++;
+                }
+            }
+            return c;
         }
-        if (this.summary) {
-            cfg.summary=this.summary;
+        return this.config.length;
+    },
+
+    /**
+     * Returns the column configs that return true by the passed function that is called with (columnConfig, index)
+     * @param {Function} fn
+     * @param {Object} scope (optional)
+     * @return {Array} result
+     */
+    getColumnsBy : function(fn, scope){
+        var r = [];
+        for(var i = 0, len = this.config.length; i < len; i++){
+            var c = this.config[i];
+            if(fn.call(scope||this, c, i) === true){
+                r[r.length] = c;
+            }
         }
-        if (this.width) {
-            cfg.width=this.width;
+        return r;
+    },
+
+    /**
+     * Returns true if the specified column is sortable.
+     * @param {Number} col The column index
+     * @return {Boolean}
+     */
+    isSortable : function(col){
+        if(typeof this.config[col].sortable == "undefined"){
+            return this.defaultSortable;
         }
-        
-        if(this.store || this.cm){
-            cfg.cn.push(this.renderHeader());
-            cfg.cn.push(this.renderBody());
-            cfg.cn.push(this.renderFooter());
-            
-            cfg.cls+=  ' TableGrid';
+        return this.config[col].sortable;
+    },
+
+    /**
+     * Returns the rendering (formatting) function defined for the column.
+     * @param {Number} col The column index.
+     * @return {Function} The function used to render the cell. See {@link #setRenderer}.
+     */
+    getRenderer : function(col){
+        if(!this.config[col].renderer){
+            return Roo.grid.ColumnModel.defaultRenderer;
         }
-        
-        return cfg;
+        return this.config[col].renderer;
     },
-//    
-//    initTableGrid : function()
-//    {
-//        var cfg = {};
-//        
-//        var header = {
-//            tag: 'thead',
-//            cn : []
-//        };
-//        
-//        var cm = this.cm;
-//        
-//        for(var i = 0, len = cm.getColumnCount(); i < len; i++){
-//            header.cn.push({
-//                tag: 'th',
-//                html: cm.getColumnHeader(i)
-//            })
-//        }
-//        
-//        cfg.push(header);
-//        
-//        return cfg;
-//        
-//        
-//    },
-    
-    initEvents : function()
-    {   
-        if(!this.store || !this.cm){
-            return;
+
+    /**
+     * Sets the rendering (formatting) function for a column.
+     * @param {Number} col The column index
+     * @param {Function} fn The function to use to process the cell's raw data
+     * to return HTML markup for the grid view. The render function is called with
+     * the following parameters:<ul>
+     * <li>Data value.</li>
+     * <li>Cell metadata. An object in which you may set the following attributes:<ul>
+     * <li>css A CSS style string to apply to the table cell.</li>
+     * <li>attr An HTML attribute definition string to apply to the data container element <i>within</i> the table cell.</li></ul>
+     * <li>The {@link Roo.data.Record} from which the data was extracted.</li>
+     * <li>Row index</li>
+     * <li>Column index</li>
+     * <li>The {@link Roo.data.Store} object from which the Record was extracted</li></ul>
+     */
+    setRenderer : function(col, fn){
+        this.config[col].renderer = fn;
+    },
+
+    /**
+     * Returns the width for the specified column.
+     * @param {Number} col The column index
+     * @return {Number}
+     */
+    getColumnWidth : function(col){
+        return this.config[col].width * 1 || this.defaultWidth;
+    },
+
+    /**
+     * Sets the width for a column.
+     * @param {Number} col The column index
+     * @param {Number} width The new width
+     */
+    setColumnWidth : function(col, width, suppressEvent){
+        this.config[col].width = width;
+        this.totalWidth = null;
+        if(!suppressEvent){
+             this.fireEvent("widthchange", this, col, width);
         }
-        
-        Roo.log('initEvents with ds!!!!');
-        
-        var _this = this;
-        
-        Roo.each(this.el.select('thead th.sortable', true).elements, function(e){
-            e.on('click', _this.sort, _this);
-        });
-//        this.maskEl = Roo.DomHelper.append(this.el.select('.TableGrid', true).first(), {tag: "div", cls:"x-dlg-mask"}, true);
-//        this.maskEl.enableDisplayMode("block");
-//        this.maskEl.show();
-        
-        this.parent().el.setStyle('position', 'relative');
-        
-        var mark = {
-            tag: "div",
-            cls:"x-dlg-mask",
-            style: "text-align:center",
-            cn: [
-                {
-                    tag: "div",
-                    style: "background-color:white;width:50%;margin:100 auto",
-                    cn: [
-                        {
-                            tag: "img",
-                            src: rootURL + '/roojs1/images/ux/lightbox/loading.gif'
-                        },
-                        {
-                            tag: "span",
-                            html: "Loading"
-                        }
-                        
-                    ]
+    },
+
+    /**
+     * Returns the total width of all columns.
+     * @param {Boolean} includeHidden True to include hidden column widths
+     * @return {Number}
+     */
+    getTotalWidth : function(includeHidden){
+        if(!this.totalWidth){
+            this.totalWidth = 0;
+            for(var i = 0, len = this.config.length; i < len; i++){
+                if(includeHidden || !this.isHidden(i)){
+                    this.totalWidth += this.getColumnWidth(i);
                 }
-            ]
+            }
         }
-        this.maskEl = Roo.DomHelper.append(this.parent().el, mark, true);
-        
-        var size = this.parent().el.getSize();
-        
-        this.maskEl.setSize(size.width, 300); // we will fix the height at the beginning...
-        
-        this.maskEl.enableDisplayMode("block");
-        
-        this.store.on('load', this.onLoad, this);
-        this.store.on('beforeload', this.onBeforeLoad, this);
-        
-        this.store.load();
-        
-        
-        
+        return this.totalWidth;
     },
-    
-    sort : function(e,el)
-    {
-        var col = Roo.get(el)
-        
-        if(!col.hasClass('sortable')){
-            return;
-        }
-        
-        var sort = col.attr('sort');
-        var dir = 'ASC';
-        
-        if(col.hasClass('glyphicon-arrow-up')){
-            dir = 'DESC';
-        }
-        
-        this.store.sortInfo = {field : sort, direction : dir};
-        
-        this.store.load();
+
+    /**
+     * Returns the header for the specified column.
+     * @param {Number} col The column index
+     * @return {String}
+     */
+    getColumnHeader : function(col){
+        return this.config[col].header;
     },
-    
-    renderHeader : function()
-    {
-        var header = {
-            tag: 'thead',
-            cn : []
-        };
-        
-        var cm = this.cm;
-        
-        for(var i = 0, len = cm.getColumnCount(); i < len; i++){
-            
-            var config = cm.config[i];
-            
-            if(typeof(config.hidden) != 'undefined' && config.hidden){
-                continue;
-            }
-                    
-            var c = {
-                tag: 'th',
-                html: cm.getColumnHeader(i)
-            };
-            
-            if(typeof(config.dataIndex) != 'undefined'){
-                c.sort = config.dataIndex;
-            }
-            
-            if(typeof(config.sortable) != 'undefined' && config.sortable){
-                c.cls = 'sortable';
-            }
-            
-            if(typeof(config.width) != 'undefined'){
-                c.style = 'width:' + config.width + 'px';
-            }
-            
-            header.cn.push(c)
-        }
-        
-        return header;
+
+    /**
+     * Sets the header for a column.
+     * @param {Number} col The column index
+     * @param {String} header The new header
+     */
+    setColumnHeader : function(col, header){
+        this.config[col].header = header;
+        this.fireEvent("headerchange", this, col, header);
     },
-    
-    renderBody : function()
-    {
-        var body = {
-            tag: 'tbody',
-            cn : []
-        };
-        
-        return body;
+
+    /**
+     * Returns the tooltip for the specified column.
+     * @param {Number} col The column index
+     * @return {String}
+     */
+    getColumnTooltip : function(col){
+            return this.config[col].tooltip;
     },
-    
-    renderFooter : function()
-    {
-        var footer = {
-            tag: 'tfoot',
-            cn : []
-        };
-        
-        return footer;
+    /**
+     * Sets the tooltip for a column.
+     * @param {Number} col The column index
+     * @param {String} tooltip The new tooltip
+     */
+    setColumnTooltip : function(col, tooltip){
+            this.config[col].tooltip = tooltip;
     },
-    
-    onLoad : function()
-    {
-        Roo.log('ds onload');
-        
-        var _this = this;
-        var cm = this.cm;
-        
-        Roo.each(this.el.select('thead th.sortable', true).elements, function(e){
-            e.removeClass(['glyphicon', 'glyphicon-arrow-up', 'glyphicon-arrow-down']);
-            
-            if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'ASC'){
-                e.addClass(['glyphicon', 'glyphicon-arrow-up']);
-            }
-            
-            if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'DESC'){
-                e.addClass(['glyphicon', 'glyphicon-arrow-down']);
-            }
-        });
-        
-        var tbody = this.el.select('tbody', true).first();
-        
-        var renders = [];
-                    
-        if(this.store.getCount() > 0){
-            this.store.data.each(function(d){
-                var row = {
-                    tag : 'tr',
-                    cn : []
-                };
-                
-                for(var i = 0, len = cm.getColumnCount(); i < len; i++){
-                    var config = cm.config[i];
-                    
-                    if(typeof(config.hidden) != 'undefined' && config.hidden){
-                        continue;
-                    }
-                    
-                    var renderer = cm.getRenderer(i);
-                    var value = '';
-                    var id = Roo.id();
-                    
-                    if(typeof(renderer) !== 'undefined'){
-                        value = renderer(d.data[cm.getDataIndex(i)], false, d);
-                    }
-                    
-                    if(typeof(value) === 'object'){
-                        renders.push({
-                            id : id,
-                            cfg : value 
-                        })
-                    }
-                    
-                    var td = {
-                        tag: 'td',
-                        id: id,
-                        html: (typeof(value) === 'object') ? '' : value
-                    };
-                    
-                    if(typeof(config.width) != 'undefined'){
-                        td.style = 'width:' +  config.width + 'px';
-                    }
-                    
-                    row.cn.push(td);
-                   
-                }
-                
-                tbody.createChild(row);
-                
-            });
-        }
-        
-        
-        if(renders.length){
-            var _this = this;
-            Roo.each(renders, function(r){
-                _this.renderColumn(r);
-            })
-        }
 
-        if(this.loadMask){
-            this.maskEl.hide();
-        }
+    /**
+     * Returns the dataIndex for the specified column.
+     * @param {Number} col The column index
+     * @return {Number}
+     */
+    getDataIndex : function(col){
+        return this.config[col].dataIndex;
     },
-    
-    onBeforeLoad : function()
-    {
-        Roo.log('ds onBeforeLoad');
-        
-        this.clear();
-        
-        if(this.loadMask){
-            this.maskEl.show();
-        }
+
+    /**
+     * Sets the dataIndex for a column.
+     * @param {Number} col The column index
+     * @param {Number} dataIndex The new dataIndex
+     */
+    setDataIndex : function(col, dataIndex){
+        this.config[col].dataIndex = dataIndex;
     },
+
     
-    clear : function()
-    {
-        this.el.select('tbody', true).first().dom.innerHTML = '';
-    },
     
-    getSelectionModel : function(){
-        if(!this.selModel){
-            this.selModel = new Roo.bootstrap.Table.RowSelectionModel();
-        }
-        return this.selModel;
+    /**
+     * Returns true if the cell is editable.
+     * @param {Number} colIndex The column index
+     * @param {Number} rowIndex The row index
+     * @return {Boolean}
+     */
+    isCellEditable : function(colIndex, rowIndex){
+        return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
     },
-    
-    renderColumn : function(r)
-    {
-        var _this = this;
-        r.cfg.render(Roo.get(r.id));
-        
-        if(r.cfg.cn){
-            Roo.each(r.cfg.cn, function(c){
-                var child = {
-                    id: r.id,
-                    cfg: c
-                }
-                _this.renderColumn(child);
-            })
-        }
-    }
-   
-});
 
+    /**
+     * Returns the editor defined for the cell/column.
+     * return false or null to disable editing.
+     * @param {Number} colIndex The column index
+     * @param {Number} rowIndex The row index
+     * @return {Object}
+     */
+    getCellEditor : function(colIndex, rowIndex){
+        return this.config[colIndex].editor;
+    },
 
- /*
- * - LGPL
- *
- * table cell
- * 
- */
+    /**
+     * Sets if a column is editable.
+     * @param {Number} col The column index
+     * @param {Boolean} editable True if the column is editable
+     */
+    setEditable : function(col, editable){
+        this.config[col].editable = editable;
+    },
 
-/**
- * @class Roo.bootstrap.TableCell
- * @extends Roo.bootstrap.Component
- * Bootstrap TableCell class
- * @cfg {String} html cell contain text
- * @cfg {String} cls cell class
- * @cfg {String} tag cell tag (td|th) default td
- * @cfg {String} abbr Specifies an abbreviated version of the content in a cell
- * @cfg {String} align Aligns the content in a cell
- * @cfg {String} axis Categorizes cells
- * @cfg {String} bgcolor Specifies the background color of a cell
- * @cfg {Number} charoff Sets the number of characters the content will be aligned from the character specified by the char attribute
- * @cfg {Number} colspan Specifies the number of columns a cell should span
- * @cfg {String} headers Specifies one or more header cells a cell is related to
- * @cfg {Number} height Sets the height of a cell
- * @cfg {String} nowrap Specifies that the content inside a cell should not wrap
- * @cfg {Number} rowspan Sets the number of rows a cell should span
- * @cfg {String} scope Defines a way to associate header cells and data cells in a table
- * @cfg {String} valign Vertical aligns the content in a cell
- * @cfg {Number} width Specifies the width of a cell
- * 
+
+    /**
+     * Returns true if the column is hidden.
+     * @param {Number} colIndex The column index
+     * @return {Boolean}
+     */
+    isHidden : function(colIndex){
+        return this.config[colIndex].hidden;
+    },
+
+
+    /**
+     * Returns true if the column width cannot be changed
+     */
+    isFixed : function(colIndex){
+        return this.config[colIndex].fixed;
+    },
+
+    /**
+     * Returns true if the column can be resized
+     * @return {Boolean}
+     */
+    isResizable : function(colIndex){
+        return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
+    },
+    /**
+     * Sets if a column is hidden.
+     * @param {Number} colIndex The column index
+     * @param {Boolean} hidden True if the column is hidden
+     */
+    setHidden : function(colIndex, hidden){
+        this.config[colIndex].hidden = hidden;
+        this.totalWidth = null;
+        this.fireEvent("hiddenchange", this, colIndex, hidden);
+    },
+
+    /**
+     * Sets the editor for a column.
+     * @param {Number} col The column index
+     * @param {Object} editor The editor object
+     */
+    setEditor : function(col, editor){
+        this.config[col].editor = editor;
+    }
+});
+
+Roo.grid.ColumnModel.defaultRenderer = function(value){
+       if(typeof value == "string" && value.length < 1){
+           return "&#160;";
+       }
+       return value;
+};
+
+// Alias for backwards compatibility
+Roo.grid.DefaultColumnModel = Roo.grid.ColumnModel;
+/*
+ * 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">
+ */
+/**
+ * @class Roo.LoadMask
+ * A simple utility class for generically masking elements while loading data.  If the element being masked has
+ * an underlying {@link Roo.data.Store}, the masking will be automatically synchronized with the store's loading
+ * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
+ * element's UpdateManager load indicator and will be destroyed after the initial load.
  * @constructor
- * Create a new TableCell
+ * Create a new LoadMask
+ * @param {String/HTMLElement/Roo.Element} el The element or DOM node, or its id
  * @param {Object} config The config object
  */
-
-Roo.bootstrap.TableCell = function(config){
-    Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
+Roo.LoadMask = function(el, config){
+    this.el = Roo.get(el);
+    Roo.apply(this, config);
+    if(this.store){
+        this.store.on('beforeload', this.onBeforeLoad, this);
+        this.store.on('load', this.onLoad, this);
+        this.store.on('loadexception', this.onLoadException, this);
+        this.removeMask = false;
+    }else{
+        var um = this.el.getUpdateManager();
+        um.showLoadIndicator = false; // disable the default indicator
+        um.on('beforeupdate', this.onBeforeLoad, this);
+        um.on('update', this.onLoad, this);
+        um.on('failure', this.onLoad, this);
+        this.removeMask = true;
+    }
 };
 
-Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component,  {
-    
-    html: false,
-    cls: false,
-    tag: false,
-    abbr: false,
-    align: false,
-    axis: false,
-    bgcolor: false,
-    charoff: false,
-    colspan: false,
-    headers: false,
-    height: false,
-    nowrap: false,
-    rowspan: false,
-    scope: false,
-    valign: false,
-    width: false,
-    
+Roo.LoadMask.prototype = {
+    /**
+     * @cfg {Boolean} removeMask
+     * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
+     * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
+     */
+    /**
+     * @cfg {String} msg
+     * The text to display in a centered loading message box (defaults to 'Loading...')
+     */
+    msg : 'Loading...',
+    /**
+     * @cfg {String} msgCls
+     * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
+     */
+    msgCls : 'x-mask-loading',
+
+    /**
+     * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
+     * @type Boolean
+     */
+    disabled: false,
+
+    /**
+     * Disables the mask to prevent it from being displayed
+     */
+    disable : function(){
+       this.disabled = true;
+    },
+
+    /**
+     * Enables the mask so that it can be displayed
+     */
+    enable : function(){
+        this.disabled = false;
+    },
     
-    getAutoCreate : function(){
-        var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
-       
-       cfg = {
-           tag: 'td'
-       }
+    onLoadException : function()
+    {
+        Roo.log(arguments);
         
-        if(this.tag){
-            cfg.tag = this.tag;
+        if (typeof(arguments[3]) != 'undefined') {
+            Roo.MessageBox.alert("Error loading",arguments[3]);
+        } 
+        /*
+        try {
+            if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
+                Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
+            }   
+        } catch(e) {
+            
         }
+        */
+    
         
-        if (this.html) {
-            cfg.html=this.html
-        }
-        if (this.cls) {
-            cfg.cls=this.cls
-        }
-        if (this.abbr) {
-            cfg.abbr=this.abbr
-        }
-        if (this.align) {
-            cfg.align=this.align
-        }
-        if (this.axis) {
-            cfg.axis=this.axis
-        }
-        if (this.bgcolor) {
-            cfg.bgcolor=this.bgcolor
-        }
-        if (this.charoff) {
-            cfg.charoff=this.charoff
-        }
-        if (this.colspan) {
-            cfg.colspan=this.colspan
-        }
-        if (this.headers) {
-            cfg.headers=this.headers
-        }
-        if (this.height) {
-            cfg.height=this.height
-        }
-        if (this.nowrap) {
-            cfg.nowrap=this.nowrap
-        }
-        if (this.rowspan) {
-            cfg.rowspan=this.rowspan
-        }
-        if (this.scope) {
-            cfg.scope=this.scope
-        }
-        if (this.valign) {
-            cfg.valign=this.valign
-        }
-        if (this.width) {
-            cfg.width=this.width
-        }
         
-       
-        return cfg;
-    }
-   
-});
+        this.el.unmask(this.removeMask);
+    },
+    // private
+    onLoad : function()
+    {
+        this.el.unmask(this.removeMask);
+    },
 
+    // private
+    onBeforeLoad : function(){
+        if(!this.disabled){
+            this.el.mask(this.msg, this.msgCls);
+        }
+    },
 
- /*
+    // private
+    destroy : function(){
+        if(this.store){
+            this.store.un('beforeload', this.onBeforeLoad, this);
+            this.store.un('load', this.onLoad, this);
+            this.store.un('loadexception', this.onLoadException, this);
+        }else{
+            var um = this.el.getUpdateManager();
+            um.un('beforeupdate', this.onBeforeLoad, this);
+            um.un('update', this.onLoad, this);
+            um.un('failure', this.onLoad, this);
+        }
+    }
+};/*
  * - LGPL
  *
- * table row
+ * table
  * 
  */
 
 /**
- * @class Roo.bootstrap.TableRow
+ * @class Roo.bootstrap.Table
  * @extends Roo.bootstrap.Component
- * Bootstrap TableRow class
- * @cfg {String} cls row class
- * @cfg {String} align Aligns the content in a table row
- * @cfg {String} bgcolor Specifies a background color for a table row
- * @cfg {Number} charoff Sets the number of characters the content will be aligned from the character specified by the char attribute
- * @cfg {String} valign Vertical aligns the content in a table row
+ * Bootstrap Table class
+ * @cfg {String} cls table class
+ * @cfg {String} align (left|center|right) Specifies the alignment of a table according to surrounding text
+ * @cfg {String} bgcolor Specifies the background color for a table
+ * @cfg {Number} border Specifies whether the table cells should have borders or not
+ * @cfg {Number} cellpadding Specifies the space between the cell wall and the cell content
+ * @cfg {Number} cellspacing Specifies the space between cells
+ * @cfg {String} frame Specifies which parts of the outside borders that should be visible
+ * @cfg {String} rules Specifies which parts of the inside borders that should be visible
+ * @cfg {String} sortable Specifies that the table should be sortable
+ * @cfg {String} summary Specifies a summary of the content of a table
+ * @cfg {Number} width Specifies the width of a table
+ * @cfg {String} layout table layout (auto | fixed | initial | inherit)
+ * 
+ * @cfg {boolean} striped Should the rows be alternative striped
+ * @cfg {boolean} bordered Add borders to the table
+ * @cfg {boolean} hover Add hover highlighting
+ * @cfg {boolean} condensed Format condensed
+ * @cfg {boolean} responsive Format condensed
+ * @cfg {Boolean} loadMask (true|false) default false
+ * @cfg {Boolean} tfoot (true|false) generate tfoot, default true
+ * @cfg {Boolean} thead (true|false) generate thead, default true
+ * @cfg {Boolean} RowSelection (true|false) default false
+ * @cfg {Boolean} CellSelection (true|false) default false
+ *
+ * @cfg {Roo.bootstrap.PagingToolbar} footer  a paging toolbar
  * 
  * @constructor
- * Create a new TableRow
+ * Create a new Table
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.TableRow = function(config){
-    Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
-};
-
-Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component,  {
+Roo.bootstrap.Table = function(config){
+    Roo.bootstrap.Table.superclass.constructor.call(this, config);
     
-    cls: false,
-    align: false,
-    bgcolor: false,
-    charoff: false,
-    valign: false,
-    
-    getAutoCreate : function(){
-        var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
-       
-        cfg = {
-            tag: 'tr'
-        }
-            
-        if(this.cls){
-            cfg.cls = this.cls;
-        }
-        if(this.align){
-            cfg.align = this.align;
-        }
-        if(this.bgcolor){
-            cfg.bgcolor = this.bgcolor;
-        }
-        if(this.charoff){
-            cfg.charoff = this.charoff;
-        }
-        if(this.valign){
-            cfg.valign = this.valign;
-        }
-       
-        return cfg;
+    if (this.sm) {
+        this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table);
+        this.sm = this.selModel;
+        this.sm.xmodule = this.xmodule || false;
     }
-   
-});
-
-
- /*
- * - LGPL
- *
- * table body
- * 
- */
-
-/**
- * @class Roo.bootstrap.TableBody
- * @extends Roo.bootstrap.Component
- * Bootstrap TableBody class
- * @cfg {String} cls element class
- * @cfg {String} tag element tag (thead|tbody|tfoot) default tbody
- * @cfg {String} align Aligns the content inside the element
- * @cfg {Number} charoff Sets the number of characters the content inside the element will be aligned from the character specified by the char attribute
- * @cfg {String} valign Vertical aligns the content inside the <tbody> element
- * 
- * @constructor
- * Create a new TableBody
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.TableBody = function(config){
-    Roo.bootstrap.TableBody.superclass.constructor.call(this, config);
+    if (this.cm && typeof(this.cm.config) == 'undefined') {
+        this.colModel = new Roo.grid.ColumnModel(this.cm);
+        this.cm = this.colModel;
+        this.cm.xmodule = this.xmodule || false;
+    }
+    if (this.store) {
+        this.store= Roo.factory(this.store, Roo.data);
+        this.ds = this.store;
+        this.ds.xmodule = this.xmodule || false;
+         
+    }
+    if (this.footer && this.store) {
+        this.footer.dataSource = this.ds;
+        this.footer = Roo.factory(this.footer);
+    }
+    
+    /** @private */
+    this.addEvents({
+        /**
+         * @event cellclick
+         * Fires when a cell is clicked
+         * @param {Roo.bootstrap.Table} this
+         * @param {Roo.Element} el
+         * @param {Number} rowIndex
+         * @param {Number} columnIndex
+         * @param {Roo.EventObject} e
+         */
+        "cellclick" : true,
+        /**
+         * @event celldblclick
+         * Fires when a cell is double clicked
+         * @param {Roo.bootstrap.Table} this
+         * @param {Roo.Element} el
+         * @param {Number} rowIndex
+         * @param {Number} columnIndex
+         * @param {Roo.EventObject} e
+         */
+        "celldblclick" : true,
+        /**
+         * @event rowclick
+         * Fires when a row is clicked
+         * @param {Roo.bootstrap.Table} this
+         * @param {Roo.Element} el
+         * @param {Number} rowIndex
+         * @param {Roo.EventObject} e
+         */
+        "rowclick" : true,
+        /**
+         * @event rowdblclick
+         * Fires when a row is double clicked
+         * @param {Roo.bootstrap.Table} this
+         * @param {Roo.Element} el
+         * @param {Number} rowIndex
+         * @param {Roo.EventObject} e
+         */
+        "rowdblclick" : true,
+        /**
+         * @event rowclass
+         * Fires when a row is rendered, so you can change add a style to it.
+         * @param {Roo.bootstrap.Table} this
+         * @param {Object} rowcfg   contains record  rowIndex colIndex and rowClass - set rowClass to add a style.
+         */
+        'rowclass' : true
+        
+    });
 };
 
-Roo.extend(Roo.bootstrap.TableBody, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     
     cls: false,
-    tag: false,
     align: false,
-    charoff: false,
-    valign: false,
+    bgcolor: false,
+    border: false,
+    cellpadding: false,
+    cellspacing: false,
+    frame: false,
+    rules: false,
+    sortable: false,
+    summary: false,
+    width: false,
+    striped : false,
+    bordered: false,
+    hover:  false,
+    condensed : false,
+    responsive : false,
+    sm : false,
+    cm : false,
+    store : false,
+    loadMask : false,
+    tfoot : true,
+    thead : true,
+    RowSelection : false,
+    CellSelection : false,
+    layout : false,
+    
     
     getAutoCreate : function(){
-        var cfg = Roo.apply({}, Roo.bootstrap.TableBody.superclass.getAutoCreate.call(this));
-       
+        var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
+        
         cfg = {
-            tag: 'tbody'
+            tag: 'table',
+            cls : 'table',
+            cn : []
         }
             
+        if (this.striped) {
+            cfg.cls += ' table-striped';
+        }
+        
+        if (this.hover) {
+            cfg.cls += ' table-hover';
+        }
+        if (this.bordered) {
+            cfg.cls += ' table-bordered';
+        }
+        if (this.condensed) {
+            cfg.cls += ' table-condensed';
+        }
+        if (this.responsive) {
+            cfg.cls += ' table-responsive';
+        }
+        
         if (this.cls) {
-            cfg.cls=this.cls
+            cfg.cls+=  ' ' +this.cls;
         }
-        if(this.tag){
-            cfg.tag = this.tag;
+        
+        // this lot should be simplifed...
+        
+        if (this.align) {
+            cfg.align=this.align;
         }
-       
-        if(this.align){
-            cfg.align = this.align;
+        if (this.bgcolor) {
+            cfg.bgcolor=this.bgcolor;
         }
-        if(this.charoff){
-            cfg.charoff = this.charoff;
+        if (this.border) {
+            cfg.border=this.border;
         }
-        if(this.valign){
-            cfg.valign = this.valign;
+        if (this.cellpadding) {
+            cfg.cellpadding=this.cellpadding;
+        }
+        if (this.cellspacing) {
+            cfg.cellspacing=this.cellspacing;
+        }
+        if (this.frame) {
+            cfg.frame=this.frame;
+        }
+        if (this.rules) {
+            cfg.rules=this.rules;
+        }
+        if (this.sortable) {
+            cfg.sortable=this.sortable;
+        }
+        if (this.summary) {
+            cfg.summary=this.summary;
+        }
+        if (this.width) {
+            cfg.width=this.width;
+        }
+        if (this.layout) {
+            cfg.style = (typeof(cfg.style) == 'undefined') ? ('table-layout:' + this.layout + ';') : (cfg.style + ('table-layout:' + this.layout + ';'));
         }
         
-        return cfg;
-    }
+        if(this.store || this.cm){
+            if(this.thead){
+                cfg.cn.push(this.renderHeader());
+            }
+            
+            cfg.cn.push(this.renderBody());
+            
+            if(this.tfoot){
+                cfg.cn.push(this.renderFooter());
+            }
+            
+            cfg.cls+=  ' TableGrid';
+        }
+        
+        return { cn : [ cfg ] };
+    },
     
+    initEvents : function()
+    {   
+        if(!this.store || !this.cm){
+            return;
+        }
+        
+        Roo.log('initEvents with ds!!!!');
+        
+        var _this = this;
+        
+        Roo.each(this.el.select('thead th.sortable', true).elements, function(e){
+            e.on('click', _this.sort, _this);
+        });
+        
+        this.el.on("click", this.onClick, this);
+        this.el.on("dblclick", this.onDblClick, this);
+        
+        this.parent().el.setStyle('position', 'relative');
+        if (this.footer) {
+            this.footer.parentId = this.id;
+            this.footer.onRender(this.el.select('tfoot tr td').first(), null);        
+        }
+        
+        this.maskEl = new Roo.LoadMask(this.el, { store : this.ds, msgCls: 'roo-el-mask-msg' });
+        
+        this.store.on('load', this.onLoad, this);
+        this.store.on('beforeload', this.onBeforeLoad, this);
+        
+    },
     
-//    initEvents : function()
-//    {
-//        
-//        if(!this.store){
-//            return;
-//        }
-//        
-//        this.store = Roo.factory(this.store, Roo.data);
-//        this.store.on('load', this.onLoad, this);
-//        
-//        this.store.load();
-//        
-//    },
-//    
-//    onLoad: function () 
-//    {   
-//        this.fireEvent('load', this);
-//    }
-//    
-//   
-});
-
-
- /*
- * 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">
- */
-
-// as we use this in bootstrap.
-Roo.namespace('Roo.form');
- /**
- * @class Roo.form.Action
- * Internal Class used to handle form actions
- * @constructor
- * @param {Roo.form.BasicForm} el The form element or its id
- * @param {Object} config Configuration options
- */
-
-// define the action interface
-Roo.form.Action = function(form, options){
-    this.form = form;
-    this.options = options || {};
-};
-/**
- * Client Validation Failed
- * @const 
- */
-Roo.form.Action.CLIENT_INVALID = 'client';
-/**
- * Server Validation Failed
- * @const 
- */
-Roo.form.Action.SERVER_INVALID = 'server';
- /**
- * Connect to Server Failed
- * @const 
- */
-Roo.form.Action.CONNECT_FAILURE = 'connect';
-/**
- * Reading Data from Server Failed
- * @const 
- */
-Roo.form.Action.LOAD_FAILURE = 'load';
-
-Roo.form.Action.prototype = {
-    type : 'default',
-    failureType : undefined,
-    response : undefined,
-    result : undefined,
-
-    // interface method
-    run : function(options){
-
-    },
-
-    // interface method
-    success : function(response){
-
-    },
-
-    // interface method
-    handleResponse : function(response){
-
-    },
-
-    // default connection failure
-    failure : function(response){
+    onClick : function(e, el)
+    {
+        var cell = Roo.get(el);
+        var row = cell.findParent('tr', false, true);
+        var cellIndex = cell.dom.cellIndex;
+        var rowIndex = row.dom.rowIndex;
         
-        this.response = response;
-        this.failureType = Roo.form.Action.CONNECT_FAILURE;
-        this.form.afterAction(this, false);
-    },
-
-    processResponse : function(response){
-        this.response = response;
-        if(!response.responseText){
-            return true;
+        if(this.CellSelection){
+            this.fireEvent('cellclick', this, cell, rowIndex, cellIndex, e);
         }
-        this.result = this.handleResponse(response);
-        return this.result;
-    },
-
-    // utility functions used internally
-    getUrl : function(appendParams){
-        var url = this.options.url || this.form.url || this.form.el.dom.action;
-        if(appendParams){
-            var p = this.getParams();
-            if(p){
-                url += (url.indexOf('?') != -1 ? '&' : '?') + p;
-            }
+        
+        if(this.RowSelection){
+            this.fireEvent('rowclick', this, row, rowIndex, e);
         }
-        return url;
-    },
-
-    getMethod : function(){
-        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
+        
+        
     },
-
-    getParams : function(){
-        var bp = this.form.baseParams;
-        var p = this.options.params;
-        if(p){
-            if(typeof p == "object"){
-                p = Roo.urlEncode(Roo.applyIf(p, bp));
-            }else if(typeof p == 'string' && bp){
-                p += '&' + Roo.urlEncode(bp);
-            }
-        }else if(bp){
-            p = Roo.urlEncode(bp);
+    
+    onDblClick : function(e,el)
+    {
+        var cell = Roo.get(el);;
+        var row = cell.findParent('tr', false, true);
+        var cellIndex = cell.dom.cellIndex;
+        var rowIndex = row.dom.rowIndex;
+        
+        if(this.CellSelection){
+            this.fireEvent('celldblclick', this, cell, rowIndex, cellIndex, e);
+        }
+        
+        if(this.RowSelection){
+            this.fireEvent('rowdblclick', this, row, rowIndex, e);
         }
-        return p;
     },
-
-    createCallback : function(){
-        return {
-            success: this.success,
-            failure: this.failure,
-            scope: this,
-            timeout: (this.form.timeout*1000),
-            upload: this.form.fileUpload ? this.success : undefined
-        };
-    }
-};
-
-Roo.form.Action.Submit = function(form, options){
-    Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
-};
-
-Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
-    type : 'submit',
-
-    haveProgress : false,
-    uploadComplete : false,
     
-    // uploadProgress indicator.
-    uploadProgress : function()
+    sort : function(e,el)
     {
-        if (!this.form.progressUrl) {
+        var col = Roo.get(el)
+        
+        if(!col.hasClass('sortable')){
             return;
         }
         
-        if (!this.haveProgress) {
-            Roo.MessageBox.progress("Uploading", "Uploading");
-        }
-        if (this.uploadComplete) {
-           Roo.MessageBox.hide();
-           return;
+        var sort = col.attr('sort');
+        var dir = 'ASC';
+        
+        if(col.hasClass('glyphicon-arrow-up')){
+            dir = 'DESC';
         }
         
-        this.haveProgress = true;
-   
-        var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
+        this.store.sortInfo = {field : sort, direction : dir};
         
-        var c = new Roo.data.Connection();
-        c.request({
-            url : this.form.progressUrl,
-            params: {
-                id : uid
-            },
-            method: 'GET',
-            success : function(req){
-               //console.log(data);
-                var rdata = false;
-                var edata;
-                try  {
-                   rdata = Roo.decode(req.responseText)
-                } catch (e) {
-                    Roo.log("Invalid data from server..");
-                    Roo.log(edata);
-                    return;
-                }
-                if (!rdata || !rdata.success) {
-                    Roo.log(rdata);
-                    Roo.MessageBox.alert(Roo.encode(rdata));
-                    return;
-                }
-                var data = rdata.data;
-                
-                if (this.uploadComplete) {
-                   Roo.MessageBox.hide();
-                   return;
-                }
-                   
-                if (data){
-                    Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
-                       Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
-                    );
-                }
-                this.uploadProgress.defer(2000,this);
-            },
-       
-            failure: function(data) {
-                Roo.log('progress url failed ');
-                Roo.log(data);
-            },
-            scope : this
-        });
-           
+        if (this.footer) {
+            Roo.log("calling footer first");
+            this.footer.onClick('first');
+        } else {
+        
+            this.store.load({ params : { start : 0 } });
+        }
     },
     
-    
-    run : function()
+    renderHeader : function()
     {
-        // run get Values on the form, so it syncs any secondary forms.
-        this.form.getValues();
+        var header = {
+            tag: 'thead',
+            cn : []
+        };
         
-        var o = this.options;
-        var method = this.getMethod();
-        var isPost = method == 'POST';
-        if(o.clientValidation === false || this.form.isValid()){
+        var cm = this.cm;
+        
+        for(var i = 0, len = cm.getColumnCount(); i < len; i++){
             
-            if (this.form.progressUrl) {
-                this.form.findField('UPLOAD_IDENTIFIER').setValue(
-                    (new Date() * 1) + '' + Math.random());
+            var config = cm.config[i];
+            
+            if(typeof(config.hidden) != 'undefined' && config.hidden){
+                continue;
+            }
                     
-            } 
+            var c = {
+                tag: 'th',
+                style : '',
+                html: cm.getColumnHeader(i)
+            };
             
+            if(typeof(config.dataIndex) != 'undefined'){
+                c.sort = config.dataIndex;
+            }
             
-            Roo.Ajax.request(Roo.apply(this.createCallback(), {
-                form:this.form.el.dom,
-                url:this.getUrl(!isPost),
-                method: method,
-                params:isPost ? this.getParams() : null,
-                isUpload: this.form.fileUpload
-            }));
+            if(typeof(config.sortable) != 'undefined' && config.sortable){
+                c.cls = 'sortable';
+            }
             
-            this.uploadProgress();
-
-        }else if (o.clientValidation !== false){ // client validation failed
-            this.failureType = Roo.form.Action.CLIENT_INVALID;
-            this.form.afterAction(this, false);
+//            if(typeof(config.align) != 'undefined' && config.align.length){
+//                c.style += ' text-align:' + config.align + ';';
+//            }
+            
+            if(typeof(config.width) != 'undefined'){
+                c.style += ' width:' + config.width + 'px;';
+            }
+            
+            header.cn.push(c)
         }
+        
+        return header;
     },
-
-    success : function(response)
+    
+    renderBody : function()
     {
-        this.uploadComplete= true;
-        if (this.haveProgress) {
-            Roo.MessageBox.hide();
-        }
-        
+        var body = {
+            tag: 'tbody',
+            cn : [
+                {
+                    tag: 'tr',
+                    cn : [
+                        {
+                            tag : 'td',
+                            colspan :  this.cm.getColumnCount()
+                        }
+                    ]
+                }
+            ]
+        };
         
-        var result = this.processResponse(response);
-        if(result === true || result.success){
-            this.form.afterAction(this, true);
-            return;
-        }
-        if(result.errors){
-            this.form.markInvalid(result.errors);
-            this.failureType = Roo.form.Action.SERVER_INVALID;
-        }
-        this.form.afterAction(this, false);
+        return body;
     },
-    failure : function(response)
+    
+    renderFooter : function()
     {
-        this.uploadComplete= true;
-        if (this.haveProgress) {
-            Roo.MessageBox.hide();
-        }
+        var footer = {
+            tag: 'tfoot',
+            cn : [
+                {
+                    tag: 'tr',
+                    cn : [
+                        {
+                            tag : 'td',
+                            colspan :  this.cm.getColumnCount()
+                        }
+                    ]
+                }
+            ]
+        };
         
-        this.response = response;
-        this.failureType = Roo.form.Action.CONNECT_FAILURE;
-        this.form.afterAction(this, false);
+        return footer;
     },
     
-    handleResponse : function(response){
-        if(this.form.errorReader){
-            var rs = this.form.errorReader.read(response);
-            var errors = [];
-            if(rs.records){
-                for(var i = 0, len = rs.records.length; i < len; i++) {
-                    var r = rs.records[i];
-                    errors[i] = r.data;
-                }
+    onLoad : function()
+    {
+        Roo.log('ds onload');
+        this.clear();
+        
+        var _this = this;
+        var cm = this.cm;
+        
+        Roo.each(this.el.select('thead th.sortable', true).elements, function(e){
+            e.removeClass(['glyphicon', 'glyphicon-arrow-up', 'glyphicon-arrow-down']);
+            
+            if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'ASC'){
+                e.addClass(['glyphicon', 'glyphicon-arrow-up']);
             }
-            if(errors.length < 1){
-                errors = null;
+            
+            if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'DESC'){
+                e.addClass(['glyphicon', 'glyphicon-arrow-down']);
             }
-            return {
-                success : rs.success,
-                errors : errors
-            };
-        }
-        var ret = false;
-        try {
-            ret = Roo.decode(response.responseText);
-        } catch (e) {
-            ret = {
-                success: false,
-                errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
-                errors : []
-            };
-        }
-        return ret;
+        });
         
-    }
-});
-
-
-Roo.form.Action.Load = function(form, options){
-    Roo.form.Action.Load.superclass.constructor.call(this, form, options);
-    this.reader = this.form.reader;
-};
-
-Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
-    type : 'load',
+        var tbody = this.el.select('tbody', true).first();
+        
+        var renders = [];
+                    
+        if(this.store.getCount() > 0){
+            this.store.data.each(function(d,rowIndex){
+                var row = {
+                    tag : 'tr',
+                    cn : []
+                };
+                
+                for(var i = 0, len = cm.getColumnCount(); i < len; i++){
+                    var config = cm.config[i];
+                    
+                    if(typeof(config.hidden) != 'undefined' && config.hidden){
+                        continue;
+                    }
+                    
+                    var renderer = cm.getRenderer(i);
+                    var value = '';
+                    var id = Roo.id();
+                    
+                    if(typeof(renderer) !== 'undefined'){
+                        value = renderer(d.data[cm.getDataIndex(i)], false, d);
+                    }
+                    
+                    if(typeof(value) === 'object'){
+                        renders.push({
+                            id : id,
+                            cfg : value 
+                        })
+                    }
+                    
+                    var rowcfg = {
+                        record: d,
+                        rowIndex : rowIndex,
+                        colIndex : i,
+                        rowClass : ''
+                    }
 
-    run : function(){
+                    _this.fireEvent('rowclass', this, rowcfg);
+                    
+                    var td = {
+                        tag: 'td',
+                        id: id,
+                        cls : rowcfg.rowClass,
+                        style: '',
+                        html: (typeof(value) === 'object') ? '' : value
+                    };
+                    
+                    if(typeof(config.align) != 'undefined' && config.align.length){
+                        td.style += ' text-align:' + config.align + ';';
+                    }
+                    
+                    if(typeof(config.width) != 'undefined'){
+                        td.style += ' width:' +  config.width + 'px;';
+                    }
+                    
+                    
+                    row.cn.push(td);
+                   
+                }
+                
+                tbody.createChild(row);
+                
+            });
+        }
         
-        Roo.Ajax.request(Roo.apply(
-                this.createCallback(), {
-                    method:this.getMethod(),
-                    url:this.getUrl(false),
-                    params:this.getParams()
-        }));
-    },
+        
+        if(renders.length){
+            var _this = this;
+            Roo.each(renders, function(r){
+                _this.renderColumn(r);
+            })
+        }
 
-    success : function(response){
+        //if(this.loadMask){
+        //    this.maskEl.hide();
+        //}
+    },
+    
+    onBeforeLoad : function()
+    {
+        //Roo.log('ds onBeforeLoad');
         
-        var result = this.processResponse(response);
-        if(result === true || !result.success || !result.data){
-            this.failureType = Roo.form.Action.LOAD_FAILURE;
-            this.form.afterAction(this, false);
-            return;
+        //this.clear();
+        
+        //if(this.loadMask){
+        //    this.maskEl.show();
+        //}
+    },
+    
+    clear : function()
+    {
+        this.el.select('tbody', true).first().dom.innerHTML = '';
+    },
+    
+    getSelectionModel : function(){
+        if(!this.selModel){
+            this.selModel = new Roo.bootstrap.Table.RowSelectionModel();
         }
-        this.form.clearInvalid();
-        this.form.setValues(result.data);
-        this.form.afterAction(this, true);
+        return this.selModel;
     },
-
-    handleResponse : function(response){
-        if(this.form.reader){
-            var rs = this.form.reader.read(response);
-            var data = rs.records && rs.records[0] ? rs.records[0].data : null;
-            return {
-                success : rs.success,
-                data : data
-            };
+    
+    renderColumn : function(r)
+    {
+        var _this = this;
+        r.cfg.render(Roo.get(r.id));
+        
+        if(r.cfg.cn){
+            Roo.each(r.cfg.cn, function(c){
+                var child = {
+                    id: r.id,
+                    cfg: c
+                }
+                _this.renderColumn(child);
+            })
         }
-        return Roo.decode(response.responseText);
     }
+   
 });
 
-Roo.form.Action.ACTION_TYPES = {
-    'load' : Roo.form.Action.Load,
-    'submit' : Roo.form.Action.Submit
-};/*
+
+ /*
  * - LGPL
  *
- * form
+ * table cell
  * 
  */
 
 /**
- * @class Roo.bootstrap.Form
+ * @class Roo.bootstrap.TableCell
  * @extends Roo.bootstrap.Component
- * Bootstrap Form class
- * @cfg {String} method  GET | POST (default POST)
- * @cfg {String} labelAlign top | left (default top)
-  * @cfg {String} align left  | right - for navbars
-
- * 
- * @constructor
- * Create a new Form
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.Form = function(config){
-    Roo.bootstrap.Form.superclass.constructor.call(this, config);
-    this.addEvents({
-        /**
-         * @event clientvalidation
-         * If the monitorValid config option is true, this event fires repetitively to notify of valid state
-         * @param {Form} this
-         * @param {Boolean} valid true if the form has passed client-side validation
-         */
-        clientvalidation: true,
-        /**
-         * @event beforeaction
-         * Fires before any action is performed. Return false to cancel the action.
-         * @param {Form} this
-         * @param {Action} action The action to be performed
-         */
-        beforeaction: true,
-        /**
-         * @event actionfailed
-         * Fires when an action fails.
-         * @param {Form} this
-         * @param {Action} action The action that failed
-         */
-        actionfailed : true,
-        /**
-         * @event actioncomplete
-         * Fires when an action is completed.
-         * @param {Form} this
-         * @param {Action} action The action that completed
-         */
-        actioncomplete : true
-    });
-    
-};
+ * Bootstrap TableCell class
+ * @cfg {String} html cell contain text
+ * @cfg {String} cls cell class
+ * @cfg {String} tag cell tag (td|th) default td
+ * @cfg {String} abbr Specifies an abbreviated version of the content in a cell
+ * @cfg {String} align Aligns the content in a cell
+ * @cfg {String} axis Categorizes cells
+ * @cfg {String} bgcolor Specifies the background color of a cell
+ * @cfg {Number} charoff Sets the number of characters the content will be aligned from the character specified by the char attribute
+ * @cfg {Number} colspan Specifies the number of columns a cell should span
+ * @cfg {String} headers Specifies one or more header cells a cell is related to
+ * @cfg {Number} height Sets the height of a cell
+ * @cfg {String} nowrap Specifies that the content inside a cell should not wrap
+ * @cfg {Number} rowspan Sets the number of rows a cell should span
+ * @cfg {String} scope Defines a way to associate header cells and data cells in a table
+ * @cfg {String} valign Vertical aligns the content in a cell
+ * @cfg {Number} width Specifies the width of a cell
+ * 
+ * @constructor
+ * Create a new TableCell
+ * @param {Object} config The config object
+ */
 
-Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
-      
-     /**
-     * @cfg {String} method
-     * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
-     */
-    method : 'POST',
-    /**
-     * @cfg {String} url
-     * The URL to use for form actions if one isn't supplied in the action options.
-     */
-    /**
-     * @cfg {Boolean} fileUpload
-     * Set to true if this form is a file upload.
-     */
-     
-    /**
-     * @cfg {Object} baseParams
-     * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
-     */
-      
-    /**
-     * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
-     */
-    timeout: 30,
-    /**
-     * @cfg {Sting} align (left|right) for navbar forms
-     */
-    align : 'left',
+Roo.bootstrap.TableCell = function(config){
+    Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
+};
 
-    // private
-    activeAction : null,
-    /**
-     * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
-     * element by passing it or its id or mask the form itself by passing in true.
-     * @type Mixed
-     */
-    waitMsgTarget : false,
+Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component,  {
     
-     
+    html: false,
+    cls: false,
+    tag: false,
+    abbr: false,
+    align: false,
+    axis: false,
+    bgcolor: false,
+    charoff: false,
+    colspan: false,
+    headers: false,
+    height: false,
+    nowrap: false,
+    rowspan: false,
+    scope: false,
+    valign: false,
+    width: false,
     
-    /**
-     * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
-     * element by passing it or its id or mask the form itself by passing in true.
-     * @type Mixed
-     */
     
     getAutoCreate : function(){
+        var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
+       
+       cfg = {
+           tag: 'td'
+       }
         
-        var cfg = {
-            tag: 'form',
-            method : this.method || 'POST',
-            id : this.id || Roo.id(),
-            cls : ''
-        }
-        if (this.parent().xtype.match(/^Nav/)) {
-            cfg.cls = 'navbar-form navbar-' + this.align;
-            
+        if(this.tag){
+            cfg.tag = this.tag;
         }
         
-        if (this.labelAlign == 'left' ) {
-            cfg.cls += ' form-horizontal';
+        if (this.html) {
+            cfg.html=this.html
         }
-        
-        
-        return cfg;
-    },
-    initEvents : function()
-    {
-        this.el.on('submit', this.onSubmit, this);
-        
-        
-    },
-    // private
-    onSubmit : function(e){
-        e.stopEvent();
-    },
-    
-     /**
-     * Returns true if client-side validation on the form is successful.
-     * @return Boolean
-     */
-    isValid : function(){
-        var items = this.getItems();
-        var valid = true;
-        items.each(function(f){
-           if(!f.validate()){
-               valid = false;
-               
-           }
-        });
-        return valid;
-    },
-    /**
-     * Returns true if any fields in this form have changed since their original load.
-     * @return Boolean
-     */
-    isDirty : function(){
-        var dirty = false;
-        var items = this.getItems();
-        items.each(function(f){
-           if(f.isDirty()){
-               dirty = true;
-               return false;
-           }
-           return true;
-        });
-        return dirty;
-    },
-     /**
-     * Performs a predefined action (submit or load) or custom actions you define on this form.
-     * @param {String} actionName The name of the action type
-     * @param {Object} options (optional) The options to pass to the action.  All of the config options listed
-     * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
-     * accept other config options):
-     * <pre>
-Property          Type             Description
-----------------  ---------------  ----------------------------------------------------------------------------------
-url               String           The url for the action (defaults to the form's url)
-method            String           The form method to use (defaults to the form's method, or POST if not defined)
-params            String/Object    The params to pass (defaults to the form's baseParams, or none if not defined)
-clientValidation  Boolean          Applies to submit only.  Pass true to call form.isValid() prior to posting to
-                                   validate the form on the client (defaults to false)
-     * </pre>
-     * @return {BasicForm} this
-     */
-    doAction : function(action, options){
-        if(typeof action == 'string'){
-            action = new Roo.form.Action.ACTION_TYPES[action](this, options);
+        if (this.cls) {
+            cfg.cls=this.cls
         }
-        if(this.fireEvent('beforeaction', this, action) !== false){
-            this.beforeAction(action);
-            action.run.defer(100, action);
+        if (this.abbr) {
+            cfg.abbr=this.abbr
+        }
+        if (this.align) {
+            cfg.align=this.align
+        }
+        if (this.axis) {
+            cfg.axis=this.axis
+        }
+        if (this.bgcolor) {
+            cfg.bgcolor=this.bgcolor
+        }
+        if (this.charoff) {
+            cfg.charoff=this.charoff
+        }
+        if (this.colspan) {
+            cfg.colspan=this.colspan
+        }
+        if (this.headers) {
+            cfg.headers=this.headers
+        }
+        if (this.height) {
+            cfg.height=this.height
+        }
+        if (this.nowrap) {
+            cfg.nowrap=this.nowrap
+        }
+        if (this.rowspan) {
+            cfg.rowspan=this.rowspan
+        }
+        if (this.scope) {
+            cfg.scope=this.scope
+        }
+        if (this.valign) {
+            cfg.valign=this.valign
+        }
+        if (this.width) {
+            cfg.width=this.width
         }
-        return this;
-    },
-    
-    // private
-    beforeAction : function(action){
-        var o = action.options;
-        
-        // not really supported yet.. ??
         
-        //if(this.waitMsgTarget === true){
-            this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
-        //}else if(this.waitMsgTarget){
-        //    this.waitMsgTarget = Roo.get(this.waitMsgTarget);
-        //    this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
-        //}else {
-        //    Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
+       
+        return cfg;
+    }
+   
+});
+
+
+ /*
+ * - LGPL
+ *
+ * table row
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.TableRow
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TableRow class
+ * @cfg {String} cls row class
+ * @cfg {String} align Aligns the content in a table row
+ * @cfg {String} bgcolor Specifies a background color for a table row
+ * @cfg {Number} charoff Sets the number of characters the content will be aligned from the character specified by the char attribute
+ * @cfg {String} valign Vertical aligns the content in a table row
+ * 
+ * @constructor
+ * Create a new TableRow
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.TableRow = function(config){
+    Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component,  {
+    
+    cls: false,
+    align: false,
+    bgcolor: false,
+    charoff: false,
+    valign: false,
+    
+    getAutoCreate : function(){
+        var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
+       
+        cfg = {
+            tag: 'tr'
+        }
+            
+        if(this.cls){
+            cfg.cls = this.cls;
+        }
+        if(this.align){
+            cfg.align = this.align;
+        }
+        if(this.bgcolor){
+            cfg.bgcolor = this.bgcolor;
+        }
+        if(this.charoff){
+            cfg.charoff = this.charoff;
+        }
+        if(this.valign){
+            cfg.valign = this.valign;
+        }
+       
+        return cfg;
+    }
+   
+});
+
+
+ /*
+ * - LGPL
+ *
+ * table body
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.TableBody
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TableBody class
+ * @cfg {String} cls element class
+ * @cfg {String} tag element tag (thead|tbody|tfoot) default tbody
+ * @cfg {String} align Aligns the content inside the element
+ * @cfg {Number} charoff Sets the number of characters the content inside the element will be aligned from the character specified by the char attribute
+ * @cfg {String} valign Vertical aligns the content inside the <tbody> element
+ * 
+ * @constructor
+ * Create a new TableBody
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.TableBody = function(config){
+    Roo.bootstrap.TableBody.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.TableBody, Roo.bootstrap.Component,  {
+    
+    cls: false,
+    tag: false,
+    align: false,
+    charoff: false,
+    valign: false,
+    
+    getAutoCreate : function(){
+        var cfg = Roo.apply({}, Roo.bootstrap.TableBody.superclass.getAutoCreate.call(this));
+       
+        cfg = {
+            tag: 'tbody'
+        }
+            
+        if (this.cls) {
+            cfg.cls=this.cls
+        }
+        if(this.tag){
+            cfg.tag = this.tag;
+        }
+       
+        if(this.align){
+            cfg.align = this.align;
+        }
+        if(this.charoff){
+            cfg.charoff = this.charoff;
+        }
+        if(this.valign){
+            cfg.valign = this.valign;
+        }
+        
+        return cfg;
+    }
+    
+    
+//    initEvents : function()
+//    {
+//        
+//        if(!this.store){
+//            return;
+//        }
+//        
+//        this.store = Roo.factory(this.store, Roo.data);
+//        this.store.on('load', this.onLoad, this);
+//        
+//        this.store.load();
+//        
+//    },
+//    
+//    onLoad: function () 
+//    {   
+//        this.fireEvent('load', this);
+//    }
+//    
+//   
+});
+
+
+ /*
+ * 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">
+ */
+
+// as we use this in bootstrap.
+Roo.namespace('Roo.form');
+ /**
+ * @class Roo.form.Action
+ * Internal Class used to handle form actions
+ * @constructor
+ * @param {Roo.form.BasicForm} el The form element or its id
+ * @param {Object} config Configuration options
+ */
+
+// define the action interface
+Roo.form.Action = function(form, options){
+    this.form = form;
+    this.options = options || {};
+};
+/**
+ * Client Validation Failed
+ * @const 
+ */
+Roo.form.Action.CLIENT_INVALID = 'client';
+/**
+ * Server Validation Failed
+ * @const 
+ */
+Roo.form.Action.SERVER_INVALID = 'server';
+ /**
+ * Connect to Server Failed
+ * @const 
+ */
+Roo.form.Action.CONNECT_FAILURE = 'connect';
+/**
+ * Reading Data from Server Failed
+ * @const 
+ */
+Roo.form.Action.LOAD_FAILURE = 'load';
+
+Roo.form.Action.prototype = {
+    type : 'default',
+    failureType : undefined,
+    response : undefined,
+    result : undefined,
+
+    // interface method
+    run : function(options){
+
+    },
+
+    // interface method
+    success : function(response){
+
+    },
+
+    // interface method
+    handleResponse : function(response){
+
+    },
+
+    // default connection failure
+    failure : function(response){
+        
+        this.response = response;
+        this.failureType = Roo.form.Action.CONNECT_FAILURE;
+        this.form.afterAction(this, false);
+    },
+
+    processResponse : function(response){
+        this.response = response;
+        if(!response.responseText){
+            return true;
+        }
+        this.result = this.handleResponse(response);
+        return this.result;
+    },
+
+    // utility functions used internally
+    getUrl : function(appendParams){
+        var url = this.options.url || this.form.url || this.form.el.dom.action;
+        if(appendParams){
+            var p = this.getParams();
+            if(p){
+                url += (url.indexOf('?') != -1 ? '&' : '?') + p;
+            }
+        }
+        return url;
+    },
+
+    getMethod : function(){
+        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
+    },
+
+    getParams : function(){
+        var bp = this.form.baseParams;
+        var p = this.options.params;
+        if(p){
+            if(typeof p == "object"){
+                p = Roo.urlEncode(Roo.applyIf(p, bp));
+            }else if(typeof p == 'string' && bp){
+                p += '&' + Roo.urlEncode(bp);
+            }
+        }else if(bp){
+            p = Roo.urlEncode(bp);
+        }
+        return p;
+    },
+
+    createCallback : function(){
+        return {
+            success: this.success,
+            failure: this.failure,
+            scope: this,
+            timeout: (this.form.timeout*1000),
+            upload: this.form.fileUpload ? this.success : undefined
+        };
+    }
+};
+
+Roo.form.Action.Submit = function(form, options){
+    Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
+};
+
+Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
+    type : 'submit',
+
+    haveProgress : false,
+    uploadComplete : false,
+    
+    // uploadProgress indicator.
+    uploadProgress : function()
+    {
+        if (!this.form.progressUrl) {
+            return;
+        }
+        
+        if (!this.haveProgress) {
+            Roo.MessageBox.progress("Uploading", "Uploading");
+        }
+        if (this.uploadComplete) {
+           Roo.MessageBox.hide();
+           return;
+        }
+        
+        this.haveProgress = true;
+   
+        var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
+        
+        var c = new Roo.data.Connection();
+        c.request({
+            url : this.form.progressUrl,
+            params: {
+                id : uid
+            },
+            method: 'GET',
+            success : function(req){
+               //console.log(data);
+                var rdata = false;
+                var edata;
+                try  {
+                   rdata = Roo.decode(req.responseText)
+                } catch (e) {
+                    Roo.log("Invalid data from server..");
+                    Roo.log(edata);
+                    return;
+                }
+                if (!rdata || !rdata.success) {
+                    Roo.log(rdata);
+                    Roo.MessageBox.alert(Roo.encode(rdata));
+                    return;
+                }
+                var data = rdata.data;
+                
+                if (this.uploadComplete) {
+                   Roo.MessageBox.hide();
+                   return;
+                }
+                   
+                if (data){
+                    Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
+                       Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
+                    );
+                }
+                this.uploadProgress.defer(2000,this);
+            },
+       
+            failure: function(data) {
+                Roo.log('progress url failed ');
+                Roo.log(data);
+            },
+            scope : this
+        });
+           
+    },
+    
+    
+    run : function()
+    {
+        // run get Values on the form, so it syncs any secondary forms.
+        this.form.getValues();
+        
+        var o = this.options;
+        var method = this.getMethod();
+        var isPost = method == 'POST';
+        if(o.clientValidation === false || this.form.isValid()){
+            
+            if (this.form.progressUrl) {
+                this.form.findField('UPLOAD_IDENTIFIER').setValue(
+                    (new Date() * 1) + '' + Math.random());
+                    
+            } 
+            
+            
+            Roo.Ajax.request(Roo.apply(this.createCallback(), {
+                form:this.form.el.dom,
+                url:this.getUrl(!isPost),
+                method: method,
+                params:isPost ? this.getParams() : null,
+                isUpload: this.form.fileUpload
+            }));
+            
+            this.uploadProgress();
+
+        }else if (o.clientValidation !== false){ // client validation failed
+            this.failureType = Roo.form.Action.CLIENT_INVALID;
+            this.form.afterAction(this, false);
+        }
+    },
+
+    success : function(response)
+    {
+        this.uploadComplete= true;
+        if (this.haveProgress) {
+            Roo.MessageBox.hide();
+        }
+        
+        
+        var result = this.processResponse(response);
+        if(result === true || result.success){
+            this.form.afterAction(this, true);
+            return;
+        }
+        if(result.errors){
+            this.form.markInvalid(result.errors);
+            this.failureType = Roo.form.Action.SERVER_INVALID;
+        }
+        this.form.afterAction(this, false);
+    },
+    failure : function(response)
+    {
+        this.uploadComplete= true;
+        if (this.haveProgress) {
+            Roo.MessageBox.hide();
+        }
+        
+        this.response = response;
+        this.failureType = Roo.form.Action.CONNECT_FAILURE;
+        this.form.afterAction(this, false);
+    },
+    
+    handleResponse : function(response){
+        if(this.form.errorReader){
+            var rs = this.form.errorReader.read(response);
+            var errors = [];
+            if(rs.records){
+                for(var i = 0, len = rs.records.length; i < len; i++) {
+                    var r = rs.records[i];
+                    errors[i] = r.data;
+                }
+            }
+            if(errors.length < 1){
+                errors = null;
+            }
+            return {
+                success : rs.success,
+                errors : errors
+            };
+        }
+        var ret = false;
+        try {
+            ret = Roo.decode(response.responseText);
+        } catch (e) {
+            ret = {
+                success: false,
+                errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
+                errors : []
+            };
+        }
+        return ret;
+        
+    }
+});
+
+
+Roo.form.Action.Load = function(form, options){
+    Roo.form.Action.Load.superclass.constructor.call(this, form, options);
+    this.reader = this.form.reader;
+};
+
+Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
+    type : 'load',
+
+    run : function(){
+        
+        Roo.Ajax.request(Roo.apply(
+                this.createCallback(), {
+                    method:this.getMethod(),
+                    url:this.getUrl(false),
+                    params:this.getParams()
+        }));
+    },
+
+    success : function(response){
+        
+        var result = this.processResponse(response);
+        if(result === true || !result.success || !result.data){
+            this.failureType = Roo.form.Action.LOAD_FAILURE;
+            this.form.afterAction(this, false);
+            return;
+        }
+        this.form.clearInvalid();
+        this.form.setValues(result.data);
+        this.form.afterAction(this, true);
+    },
+
+    handleResponse : function(response){
+        if(this.form.reader){
+            var rs = this.form.reader.read(response);
+            var data = rs.records && rs.records[0] ? rs.records[0].data : null;
+            return {
+                success : rs.success,
+                data : data
+            };
+        }
+        return Roo.decode(response.responseText);
+    }
+});
+
+Roo.form.Action.ACTION_TYPES = {
+    'load' : Roo.form.Action.Load,
+    'submit' : Roo.form.Action.Submit
+};/*
+ * - LGPL
+ *
+ * form
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.Form
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Form class
+ * @cfg {String} method  GET | POST (default POST)
+ * @cfg {String} labelAlign top | left (default top)
+  * @cfg {String} align left  | right - for navbars
+
+ * 
+ * @constructor
+ * Create a new Form
+ * @param {Object} config The config object
+ */
+
+
+Roo.bootstrap.Form = function(config){
+    Roo.bootstrap.Form.superclass.constructor.call(this, config);
+    this.addEvents({
+        /**
+         * @event clientvalidation
+         * If the monitorValid config option is true, this event fires repetitively to notify of valid state
+         * @param {Form} this
+         * @param {Boolean} valid true if the form has passed client-side validation
+         */
+        clientvalidation: true,
+        /**
+         * @event beforeaction
+         * Fires before any action is performed. Return false to cancel the action.
+         * @param {Form} this
+         * @param {Action} action The action to be performed
+         */
+        beforeaction: true,
+        /**
+         * @event actionfailed
+         * Fires when an action fails.
+         * @param {Form} this
+         * @param {Action} action The action that failed
+         */
+        actionfailed : true,
+        /**
+         * @event actioncomplete
+         * Fires when an action is completed.
+         * @param {Form} this
+         * @param {Action} action The action that completed
+         */
+        actioncomplete : true
+    });
+    
+};
+
+Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
+      
+     /**
+     * @cfg {String} method
+     * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
+     */
+    method : 'POST',
+    /**
+     * @cfg {String} url
+     * The URL to use for form actions if one isn't supplied in the action options.
+     */
+    /**
+     * @cfg {Boolean} fileUpload
+     * Set to true if this form is a file upload.
+     */
+     
+    /**
+     * @cfg {Object} baseParams
+     * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
+     */
+      
+    /**
+     * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
+     */
+    timeout: 30,
+    /**
+     * @cfg {Sting} align (left|right) for navbar forms
+     */
+    align : 'left',
+
+    // private
+    activeAction : null,
+    /**
+     * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
+     * element by passing it or its id or mask the form itself by passing in true.
+     * @type Mixed
+     */
+    waitMsgTarget : false,
+    
+     
+    
+    /**
+     * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
+     * element by passing it or its id or mask the form itself by passing in true.
+     * @type Mixed
+     */
+    
+    getAutoCreate : function(){
+        
+        var cfg = {
+            tag: 'form',
+            method : this.method || 'POST',
+            id : this.id || Roo.id(),
+            cls : ''
+        }
+        if (this.parent().xtype.match(/^Nav/)) {
+            cfg.cls = 'navbar-form navbar-' + this.align;
+            
+        }
+        
+        if (this.labelAlign == 'left' ) {
+            cfg.cls += ' form-horizontal';
+        }
+        
+        
+        return cfg;
+    },
+    initEvents : function()
+    {
+        this.el.on('submit', this.onSubmit, this);
+        this.el.on('keypress', function(e) {
+            if (e.getCharCode() != 13) {
+                return true;
+            }
+            e.preventDefault();
+            return false;
+        });
+        
+    },
+    // private
+    onSubmit : function(e){
+        e.stopEvent();
+    },
+    
+     /**
+     * Returns true if client-side validation on the form is successful.
+     * @return Boolean
+     */
+    isValid : function(){
+        var items = this.getItems();
+        var valid = true;
+        items.each(function(f){
+           if(!f.validate()){
+               valid = false;
+               
+           }
+        });
+        return valid;
+    },
+    /**
+     * Returns true if any fields in this form have changed since their original load.
+     * @return Boolean
+     */
+    isDirty : function(){
+        var dirty = false;
+        var items = this.getItems();
+        items.each(function(f){
+           if(f.isDirty()){
+               dirty = true;
+               return false;
+           }
+           return true;
+        });
+        return dirty;
+    },
+     /**
+     * Performs a predefined action (submit or load) or custom actions you define on this form.
+     * @param {String} actionName The name of the action type
+     * @param {Object} options (optional) The options to pass to the action.  All of the config options listed
+     * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
+     * accept other config options):
+     * <pre>
+Property          Type             Description
+----------------  ---------------  ----------------------------------------------------------------------------------
+url               String           The url for the action (defaults to the form's url)
+method            String           The form method to use (defaults to the form's method, or POST if not defined)
+params            String/Object    The params to pass (defaults to the form's baseParams, or none if not defined)
+clientValidation  Boolean          Applies to submit only.  Pass true to call form.isValid() prior to posting to
+                                   validate the form on the client (defaults to false)
+     * </pre>
+     * @return {BasicForm} this
+     */
+    doAction : function(action, options){
+        if(typeof action == 'string'){
+            action = new Roo.form.Action.ACTION_TYPES[action](this, options);
+        }
+        if(this.fireEvent('beforeaction', this, action) !== false){
+            this.beforeAction(action);
+            action.run.defer(100, action);
+        }
+        return this;
+    },
+    
+    // private
+    beforeAction : function(action){
+        var o = action.options;
+        
+        // not really supported yet.. ??
+        
+        //if(this.waitMsgTarget === true){
+            this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
+        //}else if(this.waitMsgTarget){
+        //    this.waitMsgTarget = Roo.get(this.waitMsgTarget);
+        //    this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
+        //}else {
+        //    Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
        // }
          
     },
@@ -5711,6 +6316,7 @@ Roo.form.VTypes = function(){
  * @cfg {Number} labelWidth set the width of label (0-12)
  * @cfg {String} labelAlign (top|left)
  * @cfg {Boolean} readOnly Specifies that the field should be read-only
+ * @cfg {String} align (left|center|right) Default left
  * 
  * 
  * @constructor
@@ -5883,6 +6489,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
     labelWidth : 2,
     labelAlign : false,
     readOnly : false,
+    align : false,
     
     parentLabelAlign : function()
     {
@@ -5919,6 +6526,10 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             
         };
         
+        if(this.align){
+            input.style = (typeof(input.style) == 'undefined') ? ('text-align:' + this.align) : (input.style + 'text-align:' + this.align);
+        }
+        
         if(this.maxLength && this.maxLength != Number.MAX_VALUE){
             input.maxLength = this.maxLength;
         }
@@ -9107,6 +9718,7 @@ Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
  * @extends Roo.bootstrap.TriggerField
  * A combobox control with support for autocomplete, remote-loading, paging and many other features.
  * @cfg {Boolean} append (true|false) default false
+ * @cfg {Boolean} autoFocus (true|false) auto focus the first item, default true
  * @constructor
  * Create a new ComboBox.
  * @param {Object} config Configuration options
@@ -9361,6 +9973,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     hasQuery: false,
     append: false,
     loadNext: false,
+    autoFocus : true,
     item: [],
     
     // element that contains real text value.. (when hidden is used..)
@@ -9532,8 +10145,15 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             },
 
             "enter" : function(e){
-                this.onViewClick();
+//                this.onViewClick();
                 //return true;
+                this.collapse();
+                
+                if(this.fireEvent("specialkey", this, e)){
+                    this.onViewClick(false);
+                }
+                
+                return true;
             },
 
             "esc" : function(e){
@@ -9691,11 +10311,13 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                 if(this.editable){
                     this.inputEl().dom.select();
                 }
-                if(!this.selectByValue(this.value, true)){
+                if(!this.selectByValue(this.value, true) && this.autoFocus){
                     this.select(0, true);
                 }
             }else{
-                this.selectNext();
+                if(this.autoFocus){
+                    this.selectNext();
+                }
                 if(this.typeAhead && this.lastKey != Roo.EventObject.BACKSPACE && this.lastKey != Roo.EventObject.DELETE){
                     this.taTask.delay(this.typeAheadDelay);
                 }
@@ -10081,7 +10703,12 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                     }
                     
                     this.store.load(options);
-                    this.expand();
+                    /*
+                     *  this code will make the page width larger, at the beginning, the list not align correctly, 
+                     *  we should expand the list on onLoad
+                     *  so command out it
+                     */
+//                    this.expand();
                 }
             }else{
                 this.selectedIndex = -1;
@@ -11363,7 +11990,7 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
                     cn: [
                         {
                             tag: "img",
-                            src: rootURL + '/roojs1/images/ux/lightbox/loading.gif'
+                            src: Roo.rootURL + '/images/ux/lightbox/loading.gif' 
                         },
                         {
                             tag: "span",
@@ -11505,7 +12132,9 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
         var format = this.format;
         
         var setCellClass = function(cal, cell){
-            
+            cell.row = 0;
+            cell.events = [];
+            cell.more = [];
             //Roo.log('set Cell Class');
             cell.title = "";
             var t = d.getTime();
@@ -11680,6 +12309,13 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
         var crow = false;
         var rows = [];
         for(var i =0; i < cells.length; i++) {
+            
+            cells[i].row = cells[0].row;
+            
+            if(i == 0){
+                cells[i].row = cells[i].row + 1;
+            }
+            
             if (!crow) {
                 crow = {
                     start : cells[i],
@@ -11705,11 +12341,8 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
         ev.els = [];
         ev.rows = rows;
         ev.cells = cells;
-        ev.rendered = false;
-//        for (var i = 0; i < cells.length;i++) {
-//            cells[i].rows = Math.max(cells[i].rows || 0 , ev.row + 1 );
-//            
-//        }
+        
+        cells[0].events.push(ev);
         
         this.calevents.push(ev);
     },
@@ -11721,7 +12354,8 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
         }
         
         Roo.each(this.cells.elements, function(c){
-            c.rows = [];
+            c.row = 0;
+            c.events = [];
             c.more = [];
         });
         
@@ -11741,50 +12375,39 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
     
     renderEvents: function()
     {   
-        // first make sure there is enough space..
-        this.cells.each(function(c) {
-            c.rows = [];
-            c.more = [];
-        });
+        var _this = this;
         
-        for (var e = 0; e < this.calevents.length; e++) {
+        this.cells.each(function(c) {
             
-            var ev = this.calevents[e];
-            var cells = ev.cells;
-            var rows = ev.rows;
+            if(c.row < 5){
+                return;
+            }
             
-            for(var i = 0; i < cells.length; i++){
-                
-                var cbox = this.cells.item(this.cells.indexOf(cells[i]));
-                
-                if(cells.length < 2 && cbox.rows.length > 3){
-                    cbox.more.push(ev);
-                    continue;
-                }
-                
-                cbox.rows.push(ev);
+            var ev = c.events;
+            
+            var r = 4;
+            if(c.row != c.events.length){
+                r = 4 - (4 - (c.row - c.events.length));
             }
-        }
-        
-        var _this = this;
-        
+            
+            c.events = ev.slice(0, r);
+            c.more = ev.slice(r);
+            
+            if(c.more.length && c.more.length == 1){
+                c.events.push(c.more.pop());
+            }
+            
+            c.row = (c.row - ev.length) + c.events.length + ((c.more.length) ? 1 : 0);
+            
+        });
+            
         this.cells.each(function(c) {
-            if(c.more.length && c.more.length == 1){
-                c.rows.push(c.more.pop());
-            }
             
-            var r = (c.more.length) ? c.rows.length + 1 : c.rows.length;
-            c.select('.fc-day-content div',true).first().setHeight(Math.max(34, r * 20));
+            c.select('.fc-day-content div',true).first().setHeight(Math.max(34, c.row * 20));
             
             
-            for (var e = 0; e < c.rows.length; e++){
-                var ev = c.rows[e];
-                
-                if(ev.rendered){
-                    continue;
-                }
-                
-                var cells = ev.cells;
+            for (var e = 0; e < c.events.length; e++){
+                var ev = c.events[e];
                 var rows = ev.rows;
                 
                 for(var i = 0; i < rows.length; i++) {
@@ -11835,7 +12458,8 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
                     var sbox = rows[i].start.select('.fc-day-content',true).first().getBox();
                     var ebox = rows[i].end.select('.fc-day-content',true).first().getBox();
 
-                    cg.setXY([sbox.x +2, sbox.y +(e * 20)]);    
+                    var r = (c.more.length) ? 1 : 0;
+                    cg.setXY([sbox.x +2, sbox.y + ((c.row - c.events.length - r + e) * 20)]);    
                     cg.setWidth(ebox.right - sbox.x -2);
 
                     cg.on('mouseenter' ,_this.onEventEnter, _this, ev);
@@ -11844,7 +12468,6 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
 
                     ev.els.push(cg);
                     
-                    ev.rendered = true;
                 }
                 
             }
@@ -11882,7 +12505,7 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
                 var sbox = c.select('.fc-day-content',true).first().getBox();
                 var ebox = c.select('.fc-day-content',true).first().getBox();
                 //Roo.log(cg);
-                cg.setXY([sbox.x +2, sbox.y +(c.rows.length * 20)]);    
+                cg.setXY([sbox.x +2, sbox.y +((c.row - 1) * 20)]);    
                 cg.setWidth(ebox.right - sbox.x -2);
 
                 cg.on('click', _this.onMoreEventClick, _this, c.more);
@@ -13300,7 +13923,7 @@ Roo.apply(Roo.bootstrap.DateField,  {
             {
                 tag: 'th',
                 cls: 'prev',
-                html: '<i class="icon-arrow-left"/>'
+                html: '<i class="fa fa-arrow-left"/>'
             },
             {
                 tag: 'th',
@@ -13310,7 +13933,7 @@ Roo.apply(Roo.bootstrap.DateField,  {
             {
                 tag: 'th',
                 cls: 'next',
-                html: '<i class="icon-arrow-right"/>'
+                html: '<i class="fa fa-arrow-right"/>'
             }
 
             ]
@@ -13751,23 +14374,46 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
     
     place: function()
     {   
-        this.picker().removeClass(['bottom', 'top']);
+        this.picker().removeClass(['bottom-left', 'bottom-right', 'top-left', 'top-right']);
         
-        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){
-            /*
-             * place to the top of element!
-             *
-             */
-            
-            this.picker().addClass('top');
-            this.picker().setTop(0 - this.picker().getHeight()).setLeft(this.inputEl().getLeft() - this.el.getLeft());
-            
-            return;
+        var cls = ['bottom'];
+        
+        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){ // top
+            cls.pop();
+            cls.push('top');
         }
         
-        this.picker().addClass('bottom');
+        cls.push('right');
+        
+        if((Roo.lib.Dom.getViewWidth() + Roo.get(document.body).getScroll().left) - (this.inputEl().getLeft() + this.picker().getWidth()) < 0){ // left
+            cls.pop();
+            cls.push('left');
+        }
+        
+        this.picker().addClass(cls.join('-'));
+        
+        var _this = this;
+        
+        Roo.each(cls, function(c){
+            if(c == 'bottom'){
+                _this.picker().setTop(_this.inputEl().getHeight());
+                return;
+            }
+            if(c == 'top'){
+                _this.picker().setTop(0 - _this.picker().getHeight());
+                return;
+            }
+            
+            if(c == 'left'){
+                _this.picker().setLeft(_this.inputEl().getLeft() + _this.inputEl().getWidth() - _this.el.getLeft() - _this.picker().getWidth());
+                return;
+            }
+            if(c == 'right'){
+                _this.picker().setLeft(_this.inputEl().getLeft() - _this.el.getLeft());
+                return;
+            }
+        });
         
-        this.picker().setTop(this.inputEl().getHeight()).setLeft(this.inputEl().getLeft() - this.el.getLeft());
     },
   
     onFocus : function()
@@ -13960,230 +14606,14 @@ Roo.bootstrap.CheckBox = function(config){
         });
 };
 
-Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
-    
-    inputType: 'checkbox',
-    inputValue: 1,
-    valueOff: 0,
-    boxLabel: false,
-    checked: false,
-    weight : false,
-    
-    getAutoCreate : function()
-    {
-        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
-        
-        var id = Roo.id();
-        
-        var cfg = {};
-        
-        cfg.cls = 'form-group checkbox' //input-group
-        
-        
-        
-        
-        var input =  {
-            tag: 'input',
-            id : id,
-            type : this.inputType,
-            value : (!this.checked) ? this.valueOff : this.inputValue,
-            cls : 'roo-checkbox', //'form-box',
-            placeholder : this.placeholder || ''
-            
-        };
-        
-        if (this.weight) { // Validity check?
-            cfg.cls += " checkbox-" + this.weight;
-        }
-        
-        if (this.disabled) {
-            input.disabled=true;
-        }
-        
-        if(this.checked){
-            input.checked = this.checked;
-        }
-        
-        if (this.name) {
-            input.name = this.name;
-        }
-        
-        if (this.size) {
-            input.cls += ' input-' + this.size;
-        }
-        
-        var settings=this;
-        ['xs','sm','md','lg'].map(function(size){
-            if (settings[size]) {
-                cfg.cls += ' col-' + size + '-' + settings[size];
-            }
-        });
-        
-       
-        
-        var inputblock = input;
-        
-        
-        
-        
-        if (this.before || this.after) {
-            
-            inputblock = {
-                cls : 'input-group',
-                cn :  [] 
-            };
-            if (this.before) {
-                inputblock.cn.push({
-                    tag :'span',
-                    cls : 'input-group-addon',
-                    html : this.before
-                });
-            }
-            inputblock.cn.push(input);
-            if (this.after) {
-                inputblock.cn.push({
-                    tag :'span',
-                    cls : 'input-group-addon',
-                    html : this.after
-                });
-            }
-            
-        };
-        
-        if (align ==='left' && this.fieldLabel.length) {
-                Roo.log("left and has label");
-                cfg.cn = [
-                    
-                    {
-                        tag: 'label',
-                        'for' :  id,
-                        cls : 'control-label col-md-' + this.labelWidth,
-                        html : this.fieldLabel
-                        
-                    },
-                    {
-                        cls : "col-md-" + (12 - this.labelWidth), 
-                        cn: [
-                            inputblock
-                        ]
-                    }
-                    
-                ];
-        } else if ( this.fieldLabel.length) {
-                Roo.log(" label");
-                cfg.cn = [
-                   
-                    {
-                        tag: this.boxLabel ? 'span' : 'label',
-                        'for': id,
-                        cls: 'control-label box-input-label',
-                        //cls : 'input-group-addon',
-                        html : this.fieldLabel
-                        
-                    },
-                    
-                    inputblock
-                    
-                ];
-
-        } else {
-            
-                Roo.log(" no label && no align");
-                cfg.cn = [  inputblock ] ;
-                
-                
-        };
-         if(this.boxLabel){
-            cfg.cn.push( {
-                tag: 'label',
-                'for': id,
-                cls: 'box-label',
-                html: this.boxLabel
-                
-            });
-        }
-        
-        
-       
-        return cfg;
-        
-    },
-    
-    /**
-     * return the real input element.
-     */
-    inputEl: function ()
-    {
-        return this.el.select('input.roo-checkbox',true).first();
-    },
-    
-    label: function()
-    {
-        return this.el.select('label.control-label',true).first();
-    },
-    
-    initEvents : function()
-    {
-//        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
-        
-        this.inputEl().on('click', this.onClick,  this);
-        
-    },
-    
-    onClick : function()
-    {   
-        this.setChecked(!this.checked);
-    },
-    
-    setChecked : function(state,suppressEvent)
-    {
-        this.checked = state;
-        
-        this.inputEl().dom.checked = state;
-        
-        if(suppressEvent !== true){
-            this.fireEvent('check', this, state);
-        }
-        
-        this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
-        
-    },
-    
-    setValue : function(v,suppressEvent)
-    {
-        this.setChecked(((typeof(v) == 'undefined') ? this.checked : (String(v) === String(this.inputValue))), suppressEvent);
-    }
-    
-});
-
-/*
- * - LGPL
- *
- * Radio
- * 
- */
-
-/**
- * @class Roo.bootstrap.Radio
- * @extends Roo.bootstrap.CheckBox
- * Bootstrap Radio class
-
- * @constructor
- * Create a new Radio
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.Radio = function(config){
-    Roo.bootstrap.Radio.superclass.constructor.call(this, config);
-   
-};
-
-Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
+Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
     
-    inputType: 'radio',
-    inputValue: '',
-    valueOff: '',
+    inputType: 'checkbox',
+    inputValue: 1,
+    valueOff: 0,
+    boxLabel: false,
+    checked: false,
+    weight : false,
     
     getAutoCreate : function()
     {
@@ -14193,20 +14623,25 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
         
         var cfg = {};
         
-        cfg.cls = 'form-group radio' //input-group
+        cfg.cls = 'form-group checkbox' //input-group
+        
+        
+        
         
         var input =  {
             tag: 'input',
             id : id,
             type : this.inputType,
             value : (!this.checked) ? this.valueOff : this.inputValue,
-            cls : 'roo-radio',
+            cls : 'roo-checkbox', //'form-box',
             placeholder : this.placeholder || ''
             
         };
-          if (this.weight) { // Validity check?
-            cfg.cls += " radio-" + this.weight;
+        
+        if (this.weight) { // Validity check?
+            cfg.cls += " checkbox-" + this.weight;
         }
+        
         if (this.disabled) {
             input.disabled=true;
         }
@@ -14230,8 +14665,13 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
             }
         });
         
+       
+        
         var inputblock = input;
         
+        
+        
+        
         if (this.before || this.after) {
             
             inputblock = {
@@ -14277,10 +14717,10 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
                 ];
         } else if ( this.fieldLabel.length) {
                 Roo.log(" label");
-                 cfg.cn = [
+                cfg.cn = [
                    
                     {
-                        tag: 'label',
+                        tag: this.boxLabel ? 'span' : 'label',
                         'for': id,
                         cls: 'control-label box-input-label',
                         //cls : 'input-group-addon',
@@ -14294,1906 +14734,1617 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
 
         } else {
             
-                   Roo.log(" no label && no align");
-                cfg.cn = [
-                    
-                        inputblock
-                    
-                ];
+                Roo.log(" no label && no align");
+                cfg.cn = [  inputblock ] ;
                 
                 
         };
-        
-        if(this.boxLabel){
-            cfg.cn.push({
+         if(this.boxLabel){
+            cfg.cn.push( {
                 tag: 'label',
                 'for': id,
                 cls: 'box-label',
                 html: this.boxLabel
-            })
+                
+            });
         }
         
+        
+       
         return cfg;
         
     },
-    inputEl: function ()
-    {
-        return this.el.select('input.roo-radio',true).first();
-    },
-    onClick : function()
-    {   
-        this.setChecked(true);
-    },
     
-    setChecked : function(state,suppressEvent)
+    /**
+     * return the real input element.
+     */
+    inputEl: function ()
     {
-        if(state){
-            Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
-                v.dom.checked = false;
-            });
-        }
-        
-        this.checked = state;
-        this.inputEl().dom.checked = state;
-        
-        if(suppressEvent !== true){
-            this.fireEvent('check', this, state);
-        }
-        
-        this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
-        
+        return this.el.select('input.roo-checkbox',true).first();
     },
     
-    getGroupValue : function()
+    label: function()
     {
-        var value = ''
-        Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
-            if(v.dom.checked == true){
-                value = v.dom.value;
-            }
-        });
-        
-        return value;
+        return this.el.select('label.control-label',true).first();
     },
     
-    /**
-     * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
-     * @return {Mixed} value The field value
-     */
-    getValue : function(){
-        return this.getGroupValue();
-    }
-    
-});
-
-//<script type="text/javascript">
-
-/*
- * Based  Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- * LGPL
- *
- */
-/**
- * @class Roo.HtmlEditorCore
- * @extends Roo.Component
- * Provides a the editing component for the HTML editors in Roo. (bootstrap and Roo.form)
- *
- * any element that has display set to 'none' can cause problems in Safari and Firefox.<br/><br/>
- */
-
-Roo.HtmlEditorCore = function(config){
-    
-    
-    Roo.HtmlEditorCore.superclass.constructor.call(this, config);
-    this.addEvents({
-        /**
-         * @event initialize
-         * Fires when the editor is fully initialized (including the iframe)
-         * @param {Roo.HtmlEditorCore} this
-         */
-        initialize: true,
-        /**
-         * @event activate
-         * Fires when the editor is first receives the focus. Any insertion must wait
-         * until after this event.
-         * @param {Roo.HtmlEditorCore} this
-         */
-        activate: true,
-         /**
-         * @event beforesync
-         * Fires before the textarea is updated with content from the editor iframe. Return false
-         * to cancel the sync.
-         * @param {Roo.HtmlEditorCore} this
-         * @param {String} html
-         */
-        beforesync: true,
-         /**
-         * @event beforepush
-         * Fires before the iframe editor is updated with content from the textarea. Return false
-         * to cancel the push.
-         * @param {Roo.HtmlEditorCore} this
-         * @param {String} html
-         */
-        beforepush: true,
-         /**
-         * @event sync
-         * Fires when the textarea is updated with content from the editor iframe.
-         * @param {Roo.HtmlEditorCore} this
-         * @param {String} html
-         */
-        sync: true,
-         /**
-         * @event push
-         * Fires when the iframe editor is updated with content from the textarea.
-         * @param {Roo.HtmlEditorCore} this
-         * @param {String} html
-         */
-        push: true,
-        
-        /**
-         * @event editorevent
-         * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
-         * @param {Roo.HtmlEditorCore} this
-         */
-        editorevent: true
-    });
-     
-};
-
-
-Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
-
-
-     /**
-     * @cfg {Roo.form.HtmlEditor|Roo.bootstrap.HtmlEditor} the owner field 
-     */
-    
-    owner : false,
-    
-     /**
-     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
-     *                        Roo.resizable.
-     */
-    resizable : false,
-     /**
-     * @cfg {Number} height (in pixels)
-     */   
-    height: 300,
-   /**
-     * @cfg {Number} width (in pixels)
-     */   
-    width: 500,
-    
-    /**
-     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
-     * 
-     */
-    stylesheets: false,
-    
-    // id of frame..
-    frameId: false,
-    
-    // private properties
-    validationEvent : false,
-    deferHeight: true,
-    initialized : false,
-    activated : false,
-    sourceEditMode : false,
-    onFocus : Roo.emptyFn,
-    iframePad:3,
-    hideMode:'offsets',
-    
-    clearUp: true,
-    
-     
-    
-
-    /**
-     * Protected method that will not generally be called directly. It
-     * is called when the editor initializes the iframe with HTML contents. Override this method if you
-     * want to change the initialization markup of the iframe (e.g. to add stylesheets).
-     */
-    getDocMarkup : function(){
-        // body styles..
-        var st = '';
-        Roo.log(this.stylesheets);
-        
-        // inherit styels from page...?? 
-        if (this.stylesheets === false) {
-            
-            Roo.get(document.head).select('style').each(function(node) {
-                st += node.dom.outerHTML || new XMLSerializer().serializeToString(node.dom);
-            });
-            
-            Roo.get(document.head).select('link').each(function(node) { 
-                st += node.dom.outerHTML || new XMLSerializer().serializeToString(node.dom);
-            });
-            
-        } else if (!this.stylesheets.length) {
-                // simple..
-                st = '<style type="text/css">' +
-                    'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
-                   '</style>';
-        } else {
-            Roo.each(this.stylesheets, function(s) {
-                st += '<link rel="stylesheet" type="text/css" href="' + s +'" />'
-            });
-            
+    initEvents : function()
+    {
+//        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
+        
+        this.inputEl().on('click', this.onClick,  this);
+        
+    },
+    
+    onClick : function()
+    {   
+        this.setChecked(!this.checked);
+    },
+    
+    setChecked : function(state,suppressEvent)
+    {
+        this.checked = state;
+        
+        this.inputEl().dom.checked = state;
+        
+        if(suppressEvent !== true){
+            this.fireEvent('check', this, state);
         }
         
-        st +=  '<style type="text/css">' +
-            'IMG { cursor: pointer } ' +
-        '</style>';
-
+        this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
         
-        return '<html><head>' + st  +
-            //<style type="text/css">' +
-            //'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
-            //'</style>' +
-            ' </head><body class="roo-htmleditor-body"></body></html>';
     },
+    
+    setValue : function(v,suppressEvent)
+    {
+        this.setChecked(((typeof(v) == 'undefined') ? this.checked : (String(v) === String(this.inputValue))), suppressEvent);
+    }
+    
+});
 
-    // private
-    onRender : function(ct, position)
+/*
+ * - LGPL
+ *
+ * Radio
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.Radio
+ * @extends Roo.bootstrap.CheckBox
+ * Bootstrap Radio class
+
+ * @constructor
+ * Create a new Radio
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Radio = function(config){
+    Roo.bootstrap.Radio.superclass.constructor.call(this, config);
+   
+};
+
+Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
+    
+    inputType: 'radio',
+    inputValue: '',
+    valueOff: '',
+    
+    getAutoCreate : function()
     {
-        var _t = this;
-        //Roo.HtmlEditorCore.superclass.onRender.call(this, ct, position);
-        this.el = this.owner.inputEl ? this.owner.inputEl() : this.owner.el;
-        
+        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
         
-        this.el.dom.style.border = '0 none';
-        this.el.dom.setAttribute('tabIndex', -1);
-        this.el.addClass('x-hidden hide');
+        var id = Roo.id();
         
+        var cfg = {};
         
+        cfg.cls = 'form-group radio' //input-group
         
-        if(Roo.isIE){ // fix IE 1px bogus margin
-            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
+        var input =  {
+            tag: 'input',
+            id : id,
+            type : this.inputType,
+            value : (!this.checked) ? this.valueOff : this.inputValue,
+            cls : 'roo-radio',
+            placeholder : this.placeholder || ''
+            
+        };
+          if (this.weight) { // Validity check?
+            cfg.cls += " radio-" + this.weight;
+        }
+        if (this.disabled) {
+            input.disabled=true;
         }
-       
         
-        this.frameId = Roo.id();
+        if(this.checked){
+            input.checked = this.checked;
+        }
         
-         
+        if (this.name) {
+            input.name = this.name;
+        }
         
-        var iframe = this.owner.wrap.createChild({
-            tag: 'iframe',
-            cls: 'form-control', // bootstrap..
-            id: this.frameId,
-            name: this.frameId,
-            frameBorder : 'no',
-            'src' : Roo.SSL_SECURE_URL ? Roo.SSL_SECURE_URL  :  "javascript:false"
-        }, this.el
-        );
+        if (this.size) {
+            input.cls += ' input-' + this.size;
+        }
         
+        var settings=this;
+        ['xs','sm','md','lg'].map(function(size){
+            if (settings[size]) {
+                cfg.cls += ' col-' + size + '-' + settings[size];
+            }
+        });
         
-        this.iframe = iframe.dom;
-
-         this.assignDocWin();
+        var inputblock = input;
         
-        this.doc.designMode = 'on';
-       
-        this.doc.open();
-        this.doc.write(this.getDocMarkup());
-        this.doc.close();
-
+        if (this.before || this.after) {
+            
+            inputblock = {
+                cls : 'input-group',
+                cn :  [] 
+            };
+            if (this.before) {
+                inputblock.cn.push({
+                    tag :'span',
+                    cls : 'input-group-addon',
+                    html : this.before
+                });
+            }
+            inputblock.cn.push(input);
+            if (this.after) {
+                inputblock.cn.push({
+                    tag :'span',
+                    cls : 'input-group-addon',
+                    html : this.after
+                });
+            }
+            
+        };
         
-        var task = { // must defer to wait for browser to be ready
-            run : function(){
-                //console.log("run task?" + this.doc.readyState);
-                this.assignDocWin();
-                if(this.doc.body || this.doc.readyState == 'complete'){
-                    try {
-                        this.doc.designMode="on";
-                    } catch (e) {
-                        return;
+        if (align ==='left' && this.fieldLabel.length) {
+                Roo.log("left and has label");
+                cfg.cn = [
+                    
+                    {
+                        tag: 'label',
+                        'for' :  id,
+                        cls : 'control-label col-md-' + this.labelWidth,
+                        html : this.fieldLabel
+                        
+                    },
+                    {
+                        cls : "col-md-" + (12 - this.labelWidth), 
+                        cn: [
+                            inputblock
+                        ]
                     }
-                    Roo.TaskMgr.stop(task);
-                    this.initEditor.defer(10, this);
-                }
-            },
-            interval : 10,
-            duration: 10000,
-            scope: this
-        };
-        Roo.TaskMgr.start(task);
+                    
+                ];
+        } else if ( this.fieldLabel.length) {
+                Roo.log(" label");
+                 cfg.cn = [
+                   
+                    {
+                        tag: 'label',
+                        'for': id,
+                        cls: 'control-label box-input-label',
+                        //cls : 'input-group-addon',
+                        html : this.fieldLabel
+                        
+                    },
+                    
+                    inputblock
+                    
+                ];
 
+        } else {
+            
+                   Roo.log(" no label && no align");
+                cfg.cn = [
+                    
+                        inputblock
+                    
+                ];
+                
+                
+        };
+        
+        if(this.boxLabel){
+            cfg.cn.push({
+                tag: 'label',
+                'for': id,
+                cls: 'box-label',
+                html: this.boxLabel
+            })
+        }
+        
+        return cfg;
+        
+    },
+    inputEl: function ()
+    {
+        return this.el.select('input.roo-radio',true).first();
+    },
+    onClick : function()
+    {   
+        this.setChecked(true);
+    },
+    
+    setChecked : function(state,suppressEvent)
+    {
+        if(state){
+            Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
+                v.dom.checked = false;
+            });
+        }
+        
+        this.checked = state;
+        this.inputEl().dom.checked = state;
+        
+        if(suppressEvent !== true){
+            this.fireEvent('check', this, state);
+        }
+        
+        this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
         
-         
     },
-
-    // private
-    onResize : function(w, h)
+    
+    getGroupValue : function()
     {
-         Roo.log('resize: ' +w + ',' + h );
-        //Roo.HtmlEditorCore.superclass.onResize.apply(this, arguments);
-        if(!this.iframe){
-            return;
-        }
-        if(typeof w == 'number'){
-            
-            this.iframe.style.width = w + 'px';
-        }
-        if(typeof h == 'number'){
-            
-            this.iframe.style.height = h + 'px';
-            if(this.doc){
-                (this.doc.body || this.doc.documentElement).style.height = (h - (this.iframePad*2)) + 'px';
+        var value = ''
+        Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
+            if(v.dom.checked == true){
+                value = v.dom.value;
             }
-        }
+        });
         
+        return value;
     },
-
+    
     /**
-     * Toggles the editor between standard and source edit mode.
-     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
+     * @return {Mixed} value The field value
      */
-    toggleSourceEdit : function(sourceEditMode){
-        
-        this.sourceEditMode = sourceEditMode === true;
-        
-        if(this.sourceEditMode){
+    getValue : function(){
+        return this.getGroupValue();
+    }
+    
+});
+
  
-            Roo.get(this.iframe).addClass(['x-hidden','hide']);     //FIXME - what's the BS styles for these
-            
-        }else{
-            Roo.get(this.iframe).removeClass(['x-hidden','hide']);
-            //this.iframe.className = '';
-            this.deferFocus();
-        }
-        //this.setSize(this.owner.wrap.getSize());
-        //this.fireEvent('editmodechange', this, this.sourceEditMode);
-    },
+//<script type="text/javascript">
+
+/*
+ * Based  Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ * LGPL
+ *
+ */
+/**
+ * @class Roo.HtmlEditorCore
+ * @extends Roo.Component
+ * Provides a the editing component for the HTML editors in Roo. (bootstrap and Roo.form)
+ *
+ * any element that has display set to 'none' can cause problems in Safari and Firefox.<br/><br/>
+ */
 
+Roo.HtmlEditorCore = function(config){
     
-  
+    
+    Roo.HtmlEditorCore.superclass.constructor.call(this, config);
+    this.addEvents({
+        /**
+         * @event initialize
+         * Fires when the editor is fully initialized (including the iframe)
+         * @param {Roo.HtmlEditorCore} this
+         */
+        initialize: true,
+        /**
+         * @event activate
+         * Fires when the editor is first receives the focus. Any insertion must wait
+         * until after this event.
+         * @param {Roo.HtmlEditorCore} this
+         */
+        activate: true,
+         /**
+         * @event beforesync
+         * Fires before the textarea is updated with content from the editor iframe. Return false
+         * to cancel the sync.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        beforesync: true,
+         /**
+         * @event beforepush
+         * Fires before the iframe editor is updated with content from the textarea. Return false
+         * to cancel the push.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        beforepush: true,
+         /**
+         * @event sync
+         * Fires when the textarea is updated with content from the editor iframe.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        sync: true,
+         /**
+         * @event push
+         * Fires when the iframe editor is updated with content from the textarea.
+         * @param {Roo.HtmlEditorCore} this
+         * @param {String} html
+         */
+        push: true,
+        
+        /**
+         * @event editorevent
+         * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
+         * @param {Roo.HtmlEditorCore} this
+         */
+        editorevent: true
+    });
+     
+};
 
-    /**
-     * Protected method that will not generally be called directly. If you need/want
-     * custom HTML cleanup, this is the method you should override.
-     * @param {String} html The HTML to be cleaned
-     * return {String} The cleaned HTML
-     */
-    cleanHtml : function(html){
-        html = String(html);
-        if(html.length > 5){
-            if(Roo.isSafari){ // strip safari nonsense
-                html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
-            }
-        }
-        if(html == '&nbsp;'){
-            html = '';
-        }
-        return html;
-    },
 
-    /**
-     * HTML Editor -> Textarea
-     * Protected method that will not generally be called directly. Syncs the contents
-     * of the editor iframe with the textarea.
-     */
-    syncValue : function(){
-        if(this.initialized){
-            var bd = (this.doc.body || this.doc.documentElement);
-            //this.cleanUpPaste(); -- this is done else where and causes havoc..
-            var html = bd.innerHTML;
-            if(Roo.isSafari){
-                var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
-                var m = bs ? bs.match(/text-align:(.*?);/i) : false;
-                if(m && m[1]){
-                    html = '<div style="'+m[0]+'">' + html + '</div>';
-                }
-            }
-            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 (
-                    (cc >= 0x4E00 && cc < 0xA000 ) ||
-                    (cc >= 0x3400 && cc < 0x4E00 ) ||
-                    (cc >= 0xf900 && cc < 0xfb00 )
-                ) {
-                        return b;
-                }
-                return "&#"+cc+";" 
-            });
-            if(this.owner.fireEvent('beforesync', this, html) !== false){
-                this.el.dom.value = html;
-                this.owner.fireEvent('sync', this, html);
-            }
-        }
-    },
+Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
+
+     /**
+     * @cfg {Roo.form.HtmlEditor|Roo.bootstrap.HtmlEditor} the owner field 
+     */
+    
+    owner : false,
+    
+     /**
+     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
+     *                        Roo.resizable.
+     */
+    resizable : false,
+     /**
+     * @cfg {Number} height (in pixels)
+     */   
+    height: 300,
+   /**
+     * @cfg {Number} width (in pixels)
+     */   
+    width: 500,
+    
     /**
-     * Protected method that will not generally be called directly. Pushes the value of the textarea
-     * into the iframe editor.
+     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
+     * 
      */
-    pushValue : function(){
-        if(this.initialized){
-            var v = this.el.dom.value.trim();
-            
-//            if(v.length < 1){
-//                v = '&#160;';
-//            }
-            
-            if(this.owner.fireEvent('beforepush', this, v) !== false){
-                var d = (this.doc.body || this.doc.documentElement);
-                d.innerHTML = v;
-                this.cleanUpPaste();
-                this.el.dom.value = d.innerHTML;
-                this.owner.fireEvent('push', this, v);
-            }
-        }
-    },
-
-    // private
-    deferFocus : function(){
-        this.focus.defer(10, this);
-    },
-
-    // doc'ed in Field
-    focus : function(){
-        if(this.win && !this.sourceEditMode){
-            this.win.focus();
-        }else{
-            this.el.focus();
-        }
-    },
+    stylesheets: false,
+    
+    // id of frame..
+    frameId: false,
+    
+    // private properties
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
+    sourceEditMode : false,
+    onFocus : Roo.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
     
-    assignDocWin: function()
-    {
-        var iframe = this.iframe;
+    clearUp: true,
+    
+     
+    
+
+    /**
+     * Protected method that will not generally be called directly. It
+     * is called when the editor initializes the iframe with HTML contents. Override this method if you
+     * want to change the initialization markup of the iframe (e.g. to add stylesheets).
+     */
+    getDocMarkup : function(){
+        // body styles..
+        var st = '';
+        Roo.log(this.stylesheets);
         
-         if(Roo.isIE){
-            this.doc = iframe.contentWindow.document;
-            this.win = iframe.contentWindow;
+        // inherit styels from page...?? 
+        if (this.stylesheets === false) {
+            
+            Roo.get(document.head).select('style').each(function(node) {
+                st += node.dom.outerHTML || new XMLSerializer().serializeToString(node.dom);
+            });
+            
+            Roo.get(document.head).select('link').each(function(node) { 
+                st += node.dom.outerHTML || new XMLSerializer().serializeToString(node.dom);
+            });
+            
+        } else if (!this.stylesheets.length) {
+                // simple..
+                st = '<style type="text/css">' +
+                    'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
+                   '</style>';
         } else {
-            if (!Roo.get(this.frameId)) {
-                return;
-            }
-            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
-            this.win = Roo.get(this.frameId).dom.contentWindow;
+            Roo.each(this.stylesheets, function(s) {
+                st += '<link rel="stylesheet" type="text/css" href="' + s +'" />'
+            });
+            
         }
-    },
-    
-    // private
-    initEditor : function(){
-        //console.log("INIT EDITOR");
-        this.assignDocWin();
-        
-        
-        
-        this.doc.designMode="on";
-        this.doc.open();
-        this.doc.write(this.getDocMarkup());
-        this.doc.close();
         
-        var dbody = (this.doc.body || this.doc.documentElement);
-        //var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
-        // this copies styles from the containing element into thsi one..
-        // not sure why we need all of this..
-        var ss = this.el.getStyles('font-size', 'background-image', 'background-repeat');
-        ss['background-attachment'] = 'fixed'; // w3c
-        dbody.bgProperties = 'fixed'; // ie
-        Roo.DomHelper.applyStyles(dbody, ss);
-        Roo.EventManager.on(this.doc, {
-            //'mousedown': this.onEditorEvent,
-            'mouseup': this.onEditorEvent,
-            'dblclick': this.onEditorEvent,
-            'click': this.onEditorEvent,
-            'keyup': this.onEditorEvent,
-            buffer:100,
-            scope: this
-        });
-        if(Roo.isGecko){
-            Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
-        }
-        if(Roo.isIE || Roo.isSafari || Roo.isOpera){
-            Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
-        }
-        this.initialized = true;
+        st +=  '<style type="text/css">' +
+            'IMG { cursor: pointer } ' +
+        '</style>';
 
-        this.owner.fireEvent('initialize', this);
-        this.pushValue();
+        
+        return '<html><head>' + st  +
+            //<style type="text/css">' +
+            //'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
+            //'</style>' +
+            ' </head><body class="roo-htmleditor-body"></body></html>';
     },
 
     // private
-    onDestroy : function(){
-        
+    onRender : function(ct, position)
+    {
+        var _t = this;
+        //Roo.HtmlEditorCore.superclass.onRender.call(this, ct, position);
+        this.el = this.owner.inputEl ? this.owner.inputEl() : this.owner.el;
         
         
-        if(this.rendered){
-            
-            //for (var i =0; i < this.toolbars.length;i++) {
-            //    // fixme - ask toolbars for heights?
-            //    this.toolbars[i].onDestroy();
-           // }
-            
-            //this.wrap.dom.innerHTML = '';
-            //this.wrap.remove();
-        }
-    },
-
-    // private
-    onFirstFocus : function(){
+        this.el.dom.style.border = '0 none';
+        this.el.dom.setAttribute('tabIndex', -1);
+        this.el.addClass('x-hidden hide');
         
-        this.assignDocWin();
         
         
-        this.activated = true;
-         
-    
-        if(Roo.isGecko){ // prevent silly gecko errors
-            this.win.focus();
-            var s = this.win.getSelection();
-            if(!s.focusNode || s.focusNode.nodeType != 3){
-                var r = s.getRangeAt(0);
-                r.selectNodeContents((this.doc.body || this.doc.documentElement));
-                r.collapse(true);
-                this.deferFocus();
-            }
-            try{
-                this.execCmd('useCSS', true);
-                this.execCmd('styleWithCSS', false);
-            }catch(e){}
-        }
-        this.owner.fireEvent('activate', this);
-    },
-
-    // private
-    adjustFont: function(btn){
-        var adjust = btn.cmd == 'increasefontsize' ? 1 : -1;
-        //if(Roo.isSafari){ // safari
-        //    adjust *= 2;
-       // }
-        var v = parseInt(this.doc.queryCommandValue('FontSize')|| 3, 10);
-        if(Roo.isSafari){ // safari
-            var sm = { 10 : 1, 13: 2, 16:3, 18:4, 24: 5, 32:6, 48: 7 };
-            v =  (v < 10) ? 10 : v;
-            v =  (v > 48) ? 48 : v;
-            v = typeof(sm[v]) == 'undefined' ? 1 : sm[v];
-            
+        if(Roo.isIE){ // fix IE 1px bogus margin
+            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
         }
+       
         
+        this.frameId = Roo.id();
         
-        v = Math.max(1, v+adjust);
-        
-        this.execCmd('FontSize', v  );
-    },
-
-    onEditorEvent : function(e){
-        this.owner.fireEvent('editorevent', this, e);
-      //  this.updateToolbar();
-        this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
-    },
-
-    insertTag : function(tg)
-    {
-        // could be a bit smarter... -> wrap the current selected tRoo..
-        if (tg.toLowerCase() == 'span' || tg.toLowerCase() == 'code') {
-            
-            range = this.createRange(this.getSelection());
-            var wrappingNode = this.doc.createElement(tg.toLowerCase());
-            wrappingNode.appendChild(range.extractContents());
-            range.insertNode(wrappingNode);
-
-            return;
-            
-            
-            
-        }
-        this.execCmd("formatblock",   tg);
+         
         
-    },
-    
-    insertText : function(txt)
-    {
+        var iframe = this.owner.wrap.createChild({
+            tag: 'iframe',
+            cls: 'form-control', // bootstrap..
+            id: this.frameId,
+            name: this.frameId,
+            frameBorder : 'no',
+            'src' : Roo.SSL_SECURE_URL ? Roo.SSL_SECURE_URL  :  "javascript:false"
+        }, this.el
+        );
         
         
-        var range = this.createRange();
-        range.deleteContents();
-               //alert(Sender.getAttribute('label'));
-               
-        range.insertNode(this.doc.createTextNode(txt));
-    } ,
-    
-     
-
-    /**
-     * Executes a Midas editor command on the editor document and performs necessary focus and
-     * toolbar updates. <b>This should only be called after the editor is initialized.</b>
-     * @param {String} cmd The Midas command
-     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
-     */
-    relayCmd : function(cmd, value){
-        this.win.focus();
-        this.execCmd(cmd, value);
-        this.owner.fireEvent('editorevent', this);
-        //this.updateToolbar();
-        this.owner.deferFocus();
-    },
+        this.iframe = iframe.dom;
 
-    /**
-     * Executes a Midas editor command directly on the editor document.
-     * For visual commands, you should use {@link #relayCmd} instead.
-     * <b>This should only be called after the editor is initialized.</b>
-     * @param {String} cmd The Midas command
-     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
-     */
-    execCmd : function(cmd, value){
-        this.doc.execCommand(cmd, false, value === undefined ? null : value);
-        this.syncValue();
-    },
-   
-    /**
-     * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
-     * to insert tRoo.
-     * @param {String} text | dom node.. 
-     */
-    insertAtCursor : function(text)
-    {
+         this.assignDocWin();
         
+        this.doc.designMode = 'on';
+       
+        this.doc.open();
+        this.doc.write(this.getDocMarkup());
+        this.doc.close();
+
         
+        var task = { // must defer to wait for browser to be ready
+            run : function(){
+                //console.log("run task?" + this.doc.readyState);
+                this.assignDocWin();
+                if(this.doc.body || this.doc.readyState == 'complete'){
+                    try {
+                        this.doc.designMode="on";
+                    } catch (e) {
+                        return;
+                    }
+                    Roo.TaskMgr.stop(task);
+                    this.initEditor.defer(10, this);
+                }
+            },
+            interval : 10,
+            duration: 10000,
+            scope: this
+        };
+        Roo.TaskMgr.start(task);
+
         
-        if(!this.activated){
+         
+    },
+
+    // private
+    onResize : function(w, h)
+    {
+         Roo.log('resize: ' +w + ',' + h );
+        //Roo.HtmlEditorCore.superclass.onResize.apply(this, arguments);
+        if(!this.iframe){
             return;
         }
-        /*
-        if(Roo.isIE){
-            this.win.focus();
-            var r = this.doc.selection.createRange();
-            if(r){
-                r.collapse(true);
-                r.pasteHTML(text);
-                this.syncValue();
-                this.deferFocus();
+        if(typeof w == 'number'){
             
-            }
-            return;
+            this.iframe.style.width = w + 'px';
         }
-        */
-        if(Roo.isGecko || Roo.isOpera || Roo.isSafari){
-            this.win.focus();
-            
-            
-            // from jquery ui (MIT licenced)
-            var range, node;
-            var win = this.win;
-            
-            if (win.getSelection && win.getSelection().getRangeAt) {
-                range = win.getSelection().getRangeAt(0);
-                node = typeof(text) == 'string' ? range.createContextualFragment(text) : text;
-                range.insertNode(node);
-            } else if (win.document.selection && win.document.selection.createRange) {
-                // no firefox support
-                var txt = typeof(text) == 'string' ? text : text.outerHTML;
-                win.document.selection.createRange().pasteHTML(txt);
-            } else {
-                // no firefox support
-                var txt = typeof(text) == 'string' ? text : text.outerHTML;
-                this.execCmd('InsertHTML', txt);
-            } 
-            
-            this.syncValue();
+        if(typeof h == 'number'){
             
-            this.deferFocus();
-        }
-    },
- // private
-    mozKeyPress : function(e){
-        if(e.ctrlKey){
-            var c = e.getCharCode(), cmd;
-          
-            if(c > 0){
-                c = String.fromCharCode(c).toLowerCase();
-                switch(c){
-                    case 'b':
-                        cmd = 'bold';
-                        break;
-                    case 'i':
-                        cmd = 'italic';
-                        break;
-                    
-                    case 'u':
-                        cmd = 'underline';
-                        break;
-                    
-                    case 'v':
-                        this.cleanUpPaste.defer(100, this);
-                        return;
-                        
-                }
-                if(cmd){
-                    this.win.focus();
-                    this.execCmd(cmd);
-                    this.deferFocus();
-                    e.preventDefault();
-                }
-                
+            this.iframe.style.height = h + 'px';
+            if(this.doc){
+                (this.doc.body || this.doc.documentElement).style.height = (h - (this.iframePad*2)) + 'px';
             }
         }
+        
     },
 
-    // private
-    fixKeys : function(){ // load time branching for fastest keydown performance
-        if(Roo.isIE){
-            return function(e){
-                var k = e.getKey(), r;
-                if(k == e.TAB){
-                    e.stopEvent();
-                    r = this.doc.selection.createRange();
-                    if(r){
-                        r.collapse(true);
-                        r.pasteHTML('&#160;&#160;&#160;&#160;');
-                        this.deferFocus();
-                    }
-                    return;
-                }
-                
-                if(k == e.ENTER){
-                    r = this.doc.selection.createRange();
-                    if(r){
-                        var target = r.parentElement();
-                        if(!target || target.tagName.toLowerCase() != 'li'){
-                            e.stopEvent();
-                            r.pasteHTML('<br />');
-                            r.collapse(false);
-                            r.select();
-                        }
-                    }
-                }
-                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
-                
-                
-            };
-        }else if(Roo.isOpera){
-            return function(e){
-                var k = e.getKey();
-                if(k == e.TAB){
-                    e.stopEvent();
-                    this.win.focus();
-                    this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
-                    this.deferFocus();
-                }
-                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
-                
-            };
-        }else if(Roo.isSafari){
-            return function(e){
-                var k = e.getKey();
-                
-                if(k == e.TAB){
-                    e.stopEvent();
-                    this.execCmd('InsertText','\t');
-                    this.deferFocus();
-                    return;
-                }
-               if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
-                
-             };
-        }
-    }(),
-    
-    getAllAncestors: function()
-    {
-        var p = this.getSelectedNode();
-        var a = [];
-        if (!p) {
-            a.push(p); // push blank onto stack..
-            p = this.getParentElement();
-        }
+    /**
+     * Toggles the editor between standard and source edit mode.
+     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     */
+    toggleSourceEdit : function(sourceEditMode){
         
+        this.sourceEditMode = sourceEditMode === true;
         
-        while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
-            a.push(p);
-            p = p.parentNode;
+        if(this.sourceEditMode){
+            Roo.get(this.iframe).addClass(['x-hidden','hide']);     //FIXME - what's the BS styles for these
+            
+        }else{
+            Roo.get(this.iframe).removeClass(['x-hidden','hide']);
+            //this.iframe.className = '';
+            this.deferFocus();
         }
-        a.push(this.doc.body);
-        return a;
+        //this.setSize(this.owner.wrap.getSize());
+        //this.fireEvent('editmodechange', this, this.sourceEditMode);
     },
-    lastSel : false,
-    lastSelNode : false,
-    
+
     
-    getSelection : function() 
-    {
-        this.assignDocWin();
-        return Roo.isIE ? this.doc.selection : this.win.getSelection();
+  
+
+    /**
+     * Protected method that will not generally be called directly. If you need/want
+     * custom HTML cleanup, this is the method you should override.
+     * @param {String} html The HTML to be cleaned
+     * return {String} The cleaned HTML
+     */
+    cleanHtml : function(html){
+        html = String(html);
+        if(html.length > 5){
+            if(Roo.isSafari){ // strip safari nonsense
+                html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
+            }
+        }
+        if(html == '&nbsp;'){
+            html = '';
+        }
+        return html;
     },
-    
-    getSelectedNode: function() 
-    {
-        // this may only work on Gecko!!!
-        
-        // should we cache this!!!!
-        
-        
-        
-         
-        var range = this.createRange(this.getSelection()).cloneRange();
-        
-        if (Roo.isIE) {
-            var parent = range.parentElement();
-            while (true) {
-                var testRange = range.duplicate();
-                testRange.moveToElementText(parent);
-                if (testRange.inRange(range)) {
-                    break;
+
+    /**
+     * HTML Editor -> Textarea
+     * Protected method that will not generally be called directly. Syncs the contents
+     * of the editor iframe with the textarea.
+     */
+    syncValue : function(){
+        if(this.initialized){
+            var bd = (this.doc.body || this.doc.documentElement);
+            //this.cleanUpPaste(); -- this is done else where and causes havoc..
+            var html = bd.innerHTML;
+            if(Roo.isSafari){
+                var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
+                var m = bs ? bs.match(/text-align:(.*?);/i) : false;
+                if(m && m[1]){
+                    html = '<div style="'+m[0]+'">' + html + '</div>';
                 }
-                if ((parent.nodeType != 1) || (parent.tagName.toLowerCase() == 'body')) {
-                    break;
+            }
+            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 (
+                    (cc >= 0x4E00 && cc < 0xA000 ) ||
+                    (cc >= 0x3400 && cc < 0x4E00 ) ||
+                    (cc >= 0xf900 && cc < 0xfb00 )
+                ) {
+                        return b;
                 }
-                parent = parent.parentElement;
+                return "&#"+cc+";" 
+            });
+            if(this.owner.fireEvent('beforesync', this, html) !== false){
+                this.el.dom.value = html;
+                this.owner.fireEvent('sync', this, html);
             }
-            return parent;
-        }
-        
-        // is ancestor a text element.
-        var ac =  range.commonAncestorContainer;
-        if (ac.nodeType == 3) {
-            ac = ac.parentNode;
         }
-        
-        var ar = ac.childNodes;
-         
-        var nodes = [];
-        var other_nodes = [];
-        var has_other_nodes = false;
-        for (var i=0;i<ar.length;i++) {
-            if ((ar[i].nodeType == 3) && (!ar[i].data.length)) { // empty text ? 
-                continue;
-            }
-            // fullly contained node.
+    },
+
+    /**
+     * Protected method that will not generally be called directly. Pushes the value of the textarea
+     * into the iframe editor.
+     */
+    pushValue : function(){
+        if(this.initialized){
+            var v = this.el.dom.value.trim();
             
-            if (this.rangeIntersectsNode(range,ar[i]) && this.rangeCompareNode(range,ar[i]) == 3) {
-                nodes.push(ar[i]);
-                continue;
-            }
+//            if(v.length < 1){
+//                v = '&#160;';
+//            }
             
-            // probably selected..
-            if ((ar[i].nodeType == 1) && this.rangeIntersectsNode(range,ar[i]) && (this.rangeCompareNode(range,ar[i]) > 0)) {
-                other_nodes.push(ar[i]);
-                continue;
-            }
-            // outer..
-            if (!this.rangeIntersectsNode(range,ar[i])|| (this.rangeCompareNode(range,ar[i]) == 0))  {
-                continue;
+            if(this.owner.fireEvent('beforepush', this, v) !== false){
+                var d = (this.doc.body || this.doc.documentElement);
+                d.innerHTML = v;
+                this.cleanUpPaste();
+                this.el.dom.value = d.innerHTML;
+                this.owner.fireEvent('push', this, v);
             }
-            
-            
-            has_other_nodes = true;
-        }
-        if (!nodes.length && other_nodes.length) {
-            nodes= other_nodes;
         }
-        if (has_other_nodes || !nodes.length || (nodes.length > 1)) {
-            return false;
-        }
-        
-        return nodes[0];
     },
-    createRange: function(sel)
-    {
-        // this has strange effects when using with 
-        // top toolbar - not sure if it's a great idea.
-        //this.editor.contentWindow.focus();
-        if (typeof sel != "undefined") {
-            try {
-                return sel.getRangeAt ? sel.getRangeAt(0) : sel.createRange();
-            } catch(e) {
-                return this.doc.createRange();
-            }
-        } else {
-            return this.doc.createRange();
-        }
+
+    // private
+    deferFocus : function(){
+        this.focus.defer(10, this);
     },
-    getParentElement: function()
-    {
-        
-        this.assignDocWin();
-        var sel = Roo.isIE ? this.doc.selection : this.win.getSelection();
-        
-        var range = this.createRange(sel);
-         
-        try {
-            var p = range.commonAncestorContainer;
-            while (p.nodeType == 3) { // text node
-                p = p.parentNode;
-            }
-            return p;
-        } catch (e) {
-            return null;
+
+    // doc'ed in Field
+    focus : function(){
+        if(this.win && !this.sourceEditMode){
+            this.win.focus();
+        }else{
+            this.el.focus();
         }
-    
     },
-    /***
-     *
-     * Range intersection.. the hard stuff...
-     *  '-1' = before
-     *  '0' = hits..
-     *  '1' = after.
-     *         [ -- selected range --- ]
-     *   [fail]                        [fail]
-     *
-     *    basically..
-     *      if end is before start or  hits it. fail.
-     *      if start is after end or hits it fail.
-     *
-     *   if either hits (but other is outside. - then it's not 
-     *   
-     *    
-     **/
     
-    
-    // @see http://www.thismuchiknow.co.uk/?p=64.
-    rangeIntersectsNode : function(range, node)
+    assignDocWin: function()
     {
-        var nodeRange = node.ownerDocument.createRange();
-        try {
-            nodeRange.selectNode(node);
-        } catch (e) {
-            nodeRange.selectNodeContents(node);
-        }
-    
-        var rangeStartRange = range.cloneRange();
-        rangeStartRange.collapse(true);
-    
-        var rangeEndRange = range.cloneRange();
-        rangeEndRange.collapse(false);
-    
-        var nodeStartRange = nodeRange.cloneRange();
-        nodeStartRange.collapse(true);
-    
-        var nodeEndRange = nodeRange.cloneRange();
-        nodeEndRange.collapse(false);
-    
-        return rangeStartRange.compareBoundaryPoints(
-                 Range.START_TO_START, nodeEndRange) == -1 &&
-               rangeEndRange.compareBoundaryPoints(
-                 Range.START_TO_START, nodeStartRange) == 1;
+        var iframe = this.iframe;
         
-         
-    },
-    rangeCompareNode : function(range, node)
-    {
-        var nodeRange = node.ownerDocument.createRange();
-        try {
-            nodeRange.selectNode(node);
-        } catch (e) {
-            nodeRange.selectNodeContents(node);
+         if(Roo.isIE){
+            this.doc = iframe.contentWindow.document;
+            this.win = iframe.contentWindow;
+        } else {
+            if (!Roo.get(this.frameId)) {
+                return;
+            }
+            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
+            this.win = Roo.get(this.frameId).dom.contentWindow;
         }
-        
-        
-        range.collapse(true);
+    },
     
-        nodeRange.collapse(true);
-     
-        var ss = range.compareBoundaryPoints( Range.START_TO_START, nodeRange);
-        var ee = range.compareBoundaryPoints(  Range.END_TO_END, nodeRange);
-         
-        //Roo.log(node.tagName + ': ss='+ss +', ee='+ee)
-        
-        var nodeIsBefore   =  ss == 1;
-        var nodeIsAfter    = ee == -1;
+    // private
+    initEditor : function(){
+        //console.log("INIT EDITOR");
+        this.assignDocWin();
         
-        if (nodeIsBefore && nodeIsAfter)
-            return 0; // outer
-        if (!nodeIsBefore && nodeIsAfter)
-            return 1; //right trailed.
         
-        if (nodeIsBefore && !nodeIsAfter)
-            return 2;  // left trailed.
-        // fully contined.
-        return 3;
-    },
-
-    // private? - in a new class?
-    cleanUpPaste :  function()
-    {
-        // cleans up the whole document..
-        Roo.log('cleanuppaste');
         
-        this.cleanUpChildren(this.doc.body);
-        var clean = this.cleanWordChars(this.doc.body.innerHTML);
-        if (clean != this.doc.body.innerHTML) {
-            this.doc.body.innerHTML = clean;
-        }
+        this.doc.designMode="on";
+        this.doc.open();
+        this.doc.write(this.getDocMarkup());
+        this.doc.close();
         
-    },
-    
-    cleanWordChars : function(input) {// change the chars to hex code
-        var he = Roo.HtmlEditorCore;
+        var dbody = (this.doc.body || this.doc.documentElement);
+        //var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
+        // this copies styles from the containing element into thsi one..
+        // not sure why we need all of this..
+        //var ss = this.el.getStyles('font-size', 'background-image', 'background-repeat');
         
-        var output = input;
-        Roo.each(he.swapCodes, function(sw) { 
-            var swapper = new RegExp("\\u" + sw[0].toString(16), "g"); // hex codes
-            
-            output = output.replace(swapper, sw[1]);
+        //var ss = this.el.getStyles( 'background-image', 'background-repeat');
+        //ss['background-attachment'] = 'fixed'; // w3c
+        dbody.bgProperties = 'fixed'; // ie
+        //Roo.DomHelper.applyStyles(dbody, ss);
+        Roo.EventManager.on(this.doc, {
+            //'mousedown': this.onEditorEvent,
+            'mouseup': this.onEditorEvent,
+            'dblclick': this.onEditorEvent,
+            'click': this.onEditorEvent,
+            'keyup': this.onEditorEvent,
+            buffer:100,
+            scope: this
         });
-        
-        return output;
-    },
-    
-    
-    cleanUpChildren : function (n)
-    {
-        if (!n.childNodes.length) {
-            return;
+        if(Roo.isGecko){
+            Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
         }
-        for (var i = n.childNodes.length-1; i > -1 ; i--) {
-           this.cleanUpChild(n.childNodes[i]);
+        if(Roo.isIE || Roo.isSafari || Roo.isOpera){
+            Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
         }
+        this.initialized = true;
+
+        this.owner.fireEvent('initialize', this);
+        this.pushValue();
     },
-    
-    
+
+    // private
+    onDestroy : function(){
         
-    
-    cleanUpChild : function (node)
-    {
-        var ed = this;
-        //console.log(node);
-        if (node.nodeName == "#text") {
-            // clean up silly Windows -- stuff?
-            return; 
-        }
-        if (node.nodeName == "#comment") {
-            node.parentNode.removeChild(node);
-            // clean up silly Windows -- stuff?
-            return; 
-        }
         
-        if (Roo.HtmlEditorCore.black.indexOf(node.tagName.toLowerCase()) > -1 && this.clearUp) {
-            // remove node.
-            node.parentNode.removeChild(node);
-            return;
+        
+        if(this.rendered){
+            
+            //for (var i =0; i < this.toolbars.length;i++) {
+            //    // fixme - ask toolbars for heights?
+            //    this.toolbars[i].onDestroy();
+           // }
             
+            //this.wrap.dom.innerHTML = '';
+            //this.wrap.remove();
         }
+    },
+
+    // private
+    onFirstFocus : function(){
         
-        var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
-        
-        // 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..
+        this.assignDocWin();
         
-        //if (node.tagName.toLowerCase() == 'a' && !node.hasAttribute('href')) {
-        //    remove_keep_children = true;
-        //}
         
-        if (remove_keep_children) {
-            this.cleanUpChildren(node);
-            // inserts everything just before this node...
-            while (node.childNodes.length) {
-                var cn = node.childNodes[0];
-                node.removeChild(cn);
-                node.parentNode.insertBefore(cn, node);
+        this.activated = true;
+         
+    
+        if(Roo.isGecko){ // prevent silly gecko errors
+            this.win.focus();
+            var s = this.win.getSelection();
+            if(!s.focusNode || s.focusNode.nodeType != 3){
+                var r = s.getRangeAt(0);
+                r.selectNodeContents((this.doc.body || this.doc.documentElement));
+                r.collapse(true);
+                this.deferFocus();
             }
-            node.parentNode.removeChild(node);
-            return;
-        }
-        
-        if (!node.attributes || !node.attributes.length) {
-            this.cleanUpChildren(node);
-            return;
+            try{
+                this.execCmd('useCSS', true);
+                this.execCmd('styleWithCSS', false);
+            }catch(e){}
         }
-        
-        function cleanAttr(n,v)
-        {
-            
-            if (v.match(/^\./) || v.match(/^\//)) {
-                return;
-            }
-            if (v.match(/^(http|https):\/\//) || v.match(/^mailto:/)) {
-                return;
-            }
-            if (v.match(/^#/)) {
-                return;
-            }
-//            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
-            node.removeAttribute(n);
+        this.owner.fireEvent('activate', this);
+    },
+
+    // private
+    adjustFont: function(btn){
+        var adjust = btn.cmd == 'increasefontsize' ? 1 : -1;
+        //if(Roo.isSafari){ // safari
+        //    adjust *= 2;
+       // }
+        var v = parseInt(this.doc.queryCommandValue('FontSize')|| 3, 10);
+        if(Roo.isSafari){ // safari
+            var sm = { 10 : 1, 13: 2, 16:3, 18:4, 24: 5, 32:6, 48: 7 };
+            v =  (v < 10) ? 10 : v;
+            v =  (v > 48) ? 48 : v;
+            v = typeof(sm[v]) == 'undefined' ? 1 : sm[v];
             
         }
         
-        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 = [];
-            
-            Roo.each(parts, function(p) {
-                p = p.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                if (!p.length) {
-                    return true;
-                }
-                var l = p.split(':').shift().replace(/\s+/g,'');
-                l = l.replace(/^\s+/g,'').replace(/\s+$/g,'');
-                
-                if ( cblack.indexOf(l) > -1) {
-//                    Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
-                    //node.removeAttribute(n);
-                    return true;
-                }
-                //Roo.log()
-                // only allow 'c whitelisted system attributes'
-                if ( cwhite.length &&  cwhite.indexOf(l) < 0) {
-//                    Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
-                    //node.removeAttribute(n);
-                    return true;
-                }
-                
-                
-                 
-                
-                clean.push(p);
-                return true;
-            });
-            if (clean.length) { 
-                node.setAttribute(n, clean.join(';'));
-            } else {
-                node.removeAttribute(n);
-            }
-            
-        }
         
+        v = Math.max(1, v+adjust);
         
-        for (var i = node.attributes.length-1; i > -1 ; i--) {
-            var a = node.attributes[i];
-            //console.log(a);
-            
-            if (a.name.toLowerCase().substr(0,2)=='on')  {
-                node.removeAttribute(a.name);
-                continue;
-            }
-            if (Roo.HtmlEditorCore.ablack.indexOf(a.name.toLowerCase()) > -1) {
-                node.removeAttribute(a.name);
-                continue;
-            }
-            if (Roo.HtmlEditorCore.aclean.indexOf(a.name.toLowerCase()) > -1) {
-                cleanAttr(a.name,a.value); // fixme..
-                continue;
-            }
-            if (a.name == 'style') {
-                cleanStyle(a.name,a.value);
-                continue;
-            }
-            /// clean up MS crap..
-            // tecnically this should be a list of valid class'es..
+        this.execCmd('FontSize', v  );
+    },
+
+    onEditorEvent : function(e){
+        this.owner.fireEvent('editorevent', this, e);
+      //  this.updateToolbar();
+        this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
+    },
+
+    insertTag : function(tg)
+    {
+        // could be a bit smarter... -> wrap the current selected tRoo..
+        if (tg.toLowerCase() == 'span' || tg.toLowerCase() == 'code') {
             
+            range = this.createRange(this.getSelection());
+            var wrappingNode = this.doc.createElement(tg.toLowerCase());
+            wrappingNode.appendChild(range.extractContents());
+            range.insertNode(wrappingNode);
+
+            return;
             
-            if (a.name == 'class') {
-                if (a.value.match(/^Mso/)) {
-                    node.className = '';
-                }
-                
-                if (a.value.match(/body/)) {
-                    node.className = '';
-                }
-                continue;
-            }
             
-            // style cleanup!?
-            // class cleanup?
             
         }
+        this.execCmd("formatblock",   tg);
         
-        
-        this.cleanUpChildren(node);
+    },
+    
+    insertText : function(txt)
+    {
         
         
+        var range = this.createRange();
+        range.deleteContents();
+               //alert(Sender.getAttribute('label'));
+               
+        range.insertNode(this.doc.createTextNode(txt));
+    } ,
+    
+     
+
+    /**
+     * Executes a Midas editor command on the editor document and performs necessary focus and
+     * toolbar updates. <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    relayCmd : function(cmd, value){
+        this.win.focus();
+        this.execCmd(cmd, value);
+        this.owner.fireEvent('editorevent', this);
+        //this.updateToolbar();
+        this.owner.deferFocus();
     },
+
     /**
-     * Clean up MS wordisms...
+     * Executes a Midas editor command directly on the editor document.
+     * For visual commands, you should use {@link #relayCmd} instead.
+     * <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    execCmd : function(cmd, value){
+        this.doc.execCommand(cmd, false, value === undefined ? null : value);
+        this.syncValue();
+    },
+   
+    /**
+     * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
+     * to insert tRoo.
+     * @param {String} text | dom node.. 
      */
-    cleanWord : function(node)
+    insertAtCursor : function(text)
     {
-        var _t = this;
-        var cleanWordChildren = function()
-        {
-            if (!node.childNodes.length) {
-                return;
-            }
-            for (var i = node.childNodes.length-1; i > -1 ; i--) {
-               _t.cleanWord(node.childNodes[i]);
-            }
-        }
         
         
-        if (!node) {
-            this.cleanWord(this.doc.body);
-            return;
-        }
-        if (node.nodeName == "#text") {
-            // clean up silly Windows -- stuff?
-            return; 
-        }
-        if (node.nodeName == "#comment") {
-            node.parentNode.removeChild(node);
-            // clean up silly Windows -- stuff?
-            return; 
-        }
         
-        if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
-            node.parentNode.removeChild(node);
+        if(!this.activated){
             return;
         }
-        
-        // remove - but keep children..
-        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|font)/)) {
-            while (node.childNodes.length) {
-                var cn = node.childNodes[0];
-                node.removeChild(cn);
-                node.parentNode.insertBefore(cn, node);
+        /*
+        if(Roo.isIE){
+            this.win.focus();
+            var r = this.doc.selection.createRange();
+            if(r){
+                r.collapse(true);
+                r.pasteHTML(text);
+                this.syncValue();
+                this.deferFocus();
+            
             }
-            node.parentNode.removeChild(node);
-            cleanWordChildren();
             return;
         }
-        // clean styles
-        if (node.className.length) {
+        */
+        if(Roo.isGecko || Roo.isOpera || Roo.isSafari){
+            this.win.focus();
             
-            var cn = node.className.split(/\W+/);
-            var cna = [];
-            Roo.each(cn, function(cls) {
-                if (cls.match(/Mso[a-zA-Z]+/)) {
-                    return;
+            
+            // from jquery ui (MIT licenced)
+            var range, node;
+            var win = this.win;
+            
+            if (win.getSelection && win.getSelection().getRangeAt) {
+                range = win.getSelection().getRangeAt(0);
+                node = typeof(text) == 'string' ? range.createContextualFragment(text) : text;
+                range.insertNode(node);
+            } else if (win.document.selection && win.document.selection.createRange) {
+                // no firefox support
+                var txt = typeof(text) == 'string' ? text : text.outerHTML;
+                win.document.selection.createRange().pasteHTML(txt);
+            } else {
+                // no firefox support
+                var txt = typeof(text) == 'string' ? text : text.outerHTML;
+                this.execCmd('InsertHTML', txt);
+            } 
+            
+            this.syncValue();
+            
+            this.deferFocus();
+        }
+    },
+ // private
+    mozKeyPress : function(e){
+        if(e.ctrlKey){
+            var c = e.getCharCode(), cmd;
+          
+            if(c > 0){
+                c = String.fromCharCode(c).toLowerCase();
+                switch(c){
+                    case 'b':
+                        cmd = 'bold';
+                        break;
+                    case 'i':
+                        cmd = 'italic';
+                        break;
+                    
+                    case 'u':
+                        cmd = 'underline';
+                        break;
+                    
+                    case 'v':
+                        this.cleanUpPaste.defer(100, this);
+                        return;
+                        
                 }
-                cna.push(cls);
-            });
-            node.className = cna.length ? cna.join(' ') : '';
-            if (!cna.length) {
-                node.removeAttribute("class");
+                if(cmd){
+                    this.win.focus();
+                    this.execCmd(cmd);
+                    this.deferFocus();
+                    e.preventDefault();
+                }
+                
             }
         }
-        
-        if (node.hasAttribute("lang")) {
-            node.removeAttribute("lang");
-        }
-        
-        if (node.hasAttribute("style")) {
-            
-            var styles = node.getAttribute("style").split(";");
-            var nstyle = [];
-            Roo.each(styles, function(s) {
-                if (!s.match(/:/)) {
+    },
+
+    // private
+    fixKeys : function(){ // load time branching for fastest keydown performance
+        if(Roo.isIE){
+            return function(e){
+                var k = e.getKey(), r;
+                if(k == e.TAB){
+                    e.stopEvent();
+                    r = this.doc.selection.createRange();
+                    if(r){
+                        r.collapse(true);
+                        r.pasteHTML('&#160;&#160;&#160;&#160;');
+                        this.deferFocus();
+                    }
                     return;
                 }
-                var kv = s.split(":");
-                if (kv[0].match(/^(mso-|line|font|background|margin|padding|color)/)) {
+                
+                if(k == e.ENTER){
+                    r = this.doc.selection.createRange();
+                    if(r){
+                        var target = r.parentElement();
+                        if(!target || target.tagName.toLowerCase() != 'li'){
+                            e.stopEvent();
+                            r.pasteHTML('<br />');
+                            r.collapse(false);
+                            r.select();
+                        }
+                    }
+                }
+                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
                     return;
                 }
-                // what ever is left... we allow.
-                nstyle.push(s);
-            });
-            node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
-            if (!nstyle.length) {
-                node.removeAttribute('style');
-            }
+                
+                
+            };
+        }else if(Roo.isOpera){
+            return function(e){
+                var k = e.getKey();
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.win.focus();
+                    this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
+                    this.deferFocus();
+                }
+                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+            };
+        }else if(Roo.isSafari){
+            return function(e){
+                var k = e.getKey();
+                
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.execCmd('InsertText','\t');
+                    this.deferFocus();
+                    return;
+                }
+               if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+             };
+        }
+    }(),
+    
+    getAllAncestors: function()
+    {
+        var p = this.getSelectedNode();
+        var a = [];
+        if (!p) {
+            a.push(p); // push blank onto stack..
+            p = this.getParentElement();
         }
-        
-        cleanWordChildren();
         
         
+        while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
+            a.push(p);
+            p = p.parentNode;
+        }
+        a.push(this.doc.body);
+        return a;
     },
-    domToHTML : function(currentElement, depth, nopadtext) {
+    lastSel : false,
+    lastSelNode : false,
+    
+    
+    getSelection : function() 
+    {
+        this.assignDocWin();
+        return Roo.isIE ? this.doc.selection : this.win.getSelection();
+    },
+    
+    getSelectedNode: function() 
+    {
+        // this may only work on Gecko!!!
+        
+        // should we cache this!!!!
+        
+        
+        
+         
+        var range = this.createRange(this.getSelection()).cloneRange();
+        
+        if (Roo.isIE) {
+            var parent = range.parentElement();
+            while (true) {
+                var testRange = range.duplicate();
+                testRange.moveToElementText(parent);
+                if (testRange.inRange(range)) {
+                    break;
+                }
+                if ((parent.nodeType != 1) || (parent.tagName.toLowerCase() == 'body')) {
+                    break;
+                }
+                parent = parent.parentElement;
+            }
+            return parent;
+        }
         
-            depth = depth || 0;
-            nopadtext = nopadtext || false;
+        // is ancestor a text element.
+        var ac =  range.commonAncestorContainer;
+        if (ac.nodeType == 3) {
+            ac = ac.parentNode;
+        }
         
-            if (!currentElement) {
-                return this.domToHTML(this.doc.body);
+        var ar = ac.childNodes;
+         
+        var nodes = [];
+        var other_nodes = [];
+        var has_other_nodes = false;
+        for (var i=0;i<ar.length;i++) {
+            if ((ar[i].nodeType == 3) && (!ar[i].data.length)) { // empty text ? 
+                continue;
             }
+            // fullly contained node.
             
-            //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;
+            if (this.rangeIntersectsNode(range,ar[i]) && this.rangeCompareNode(range,ar[i]) == 3) {
+                nodes.push(ar[i]);
+                continue;
             }
             
-            
-            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) + '"' );
-                    }
-                    
-                    ret = "<"+currentElement.tagName+ ( attr.length ? (' ' + attr.join(' ') ) : '') + ">";
-                } 
-                else {
-                    
-                    // eack
-                }
-            } 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;
+            // probably selected..
+            if ((ar[i].nodeType == 1) && this.rangeIntersectsNode(range,ar[i]) && (this.rangeCompareNode(range,ar[i]) > 0)) {
+                other_nodes.push(ar[i]);
+                continue;
             }
-            
-            
-            // 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;
-                }
-                allText = false;
-                
-                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);
+            // outer..
+            if (!this.rangeIntersectsNode(range,ar[i])|| (this.rangeCompareNode(range,ar[i]) == 0))  {
+                continue;
             }
             
-            ret += innerHTML;
             
-            if (!allText) {
-                    // The remaining code is mostly for formatting the tree
-                ret+= nopadtext ? '' : "\n" + (new Array( depth  )).join( "  "  );
+            has_other_nodes = true;
+        }
+        if (!nodes.length && other_nodes.length) {
+            nodes= other_nodes;
+        }
+        if (has_other_nodes || !nodes.length || (nodes.length > 1)) {
+            return false;
+        }
+        
+        return nodes[0];
+    },
+    createRange: function(sel)
+    {
+        // this has strange effects when using with 
+        // top toolbar - not sure if it's a great idea.
+        //this.editor.contentWindow.focus();
+        if (typeof sel != "undefined") {
+            try {
+                return sel.getRangeAt ? sel.getRangeAt(0) : sel.createRange();
+            } catch(e) {
+                return this.doc.createRange();
             }
-            
-            
-            if (tagName) {
-                ret+= "</"+tagName+">";
+        } else {
+            return this.doc.createRange();
+        }
+    },
+    getParentElement: function()
+    {
+        
+        this.assignDocWin();
+        var sel = Roo.isIE ? this.doc.selection : this.win.getSelection();
+        
+        var range = this.createRange(sel);
+         
+        try {
+            var p = range.commonAncestorContainer;
+            while (p.nodeType == 3) { // text node
+                p = p.parentNode;
             }
-            return ret;
-            
+            return p;
+        } catch (e) {
+            return null;
         }
     
-    // hide stuff that is not compatible
-    /**
-     * @event blur
-     * @hide
-     */
-    /**
-     * @event change
-     * @hide
-     */
-    /**
-     * @event focus
-     * @hide
-     */
-    /**
-     * @event specialkey
-     * @hide
-     */
-    /**
-     * @cfg {String} fieldClass @hide
-     */
-    /**
-     * @cfg {String} focusClass @hide
-     */
-    /**
-     * @cfg {String} autoCreate @hide
-     */
-    /**
-     * @cfg {String} inputType @hide
-     */
-    /**
-     * @cfg {String} invalidClass @hide
-     */
-    /**
-     * @cfg {String} invalidText @hide
-     */
-    /**
-     * @cfg {String} msgFx @hide
-     */
-    /**
-     * @cfg {String} validateOnBlur @hide
-     */
-});
-
-Roo.HtmlEditorCore.white = [
-        'area', 'br', 'img', 'input', 'hr', 'wbr',
-        
-       'address', 'blockquote', 'center', 'dd',      'dir',       'div', 
-       'dl',      'dt',         'h1',     'h2',      'h3',        'h4', 
-       'h5',      'h6',         'hr',     'isindex', 'listing',   'marquee', 
-       'menu',    'multicol',   'ol',     'p',       'plaintext', 'pre', 
-       'table',   'ul',         'xmp', 
-       
-       'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', 
-      'thead',   'tr', 
-     
-      'dir', 'menu', 'ol', 'ul', 'dl',
-       
-      'embed',  'object'
-];
-
-
-Roo.HtmlEditorCore.black = [
-    //    'embed',  'object', // enable - backend responsiblity to clean thiese
-        'applet', // 
-        'base',   'basefont', 'bgsound', 'blink',  'body', 
-        'frame',  'frameset', 'head',    'html',   'ilayer', 
-        'iframe', 'layer',  'link',     'meta',    'object',   
-        'script', 'style' ,'title',  'xml' // clean later..
-];
-Roo.HtmlEditorCore.clean = [
-    'script', 'style', 'title', 'xml'
-];
-Roo.HtmlEditorCore.remove = [
-    'font'
-];
-// attributes..
-
-Roo.HtmlEditorCore.ablack = [
-    'on'
-];
+    },
+    /***
+     *
+     * Range intersection.. the hard stuff...
+     *  '-1' = before
+     *  '0' = hits..
+     *  '1' = after.
+     *         [ -- selected range --- ]
+     *   [fail]                        [fail]
+     *
+     *    basically..
+     *      if end is before start or  hits it. fail.
+     *      if start is after end or hits it fail.
+     *
+     *   if either hits (but other is outside. - then it's not 
+     *   
+     *    
+     **/
+    
+    
+    // @see http://www.thismuchiknow.co.uk/?p=64.
+    rangeIntersectsNode : function(range, node)
+    {
+        var nodeRange = node.ownerDocument.createRange();
+        try {
+            nodeRange.selectNode(node);
+        } catch (e) {
+            nodeRange.selectNodeContents(node);
+        }
     
-Roo.HtmlEditorCore.aclean = [ 
-    'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc' 
-];
-
-// protocols..
-Roo.HtmlEditorCore.pwhite= [
-        'http',  'https',  'mailto'
-];
-
-// white listed style attributes.
-Roo.HtmlEditorCore.cwhite= [
-      //  'text-align', /// default is to allow most things..
-      
-         
-//        'font-size'//??
-];
-
-// black listed style attributes.
-Roo.HtmlEditorCore.cblack= [
-      //  'font-size' -- this can be set by the project 
-];
-
-
-Roo.HtmlEditorCore.swapCodes   =[ 
-    [    8211, "--" ], 
-    [    8212, "--" ], 
-    [    8216,  "'" ],  
-    [    8217, "'" ],  
-    [    8220, '"' ],  
-    [    8221, '"' ],  
-    [    8226, "*" ],  
-    [    8230, "..." ]
-]; 
-
-    /*
- * - LGPL
- *
- * HtmlEditor
- * 
- */
-
-/**
- * @class Roo.bootstrap.HtmlEditor
- * @extends Roo.bootstrap.TextArea
- * Bootstrap HtmlEditor class
-
- * @constructor
- * Create a new HtmlEditor
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.HtmlEditor = function(config){
-    Roo.bootstrap.HtmlEditor.superclass.constructor.call(this, config);
-    if (!this.toolbars) {
-        this.toolbars = [];
-    }
-    this.editorcore = new Roo.HtmlEditorCore(Roo.apply({ owner : this} , config));
-    this.addEvents({
-            /**
-             * @event initialize
-             * Fires when the editor is fully initialized (including the iframe)
-             * @param {HtmlEditor} this
-             */
-            initialize: true,
-            /**
-             * @event activate
-             * Fires when the editor is first receives the focus. Any insertion must wait
-             * until after this event.
-             * @param {HtmlEditor} this
-             */
-            activate: true,
-             /**
-             * @event beforesync
-             * Fires before the textarea is updated with content from the editor iframe. Return false
-             * to cancel the sync.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            beforesync: true,
-             /**
-             * @event beforepush
-             * Fires before the iframe editor is updated with content from the textarea. Return false
-             * to cancel the push.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            beforepush: true,
-             /**
-             * @event sync
-             * Fires when the textarea is updated with content from the editor iframe.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            sync: true,
-             /**
-             * @event push
-             * Fires when the iframe editor is updated with content from the textarea.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            push: true,
-             /**
-             * @event editmodechange
-             * Fires when the editor switches edit modes
-             * @param {HtmlEditor} this
-             * @param {Boolean} sourceEdit True if source edit, false if standard editing.
-             */
-            editmodechange: true,
-            /**
-             * @event editorevent
-             * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
-             * @param {HtmlEditor} this
-             */
-            editorevent: true,
-            /**
-             * @event firstfocus
-             * Fires when on first focus - needed by toolbars..
-             * @param {HtmlEditor} this
-             */
-            firstfocus: true,
-            /**
-             * @event autosave
-             * Auto save the htmlEditor value as a file into Events
-             * @param {HtmlEditor} this
-             */
-            autosave: true,
-            /**
-             * @event savedpreview
-             * preview the saved version of htmlEditor
-             * @param {HtmlEditor} this
-             */
-            savedpreview: true
-        });
-};
-
-
-Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
+        var rangeStartRange = range.cloneRange();
+        rangeStartRange.collapse(true);
     
+        var rangeEndRange = range.cloneRange();
+        rangeEndRange.collapse(false);
     
-      /**
-     * @cfg {Array} toolbars Array of toolbars. - defaults to just the Standard one
-     */
-    toolbars : false,
-   
-     /**
-     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
-     *                        Roo.resizable.
-     */
-    resizable : false,
-     /**
-     * @cfg {Number} height (in pixels)
-     */   
-    height: 300,
-   /**
-     * @cfg {Number} width (in pixels)
-     */   
-    width: false,
+        var nodeStartRange = nodeRange.cloneRange();
+        nodeStartRange.collapse(true);
     
-    /**
-     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
-     * 
-     */
-    stylesheets: false,
+        var nodeEndRange = nodeRange.cloneRange();
+        nodeEndRange.collapse(false);
     
-    // id of frame..
-    frameId: false,
+        return rangeStartRange.compareBoundaryPoints(
+                 Range.START_TO_START, nodeEndRange) == -1 &&
+               rangeEndRange.compareBoundaryPoints(
+                 Range.START_TO_START, nodeStartRange) == 1;
+        
+         
+    },
+    rangeCompareNode : function(range, node)
+    {
+        var nodeRange = node.ownerDocument.createRange();
+        try {
+            nodeRange.selectNode(node);
+        } catch (e) {
+            nodeRange.selectNodeContents(node);
+        }
+        
+        
+        range.collapse(true);
     
-    // private properties
-    validationEvent : false,
-    deferHeight: true,
-    initialized : false,
-    activated : false,
+        nodeRange.collapse(true);
+     
+        var ss = range.compareBoundaryPoints( Range.START_TO_START, nodeRange);
+        var ee = range.compareBoundaryPoints(  Range.END_TO_END, nodeRange);
+         
+        //Roo.log(node.tagName + ': ss='+ss +', ee='+ee)
+        
+        var nodeIsBefore   =  ss == 1;
+        var nodeIsAfter    = ee == -1;
+        
+        if (nodeIsBefore && nodeIsAfter)
+            return 0; // outer
+        if (!nodeIsBefore && nodeIsAfter)
+            return 1; //right trailed.
+        
+        if (nodeIsBefore && !nodeIsAfter)
+            return 2;  // left trailed.
+        // fully contined.
+        return 3;
+    },
+
+    // private? - in a new class?
+    cleanUpPaste :  function()
+    {
+        // cleans up the whole document..
+        Roo.log('cleanuppaste');
+        
+        this.cleanUpChildren(this.doc.body);
+        var clean = this.cleanWordChars(this.doc.body.innerHTML);
+        if (clean != this.doc.body.innerHTML) {
+            this.doc.body.innerHTML = clean;
+        }
+        
+    },
     
-    onFocus : Roo.emptyFn,
-    iframePad:3,
-    hideMode:'offsets',
+    cleanWordChars : function(input) {// change the chars to hex code
+        var he = Roo.HtmlEditorCore;
+        
+        var output = input;
+        Roo.each(he.swapCodes, function(sw) { 
+            var swapper = new RegExp("\\u" + sw[0].toString(16), "g"); // hex codes
+            
+            output = output.replace(swapper, sw[1]);
+        });
+        
+        return output;
+    },
+    
+    
+    cleanUpChildren : function (n)
+    {
+        if (!n.childNodes.length) {
+            return;
+        }
+        for (var i = n.childNodes.length-1; i > -1 ; i--) {
+           this.cleanUpChild(n.childNodes[i]);
+        }
+    },
     
     
-    tbContainer : false,
+        
     
-    toolbarContainer :function() {
-        return this.wrap.select('.x-html-editor-tb',true).first();
-    },
-
-    /**
-     * Protected method that will not generally be called directly. It
-     * is called when the editor creates its toolbar. Override this method if you need to
-     * add custom toolbar buttons.
-     * @param {HtmlEditor} editor
-     */
-    createToolbar : function(){
+    cleanUpChild : function (node)
+    {
+        var ed = this;
+        //console.log(node);
+        if (node.nodeName == "#text") {
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        if (node.nodeName == "#comment") {
+            node.parentNode.removeChild(node);
+            // clean up silly Windows -- stuff?
+            return; 
+        }
         
-        Roo.log("create toolbars");
+        if (Roo.HtmlEditorCore.black.indexOf(node.tagName.toLowerCase()) > -1 && this.clearUp) {
+            // remove node.
+            node.parentNode.removeChild(node);
+            return;
+            
+        }
         
-        this.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard({editor: this} ) ];
-        this.toolbars[0].render(this.toolbarContainer());
+        var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
+        
+        // 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..
+        
+        //if (node.tagName.toLowerCase() == 'a' && !node.hasAttribute('href')) {
+        //    remove_keep_children = true;
+        //}
+        
+        if (remove_keep_children) {
+            this.cleanUpChildren(node);
+            // inserts everything just before this node...
+            while (node.childNodes.length) {
+                var cn = node.childNodes[0];
+                node.removeChild(cn);
+                node.parentNode.insertBefore(cn, node);
+            }
+            node.parentNode.removeChild(node);
+            return;
+        }
+        
+        if (!node.attributes || !node.attributes.length) {
+            this.cleanUpChildren(node);
+            return;
+        }
+        
+        function cleanAttr(n,v)
+        {
+            
+            if (v.match(/^\./) || v.match(/^\//)) {
+                return;
+            }
+            if (v.match(/^(http|https):\/\//) || v.match(/^mailto:/)) {
+                return;
+            }
+            if (v.match(/^#/)) {
+                return;
+            }
+//            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
+            node.removeAttribute(n);
+            
+        }
+        
+        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 = [];
+            
+            Roo.each(parts, function(p) {
+                p = p.replace(/^\s+/g,'').replace(/\s+$/g,'');
+                if (!p.length) {
+                    return true;
+                }
+                var l = p.split(':').shift().replace(/\s+/g,'');
+                l = l.replace(/^\s+/g,'').replace(/\s+$/g,'');
+                
+                if ( cblack.indexOf(l) > -1) {
+//                    Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
+                    //node.removeAttribute(n);
+                    return true;
+                }
+                //Roo.log()
+                // only allow 'c whitelisted system attributes'
+                if ( cwhite.length &&  cwhite.indexOf(l) < 0) {
+//                    Roo.log('(REMOVE CSS)' + node.tagName +'.' + n + ':'+l + '=' + v);
+                    //node.removeAttribute(n);
+                    return true;
+                }
+                
+                
+                 
+                
+                clean.push(p);
+                return true;
+            });
+            if (clean.length) { 
+                node.setAttribute(n, clean.join(';'));
+            } else {
+                node.removeAttribute(n);
+            }
+            
+        }
+        
+        
+        for (var i = node.attributes.length-1; i > -1 ; i--) {
+            var a = node.attributes[i];
+            //console.log(a);
+            
+            if (a.name.toLowerCase().substr(0,2)=='on')  {
+                node.removeAttribute(a.name);
+                continue;
+            }
+            if (Roo.HtmlEditorCore.ablack.indexOf(a.name.toLowerCase()) > -1) {
+                node.removeAttribute(a.name);
+                continue;
+            }
+            if (Roo.HtmlEditorCore.aclean.indexOf(a.name.toLowerCase()) > -1) {
+                cleanAttr(a.name,a.value); // fixme..
+                continue;
+            }
+            if (a.name == 'style') {
+                cleanStyle(a.name,a.value);
+                continue;
+            }
+            /// clean up MS crap..
+            // tecnically this should be a list of valid class'es..
+            
+            
+            if (a.name == 'class') {
+                if (a.value.match(/^Mso/)) {
+                    node.className = '';
+                }
+                
+                if (a.value.match(/body/)) {
+                    node.className = '';
+                }
+                continue;
+            }
+            
+            // style cleanup!?
+            // class cleanup?
+            
+        }
+        
+        
+        this.cleanUpChildren(node);
         
-        return;
         
-//        if (!editor.toolbars || !editor.toolbars.length) {
-//            editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
-//        }
-//        
-//        for (var i =0 ; i < editor.toolbars.length;i++) {
-//            editor.toolbars[i] = Roo.factory(
-//                    typeof(editor.toolbars[i]) == 'string' ?
-//                        { xtype: editor.toolbars[i]} : editor.toolbars[i],
-//                Roo.bootstrap.HtmlEditor);
-//            editor.toolbars[i].init(editor);
-//        }
     },
-
-     
-    // private
-    onRender : function(ct, position)
+    /**
+     * Clean up MS wordisms...
+     */
+    cleanWord : function(node)
     {
-       // Roo.log("Call onRender: " + this.xtype);
         var _t = this;
-        Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
-      
-        this.wrap = this.inputEl().wrap({
-            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
-        });
+        var cleanWordChildren = function()
+        {
+            if (!node.childNodes.length) {
+                return;
+            }
+            for (var i = node.childNodes.length-1; i > -1 ; i--) {
+               _t.cleanWord(node.childNodes[i]);
+            }
+        }
         
-        this.editorcore.onRender(ct, position);
-         
-        if (this.resizable) {
-            this.resizeEl = new Roo.Resizable(this.wrap, {
-                pinned : true,
-                wrap: true,
-                dynamic : true,
-                minHeight : this.height,
-                height: this.height,
-                handles : this.resizable,
-                width: this.width,
-                listeners : {
-                    resize : function(r, w, h) {
-                        _t.onResize(w,h); // -something
-                    }
+        
+        if (!node) {
+            this.cleanWord(this.doc.body);
+            return;
+        }
+        if (node.nodeName == "#text") {
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        if (node.nodeName == "#comment") {
+            node.parentNode.removeChild(node);
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        
+        if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
+            node.parentNode.removeChild(node);
+            return;
+        }
+        
+        // remove - but keep children..
+        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|font)/)) {
+            while (node.childNodes.length) {
+                var cn = node.childNodes[0];
+                node.removeChild(cn);
+                node.parentNode.insertBefore(cn, node);
+            }
+            node.parentNode.removeChild(node);
+            cleanWordChildren();
+            return;
+        }
+        // clean styles
+        if (node.className.length) {
+            
+            var cn = node.className.split(/\W+/);
+            var cna = [];
+            Roo.each(cn, function(cls) {
+                if (cls.match(/Mso[a-zA-Z]+/)) {
+                    return;
                 }
+                cna.push(cls);
             });
-            
+            node.className = cna.length ? cna.join(' ') : '';
+            if (!cna.length) {
+                node.removeAttribute("class");
+            }
         }
-        this.createToolbar(this);
-       
         
-        if(!this.width && this.resizable){
-            this.setSize(this.wrap.getSize());
-        }
-        if (this.resizeEl) {
-            this.resizeEl.resizeTo.defer(100, this.resizeEl,[ this.width,this.height ] );
-            // should trigger onReize..
+        if (node.hasAttribute("lang")) {
+            node.removeAttribute("lang");
         }
         
-    },
-
-    // private
-    onResize : function(w, h)
-    {
-        Roo.log('resize: ' +w + ',' + h );
-        Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
-        var ew = false;
-        var eh = false;
-        
-        if(this.inputEl() ){
-            if(typeof w == 'number'){
-                var aw = w - this.wrap.getFrameWidth('lr');
-                this.inputEl().setWidth(this.adjustWidth('textarea', aw));
-                ew = aw;
-            }
-            if(typeof h == 'number'){
-                 var tbh = -11;  // fixme it needs to tool bar size!
-                for (var i =0; i < this.toolbars.length;i++) {
-                    // fixme - ask toolbars for heights?
-                    tbh += this.toolbars[i].el.getHeight();
-                    //if (this.toolbars[i].footer) {
-                    //    tbh += this.toolbars[i].footer.el.getHeight();
-                    //}
+        if (node.hasAttribute("style")) {
+            
+            var styles = node.getAttribute("style").split(";");
+            var nstyle = [];
+            Roo.each(styles, function(s) {
+                if (!s.match(/:/)) {
+                    return;
                 }
-              
-                
-                
-                
-                
-                var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
-                ah -= 5; // knock a few pixes off for look..
-                this.inputEl().setHeight(this.adjustWidth('textarea', ah));
-                var eh = ah;
+                var kv = s.split(":");
+                if (kv[0].match(/^(mso-|line|font|background|margin|padding|color)/)) {
+                    return;
+                }
+                // what ever is left... we allow.
+                nstyle.push(s);
+            });
+            node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
+            if (!nstyle.length) {
+                node.removeAttribute('style');
             }
         }
-        Roo.log('onResize:' + [w,h,ew,eh].join(',') );
-        this.editorcore.onResize(ew,eh);
-        
-    },
-
-    /**
-     * Toggles the editor between standard and source edit mode.
-     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
-     */
-    toggleSourceEdit : function(sourceEditMode)
-    {
-        this.editorcore.toggleSourceEdit(sourceEditMode);
         
-        if(this.editorcore.sourceEditMode){
-            Roo.log('editor - showing textarea');
-            
-//            Roo.log('in');
-//            Roo.log(this.syncValue());
-            this.syncValue();
-            this.inputEl().removeClass('hide');
-            this.inputEl().dom.removeAttribute('tabIndex');
-            this.inputEl().focus();
-        }else{
-            Roo.log('editor - hiding textarea');
-//            Roo.log('out')
-//            Roo.log(this.pushValue()); 
-            this.pushValue();
-            
-            this.inputEl().addClass('hide');
-            this.inputEl().dom.setAttribute('tabIndex', -1);
-            //this.deferFocus();
-        }
-         
-        if(this.resizable){
-            this.setSize(this.wrap.getSize());
-        }
+        cleanWordChildren();
         
-        this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
-    },
-    // private (for BoxComponent)
-    adjustSize : Roo.BoxComponent.prototype.adjustSize,
-
-    // private (for BoxComponent)
-    getResizeEl : function(){
-        return this.wrap;
-    },
-
-    // private (for BoxComponent)
-    getPositionEl : function(){
-        return this.wrap;
-    },
-
-    // private
-    initEvents : function(){
-        this.originalValue = this.getValue();
-    },
-
-//    /**
-//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-//     * @method
-//     */
-//    markInvalid : Roo.emptyFn,
-//    /**
-//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-//     * @method
-//     */
-//    clearInvalid : Roo.emptyFn,
-
-    setValue : function(v){
-        Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
-        this.editorcore.pushValue();
-    },
-
-     
-    // private
-    deferFocus : function(){
-        this.focus.defer(10, this);
-    },
-
-    // doc'ed in Field
-    focus : function(){
-        this.editorcore.focus();
         
     },
-      
-
-    // private
-    onDestroy : function(){
-        
+    domToHTML : function(currentElement, depth, nopadtext) {
         
+            depth = depth || 0;
+            nopadtext = nopadtext || false;
         
-        if(this.rendered){
+            if (!currentElement) {
+                return this.domToHTML(this.doc.body);
+            }
             
-            for (var i =0; i < this.toolbars.length;i++) {
-                // fixme - ask toolbars for heights?
-                this.toolbars[i].onDestroy();
+            //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;
+            }
+            
+            
+            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) + '"' );
+                    }
+                    
+                    ret = "<"+currentElement.tagName+ ( attr.length ? (' ' + attr.join(' ') ) : '') + ">";
+                } 
+                else {
+                    
+                    // eack
+                }
+            } 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;
+                }
+                // 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;
+                }
+                allText = false;
+                
+                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;
             
-            this.wrap.dom.innerHTML = '';
-            this.wrap.remove();
-        }
-    },
-
-    // private
-    onFirstFocus : function(){
-        //Roo.log("onFirstFocus");
-        this.editorcore.onFirstFocus();
-         for (var i =0; i < this.toolbars.length;i++) {
-            this.toolbars[i].onFirstFocus();
         }
-        
-    },
-    
-    // private
-    syncValue : function()
-    {   
-        this.editorcore.syncValue();
-    },
-    
-    pushValue : function()
-    {   
-        this.editorcore.pushValue();
-    }
-     
     
     // hide stuff that is not compatible
     /**
@@ -16237,825 +16388,828 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
      * @cfg {String} validateOnBlur @hide
      */
 });
+
+Roo.HtmlEditorCore.white = [
+        'area', 'br', 'img', 'input', 'hr', 'wbr',
+        
+       'address', 'blockquote', 'center', 'dd',      'dir',       'div', 
+       'dl',      'dt',         'h1',     'h2',      'h3',        'h4', 
+       'h5',      'h6',         'hr',     'isindex', 'listing',   'marquee', 
+       'menu',    'multicol',   'ol',     'p',       'plaintext', 'pre', 
+       'table',   'ul',         'xmp', 
+       
+       'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', 
+      'thead',   'tr', 
+     
+      'dir', 'menu', 'ol', 'ul', 'dl',
+       
+      'embed',  'object'
+];
+
+
+Roo.HtmlEditorCore.black = [
+    //    'embed',  'object', // enable - backend responsiblity to clean thiese
+        'applet', // 
+        'base',   'basefont', 'bgsound', 'blink',  'body', 
+        'frame',  'frameset', 'head',    'html',   'ilayer', 
+        'iframe', 'layer',  'link',     'meta',    'object',   
+        'script', 'style' ,'title',  'xml' // clean later..
+];
+Roo.HtmlEditorCore.clean = [
+    'script', 'style', 'title', 'xml'
+];
+Roo.HtmlEditorCore.remove = [
+    'font'
+];
+// attributes..
+
+Roo.HtmlEditorCore.ablack = [
+    'on'
+];
     
-   
-   
-   
+Roo.HtmlEditorCore.aclean = [ 
+    'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc' 
+];
+
+// protocols..
+Roo.HtmlEditorCore.pwhite= [
+        'http',  'https',  'mailto'
+];
+
+// white listed style attributes.
+Roo.HtmlEditorCore.cwhite= [
+      //  'text-align', /// default is to allow most things..
       
+         
+//        'font-size'//??
+];
 
-/**
- * @class Roo.bootstrap.HtmlEditorToolbar1
- * Basic Toolbar
- * 
- * Usage:
+// black listed style attributes.
+Roo.HtmlEditorCore.cblack= [
+      //  'font-size' -- this can be set by the project 
+];
+
+
+Roo.HtmlEditorCore.swapCodes   =[ 
+    [    8211, "--" ], 
+    [    8212, "--" ], 
+    [    8216,  "'" ],  
+    [    8217, "'" ],  
+    [    8220, '"' ],  
+    [    8221, '"' ],  
+    [    8226, "*" ],  
+    [    8230, "..." ]
+]; 
+
+    /*
+ * - LGPL
  *
- new Roo.bootstrap.HtmlEditor({
-    ....
-    toolbars : [
-        new Roo.bootstrap.HtmlEditorToolbar1({
-            disable : { fonts: 1 , format: 1, ..., ... , ...],
-            btns : [ .... ]
-        })
-    }
-     
- * 
- * @cfg {Object} disable List of elements to disable..
- * @cfg {Array} btns List of additional buttons.
- * 
+ * HtmlEditor
  * 
- * NEEDS Extra CSS? 
- * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
  */
-Roo.bootstrap.HtmlEditor.ToolbarStandard = function(config)
-{
-    
-    Roo.apply(this, config);
-    
-    // default disabled, based on 'good practice'..
-    this.disable = this.disable || {};
-    Roo.applyIf(this.disable, {
-        fontSize : true,
-        colors : true,
-        specialElements : true
-    });
-    Roo.bootstrap.HtmlEditor.ToolbarStandard.superclass.constructor.call(this, config);
+
+/**
+ * @class Roo.bootstrap.HtmlEditor
+ * @extends Roo.bootstrap.TextArea
+ * Bootstrap HtmlEditor class
+
+ * @constructor
+ * Create a new HtmlEditor
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.HtmlEditor = function(config){
+    Roo.bootstrap.HtmlEditor.superclass.constructor.call(this, config);
+    if (!this.toolbars) {
+        this.toolbars = [];
+    }
+    this.editorcore = new Roo.HtmlEditorCore(Roo.apply({ owner : this} , config));
+    this.addEvents({
+            /**
+             * @event initialize
+             * Fires when the editor is fully initialized (including the iframe)
+             * @param {HtmlEditor} this
+             */
+            initialize: true,
+            /**
+             * @event activate
+             * Fires when the editor is first receives the focus. Any insertion must wait
+             * until after this event.
+             * @param {HtmlEditor} this
+             */
+            activate: true,
+             /**
+             * @event beforesync
+             * Fires before the textarea is updated with content from the editor iframe. Return false
+             * to cancel the sync.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            beforesync: true,
+             /**
+             * @event beforepush
+             * Fires before the iframe editor is updated with content from the textarea. Return false
+             * to cancel the push.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            beforepush: true,
+             /**
+             * @event sync
+             * Fires when the textarea is updated with content from the editor iframe.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            sync: true,
+             /**
+             * @event push
+             * Fires when the iframe editor is updated with content from the textarea.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            push: true,
+             /**
+             * @event editmodechange
+             * Fires when the editor switches edit modes
+             * @param {HtmlEditor} this
+             * @param {Boolean} sourceEdit True if source edit, false if standard editing.
+             */
+            editmodechange: true,
+            /**
+             * @event editorevent
+             * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
+             * @param {HtmlEditor} this
+             */
+            editorevent: true,
+            /**
+             * @event firstfocus
+             * Fires when on first focus - needed by toolbars..
+             * @param {HtmlEditor} this
+             */
+            firstfocus: true,
+            /**
+             * @event autosave
+             * Auto save the htmlEditor value as a file into Events
+             * @param {HtmlEditor} this
+             */
+            autosave: true,
+            /**
+             * @event savedpreview
+             * preview the saved version of htmlEditor
+             * @param {HtmlEditor} this
+             */
+            savedpreview: true
+        });
+};
+
+
+Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
     
-    this.editor = config.editor;
-    this.editorcore = config.editor.editorcore;
     
-    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
+      /**
+     * @cfg {Array} toolbars Array of toolbars. - defaults to just the Standard one
+     */
+    toolbars : false,
+   
+     /**
+     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
+     *                        Roo.resizable.
+     */
+    resizable : false,
+     /**
+     * @cfg {Number} height (in pixels)
+     */   
+    height: 300,
+   /**
+     * @cfg {Number} width (in pixels)
+     */   
+    width: false,
     
-    //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
-    // dont call parent... till later.
-}
-Roo.extend(Roo.bootstrap.HtmlEditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,  {
+    /**
+     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
+     * 
+     */
+    stylesheets: false,
     
+    // id of frame..
+    frameId: false,
     
-    bar : true,
+    // private properties
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
     
-    editor : false,
-    editorcore : false,
+    onFocus : Roo.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
     
     
-    formats : [
-        "p" ,  
-        "h1","h2","h3","h4","h5","h6", 
-        "pre", "code", 
-        "abbr", "acronym", "address", "cite", "samp", "var",
-        'div','span'
-    ],
+    tbContainer : false,
     
+    toolbarContainer :function() {
+        return this.wrap.select('.x-html-editor-tb',true).first();
+    },
+
+    /**
+     * Protected method that will not generally be called directly. It
+     * is called when the editor creates its toolbar. Override this method if you need to
+     * add custom toolbar buttons.
+     * @param {HtmlEditor} editor
+     */
+    createToolbar : function(){
+        
+        Roo.log("create toolbars");
+        
+        this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
+        this.toolbars[0].render(this.toolbarContainer());
+        
+        return;
+        
+//        if (!editor.toolbars || !editor.toolbars.length) {
+//            editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
+//        }
+//        
+//        for (var i =0 ; i < editor.toolbars.length;i++) {
+//            editor.toolbars[i] = Roo.factory(
+//                    typeof(editor.toolbars[i]) == 'string' ?
+//                        { xtype: editor.toolbars[i]} : editor.toolbars[i],
+//                Roo.bootstrap.HtmlEditor);
+//            editor.toolbars[i].init(editor);
+//        }
+    },
+
+     
+    // private
     onRender : function(ct, position)
     {
        // Roo.log("Call onRender: " + this.xtype);
+        var _t = this;
+        Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
+      
+        this.wrap = this.inputEl().wrap({
+            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
+        });
         
-       Roo.bootstrap.HtmlEditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
-       Roo.log(this.el);
-       this.el.dom.style.marginBottom = '0';
-       var _this = this;
-       var editorcore = this.editorcore;
-       var editor= this.editor;
-       
-       var children = [];
-       var btn = function(id,cmd , toggle, handler){
-       
-            var  event = toggle ? 'toggle' : 'click';
-       
-            var a = {
-                size : 'sm',
-                xtype: 'Button',
-                xns: Roo.bootstrap,
-                glyphicon : id,
-                cmd : id || cmd,
-                enableToggle:toggle !== false,
-                //html : 'submit'
-                pressed : toggle ? false : null,
-                listeners : {}
-            }
-            a.listeners[toggle ? 'toggle' : 'click'] = function() {
-                handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd ||  id);
-            }
-            children.push(a);
-            return a;
-       }
-        
-        var style = {
-                xtype: 'Button',
-                size : 'sm',
-                xns: Roo.bootstrap,
-                glyphicon : 'font',
-                //html : 'submit'
-                menu : {
-                    xtype: 'Menu',
-                    xns: Roo.bootstrap,
-                    items:  []
-                }
-        };
-        Roo.each(this.formats, function(f) {
-            style.menu.items.push({
-                xtype :'MenuItem',
-                xns: Roo.bootstrap,
-                html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
-                tagname : f,
+        this.editorcore.onRender(ct, position);
+         
+        if (this.resizable) {
+            this.resizeEl = new Roo.Resizable(this.wrap, {
+                pinned : true,
+                wrap: true,
+                dynamic : true,
+                minHeight : this.height,
+                height: this.height,
+                handles : this.resizable,
+                width: this.width,
                 listeners : {
-                    click : function()
-                    {
-                        editorcore.insertTag(this.tagname);
-                        editor.focus();
+                    resize : function(r, w, h) {
+                        _t.onResize(w,h); // -something
                     }
                 }
-                
             });
-        });
-         children.push(style);   
-            
-            
-        btn('bold',false,true);
-        btn('italic',false,true);
-        btn('align-left', 'justifyleft',true);
-        btn('align-center', 'justifycenter',true);
-        btn('align-right' , 'justifyright',true);
-        btn('link', false, false, function(btn) {
-            //Roo.log("create link?");
-            var url = prompt(this.createLinkText, this.defaultLinkValue);
-            if(url && url != 'http:/'+'/'){
-                this.editorcore.relayCmd('createlink', url);
-            }
-        }),
-        btn('list','insertunorderedlist',true);
-        btn('pencil', false,true, function(btn){
-                Roo.log(this);
-                
-                this.toggleSourceEdit(btn.pressed);
-        });
-        /*
-        var cog = {
-                xtype: 'Button',
-                size : 'sm',
-                xns: Roo.bootstrap,
-                glyphicon : 'cog',
-                //html : 'submit'
-                menu : {
-                    xtype: 'Menu',
-                    xns: Roo.bootstrap,
-                    items:  []
-                }
-        };
-        
-        cog.menu.items.push({
-            xtype :'MenuItem',
-            xns: Roo.bootstrap,
-            html : Clean styles,
-            tagname : f,
-            listeners : {
-                click : function()
-                {
-                    editorcore.insertTag(this.tagname);
-                    editor.focus();
-                }
-            }
             
-        });
-       */
-        
-         
-       this.xtype = 'NavSimplebar';
+        }
+        this.createToolbar(this);
+       
         
-        for(var i=0;i< children.length;i++) {
-            
-            this.buttons.add(this.addxtypeChild(children[i]));
-            
+        if(!this.width && this.resizable){
+            this.setSize(this.wrap.getSize());
+        }
+        if (this.resizeEl) {
+            this.resizeEl.resizeTo.defer(100, this.resizeEl,[ this.width,this.height ] );
+            // should trigger onReize..
         }
         
-        editor.on('editorevent', this.updateToolbar, this);
     },
-    onBtnClick : function(id)
-    {
-       this.editorcore.relayCmd(id);
-       this.editorcore.focus();
-    },
-    
-    /**
-     * Protected method that will not generally be called directly. It triggers
-     * a toolbar update by reading the markup state of the current selection in the editor.
-     */
-    updateToolbar: function(){
-
-        if(!this.editorcore.activated){
-            this.editor.onFirstFocus(); // is this neeed?
-            return;
-        }
 
-        var btns = this.buttons; 
-        var doc = this.editorcore.doc;
-        btns.get('bold').setActive(doc.queryCommandState('bold'));
-        btns.get('italic').setActive(doc.queryCommandState('italic'));
-        //btns.get('underline').setActive(doc.queryCommandState('underline'));
-        
-        btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
-        btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
-        btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
-        
-        //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
-        btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
-         /*
+    // private
+    onResize : function(w, h)
+    {
+        Roo.log('resize: ' +w + ',' + h );
+        Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
+        var ew = false;
+        var eh = false;
         
-        var ans = this.editorcore.getAllAncestors();
-        if (this.formatCombo) {
-            
-            
-            var store = this.formatCombo.store;
-            this.formatCombo.setValue("");
-            for (var i =0; i < ans.length;i++) {
-                if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
-                    // select it..
-                    this.formatCombo.setValue(ans[i].tagName.toLowerCase());
-                    break;
+        if(this.inputEl() ){
+            if(typeof w == 'number'){
+                var aw = w - this.wrap.getFrameWidth('lr');
+                this.inputEl().setWidth(this.adjustWidth('textarea', aw));
+                ew = aw;
+            }
+            if(typeof h == 'number'){
+                 var tbh = -11;  // fixme it needs to tool bar size!
+                for (var i =0; i < this.toolbars.length;i++) {
+                    // fixme - ask toolbars for heights?
+                    tbh += this.toolbars[i].el.getHeight();
+                    //if (this.toolbars[i].footer) {
+                    //    tbh += this.toolbars[i].footer.el.getHeight();
+                    //}
                 }
+              
+                
+                
+                
+                
+                var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
+                ah -= 5; // knock a few pixes off for look..
+                this.inputEl().setHeight(this.adjustWidth('textarea', ah));
+                var eh = ah;
             }
         }
+        Roo.log('onResize:' + [w,h,ew,eh].join(',') );
+        this.editorcore.onResize(ew,eh);
         
-        
-        
-        // hides menus... - so this cant be on a menu...
-        Roo.bootstrap.MenuMgr.hideAll();
-        */
-        Roo.bootstrap.MenuMgr.hideAll();
-        //this.editorsyncValue();
-    },
-    onFirstFocus: function() {
-        this.buttons.each(function(item){
-           item.enable();
-        });
     },
-    toggleSourceEdit : function(sourceEditMode){
+
+    /**
+     * Toggles the editor between standard and source edit mode.
+     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     */
+    toggleSourceEdit : function(sourceEditMode)
+    {
+        this.editorcore.toggleSourceEdit(sourceEditMode);
         
-          
-        if(sourceEditMode){
-            Roo.log("disabling buttons");
-           this.buttons.each( function(item){
-                if(item.cmd != 'pencil'){
-                    item.disable();
-                }
-            });
-          
+        if(this.editorcore.sourceEditMode){
+            Roo.log('editor - showing textarea');
+            
+//            Roo.log('in');
+//            Roo.log(this.syncValue());
+            this.syncValue();
+            this.inputEl().removeClass('hide');
+            this.inputEl().dom.removeAttribute('tabIndex');
+            this.inputEl().focus();
         }else{
-            Roo.log("enabling buttons");
-            if(this.editorcore.initialized){
-                this.buttons.each( function(item){
-                    item.enable();
-                });
-            }
+            Roo.log('editor - hiding textarea');
+//            Roo.log('out')
+//            Roo.log(this.pushValue()); 
+            this.pushValue();
             
+            this.inputEl().addClass('hide');
+            this.inputEl().dom.setAttribute('tabIndex', -1);
+            //this.deferFocus();
         }
-        Roo.log("calling toggole on editor");
-        // tell the editor that it's been pressed..
-        this.editor.toggleSourceEdit(sourceEditMode);
-       
-    }
-});
-
-
+         
+        if(this.resizable){
+            this.setSize(this.wrap.getSize());
+        }
+        
+        this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
+    },
+    // private (for BoxComponent)
+    adjustSize : Roo.BoxComponent.prototype.adjustSize,
 
+    // private (for BoxComponent)
+    getResizeEl : function(){
+        return this.wrap;
+    },
 
+    // private (for BoxComponent)
+    getPositionEl : function(){
+        return this.wrap;
+    },
 
-/**
- * @class Roo.bootstrap.Table.AbstractSelectionModel
- * @extends Roo.util.Observable
- * Abstract base class for grid SelectionModels.  It provides the interface that should be
- * implemented by descendant classes.  This class should not be directly instantiated.
- * @constructor
- */
-Roo.bootstrap.Table.AbstractSelectionModel = function(){
-    this.locked = false;
-    Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
-};
+    // private
+    initEvents : function(){
+        this.originalValue = this.getValue();
+    },
 
+//    /**
+//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+//     * @method
+//     */
+//    markInvalid : Roo.emptyFn,
+//    /**
+//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+//     * @method
+//     */
+//    clearInvalid : Roo.emptyFn,
 
-Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable,  {
-    /** @ignore Called by the grid automatically. Do not call directly. */
-    init : function(grid){
-        this.grid = grid;
-        this.initEvents();
+    setValue : function(v){
+        Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
+        this.editorcore.pushValue();
     },
 
-    /**
-     * Locks the selections.
-     */
-    lock : function(){
-        this.locked = true;
+     
+    // private
+    deferFocus : function(){
+        this.focus.defer(10, this);
     },
 
-    /**
-     * Unlocks the selections.
-     */
-    unlock : function(){
-        this.locked = false;
+    // doc'ed in Field
+    focus : function(){
+        this.editorcore.focus();
+        
     },
+      
 
-    /**
-     * Returns true if the selections are locked.
-     * @return {Boolean}
-     */
-    isLocked : function(){
-        return this.locked;
-    }
-});
-/**
- * @class Roo.bootstrap.Table.ColumnModel
- * @extends Roo.util.Observable
- * This is the default implementation of a ColumnModel used by the bootstrap table. It defines
- * the columns in the table.
- * @constructor
- * @param {Object} config An Array of column config objects. See this class's
- * config objects for details.
-*/
-Roo.bootstrap.Table.ColumnModel = function(config){
-       /**
-     * The config passed into the constructor
-     */
-    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();
+    // private
+    onDestroy : function(){
+        
+        
+        
+        if(this.rendered){
+            
+            for (var i =0; i < this.toolbars.length;i++) {
+                // fixme - ask toolbars for heights?
+                this.toolbars[i].onDestroy();
+            }
+            
+            this.wrap.dom.innerHTML = '';
+            this.wrap.remove();
         }
-//        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;
-    }
-
-    /**
-     * The width of columns which have no width specified (defaults to 100)
-     * @type Number
-     */
-    this.defaultWidth = 100;
-
-    /**
-     * Default sortable of columns which have no sortable specified (defaults to false)
-     * @type Boolean
-     */
-    this.defaultSortable = false;
-
-    this.addEvents({
-        /**
-            * @event widthchange
-            * Fires when the width of a column changes.
-            * @param {ColumnModel} this
-            * @param {Number} columnIndex The column index
-            * @param {Number} newWidth The new width
-            */
-           "widthchange": true,
-        /**
-            * @event headerchange
-            * Fires when the text of a header changes.
-            * @param {ColumnModel} this
-            * @param {Number} columnIndex The column index
-            * @param {Number} newText The new header text
-            */
-           "headerchange": true,
-        /**
-            * @event hiddenchange
-            * Fires when a column is hidden or "unhidden".
-            * @param {ColumnModel} this
-            * @param {Number} columnIndex The column index
-            * @param {Boolean} hidden true if hidden, false otherwise
-            */
-           "hiddenchange": true,
-           /**
-         * @event columnmoved
-         * Fires when a column is moved.
-         * @param {ColumnModel} this
-         * @param {Number} oldIndex
-         * @param {Number} newIndex
-         */
-        "columnmoved" : true,
-        /**
-         * @event columlockchange
-         * Fires when a column's locked state is changed
-         * @param {ColumnModel} this
-         * @param {Number} colIndex
-         * @param {Boolean} locked true if locked
-         */
-        "columnlockchange" : true
-    });
-    Roo.bootstrap.Table.ColumnModel.superclass.constructor.call(this);
-};
-Roo.extend(Roo.bootstrap.Table.ColumnModel, Roo.util.Observable, {
+    },
+
+    // private
+    onFirstFocus : function(){
+        //Roo.log("onFirstFocus");
+        this.editorcore.onFirstFocus();
+         for (var i =0; i < this.toolbars.length;i++) {
+            this.toolbars[i].onFirstFocus();
+        }
+        
+    },
+    
+    // private
+    syncValue : function()
+    {   
+        this.editorcore.syncValue();
+    },
+    
+    pushValue : function()
+    {   
+        this.editorcore.pushValue();
+    }
+     
+    
+    // hide stuff that is not compatible
     /**
-     * @cfg {String} header The header text to display in the Grid view.
+     * @event blur
+     * @hide
      */
     /**
-     * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s
-     * {@link Roo.data.Record} definition from which to draw the column's value. If not
-     * specified, the column's index is used as an index into the Record's data Array.
+     * @event change
+     * @hide
      */
     /**
-     * @cfg {Number} width (Optional) The initial width in pixels of the column. Using this
-     * instead of {@link Roo.grid.Grid#autoSizeColumns} is more efficient.
+     * @event focus
+     * @hide
      */
     /**
-     * @cfg {Boolean} sortable (Optional) True if sorting is to be allowed on this column.
-     * Defaults to the value of the {@link #defaultSortable} property.
-     * Whether local/remote sorting is used is specified in {@link Roo.data.Store#remoteSort}.
+     * @event specialkey
+     * @hide
      */
     /**
-     * @cfg {Boolean} locked (Optional) True to lock the column in place while scrolling the Grid.  Defaults to false.
+     * @cfg {String} fieldClass @hide
      */
     /**
-     * @cfg {Boolean} fixed (Optional) True if the column width cannot be changed.  Defaults to false.
+     * @cfg {String} focusClass @hide
      */
     /**
-     * @cfg {Boolean} resizable (Optional) False to disable column resizing. Defaults to true.
+     * @cfg {String} autoCreate @hide
      */
     /**
-     * @cfg {Boolean} hidden (Optional) True to hide the column. Defaults to false.
+     * @cfg {String} inputType @hide
      */
     /**
-     * @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.
+     * @cfg {String} invalidClass @hide
      */
     /**
-     * @cfg {String} align (Optional) Set the CSS text-align property of the column.  Defaults to undefined.
+     * @cfg {String} invalidText @hide
      */
-
     /**
-     * Returns the id of the column at the specified index.
-     * @param {Number} index The column index
-     * @return {String} the id
+     * @cfg {String} msgFx @hide
      */
-    getColumnId : function(index){
-        return this.config[index].id;
-    },
-
     /**
-     * Returns the column for a specified id.
-     * @param {String} id The column id
-     * @return {Object} the column
+     * @cfg {String} validateOnBlur @hide
      */
-    getColumnById : function(id){
-        return this.lookup[id];
-    },
-
+});
     
-    /**
-     * Returns the column for a specified dataIndex.
-     * @param {String} dataIndex The column dataIndex
-     * @return {Object|Boolean} the column or false if not found
-     */
-    getColumnByDataIndex: function(dataIndex){
-        var index = this.findColumnIndex(dataIndex);
-        return index > -1 ? this.config[index] : false;
-    },
+   
+   
+   
+      
+Roo.namespace('Roo.bootstrap.htmleditor');
+/**
+ * @class Roo.bootstrap.HtmlEditorToolbar1
+ * Basic Toolbar
+ * 
+ * Usage:
+ *
+ new Roo.bootstrap.HtmlEditor({
+    ....
+    toolbars : [
+        new Roo.bootstrap.HtmlEditorToolbar1({
+            disable : { fonts: 1 , format: 1, ..., ... , ...],
+            btns : [ .... ]
+        })
+    }
+     
+ * 
+ * @cfg {Object} disable List of elements to disable..
+ * @cfg {Array} btns List of additional buttons.
+ * 
+ * 
+ * NEEDS Extra CSS? 
+ * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
+ */
+Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
+{
     
-    /**
-     * Returns the index for a specified column id.
-     * @param {String} id The column id
-     * @return {Number} the index, or -1 if not found
-     */
-    getIndexById : function(id){
-        for(var i = 0, len = this.config.length; i < len; i++){
-            if(this.config[i].id == id){
-                return i;
-            }
-        }
-        return -1;
-    },
+    Roo.apply(this, config);
     
-    /**
-     * Returns the index for a specified column dataIndex.
-     * @param {String} dataIndex The column dataIndex
-     * @return {Number} the index, or -1 if not found
-     */
+    // default disabled, based on 'good practice'..
+    this.disable = this.disable || {};
+    Roo.applyIf(this.disable, {
+        fontSize : true,
+        colors : true,
+        specialElements : true
+    });
+    Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
     
-    findColumnIndex : function(dataIndex){
-        for(var i = 0, len = this.config.length; i < len; i++){
-            if(this.config[i].dataIndex == dataIndex){
-                return i;
-            }
-        }
-        return -1;
-    },
+    this.editor = config.editor;
+    this.editorcore = config.editor.editorcore;
     
+    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
     
-    moveColumn : function(oldIndex, newIndex){
-        var c = this.config[oldIndex];
-        this.config.splice(oldIndex, 1);
-        this.config.splice(newIndex, 0, c);
-        this.dataMap = null;
-        this.fireEvent("columnmoved", this, oldIndex, newIndex);
-    },
-
-    isLocked : function(colIndex){
-        return this.config[colIndex].locked === true;
-    },
-
-    setLocked : function(colIndex, value, suppressEvent){
-        if(this.isLocked(colIndex) == value){
-            return;
-        }
-        this.config[colIndex].locked = value;
-        if(!suppressEvent){
-            this.fireEvent("columnlockchange", this, colIndex, value);
-        }
-    },
-
-    getTotalLockedWidth : function(){
-        var totalWidth = 0;
-        for(var i = 0; i < this.config.length; i++){
-            if(this.isLocked(i) && !this.isHidden(i)){
-                this.totalWidth += this.getColumnWidth(i);
+    //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
+    // dont call parent... till later.
+}
+Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,  {
+     
+    bar : true,
+    
+    editor : false,
+    editorcore : false,
+    
+    
+    formats : [
+        "p" ,  
+        "h1","h2","h3","h4","h5","h6", 
+        "pre", "code", 
+        "abbr", "acronym", "address", "cite", "samp", "var",
+        'div','span'
+    ],
+    
+    onRender : function(ct, position)
+    {
+       // Roo.log("Call onRender: " + this.xtype);
+        
+       Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
+       Roo.log(this.el);
+       this.el.dom.style.marginBottom = '0';
+       var _this = this;
+       var editorcore = this.editorcore;
+       var editor= this.editor;
+       
+       var children = [];
+       var btn = function(id,cmd , toggle, handler){
+       
+            var  event = toggle ? 'toggle' : 'click';
+       
+            var a = {
+                size : 'sm',
+                xtype: 'Button',
+                xns: Roo.bootstrap,
+                glyphicon : id,
+                cmd : id || cmd,
+                enableToggle:toggle !== false,
+                //html : 'submit'
+                pressed : toggle ? false : null,
+                listeners : {}
             }
-        }
-        return totalWidth;
-    },
-
-    getLockedCount : function(){
-        for(var i = 0, len = this.config.length; i < len; i++){
-            if(!this.isLocked(i)){
-                return i;
+            a.listeners[toggle ? 'toggle' : 'click'] = function() {
+                handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd ||  id);
             }
-        }
-    },
-
-    /**
-     * Returns the number of columns.
-     * @return {Number}
-     */
-    getColumnCount : function(visibleOnly){
-        if(visibleOnly === true){
-            var c = 0;
-            for(var i = 0, len = this.config.length; i < len; i++){
-                if(!this.isHidden(i)){
-                    c++;
+            children.push(a);
+            return a;
+       }
+        
+        var style = {
+                xtype: 'Button',
+                size : 'sm',
+                xns: Roo.bootstrap,
+                glyphicon : 'font',
+                //html : 'submit'
+                menu : {
+                    xtype: 'Menu',
+                    xns: Roo.bootstrap,
+                    items:  []
                 }
+        };
+        Roo.each(this.formats, function(f) {
+            style.menu.items.push({
+                xtype :'MenuItem',
+                xns: Roo.bootstrap,
+                html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
+                tagname : f,
+                listeners : {
+                    click : function()
+                    {
+                        editorcore.insertTag(this.tagname);
+                        editor.focus();
+                    }
+                }
+                
+            });
+        });
+         children.push(style);   
+            
+            
+        btn('bold',false,true);
+        btn('italic',false,true);
+        btn('align-left', 'justifyleft',true);
+        btn('align-center', 'justifycenter',true);
+        btn('align-right' , 'justifyright',true);
+        btn('link', false, false, function(btn) {
+            //Roo.log("create link?");
+            var url = prompt(this.createLinkText, this.defaultLinkValue);
+            if(url && url != 'http:/'+'/'){
+                this.editorcore.relayCmd('createlink', url);
             }
-            return c;
-        }
-        return this.config.length;
-    },
-
-    /**
-     * Returns the column configs that return true by the passed function that is called with (columnConfig, index)
-     * @param {Function} fn
-     * @param {Object} scope (optional)
-     * @return {Array} result
-     */
-    getColumnsBy : function(fn, scope){
-        var r = [];
-        for(var i = 0, len = this.config.length; i < len; i++){
-            var c = this.config[i];
-            if(fn.call(scope||this, c, i) === true){
-                r[r.length] = c;
+        }),
+        btn('list','insertunorderedlist',true);
+        btn('pencil', false,true, function(btn){
+                Roo.log(this);
+                
+                this.toggleSourceEdit(btn.pressed);
+        });
+        /*
+        var cog = {
+                xtype: 'Button',
+                size : 'sm',
+                xns: Roo.bootstrap,
+                glyphicon : 'cog',
+                //html : 'submit'
+                menu : {
+                    xtype: 'Menu',
+                    xns: Roo.bootstrap,
+                    items:  []
+                }
+        };
+        
+        cog.menu.items.push({
+            xtype :'MenuItem',
+            xns: Roo.bootstrap,
+            html : Clean styles,
+            tagname : f,
+            listeners : {
+                click : function()
+                {
+                    editorcore.insertTag(this.tagname);
+                    editor.focus();
+                }
             }
+            
+        });
+       */
+        
+         
+       this.xtype = 'NavSimplebar';
+        
+        for(var i=0;i< children.length;i++) {
+            
+            this.buttons.add(this.addxtypeChild(children[i]));
+            
         }
-        return r;
-    },
-
-    /**
-     * Returns true if the specified column is sortable.
-     * @param {Number} col The column index
-     * @return {Boolean}
-     */
-    isSortable : function(col){
-        if(typeof this.config[col].sortable == "undefined"){
-            return this.defaultSortable;
-        }
-        return this.config[col].sortable;
-    },
-
-    /**
-     * Returns the rendering (formatting) function defined for the column.
-     * @param {Number} col The column index.
-     * @return {Function} The function used to render the cell. See {@link #setRenderer}.
-     */
-    getRenderer : function(col){
-        if(!this.config[col].renderer){
-            return Roo.bootstrap.Table.ColumnModel.defaultRenderer;
-        }
-        return this.config[col].renderer;
+        
+        editor.on('editorevent', this.updateToolbar, this);
     },
-
-    /**
-     * Sets the rendering (formatting) function for a column.
-     * @param {Number} col The column index
-     * @param {Function} fn The function to use to process the cell's raw data
-     * to return HTML markup for the grid view. The render function is called with
-     * the following parameters:<ul>
-     * <li>Data value.</li>
-     * <li>Cell metadata. An object in which you may set the following attributes:<ul>
-     * <li>css A CSS style string to apply to the table cell.</li>
-     * <li>attr An HTML attribute definition string to apply to the data container element <i>within</i> the table cell.</li></ul>
-     * <li>The {@link Roo.data.Record} from which the data was extracted.</li>
-     * <li>Row index</li>
-     * <li>Column index</li>
-     * <li>The {@link Roo.data.Store} object from which the Record was extracted</li></ul>
-     */
-    setRenderer : function(col, fn){
-        this.config[col].renderer = fn;
+    onBtnClick : function(id)
+    {
+       this.editorcore.relayCmd(id);
+       this.editorcore.focus();
     },
-
+    
     /**
-     * Returns the width for the specified column.
-     * @param {Number} col The column index
-     * @return {Number}
+     * Protected method that will not generally be called directly. It triggers
+     * a toolbar update by reading the markup state of the current selection in the editor.
      */
-    getColumnWidth : function(col){
-        return this.config[col].width * 1 || this.defaultWidth;
-    },
+    updateToolbar: function(){
 
-    /**
-     * Sets the width for a column.
-     * @param {Number} col The column index
-     * @param {Number} width The new width
-     */
-    setColumnWidth : function(col, width, suppressEvent){
-        this.config[col].width = width;
-        this.totalWidth = null;
-        if(!suppressEvent){
-             this.fireEvent("widthchange", this, col, width);
+        if(!this.editorcore.activated){
+            this.editor.onFirstFocus(); // is this neeed?
+            return;
         }
-    },
 
-    /**
-     * Returns the total width of all columns.
-     * @param {Boolean} includeHidden True to include hidden column widths
-     * @return {Number}
-     */
-    getTotalWidth : function(includeHidden){
-        if(!this.totalWidth){
-            this.totalWidth = 0;
-            for(var i = 0, len = this.config.length; i < len; i++){
-                if(includeHidden || !this.isHidden(i)){
-                    this.totalWidth += this.getColumnWidth(i);
+        var btns = this.buttons; 
+        var doc = this.editorcore.doc;
+        btns.get('bold').setActive(doc.queryCommandState('bold'));
+        btns.get('italic').setActive(doc.queryCommandState('italic'));
+        //btns.get('underline').setActive(doc.queryCommandState('underline'));
+        
+        btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
+        btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
+        btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
+        
+        //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
+        btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
+         /*
+        
+        var ans = this.editorcore.getAllAncestors();
+        if (this.formatCombo) {
+            
+            
+            var store = this.formatCombo.store;
+            this.formatCombo.setValue("");
+            for (var i =0; i < ans.length;i++) {
+                if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
+                    // select it..
+                    this.formatCombo.setValue(ans[i].tagName.toLowerCase());
+                    break;
                 }
             }
         }
-        return this.totalWidth;
-    },
-
-    /**
-     * Returns the header for the specified column.
-     * @param {Number} col The column index
-     * @return {String}
-     */
-    getColumnHeader : function(col){
-        return this.config[col].header;
-    },
-
-    /**
-     * Sets the header for a column.
-     * @param {Number} col The column index
-     * @param {String} header The new header
-     */
-    setColumnHeader : function(col, header){
-        this.config[col].header = header;
-        this.fireEvent("headerchange", this, col, header);
-    },
-
-    /**
-     * Returns the tooltip for the specified column.
-     * @param {Number} col The column index
-     * @return {String}
-     */
-    getColumnTooltip : function(col){
-            return this.config[col].tooltip;
-    },
-    /**
-     * Sets the tooltip for a column.
-     * @param {Number} col The column index
-     * @param {String} tooltip The new tooltip
-     */
-    setColumnTooltip : function(col, tooltip){
-            this.config[col].tooltip = tooltip;
-    },
-
-    /**
-     * Returns the dataIndex for the specified column.
-     * @param {Number} col The column index
-     * @return {Number}
-     */
-    getDataIndex : function(col){
-        return this.config[col].dataIndex;
-    },
-
-    /**
-     * Sets the dataIndex for a column.
-     * @param {Number} col The column index
-     * @param {Number} dataIndex The new dataIndex
-     */
-    setDataIndex : function(col, dataIndex){
-        this.config[col].dataIndex = dataIndex;
+        
+        
+        
+        // hides menus... - so this cant be on a menu...
+        Roo.bootstrap.MenuMgr.hideAll();
+        */
+        Roo.bootstrap.MenuMgr.hideAll();
+        //this.editorsyncValue();
     },
-
-    
-    
-    /**
-     * Returns true if the cell is editable.
-     * @param {Number} colIndex The column index
-     * @param {Number} rowIndex The row index
-     * @return {Boolean}
-     */
-    isCellEditable : function(colIndex, rowIndex){
-        return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
+    onFirstFocus: function() {
+        this.buttons.each(function(item){
+           item.enable();
+        });
     },
+    toggleSourceEdit : function(sourceEditMode){
+        
+          
+        if(sourceEditMode){
+            Roo.log("disabling buttons");
+           this.buttons.each( function(item){
+                if(item.cmd != 'pencil'){
+                    item.disable();
+                }
+            });
+          
+        }else{
+            Roo.log("enabling buttons");
+            if(this.editorcore.initialized){
+                this.buttons.each( function(item){
+                    item.enable();
+                });
+            }
+            
+        }
+        Roo.log("calling toggole on editor");
+        // tell the editor that it's been pressed..
+        this.editor.toggleSourceEdit(sourceEditMode);
+       
+    }
+});
 
-    /**
-     * Returns the editor defined for the cell/column.
-     * return false or null to disable editing.
-     * @param {Number} colIndex The column index
-     * @param {Number} rowIndex The row index
-     * @return {Object}
-     */
-    getCellEditor : function(colIndex, rowIndex){
-        return this.config[colIndex].editor;
-    },
 
-    /**
-     * Sets if a column is editable.
-     * @param {Number} col The column index
-     * @param {Boolean} editable True if the column is editable
-     */
-    setEditable : function(col, editable){
-        this.config[col].editable = editable;
-    },
 
 
-    /**
-     * Returns true if the column is hidden.
-     * @param {Number} colIndex The column index
-     * @return {Boolean}
-     */
-    isHidden : function(colIndex){
-        return this.config[colIndex].hidden;
-    },
+
+/**
+ * @class Roo.bootstrap.Table.AbstractSelectionModel
+ * @extends Roo.util.Observable
+ * Abstract base class for grid SelectionModels.  It provides the interface that should be
+ * implemented by descendant classes.  This class should not be directly instantiated.
+ * @constructor
+ */
+Roo.bootstrap.Table.AbstractSelectionModel = function(){
+    this.locked = false;
+    Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
+};
 
 
-    /**
-     * Returns true if the column width cannot be changed
-     */
-    isFixed : function(colIndex){
-        return this.config[colIndex].fixed;
+Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable,  {
+    /** @ignore Called by the grid automatically. Do not call directly. */
+    init : function(grid){
+        this.grid = grid;
+        this.initEvents();
     },
 
     /**
-     * Returns true if the column can be resized
-     * @return {Boolean}
+     * Locks the selections.
      */
-    isResizable : function(colIndex){
-        return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
+    lock : function(){
+        this.locked = true;
     },
+
     /**
-     * Sets if a column is hidden.
-     * @param {Number} colIndex The column index
-     * @param {Boolean} hidden True if the column is hidden
+     * Unlocks the selections.
      */
-    setHidden : function(colIndex, hidden){
-        this.config[colIndex].hidden = hidden;
-        this.totalWidth = null;
-        this.fireEvent("hiddenchange", this, colIndex, hidden);
+    unlock : function(){
+        this.locked = false;
     },
 
     /**
-     * Sets the editor for a column.
-     * @param {Number} col The column index
-     * @param {Object} editor The editor object
+     * Returns true if the selections are locked.
+     * @return {Boolean}
      */
-    setEditor : function(col, editor){
-        this.config[col].editor = editor;
+    isLocked : function(){
+        return this.locked;
     }
 });
-
-Roo.bootstrap.Table.ColumnModel.defaultRenderer = function(value){
-       if(typeof value == "string" && value.length < 1){
-           return "&#160;";
-       }
-       return value;
-};
-
-// Alias for backwards compatibility
-Roo.bootstrap.Table.DefaultColumnModel = Roo.bootstrap.Table.ColumnModel;
-
 /**
  * @extends Roo.bootstrap.Table.AbstractSelectionModel
  * @class Roo.bootstrap.Table.RowSelectionModel
@@ -17413,85 +17567,425 @@ Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSe
     },
 
     /**
-     * Selects a row.
-     * @param {Number} row The index of the row to select
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     * Selects a row.
+     * @param {Number} row The index of the row to select
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectRow : function(index, keepExisting, preventViewNotify){
+        if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) return;
+        if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
+            if(!keepExisting || this.singleSelect){
+                this.clearSelections();
+            }
+            var r = this.grid.dataSource.getAt(index);
+            this.selections.add(r);
+            this.last = this.lastActive = index;
+            if(!preventViewNotify){
+                this.grid.getView().onRowSelect(index);
+            }
+            this.fireEvent("rowselect", this, index, r);
+            this.fireEvent("selectionchange", this);
+        }
+    },
+
+    /**
+     * Deselects a row.
+     * @param {Number} row The index of the row to deselect
+     */
+    deselectRow : function(index, preventViewNotify){
+        if(this.locked) return;
+        if(this.last == index){
+            this.last = false;
+        }
+        if(this.lastActive == index){
+            this.lastActive = false;
+        }
+        var r = this.grid.dataSource.getAt(index);
+        this.selections.remove(r);
+        if(!preventViewNotify){
+            this.grid.getView().onRowDeselect(index);
+        }
+        this.fireEvent("rowdeselect", this, index);
+        this.fireEvent("selectionchange", this);
+    },
+
+    // private
+    restoreLast : function(){
+        if(this._last){
+            this.last = this._last;
+        }
+    },
+
+    // private
+    acceptsNav : function(row, col, cm){
+        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    },
+
+    // private
+    onEditorKey : function(field, e){
+        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
+        if(k == e.TAB){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
+            }
+        }else if(k == e.ENTER && !e.ctrlKey){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
+            }
+        }else if(k == e.ESC){
+            ed.cancelEdit();
+        }
+        if(newCell){
+            g.startEditing(newCell[0], newCell[1]);
+        }
+    }
+});/*
+ * 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">
+ */
+/**
+ * @class Roo.bootstrap.PagingToolbar
+ * @extends Roo.Row
+ * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
+ * @constructor
+ * Create a new PagingToolbar
+ * @param {Object} config The config object
+ */
+Roo.bootstrap.PagingToolbar = function(config)
+{
+    // old args format still supported... - xtype is prefered..
+        // created from xtype...
+    var ds = config.dataSource;
+    this.toolbarItems = [];
+    if (config.items) {
+        this.toolbarItems = config.items;
+//        config.items = [];
+    }
+    
+    Roo.bootstrap.PagingToolbar.superclass.constructor.call(this, config);
+    this.ds = ds;
+    this.cursor = 0;
+    if (ds) { 
+        this.bind(ds);
+    }
+    
+    this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
+    
+};
+
+Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
+    /**
+     * @cfg {Roo.data.Store} dataSource
+     * The underlying data store providing the paged data
+     */
+    /**
+     * @cfg {String/HTMLElement/Element} container
+     * container The id or element that will contain the toolbar
+     */
+    /**
+     * @cfg {Boolean} displayInfo
+     * True to display the displayMsg (defaults to false)
+     */
+    /**
+     * @cfg {Number} pageSize
+     * The number of records to display per page (defaults to 20)
+     */
+    pageSize: 20,
+    /**
+     * @cfg {String} displayMsg
+     * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
+     */
+    displayMsg : 'Displaying {0} - {1} of {2}',
+    /**
+     * @cfg {String} emptyMsg
+     * The message to display when no records are found (defaults to "No data to display")
+     */
+    emptyMsg : 'No data to display',
+    /**
+     * Customizable piece of the default paging text (defaults to "Page")
+     * @type String
+     */
+    beforePageText : "Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "of %0")
+     * @type String
+     */
+    afterPageText : "of {0}",
+    /**
+     * Customizable piece of the default paging text (defaults to "First Page")
+     * @type String
+     */
+    firstText : "First Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Previous Page")
+     * @type String
+     */
+    prevText : "Previous Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Next Page")
+     * @type String
+     */
+    nextText : "Next Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Last Page")
+     * @type String
      */
-    selectRow : function(index, keepExisting, preventViewNotify){
-        if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) return;
-        if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
-            if(!keepExisting || this.singleSelect){
-                this.clearSelections();
-            }
-            var r = this.grid.dataSource.getAt(index);
-            this.selections.add(r);
-            this.last = this.lastActive = index;
-            if(!preventViewNotify){
-                this.grid.getView().onRowSelect(index);
-            }
-            this.fireEvent("rowselect", this, index, r);
-            this.fireEvent("selectionchange", this);
-        }
-    },
-
+    lastText : "Last Page",
     /**
-     * Deselects a row.
-     * @param {Number} row The index of the row to deselect
+     * Customizable piece of the default paging text (defaults to "Refresh")
+     * @type String
      */
-    deselectRow : function(index, preventViewNotify){
-        if(this.locked) return;
-        if(this.last == index){
-            this.last = false;
-        }
-        if(this.lastActive == index){
-            this.lastActive = false;
+    refreshText : "Refresh",
+
+    buttons : false,
+    // private
+    onRender : function(ct, position) 
+    {
+        Roo.bootstrap.PagingToolbar.superclass.onRender.call(this, ct, position);
+        this.navgroup.parentId = this.id;
+        this.navgroup.onRender(this.el, null);
+        // add the buttons to the navgroup
+        
+        if(this.displayInfo){
+            Roo.log(this.el.select('ul.navbar-nav',true).first());
+            this.el.select('ul.navbar-nav',true).first().createChild({cls:'x-paging-info'});
+            this.displayEl = this.el.select('.x-paging-info', true).first();
+//            var navel = this.navgroup.addItem( { tagtype : 'span', html : '', cls : 'x-paging-info', preventDefault : true } );
+//            this.displayEl = navel.el.select('span',true).first();
         }
-        var r = this.grid.dataSource.getAt(index);
-        this.selections.remove(r);
-        if(!preventViewNotify){
-            this.grid.getView().onRowDeselect(index);
+        
+        var _this = this;
+        
+        if(this.buttons){
+            Roo.each(_this.buttons, function(e){
+               Roo.factory(e).onRender(_this.el, null);
+            });
         }
-        this.fireEvent("rowdeselect", this, index);
-        this.fireEvent("selectionchange", this);
+            
+        Roo.each(_this.toolbarItems, function(e) {
+            _this.navgroup.addItem(e);
+        });
+        
+        this.first = this.navgroup.addItem({
+            tooltip: this.firstText,
+            cls: "prev",
+            icon : 'fa fa-backward',
+            disabled: true,
+            listeners : { click : this.onClick.createDelegate(this, ["first"]) }
+        });
+        
+        this.prev =  this.navgroup.addItem({
+            tooltip: this.prevText,
+            cls: "prev",
+            icon : 'fa fa-step-backward',
+            disabled: true,
+            listeners : { click :  this.onClick.createDelegate(this, ["prev"]) }
+        });
+    //this.addSeparator();
+        
+        
+        var field = this.navgroup.addItem( {
+            tagtype : 'span',
+            cls : 'x-paging-position',
+            
+            html : this.beforePageText  +
+                '<input type="text" size="3" value="1" class="x-grid-page-number">' +
+                '<span class="x-paging-after">' +  String.format(this.afterPageText, 1) + '</span>'
+         } ); //?? escaped?
+        
+        this.field = field.el.select('input', true).first();
+        this.field.on("keydown", this.onPagingKeydown, this);
+        this.field.on("focus", function(){this.dom.select();});
+    
+    
+        this.afterTextEl =  field.el.select('.x-paging-after',true).first();
+        //this.field.setHeight(18);
+        //this.addSeparator();
+        this.next = this.navgroup.addItem({
+            tooltip: this.nextText,
+            cls: "next",
+            html : ' <i class="fa fa-step-forward">',
+            disabled: true,
+            listeners : { click :  this.onClick.createDelegate(this, ["next"]) }
+        });
+        this.last = this.navgroup.addItem({
+            tooltip: this.lastText,
+            icon : 'fa fa-forward',
+            cls: "next",
+            disabled: true,
+            listeners : { click :  this.onClick.createDelegate(this, ["last"]) }
+        });
+    //this.addSeparator();
+        this.loading = this.navgroup.addItem({
+            tooltip: this.refreshText,
+            icon: 'fa fa-refresh',
+            
+            listeners : { click : this.onClick.createDelegate(this, ["refresh"]) }
+        });
+
     },
 
     // private
-    restoreLast : function(){
-        if(this._last){
-            this.last = this._last;
+    updateInfo : function(){
+        if(this.displayEl){
+            var count = this.ds.getCount();
+            var msg = count == 0 ?
+                this.emptyMsg :
+                String.format(
+                    this.displayMsg,
+                    this.cursor+1, this.cursor+count, this.ds.getTotalCount()    
+                );
+            this.displayEl.update(msg);
         }
     },
 
     // private
-    acceptsNav : function(row, col, cm){
-        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    onLoad : function(ds, r, o){
+       this.cursor = o.params ? o.params.start : 0;
+       var d = this.getPageData(),
+            ap = d.activePage,
+            ps = d.pages;
+        
+       this.afterTextEl.dom.innerHTML = String.format(this.afterPageText, d.pages);
+       this.field.dom.value = ap;
+       this.first.setDisabled(ap == 1);
+       this.prev.setDisabled(ap == 1);
+       this.next.setDisabled(ap == ps);
+       this.last.setDisabled(ap == ps);
+       this.loading.enable();
+       this.updateInfo();
     },
 
     // private
-    onEditorKey : function(field, e){
-        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
-        if(k == e.TAB){
-            e.stopEvent();
-            ed.completeEdit();
-            if(e.shiftKey){
-                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
-            }else{
-                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
+    getPageData : function(){
+        var total = this.ds.getTotalCount();
+        return {
+            total : total,
+            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
+            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
+        };
+    },
+
+    // private
+    onLoadError : function(){
+        this.loading.enable();
+    },
+
+    // private
+    onPagingKeydown : function(e){
+        var k = e.getKey();
+        var d = this.getPageData();
+        if(k == e.RETURN){
+            var v = this.field.dom.value, pageNum;
+            if(!v || isNaN(pageNum = parseInt(v, 10))){
+                this.field.dom.value = d.activePage;
+                return;
             }
-        }else if(k == e.ENTER && !e.ctrlKey){
+            pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
+            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
             e.stopEvent();
-            ed.completeEdit();
-            if(e.shiftKey){
-                newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
-            }else{
-                newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
-            }
-        }else if(k == e.ESC){
-            ed.cancelEdit();
         }
-        if(newCell){
-            g.startEditing(newCell[0], newCell[1]);
+        else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
+        {
+          var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
+          this.field.dom.value = pageNum;
+          this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
+          e.stopEvent();
+        }
+        else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+        {
+          var v = this.field.dom.value, pageNum; 
+          var increment = (e.shiftKey) ? 10 : 1;
+          if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+            increment *= -1;
+          if(!v || isNaN(pageNum = parseInt(v, 10))) {
+            this.field.dom.value = d.activePage;
+            return;
+          }
+          else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
+          {
+            this.field.dom.value = parseInt(v, 10) + increment;
+            pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
+            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
+          }
+          e.stopEvent();
+        }
+    },
+
+    // private
+    beforeLoad : function(){
+        if(this.loading){
+            this.loading.disable();
+        }
+    },
+
+    // private
+    onClick : function(which){
+        var ds = this.ds;
+        if (!ds) {
+            return;
         }
+        switch(which){
+            case "first":
+                ds.load({params:{start: 0, limit: this.pageSize}});
+            break;
+            case "prev":
+                ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
+            break;
+            case "next":
+                ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
+            break;
+            case "last":
+                var total = ds.getTotalCount();
+                var extra = total % this.pageSize;
+                var lastStart = extra ? (total - extra) : total-this.pageSize;
+                ds.load({params:{start: lastStart, limit: this.pageSize}});
+            break;
+            case "refresh":
+                ds.load({params:{start: this.cursor, limit: this.pageSize}});
+            break;
+        }
+    },
+
+    /**
+     * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
+     * @param {Roo.data.Store} store The data store to unbind
+     */
+    unbind : function(ds){
+        ds.un("beforeload", this.beforeLoad, this);
+        ds.un("load", this.onLoad, this);
+        ds.un("loadexception", this.onLoadError, this);
+        ds.un("remove", this.updateInfo, this);
+        ds.un("add", this.updateInfo, this);
+        this.ds = undefined;
+    },
+
+    /**
+     * Binds the paging toolbar to the specified {@link Roo.data.Store}
+     * @param {Roo.data.Store} store The data store to bind
+     */
+    bind : function(ds){
+        ds.on("beforeload", this.beforeLoad, this);
+        ds.on("load", this.onLoad, this);
+        ds.on("loadexception", this.onLoadError, this);
+        ds.on("remove", this.updateInfo, this);
+        ds.on("add", this.updateInfo, this);
+        this.ds = ds;
     }
 });/*
  * - LGPL
@@ -17619,4 +18113,281 @@ Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component,  {
 
  
 
\ No newline at end of file
+ /*
+ * - LGPL
+ *
+ * Graph
+ * 
+ */
+
+
+/**
+ * @class Roo.bootstrap.Graph
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Graph class
+> Prameters
+ -sm {number} sm 4
+ -md {number} md 5
+ -graphtype {String} graphtype bar | vbar | pie
+ -g_x {number}  x coodinator | centre x (pie)
+ -g_y {number}  y coodinator | centre y (pie)
+ -g_r {number}  radius (pie)
+ -g_height {number} height of the chart (respected by all elements in the set)
+ -g_width {number}  width of the chart (respected by all elements in the set)
+ -{Array}  values
+ -opts (object) options for the chart 
+     o {
+     o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
+     o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
+     o vgutter (number)
+     o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
+     o stacked (boolean) whether or not to tread values as in a stacked bar chart
+     o to
+     o stretch (boolean)
+     o }
+ -opts (object) options for the pie
+     o{
+     o cut
+     o startAngle (number)
+     o endAngle (number)
+     } 
+ *
+ * @constructor
+ * Create a new Input
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Graph = function(config){
+    Roo.bootstrap.Graph.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // img events
+        /**
+         * @event click
+         * The img click event for the img.
+         * @param {Roo.EventObject} e
+         */
+        "click" : true
+    });
+};
+
+Roo.extend(Roo.bootstrap.Graph, Roo.bootstrap.Component,  {
+    
+    sm: 4,
+    md: 5,
+    graphtype: 'bar',
+    g_height: 250,
+    g_width: 650,
+    g_x: 50,
+    g_y: 50,
+    g_r: 30,
+    opts:{
+        //g_colors: this.colors,
+        g_type: 'soft',
+        g_gutter: '20%'
+
+    },
+
+    getAutoCreate : function(){
+        
+        var cfg = {
+            tag: 'div',
+            html : null
+        }
+        
+        
+        return  cfg;
+    },
+
+    onRender : function(ct,position){
+        Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
+        var r = {};
+        this.raphael = Raphael(this.el.dom),
+                    data1 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    data2 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    data3 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    txtattr = { font: "12px 'Fontin Sans', Fontin-Sans, sans-serif" };
+                /*
+                r.text(160, 10, "Single Series Chart").attr(txtattr);
+                r.text(480, 10, "Multiline Series Chart").attr(txtattr);
+                r.text(160, 250, "Multiple Series Stacked Chart").attr(txtattr);
+                r.text(480, 250, 'Multiline Series Stacked Vertical Chart. Type "round"').attr(txtattr);
+                
+                r.barchart(10, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10]], 0, {type: "sharp"});
+                r.barchart(330, 10, 300, 220, data1);
+                r.barchart(10, 250, 300, 220, data2, {stacked: true});
+                r.barchart(330, 250, 300, 220, data3, {stacked: true, type: "round"});
+                */
+                
+                // var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
+                // r.barchart(30, 30, 560, 250,  xdata, {
+                //    labels : [55, 20, 13, 32, 5, 1, 2, 10,5 , 10],
+                //     axis : "0 0 1 1",
+                //     axisxlabels :  xdata
+                //     //yvalues : cols,
+                   
+                // });
+
+    },
+
+    load : function(graphtype,xdata,opts){
+        this.raphael.clear();
+        if(!graphtype) {
+            graphtype = this.graphtype;
+        }
+        if(!opts){
+            opts = this.opts;
+        }
+        switch(graphtype){
+            case 'bar':
+                this.raphael.barchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts);
+                break;
+            case 'hbar':
+                this.raphael.hbarchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts);
+                break;
+            case 'pie':
+                this.raphael.piechart(this.g_x,this.g_y,this.g_r,xdata,opts);
+                break;
+
+        }
+    },
+    
+    initEvents: function() {
+        
+        if(!this.href){
+            this.el.on('click', this.onClick, this);
+        }
+    },
+    
+    onClick : function(e)
+    {
+        Roo.log('img onclick');
+        this.fireEvent('click', this, e);
+    }
+   
+});
+
+/*
+ * - LGPL
+ *
+ * numberBox
+ * 
+ */
+
+
+/**
+ * @class Roo.bootstrap.dash.NumberBox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap NumberBox class
+ * @cfg {number} sm 4
+ * @cfg {number} md 5
+ * @cfg {String} headline
+ * @cfg {String} title
+ * @cfg {String} more info url
+ * @cfg {String} more info text
+ * @cfg {Array}  opts values
+ * 
+ * @constructor
+ * Create a new Input
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.dash.NumberBox = function(config){
+    Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // img events
+        /**
+         * @event click
+         * The img click event for the img.
+         * @param {Roo.EventObject} e
+         */
+        "click" : true
+    });
+};
+
+Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component,  {
+    
+    width: 200,
+    height: 150,
+    headline: '',
+    title: 'Title',
+    more_url: '',
+    more_text: '',
+
+    getAutoCreate : function(){
+        
+        var cfg = {
+            tag: 'div',
+            cls: '',
+            html : null,
+            cn: [
+            {
+                tag: 'h',
+                cls: '',
+                html: this.headline ? this.headline : 'Headline'
+            },
+            {
+                tag: 'p',
+                cls: '',
+                html: this.title ? this.title : 'Title'
+            },
+            {
+                tag: 'div',
+                cls: '',
+                html : null,
+                cn: [{
+                    tag: 'a',
+                    href: this.more_url,
+                    cls: '',
+                    html: this.more_text
+                }]
+
+            }]
+        }
+    
+        
+        return  cfg;
+    },
+
+    // onRender : function(ct,position){
+    //     Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
+                
+    // },
+
+    // load : function(graphtype,xdata){
+    //     this.raphael.clear();
+    //     if(!graphtype) {
+    //         graphtype = this.graphtype;
+    //     }
+    //     switch(graphtype){
+    //         case 'bar':
+    //             this.raphael.barchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,this.opts);
+    //             break;
+    //         case 'hbar':
+    //             this.raphael.hbarchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,this.opts);
+    //             break;
+    //         case 'pie':
+    //             this.raphael.piechart(this.g_x,this.g_y,this.g_r,xdata,this.opts);
+    //             break;
+
+    //     }
+    // },
+    
+    initEvents: function() {
+        
+        if(!this.href){
+            this.el.on('click', this.onClick, this);
+        }
+    },
+    
+    onClick : function(e)
+    {
+        Roo.log('img onclick');
+        this.fireEvent('click', this, e);
+    }
+   
+});
+