fix broken commit
[roojs1] / roojs-bootstrap-debug.js
index 1b68801..4d87cb6 100644 (file)
@@ -1,4 +1,4 @@
-/**
+Roo.bootstrap = {};/**
  * set the version of bootstrap based on the stylesheet...
  *
  */
@@ -14,7 +14,13 @@ Roo.bootstrap.version = ( function() {
          Roo.Element.prototype.visibilityMode = Roo.Element.DISPLAY;
     }
     return ret;
-})(); /*
+})(); Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+Roo.bootstrap.nav = {};
+
+Roo.bootstrap.form = {};Roo.bootstrap.panel = {};Roo.bootstrap.layout = {};
+Roo.htmleditor = {};
+Roo.namespace('Roo.bootstrap.form.HtmlEditorToolbar');
+/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -223,6 +229,8 @@ Roo.bootstrap = Roo.bootstrap || {};
 /**
  * @class Roo.bootstrap.Component
  * @extends Roo.Component
+ * @abstract
+ * @children Roo.bootstrap.Component
  * Bootstrap Component base class
  * @cfg {String} cls css class
  * @cfg {String} style any extra css
@@ -650,7 +658,9 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
 /**
  * @class Roo.bootstrap.Element
  * @extends Roo.bootstrap.Component
- * Bootstrap Element class
+ * @children Roo.bootstrap.Component
+ * Bootstrap Element class (basically a DIV used to make random stuff )
+ * 
  * @cfg {String} html contents of the element
  * @cfg {String} tag tag of the element
  * @cfg {String} cls class of the element
@@ -848,6 +858,8 @@ Roo.extend(Roo.bootstrap.DropTarget, Roo.bootstrap.Element,  {
 /**
  * @class Roo.bootstrap.Body
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component 
+ * @parent none builder
  * Bootstrap Body class
  *
  * @constructor
@@ -899,6 +911,8 @@ Roo.extend(Roo.bootstrap.Body, Roo.bootstrap.Component,  {
  * @class Roo.bootstrap.ButtonGroup
  * @extends Roo.bootstrap.Component
  * Bootstrap ButtonGroup class
+ * @children Roo.bootstrap.Button Roo.bootstrap.form.Form
+ * 
  * @cfg {String} size lg | sm | xs (default empty normal)
  * @cfg {String} align vertical | justified  (default none)
  * @cfg {String} direction up | down (default down)
@@ -1005,7 +1019,8 @@ Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component,  {
  * @cfg {Boolean} removeClass remove the standard class..
  * @cfg {String} target (_self|_blank|_parent|_top|other) target for a href. 
  * @cfg {Boolean} grpup if parent is a btn group - then it turns it into a toogleGroup.
- * 
+ * @cfg {Roo.bootstrap.menu.Menu} menu a Menu 
+
  * @constructor
  * Create a new button
  * @param {Object} config The config object
@@ -1328,7 +1343,7 @@ Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
         }
         
         Roo.log('button on click ');
-        if(this.preventDefault){
+        if(this.href === '' || this.preventDefault){
             e.preventDefault();
         }
         
@@ -1466,6 +1481,7 @@ Roo.bootstrap.Button.weights = [
 /**
  * @class Roo.bootstrap.Column
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
  * Bootstrap Column class
  * @cfg {Number} xs colspan out of 12 for mobile-sized screens or 0 for hidden
  * @cfg {Number} sm colspan out of 12 for tablet-sized screens or 0 for hidden
@@ -1593,6 +1609,8 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.Container
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * @parent builder
  * Bootstrap Container class
  * @cfg {Boolean} jumbotron is it a jumbotron element
  * @cfg {String} html content of element
@@ -1956,16 +1974,12 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
     }
 });
 
- /*
- *  - LGPL
- *
- *  This is BS4's Card element.. - similar to our containers probably..
- * 
- */
-/**
+ /**
  * @class Roo.bootstrap.Card
  * @extends Roo.bootstrap.Component
- * Bootstrap Card class
+ * @children Roo.bootstrap.Component
+ * @licence LGPL
+ * Bootstrap Card class - note this has children as CardHeader/ImageTop/Footer.. - which should really be listed properties?
  *
  *
  * possible... may not be implemented..
@@ -2766,6 +2780,8 @@ Roo.extend(Roo.bootstrap.Card, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.CardHeader
  * @extends Roo.bootstrap.Element
+ * @parent Roo.bootstrap.Card
+ * @children Roo.bootstrap.Component
  * Bootstrap CardHeader class
  * @constructor
  * Create a new Card Header - that you can embed children into
@@ -2799,7 +2815,10 @@ Roo.extend(Roo.bootstrap.CardHeader, Roo.bootstrap.Element,  {
 /**
  * @class Roo.bootstrap.CardFooter
  * @extends Roo.bootstrap.Element
+ * @parent Roo.bootstrap.Card
+ * @children Roo.bootstrap.Component
  * Bootstrap CardFooter class
+ * 
  * @constructor
  * Create a new Card Footer - that you can embed children into
  * @param {Object} config The config object
@@ -2832,7 +2851,10 @@ Roo.extend(Roo.bootstrap.CardFooter, Roo.bootstrap.Element,  {
 /**
  * @class Roo.bootstrap.CardImageTop
  * @extends Roo.bootstrap.Element
+ * @parent Roo.bootstrap.Card
+ * @children Roo.bootstrap.Component
  * Bootstrap CardImageTop class
+ * 
  * @constructor
  * Create a new Card Image Top container
  * @param {Object} config The config object
@@ -2916,22 +2938,12 @@ Roo.extend(Roo.bootstrap.ButtonUploader, Roo.bootstrap.Button,  {
     
     getAutoCreate : function()
     {
-        var im = {
-            tag: 'input',
-            type : 'file',
-            cls : 'd-none  roo-card-upload-selector' 
-          
-        };
-        if (this.multiple) {
-            im.multiple = 'multiple';
-        }
+       
         
         return  {
             cls :'div' ,
             cn : [
-                Roo.bootstrap.Button.prototype.getAutoCreate.call(this),
-                im
-
+                Roo.bootstrap.Button.prototype.getAutoCreate.call(this) 
             ]
         };
            
@@ -2952,10 +2964,18 @@ Roo.extend(Roo.bootstrap.ButtonUploader, Roo.bootstrap.Button,  {
                                 (window.URL && URL.revokeObjectURL && URL) || 
                                 (window.webkitURL && webkitURL);
                         
-         
-         
-         
-        this.selectorEl = this.el.select('.roo-card-upload-selector', true).first();
+        var im = {
+            tag: 'input',
+            type : 'file',
+            cls : 'd-none  roo-card-upload-selector' 
+          
+        };
+        if (this.multiple) {
+            im.multiple = 'multiple';
+        }
+        this.selectorEl = Roo.get(document.body).createChild(im); // so it does not capture click event for navitem.
+       
+        //this.selectorEl = this.el.select('.roo-card-upload-selector', true).first();
         
         this.selectorEl.on('change', this.onFileSelected, this);
          
@@ -3257,7 +3277,9 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.Link
  * @extends Roo.bootstrap.Component
- * Bootstrap Link Class
+ * @children Roo.bootstrap.Component
+ * Bootstrap Link Class (eg. '<a href>')
  * @cfg {String} alt image alternative text
  * @cfg {String} href a tag href
  * @cfg {String} target (_self|_blank|_parent|_top) target for a href.
@@ -3361,7 +3383,10 @@ Roo.extend(Roo.bootstrap.Link, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.Header
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
  * Bootstrap Header class
+ *
+ * 
  * @cfg {String} html content of header
  * @cfg {Number} level (1|2|3|4|5|6) default 1
  * 
@@ -3399,23 +3424,13 @@ Roo.extend(Roo.bootstrap.Header, Roo.bootstrap.Component,  {
 
  
 
- /*
- * 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.MenuMgr
+ * @licence LGPL
  * Provides a common registry of all menu items on a page so that they can be easily accessed by id.
- * @singleton
+ * @static
  */
-Roo.bootstrap.MenuMgr = function(){
+Roo.bootstrap.menu.Manager = function(){
    var menus, active, groups = {}, attached = false, lastShow = new Date();
 
    // private - called when first menu is created
@@ -3597,31 +3612,29 @@ Roo.bootstrap.MenuMgr = function(){
            }
        }
    };
-}();/*
- * - LGPL
- *
- * menu
- * 
- */
-
+}(); 
 /**
- * @class Roo.bootstrap.Menu
+ * @class Roo.bootstrap.menu.Menu
  * @extends Roo.bootstrap.Component
- * Bootstrap Menu class - container for MenuItems
+ * @licence LGPL
+ * @children Roo.bootstrap.menu.Item Roo.bootstrap.menu.Separator
+ * @parent none
+ * Bootstrap Menu class - container for MenuItems - normally has to be added to a object that supports the menu property
+ * 
  * @cfg {String} type (dropdown|treeview|submenu) type of menu
  * @cfg {bool} hidden  if the menu should be hidden when rendered.
  * @cfg {bool} stopEvent (true|false)  Stop event after trigger press (default true)
  * @cfg {bool} isLink (true|false)  the menu has link disable auto expand and collaspe (default false)
-  * @cfg {bool} hideTrigger (true|false)  default false - hide the carret for trigger.
-  * @cfg {String} align  default tl-bl? == below  - how the menu should be aligned. 
+* @cfg {bool} hideTrigger (true|false)  default false - hide the carret for trigger.
+* @cfg {String} align  default tl-bl? == below  - how the menu should be aligned. 
  
  * @constructor
  * Create a new Menu
- * @param {Object} config The config object
+ * @param {Object} config The config objectQ
  */
 
 
-Roo.bootstrap.Menu = function(config){
+Roo.bootstrap.menu.Menu = function(config){
     
     if (config.type == 'treeview') {
        // normally menu's are drawn attached to the document to handle layering etc..
@@ -3629,9 +3642,9 @@ Roo.bootstrap.Menu = function(config){
        this.container_method = 'getChildContainer'; 
     }
     
-    Roo.bootstrap.Menu.superclass.constructor.call(this, config);
+    Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
     if (this.registerMenu && this.type != 'treeview')  {
-        Roo.bootstrap.MenuMgr.register(this);
+        Roo.bootstrap.menu.Manager.register(this);
     }
     
     
@@ -3695,7 +3708,7 @@ Roo.bootstrap.Menu = function(config){
     this.menuitems = new Roo.util.MixedCollection(false, function(o) { return o.el.id; });
 };
 
-Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component,  {
     
    /// html : false,
    
@@ -4056,7 +4069,7 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         });
     },
     addxtypeChild : function (tree, cntr) {
-        var comp= Roo.bootstrap.Menu.superclass.addxtypeChild.call(this, tree, cntr);
+        var comp= Roo.bootstrap.menu.Menu.superclass.addxtypeChild.call(this, tree, cntr);
           
         this.menuitems.add(comp);
         return comp;
@@ -4076,18 +4089,14 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
 });
 
  
- /*
- * - LGPL
- *
- * menu item
- * 
- */
-
-
-/**
- * @class Roo.bootstrap.MenuItem
+ /**
+ * @class Roo.bootstrap.menu.Item
  * @extends Roo.bootstrap.Component
+ * @children  Roo.bootstrap.Button Roo.bootstrap.ButtonUploader Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Container
+ * @parent Roo.bootstrap.menu.Menu
+ * @licence LGPL
  * Bootstrap MenuItem class
+ * 
  * @cfg {String} html the menu label
  * @cfg {String} href the link
  * @cfg {Boolean} preventDefault do not trigger A href on clicks (default false).
@@ -4103,21 +4112,21 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
  */
 
 
-Roo.bootstrap.MenuItem = function(config){
-    Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
+Roo.bootstrap.menu.Item = function(config){
+    Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
     this.addEvents({
         // raw events
         /**
          * @event click
          * The raw click event for the entire grid.
-         * @param {Roo.bootstrap.MenuItem} this
+         * @param {Roo.bootstrap.menu.Item} this
          * @param {Roo.EventObject} e
          */
         "click" : true
     });
 };
 
-Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component,  {
     
     href : false,
     html : false,
@@ -4190,9 +4199,9 @@ Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
     },
     onClick : function(e)
     {
-        Roo.log('item on click ');
+        //Roo.log('item on click ');
         
-        if(this.preventDefault){
+        if(this.href === false || this.preventDefault){
             e.preventDefault();
         }
         //this.parent().hideMenuItems();
@@ -4207,35 +4216,32 @@ Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
 
  
 
- /*
- * - LGPL
- *
- * menu separator
- * 
- */
-
 
+  
 /**
- * @class Roo.bootstrap.MenuSeparator
+ * @class Roo.bootstrap.menu.Separator
  * @extends Roo.bootstrap.Component
- * Bootstrap MenuSeparator class
+ * @licence LGPL
+ * @parent Roo.bootstrap.menu.Menu
+ * Bootstrap Separator class
  * 
  * @constructor
- * Create a new MenuItem
+ * Create a new Separator
  * @param {Object} config The config object
  */
 
 
-Roo.bootstrap.MenuSeparator = function(config){
-    Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
+Roo.bootstrap.menu.Separator = function(config){
+    Roo.bootstrap.menu.Separator.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component,  {
     
     getAutoCreate : function(){
         var cfg = {
-            cls: 'divider',
-            tag : 'li'
+            tag : 'li',
+            cls: 'dropdown-divider divider'
         };
         
         return cfg;
@@ -4253,12 +4259,14 @@ Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.Modal
  * @extends Roo.bootstrap.Component
+ * @parent none builder
+ * @children Roo.bootstrap.Component
  * Bootstrap Modal class
  * @cfg {String} title Title of dialog
  * @cfg {String} html - the body of the dialog (for simple ones) - you can also use template..
  * @cfg {Roo.Template} tmpl - a template with variables. to use it, add a handler in show:method  adn
  * @cfg {Boolean} specificTitle default false
- * @cfg {Array} buttons Array of buttons or standard button set..
+ * @cfg {Roo.bootstrap.Button} buttons[] Array of buttons or standard button set..
  * @cfg {String} buttonPosition (left|right|center) default right (DEPRICATED) - use mr-auto on buttons to put them on the left
  * @cfg {Boolean} animate default true
  * @cfg {Boolean} allow_close default true
@@ -4411,6 +4419,8 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
             delete this.items;
 
             for(var i =0;i < items.length;i++) {
+                // we force children not to montor widnow resize  - as we do that for them.
+                items[i].monitorWindowResize = false;
                 nitems.push(this.addxtype(Roo.apply({}, items[i])));
             }
         }
@@ -4538,10 +4548,16 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
             : this.el.select('.modal-footer div',true).first();
 
     },
+    
+    closeClick : function()
+    {
+        this.hide();
+    },
+    
     initEvents : function()
     {
         if (this.allow_close) {
-            this.closeEl.on('click', this.hide, this);
+            this.closeEl.on('click', this.closeClick, this);
         }
         Roo.EventManager.onWindowResize(this.resize, this, true);
         if (this.editableTitle) {
@@ -4618,6 +4634,14 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         }
         
         this.resizeTo(w,h);
+        // any layout/border etc.. resize..
+        (function () {
+            this.items.forEach( function(e) {
+                e.layout ? e.layout() : false;
+
+            });
+        }).defer(100,this);
+        
     },
 
     show : function() {
@@ -4662,7 +4686,9 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
 
         // set zindex here - otherwise it appears to be ignored...
         this.el.setStyle('z-index', Roo.bootstrap.Modal.zIndex++);
-
+        
+        
+        // this is for children that are... layout.Border 
         (function () {
             this.items.forEach( function(e) {
                 e.layout ? e.layout() : false;
@@ -4971,7 +4997,7 @@ Roo.Msg.show({
    animEl: 'elId'
 });
 </code></pre>
- * @singleton
+ * @static
  */
 Roo.bootstrap.MessageBox = function(){
     var dlg, opt, mask, waitTimer;
@@ -5514,8 +5540,9 @@ Roo.Msg = Roo.Msg || Roo.MessageBox;
  */
 
 /**
- * @class Roo.bootstrap.Navbar
+ * @class Roo.bootstrap.nav.Bar
  * @extends Roo.bootstrap.Component
+ * @abstract
  * Bootstrap Navbar class
 
  * @constructor
@@ -5524,8 +5551,8 @@ Roo.Msg = Roo.Msg || Roo.MessageBox;
  */
 
 
-Roo.bootstrap.Navbar = function(config){
-    Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Bar = function(config){
+    Roo.bootstrap.nav.Bar.superclass.constructor.call(this, config);
     this.addEvents({
         // raw events
         /**
@@ -5537,7 +5564,7 @@ Roo.bootstrap.Navbar = function(config){
     });
 };
 
-Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.nav.Bar, Roo.bootstrap.Component,  {
     
     
    
@@ -5684,8 +5711,9 @@ Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
  */
 
 /**
- * @class Roo.bootstrap.NavSimplebar
- * @extends Roo.bootstrap.Navbar
+ * @class Roo.bootstrap.nav.Simplebar
+ * @extends Roo.bootstrap.nav.Bar
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container Roo.bootstrap.form.Form Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Link
  * Bootstrap Sidebar class
  *
  * @cfg {Boolean} inverse is inverted color
@@ -5708,11 +5736,11 @@ Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
  */
 
 
-Roo.bootstrap.NavSimplebar = function(config){
-    Roo.bootstrap.NavSimplebar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Simplebar = function(config){
+    Roo.bootstrap.nav.Simplebar.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar,  {
+Roo.extend(Roo.bootstrap.nav.Simplebar, Roo.bootstrap.nav.Bar,  {
     
     inverse: false,
     
@@ -5812,8 +5840,9 @@ Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar,  {
  */
 
 /**
- * @class Roo.bootstrap.NavHeaderbar
- * @extends Roo.bootstrap.NavSimplebar
+ * @class Roo.bootstrap.nav.Headerbar
+ * @extends Roo.bootstrap.nav.Simplebar
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container Roo.bootstrap.form.Form Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Link
  * Bootstrap Sidebar class
  *
  * @cfg {String} brand what is brand
@@ -5830,12 +5859,12 @@ Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar,  {
  */
 
 
-Roo.bootstrap.NavHeaderbar = function(config){
-    Roo.bootstrap.NavHeaderbar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Headerbar = function(config){
+    Roo.bootstrap.nav.Headerbar.superclass.constructor.call(this, config);
       
 };
 
-Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
+Roo.extend(Roo.bootstrap.nav.Headerbar, Roo.bootstrap.nav.Simplebar,  {
     
     position: '',
     brand: '',
@@ -5958,7 +5987,7 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
     
     initEvents : function()
     {
-        Roo.bootstrap.NavHeaderbar.superclass.initEvents.call(this);
+        Roo.bootstrap.nav.Headerbar.superclass.initEvents.call(this);
         
         if (this.autohide) {
             
@@ -5997,8 +6026,9 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
  */
 
 /**
- * @class Roo.bootstrap.NavSidebar
- * @extends Roo.bootstrap.Navbar
+ * @class Roo.bootstrap.nav.Sidebar
+ * @extends Roo.bootstrap.nav.Bar
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container Roo.bootstrap.form.Form Roo.bootstrap.Row Roo.bootstrap.Column Roo.bootstrap.Link
  * Bootstrap Sidebar class
  * 
  * @constructor
@@ -6007,11 +6037,11 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
  */
 
 
-Roo.bootstrap.NavSidebar = function(config){
-    Roo.bootstrap.NavSidebar.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Sidebar = function(config){
+    Roo.bootstrap.nav.Sidebar.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.NavSidebar, Roo.bootstrap.Navbar,  {
+Roo.extend(Roo.bootstrap.nav.Sidebar, Roo.bootstrap.nav.Bar,  {
     
     sidebar : true, // used by Navbar Item and NavbarGroup at present...
     
@@ -6042,8 +6072,9 @@ Roo.extend(Roo.bootstrap.NavSidebar, Roo.bootstrap.Navbar,  {
  */
 
 /**
- * @class Roo.bootstrap.NavGroup
+ * @class Roo.bootstrap.nav.Group
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.nav.Item
  * Bootstrap NavGroup class
  * @cfg {String} align (left|right)
  * @cfg {Boolean} inverse
@@ -6056,16 +6087,16 @@ Roo.extend(Roo.bootstrap.NavSidebar, Roo.bootstrap.Navbar,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.NavGroup = function(config){
-    Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Group = function(config){
+    Roo.bootstrap.nav.Group.superclass.constructor.call(this, config);
     this.navItems = [];
    
-    Roo.bootstrap.NavGroup.register(this);
+    Roo.bootstrap.nav.Group.register(this);
      this.addEvents({
         /**
             * @event changed
             * Fires when the active item changes
-            * @param {Roo.bootstrap.NavGroup} this
+            * @param {Roo.bootstrap.nav.Group} this
             * @param {Roo.bootstrap.Navbar.Item} selected The item selected
             * @param {Roo.bootstrap.Navbar.Item} prev The previously selected item 
          */
@@ -6074,7 +6105,7 @@ Roo.bootstrap.NavGroup = function(config){
     
 };
 
-Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.nav.Group, Roo.bootstrap.Component,  {
     
     align: '',
     inverse: false,
@@ -6088,7 +6119,7 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
     
     getAutoCreate : function()
     {
-        var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
+        var cfg = Roo.apply({}, Roo.bootstrap.nav.Group.superclass.getAutoCreate.call(this));
         
         cfg = {
             tag : 'ul',
@@ -6154,7 +6185,7 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
     },
     /**
     * sets the active Navigation item
-    * @param {Roo.bootstrap.NavItem} the new current navitem
+    * @param {Roo.bootstrap.nav.Item} the new current navitem
     */
     setActiveItem : function(item)
     {
@@ -6178,7 +6209,7 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
     },
     /**
     * gets the active Navigation item
-    * @return {Roo.bootstrap.NavItem} the current navitem
+    * @return {Roo.bootstrap.nav.Item} the current navitem
     */
     getActive : function()
     {
@@ -6211,14 +6242,14 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
     },
     /**
     * adds a Navigation item
-    * @param {Roo.bootstrap.NavItem} the navitem to add
+    * @param {Roo.bootstrap.nav.Item} the navitem to add
     */
     addItem : function(cfg)
     {
         if (this.form && Roo.bootstrap.version == 4) {
            cfg.tag = 'div';
        }
-       var cn = new Roo.bootstrap.NavItem(cfg);
+       var cn = new Roo.bootstrap.nav.Item(cfg);
         this.register(cn);
         cn.parentId = this.id;
         cn.onRender(this.el, null);
@@ -6226,7 +6257,7 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
     },
     /**
     * register a Navigation item
-    * @param {Roo.bootstrap.NavItem} the navitem to add
+    * @param {Roo.bootstrap.nav.Item} the navitem to add
     */
     register : function(item)
     {
@@ -6303,12 +6334,12 @@ Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
 });
 
  
-Roo.apply(Roo.bootstrap.NavGroup, {
+Roo.apply(Roo.bootstrap.nav.Group, {
     
     groups: {},
      /**
     * register a Navigation Group
-    * @param {Roo.bootstrap.NavGroup} the navgroup to add
+    * @param {Roo.bootstrap.nav.Group} the navgroup to add
     */
     register : function(navgrp)
     {
@@ -6318,12 +6349,12 @@ Roo.apply(Roo.bootstrap.NavGroup, {
     /**
     * fetch a Navigation Group based on the navigation ID
     * @param {string} the navgroup to add
-    * @returns {Roo.bootstrap.NavGroup} the navgroup 
+    * @returns {Roo.bootstrap.nav.Group} the navgroup 
     */
     get: function(navId) {
         if (typeof(this.groups[navId]) == 'undefined') {
             return false;
-            //this.register(new Roo.bootstrap.NavGroup({ navId : navId }));
+            //this.register(new Roo.bootstrap.nav.Group({ navId : navId }));
         }
         return this.groups[navId] ;
     }
@@ -6332,17 +6363,14 @@ Roo.apply(Roo.bootstrap.NavGroup, {
     
 });
 
- /*
- * - LGPL
- *
- * row
- * 
- */
-
-/**
- * @class Roo.bootstrap.NavItem
+ /**
+ * @class Roo.bootstrap.nav.Item
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Container Roo.bootstrap.Button
+ * @parent Roo.bootstrap.nav.Group
+ * @licence LGPL
  * Bootstrap Navbar.NavItem class
+ * 
  * @cfg {String} href  link to
  * @cfg {String} button_weight (default|primary|secondary|success|info|warning|danger|link|light|dark) default none
  * @cfg {Boolean} button_outline show and outlined button
@@ -6359,13 +6387,14 @@ Roo.apply(Roo.bootstrap.NavGroup, {
  * @cfg {String} tabId the tab that this item activates.
  * @cfg {String} tagtype (a|span) render as a href or span?
  * @cfg {Boolean} animateRef (true|false) link to element default false  
+ * @cfg {Roo.bootstrap.menu.Menu} menu a Menu 
   
  * @constructor
  * Create a new Navbar Item
  * @param {Object} config The config object
  */
-Roo.bootstrap.NavItem = function(config){
-    Roo.bootstrap.NavItem.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.Item = function(config){
+    Roo.bootstrap.nav.Item.superclass.constructor.call(this, config);
     this.addEvents({
         // raw events
         /**
@@ -6377,7 +6406,7 @@ Roo.bootstrap.NavItem = function(config){
         /**
            * @event changed
            * Fires when the active item active state changes
-           * @param {Roo.bootstrap.NavItem} this
+           * @param {Roo.bootstrap.nav.Item} this
            * @param {boolean} state the new state
             
          */
@@ -6385,7 +6414,7 @@ Roo.bootstrap.NavItem = function(config){
         /**
            * @event scrollto
            * Fires when scroll to element
-           * @param {Roo.bootstrap.NavItem} this
+           * @param {Roo.bootstrap.nav.Item} this
            * @param {Object} options
             * @param {Roo.EventObject} e
             
@@ -6395,7 +6424,7 @@ Roo.bootstrap.NavItem = function(config){
    
 };
 
-Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.nav.Item, Roo.bootstrap.Component,  {
     
     href: false,
     html: '',
@@ -6499,7 +6528,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
            this.tag = 'div';
        }
        
-        var ret = Roo.bootstrap.NavItem.superclass.onRender.call(this, ct, position);
+        var ret = Roo.bootstrap.nav.Item.superclass.onRender.call(this, ct, position);
        this.navLink = this.el.select('.nav-link',true).first();
        this.htmlEl = this.el.hasClass('nav-html') ? this.el : this.el.select('.nav-html',true).first();
        return ret;
@@ -6532,10 +6561,11 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
         }
         
         if(
-                this.preventDefault || 
-                this.href == '#' 
+                this.preventDefault ||
+                               this.href === false ||
+                this.href === '#' 
         ){
-            Roo.log("NavItem - prevent Default?");
+            //Roo.log("NavItem - prevent Default?");
             e.preventDefault();
         }
         
@@ -6597,7 +6627,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     {
         if (this.active && !state && this.navId) {
             this.was_active = true;
-            var nv = Roo.bootstrap.NavGroup.get(this.navId);
+            var nv = Roo.bootstrap.nav.Group.get(this.navId);
             if (nv) {
                 nv.clearWasActive(this);
             }
@@ -6636,7 +6666,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
         }
         // if we can not flip to new panel - go back to old nav highlight..
         if (false == tg.showPanel(pan)) {
-            var nv = Roo.bootstrap.NavGroup.get(this.navId);
+            var nv = Roo.bootstrap.nav.Group.get(this.navId);
             if (nv) {
                 var onav = nv.getWasActive();
                 if (onav) {
@@ -6725,9 +6755,10 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
  */
 
 /**
- * @class Roo.bootstrap.NavSidebarItem
- * @extends Roo.bootstrap.NavItem
+ * @class Roo.bootstrap.nav.SidebarItem
+ * @extends Roo.bootstrap.nav.Item
  * Bootstrap Navbar.NavSidebarItem class
+ * 
  * {String} badgeWeight (default|primary|success|info|warning|danger)the extra classes for the badge
  * {Boolean} open is the menu open
  * {Boolean} buttonView use button as the tigger el rather that a (default false)
@@ -6738,8 +6769,8 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
  * Create a new Navbar Button
  * @param {Object} config The config object
  */
-Roo.bootstrap.NavSidebarItem = function(config){
-    Roo.bootstrap.NavSidebarItem.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.SidebarItem = function(config){
+    Roo.bootstrap.nav.SidebarItem.superclass.constructor.call(this, config);
     this.addEvents({
         // raw events
         /**
@@ -6751,7 +6782,7 @@ Roo.bootstrap.NavSidebarItem = function(config){
         /**
            * @event changed
            * Fires when the active item active state changes
-           * @param {Roo.bootstrap.NavSidebarItem} this
+           * @param {Roo.bootstrap.nav.SidebarItem} this
            * @param {boolean} state the new state
             
          */
@@ -6760,7 +6791,7 @@ Roo.bootstrap.NavSidebarItem = function(config){
    
 };
 
-Roo.extend(Roo.bootstrap.NavSidebarItem, Roo.bootstrap.NavItem,  {
+Roo.extend(Roo.bootstrap.nav.SidebarItem, Roo.bootstrap.nav.Item,  {
     
     badgeWeight : 'default',
     
@@ -6942,157 +6973,563 @@ Roo.extend(Roo.bootstrap.NavSidebarItem, Roo.bootstrap.NavItem,  {
  /*
  * - LGPL
  *
- *  Breadcrumb Nav
+ * nav progress bar
  * 
  */
-Roo.namespace('Roo.bootstrap.breadcrumb');
-
 
 /**
- * @class Roo.bootstrap.breadcrumb.Nav
+ * @class Roo.bootstrap.nav.ProgressBar
  * @extends Roo.bootstrap.Component
- * Bootstrap Breadcrumb Nav Class
- *  
- * @children Roo.bootstrap.breadcrumb.Item
+ * @children Roo.bootstrap.nav.ProgressBarItem
+ * Bootstrap NavProgressBar class
  * 
  * @constructor
- * Create a new breadcrumb.Nav
+ * Create a new nav progress bar - a bar indicating step along a process
  * @param {Object} config The config object
  */
 
+Roo.bootstrap.nav.ProgressBar = function(config){
+    Roo.bootstrap.nav.ProgressBar.superclass.constructor.call(this, config);
 
-Roo.bootstrap.breadcrumb.Nav = function(config){
-    Roo.bootstrap.breadcrumb.Nav.superclass.constructor.call(this, config);
-    
+    this.bullets = this.bullets || [];
+   
+//    Roo.bootstrap.nav.ProgressBar.register(this);
+     this.addEvents({
+        /**
+            * @event changed
+            * Fires when the active item changes
+            * @param {Roo.bootstrap.nav.ProgressBar} this
+            * @param {Roo.bootstrap.nav.ProgressItem} selected The item selected
+            * @param {Roo.bootstrap.nav.ProgressItem} prev The previously selected item 
+         */
+        'changed': true
+     });
     
 };
 
-Roo.extend(Roo.bootstrap.breadcrumb.Nav, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.nav.ProgressBar, Roo.bootstrap.Component,  {
+    /**
+     * @cfg {Roo.bootstrap.nav.ProgressItem} NavProgressBar:bullets[]
+     * Bullets for the Nav Progress bar for the toolbar
+     */
+    bullets : [],
+    barItems : [],
     
     getAutoCreate : function()
     {
-
-        var cfg = {
-            tag: 'nav',
+        var cfg = Roo.apply({}, Roo.bootstrap.nav.ProgressBar.superclass.getAutoCreate.call(this));
+        
+        cfg = {
+            tag : 'div',
+            cls : 'roo-navigation-bar-group',
             cn : [
                 {
-                    tag : 'ol',
-                    cls : 'breadcrumb'
+                    tag : 'div',
+                    cls : 'roo-navigation-top-bar'
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-navigation-bullets-bar',
+                    cn : [
+                        {
+                            tag : 'ul',
+                            cls : 'roo-navigation-bar'
+                        }
+                    ]
+                },
+                
+                {
+                    tag : 'div',
+                    cls : 'roo-navigation-bottom-bar'
                 }
             ]
             
         };
-          
+        
         return cfg;
+        
     },
     
-    initEvents: function()
+    initEvents: function() 
     {
-        this.olEl = this.el.select('ol',true).first();    
+        
     },
-    getChildContainer : function()
+    
+    onRender : function(ct, position) 
     {
-        return this.olEl;  
+        Roo.bootstrap.nav.ProgressBar.superclass.onRender.call(this, ct, position);
+        
+        if(this.bullets.length){
+            Roo.each(this.bullets, function(b){
+               this.addItem(b);
+            }, this);
+        }
+        
+        this.format();
+        
+    },
+    
+    addItem : function(cfg)
+    {
+        var item = new Roo.bootstrap.nav.ProgressItem(cfg);
+        
+        item.parentId = this.id;
+        item.render(this.el.select('.roo-navigation-bar', true).first(), null);
+        
+        if(cfg.html){
+            var top = new Roo.bootstrap.Element({
+                tag : 'div',
+                cls : 'roo-navigation-bar-text'
+            });
+            
+            var bottom = new Roo.bootstrap.Element({
+                tag : 'div',
+                cls : 'roo-navigation-bar-text'
+            });
+            
+            top.onRender(this.el.select('.roo-navigation-top-bar', true).first(), null);
+            bottom.onRender(this.el.select('.roo-navigation-bottom-bar', true).first(), null);
+            
+            var topText = new Roo.bootstrap.Element({
+                tag : 'span',
+                html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? cfg.html : ''
+            });
+            
+            var bottomText = new Roo.bootstrap.Element({
+                tag : 'span',
+                html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? '' : cfg.html
+            });
+            
+            topText.onRender(top.el, null);
+            bottomText.onRender(bottom.el, null);
+            
+            item.topEl = top;
+            item.bottomEl = bottom;
+        }
+        
+        this.barItems.push(item);
+        
+        return item;
+    },
+    
+    getActive : function()
+    {
+        var active = false;
+        
+        Roo.each(this.barItems, function(v){
+            
+            if (!v.isActive()) {
+                return;
+            }
+            
+            active = v;
+            return false;
+            
+        });
+        
+        return active;
+    },
+    
+    setActiveItem : function(item)
+    {
+        var prev = false;
+        
+        Roo.each(this.barItems, function(v){
+            if (v.rid == item.rid) {
+                return ;
+            }
+            
+            if (v.isActive()) {
+                v.setActive(false);
+                prev = v;
+            }
+        });
+
+        item.setActive(true);
+        
+        this.fireEvent('changed', this, item, prev);
+    },
+    
+    getBarItem: function(rid)
+    {
+        var ret = false;
+        
+        Roo.each(this.barItems, function(e) {
+            if (e.rid != rid) {
+                return;
+            }
+            
+            ret =  e;
+            return false;
+        });
+        
+        return ret;
+    },
+    
+    indexOfItem : function(item)
+    {
+        var index = false;
+        
+        Roo.each(this.barItems, function(v, i){
+            
+            if (v.rid != item.rid) {
+                return;
+            }
+            
+            index = i;
+            return false
+        });
+        
+        return index;
+    },
+    
+    setActiveNext : function()
+    {
+        var i = this.indexOfItem(this.getActive());
+        
+        if (i > this.barItems.length) {
+            return;
+        }
+        
+        this.setActiveItem(this.barItems[i+1]);
+    },
+    
+    setActivePrev : function()
+    {
+        var i = this.indexOfItem(this.getActive());
+        
+        if (i  < 1) {
+            return;
+        }
+        
+        this.setActiveItem(this.barItems[i-1]);
+    },
+    
+    format : function()
+    {
+        if(!this.barItems.length){
+            return;
+        }
+     
+        var width = 100 / this.barItems.length;
+        
+        Roo.each(this.barItems, function(i){
+            i.el.setStyle('width', width + '%');
+            i.topEl.el.setStyle('width', width + '%');
+            i.bottomEl.el.setStyle('width', width + '%');
+        }, this);
+        
     }
     
 });
-
- /*
+/*
  * - LGPL
  *
- *  Breadcrumb Item
+ * Nav Progress Item
  * 
  */
 
-
 /**
- * @class Roo.bootstrap.breadcrumb.Nav
+ * @class Roo.bootstrap.nav.ProgressBarItem
  * @extends Roo.bootstrap.Component
- * Bootstrap Breadcrumb Nav Class
- *  
- * @children Roo.bootstrap.breadcrumb.Component
- * @cfg {String} html the content of the link.
- * @cfg {String} href where it links to if '#' is used the link will be handled by onClick.
- * @cfg {Boolean} active is it active
-
+ * Bootstrap NavProgressBarItem class
+ * @cfg {String} rid the reference id
+ * @cfg {Boolean} active (true|false) Is item active default false
+ * @cfg {Boolean} disabled (true|false) Is item active default false
+ * @cfg {String} html
+ * @cfg {String} position (top|bottom) text position default bottom
+ * @cfg {String} icon show icon instead of number
  * 
  * @constructor
- * Create a new breadcrumb.Nav
+ * Create a new NavProgressBarItem
  * @param {Object} config The config object
  */
-
-Roo.bootstrap.breadcrumb.Item = function(config){
-    Roo.bootstrap.breadcrumb.Item.superclass.constructor.call(this, config);
+Roo.bootstrap.nav.ProgressBarItem = function(config){
+    Roo.bootstrap.nav.ProgressBarItem.superclass.constructor.call(this, config);
     this.addEvents({
-        // img events
+        // raw events
         /**
          * @event click
-         * The img click event for the img.
+         * The raw click event for the entire grid.
+         * @param {Roo.bootstrap.nav.ProgressBarItem} this
          * @param {Roo.EventObject} e
          */
         "click" : true
     });
-    
+   
 };
 
-Roo.extend(Roo.bootstrap.breadcrumb.Item, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.nav.ProgressBarItem, Roo.bootstrap.Component,  {
     
-    href: false,
+    rid : '',
+    active : false,
+    disabled : false,
     html : '',
+    position : 'bottom',
+    icon : false,
     
     getAutoCreate : function()
     {
-
+        var iconCls = 'roo-navigation-bar-item-icon';
+        
+        iconCls += ((this.icon) ? (' ' + this.icon) : (' step-number')) ;
+        
         var cfg = {
             tag: 'li',
-            cls : 'breadcrumb-item' + (this.active ? ' active' : '')
+            cls: 'roo-navigation-bar-item',
+            cn : [
+                {
+                    tag : 'i',
+                    cls : iconCls
+                }
+            ]
         };
-        if (this.href !== false) {
-            cfg.cn = [{
-                tag : 'a',
-                href : this.href,
-                html : this.html
-            }];
-        } else {
-            cfg.html = this.html;
+        
+        if(this.active){
+            cfg.cls += ' active';
+        }
+        if(this.disabled){
+            cfg.cls += ' disabled';
         }
         
         return cfg;
     },
     
-    initEvents: function()
+    disable : function()
     {
-        if (this.href) {
-            this.el.select('a', true).first().on('click',this.onClick, this)
-        }
+        this.setDisabled(true);
+    },
+    
+    enable : function()
+    {
+        this.setDisabled(false);
+    },
+    
+    initEvents: function() 
+    {
+        this.iconEl = this.el.select('.roo-navigation-bar-item-icon', true).first();
         
+        this.iconEl.on('click', this.onClick, this);
     },
+    
     onClick : function(e)
     {
         e.preventDefault();
-        this.fireEvent('click',this,  e);
-    }
+        
+        if(this.disabled){
+            return;
+        }
+        
+        if(this.fireEvent('click', this, e) === false){
+            return;
+        };
+        
+        this.parent().setActiveItem(this);
+    },
+    
+    isActive: function () 
+    {
+        return this.active;
+    },
+    
+    setActive : function(state)
+    {
+        if(this.active == state){
+            return;
+        }
+        
+        this.active = state;
+        
+        if (state) {
+            this.el.addClass('active');
+            return;
+        }
+        
+        this.el.removeClass('active');
+        
+        return;
+    },
+    
+    setDisabled : function(state)
+    {
+        if(this.disabled == state){
+            return;
+        }
+        
+        this.disabled = state;
+        
+        if (state) {
+            this.el.addClass('disabled');
+            return;
+        }
+        
+        this.el.removeClass('disabled');
+    },
     
+    tooltipEl : function()
+    {
+        return this.el.select('.roo-navigation-bar-item-icon', true).first();;
+    }
 });
 
  /*
  * - LGPL
  *
- * row
+ *  Breadcrumb Nav
  * 
  */
+Roo.namespace('Roo.bootstrap.breadcrumb');
+
 
 /**
- * @class Roo.bootstrap.Row
+ * @class Roo.bootstrap.breadcrumb.Nav
  * @extends Roo.bootstrap.Component
- * Bootstrap Row class (contains columns...)
+ * Bootstrap Breadcrumb Nav Class
+ *  
+ * @children Roo.bootstrap.breadcrumb.Item
  * 
  * @constructor
- * Create a new Row
+ * Create a new breadcrumb.Nav
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.Row = function(config){
+
+Roo.bootstrap.breadcrumb.Nav = function(config){
+    Roo.bootstrap.breadcrumb.Nav.superclass.constructor.call(this, config);
+    
+    
+};
+
+Roo.extend(Roo.bootstrap.breadcrumb.Nav, Roo.bootstrap.Component,  {
+    
+    getAutoCreate : function()
+    {
+
+        var cfg = {
+            tag: 'nav',
+            cn : [
+                {
+                    tag : 'ol',
+                    cls : 'breadcrumb'
+                }
+            ]
+            
+        };
+          
+        return cfg;
+    },
+    
+    initEvents: function()
+    {
+        this.olEl = this.el.select('ol',true).first();    
+    },
+    getChildContainer : function()
+    {
+        return this.olEl;  
+    }
+    
+});
+
+ /*
+ * - LGPL
+ *
+ *  Breadcrumb Item
+ * 
+ */
+
+
+/**
+ * @class Roo.bootstrap.breadcrumb.Nav
+ * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * @parent Roo.bootstrap.breadcrumb.Nav
+ * Bootstrap Breadcrumb Nav Class
+ *  
+ * 
+ * @cfg {String} html the content of the link.
+ * @cfg {String} href where it links to if '#' is used the link will be handled by onClick.
+ * @cfg {Boolean} active is it active
+
+ * 
+ * @constructor
+ * Create a new breadcrumb.Nav
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.breadcrumb.Item = function(config){
+    Roo.bootstrap.breadcrumb.Item.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.breadcrumb.Item, Roo.bootstrap.Component,  {
+    
+    href: false,
+    html : '',
+    
+    getAutoCreate : function()
+    {
+
+        var cfg = {
+            tag: 'li',
+            cls : 'breadcrumb-item' + (this.active ? ' active' : '')
+        };
+        if (this.href !== false) {
+            cfg.cn = [{
+                tag : 'a',
+                href : this.href,
+                html : this.html
+            }];
+        } else {
+            cfg.html = this.html;
+        }
+        
+        return cfg;
+    },
+    
+    initEvents: function()
+    {
+        if (this.href) {
+            this.el.select('a', true).first().on('click',this.onClick, this)
+        }
+        
+    },
+    onClick : function(e)
+    {
+        e.preventDefault();
+        this.fireEvent('click',this,  e);
+    }
+    
+});
+
+ /*
+ * - LGPL
+ *
+ * row
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.Row
+ * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * Bootstrap Row class (contains columns...)
+ * 
+ * @constructor
+ * Create a new Row
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Row = function(config){
     Roo.bootstrap.Row.superclass.constructor.call(this, config);
 };
 
@@ -7119,9 +7556,11 @@ Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.Pagination
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Pagination
  * Bootstrap Pagination class
- * @cfg {String} size xs | sm | md | lg
- * @cfg {Boolean} inverse false | true
+ * 
+ * @cfg {String} size (xs|sm|md|lg|xl)
+ * @cfg {Boolean} inverse 
  * 
  * @constructor
  * Create a new Pagination
@@ -7419,6 +7858,7 @@ Roo.extend(Roo.grid.SplitDragZone, Roo.dd.DDProxy, {
 /**
  * @class Roo.grid.AbstractSelectionModel
  * @extends Roo.util.Observable
+ * @abstract
  * 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
@@ -8032,7 +8472,7 @@ Roo.grid.ColumnModel = function(config){
 };
 Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
     /**
-     * @cfg {String} header The header text to display in the Grid view.
+     * @cfg {String} header [required] The header text to display in the Grid view.
      */
        /**
      * @cfg {String} xsHeader Header at Bootsrap Extra Small width (default for all)
@@ -8050,66 +8490,66 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
      * @cfg {String} xlHeader Header at Bootsrap extra Large width
      */
     /**
-     * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s
+     * @cfg {String} dataIndex  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
+     * @cfg {Number} width  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.
+     * @cfg {Boolean} sortable 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} locked  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} fixed  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} resizable  False to disable column resizing. Defaults to true.
      */
     /**
-     * @cfg {Boolean} hidden (Optional) True to hide the column. Defaults to false.
+     * @cfg {Boolean} hidden  True to hide the column. Defaults to false.
      */
     /**
-     * @cfg {Function} renderer (Optional) A function used to generate HTML markup for a cell
+     * @cfg {Function} renderer 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 returns the escaped data value. If an object is returned (bootstrap only)
      * then it is treated as a Roo Component object instance, and it is rendered after the initial row is rendered
      */
        /**
-     * @cfg {Roo.grid.GridEditor} editor (Optional) For grid editors - returns the grid editor 
+     * @cfg {Roo.grid.GridEditor} editor  For grid editors - returns the grid editor 
      */
     /**
-     * @cfg {String} align (Optional) Set the CSS text-align property of the column.  Defaults to undefined.
+     * @cfg {String} align (left|right) Set the CSS text-align property of the column.  Defaults to undefined (left).
      */
     /**
-     * @cfg {String} valign (Optional) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc).  Defaults to undefined.
+     * @cfg {String} valign (top|bottom|middle) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc).  Defaults to undefined (middle)
      */
     /**
-     * @cfg {String} cursor (Optional)
+     * @cfg {String} cursor ( auto|default|none|context-menu|help|pointer|progress|wait|cell|crosshair|text|vertical-text|alias|copy|move|no-drop|not-allowed|e-resize|n-resize|ne-resize|nw-resize|s-resize|se-resize|sw-resize|w-resize|ew-resize|ns-resize|nesw-resize|nwse-resize|col-resize|row-resize|all-scroll|zoom-in|zoom-out|grab|grabbing)
      */
     /**
-     * @cfg {String} tooltip (Optional)
+     * @cfg {String} tooltip mouse over tooltip text
      */
     /**
-     * @cfg {Number} xs (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} xs  can be '0' for hidden at this size (number less than 12)
      */
     /**
-     * @cfg {Number} sm (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} sm can be '0' for hidden at this size (number less than 12)
      */
     /**
-     * @cfg {Number} md (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} md can be '0' for hidden at this size (number less than 12)
      */
     /**
-     * @cfg {Number} lg (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} lg   can be '0' for hidden at this size (number less than 12)
      */
        /**
-     * @cfg {Number} xl (Optional) can be '0' for hidden at this size (number less than 12)
+     * @cfg {Number} xl   can be '0' for hidden at this size (number less than 12)
      */
     /**
      * Returns the id of the column at the specified index.
@@ -8648,6 +9088,7 @@ Roo.LoadMask.prototype = {
  * @class Roo.bootstrap.Table
  * @licence LGBL
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.TableBody
  * Bootstrap Table class.  This class represents the primary interface of a component based grid control.
  * Similar to Roo.grid.Grid
  * <pre><code>
@@ -8709,13 +9150,14 @@ Currently the Table  uses multiple headers to try and handle XL / Medium etc...
 
 
  *
- * @cfg {Roo.grid.RowSelectionModel|Roo.grid.CellSelectionModel} sm The selection model to use (cell selection is not supported yet)
- * @cfg {Roo.data.Store|Roo.data.SimpleStore} store The data store to use
- * @cfg {Roo.grid.ColumnModel} cm[] A column for th grid.
+ * @cfg {Roo.grid.AbstractSelectionModel} sm The selection model to use (cell selection is not supported yet)
+ * @cfg {Roo.data.Store} store The data store to use
+ * @cfg {Roo.grid.ColumnModel} cm[] A column for the grid.
  * 
  * @cfg {String} cls table class
  *
- * 
+ *
+ * @cfg {string} empty_results  Text to display for no results 
  * @cfg {boolean} striped Should the rows be alternative striped
  * @cfg {boolean} bordered Add borders to the table
  * @cfg {boolean} hover Add hover highlighting
@@ -8724,14 +9166,18 @@ Currently the Table  uses multiple headers to try and handle XL / Medium etc...
  *                also adds table-responsive (see bootstrap docs for details)
  * @cfg {Boolean} loadMask (true|false) default false
  * @cfg {Boolean} footerShow (true|false) generate tfoot, default true
+ * @cfg {Boolean} footerRow (true|false) generate tfoot with columns of values, default false
  * @cfg {Boolean} headerShow (true|false) generate thead, default true
  * @cfg {Boolean} rowSelection (true|false) default false
  * @cfg {Boolean} cellSelection (true|false) default false
- * @cfg {Boolean} scrollBody (true|false) default false - body scrolled / fixed header
+ * @cfg {Boolean} scrollBody (true|false) default false - body scrolled / fixed header (with resizable columns)
  * @cfg {Roo.bootstrap.PagingToolbar} footer  a paging toolbar
  * @cfg {Boolean} lazyLoad  auto load data while scrolling to the end (default false)
  * @cfg {Boolean} auto_hide_footer  auto hide footer if only one page (default false)
- * @cfg {Boolean} enableColumnResize default true if columns can be resized (drag/drop)
+ * @cfg {Boolean} enableColumnResize default true if columns can be resized = needs scrollBody to be set to work (drag/drop)
+ * @cfg {Boolean} disableAutoSize disable autoSize() and initCSS()
+ *
+ * 
  * @cfg {Number} minColumnWidth default 50 pixels minimum column width 
  * 
  * @constructor
@@ -8893,6 +9339,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     
     cls: false,
     
+    empty_results : '',
     striped : false,
     scrollBody : false,
     bordered: false,
@@ -8904,8 +9351,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     store : false,
     loadMask : false,
     footerShow : true,
+    footerRow : false,
     headerShow : true,
     enableColumnResize: true,
+    disableAutoSize: false,
   
     rowSelection : false,
     cellSelection : false,
@@ -8978,9 +9427,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
             
             cfg.cn.push(this.renderBody());
             
-            if(this.footerShow){
+            if(this.footerShow || this.footerRow){
                 cfg.cn.push(this.renderFooter());
             }
+
             // where does this come from?
             //cfg.cls+=  ' TableGrid';
         }
@@ -9067,7 +9517,9 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     
     initCSS : function()
     {
-        
+        if(this.disableAutoSize) {
+            return;
+        }
         
         var cm = this.cm, styles = [];
         this.CSS.removeStyleSheet(this.id + '-cssrules');
@@ -9144,7 +9596,9 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
                 }
                 
                 styles.push('#' , this.id , ' .x-hcol-' , i, " { ", width, hidden," }\n",
-                            '#' , this.id , ' .x-grid-split-' , i, " { ", left, splithide,'height:', (headHeight - 4), "px;}\n"
+                            '#' , this.id , ' .x-grid-split-' , i, " { ", left, splithide, 'height:', (headHeight - 4), "px;}\n",
+                            // this is the popover version..
+                            '.popover-inner #' , this.id , ' .x-grid-split-' , i, " { ", left, splithide, 'height:', 100, "%;}\n"
                 );
             }
             
@@ -9537,8 +9991,6 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
         return footer;
     },
     
-    
-    
     onLoad : function()
     {
 //        Roo.log('ds onload');
@@ -9579,11 +10031,13 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
                 }
                 
             }, this);
+        } else if (this.empty_results.length) {
+            this.el.mask(this.empty_results, 'no-spinner');
         }
         
         var tfoot = this.el.select('tfoot', true).first();
         
-        if(this.footerShow && this.auto_hide_footer && this.mainFoot){
+        if(this.footerShow && !this.footerRow && this.auto_hide_footer && this.mainFoot){
             
             this.mainFoot.setVisibilityMode(Roo.Element.DISPLAY).hide();
             
@@ -9593,6 +10047,30 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
                 this.mainFoot.show();
             }
         }
+
+        if(!this.footerShow && this.footerRow) {
+
+            var tr = {
+                tag : 'tr',
+                cn : []
+            };
+
+            for(var i = 0, len = cm.getColumnCount(); i < len; i++){
+                var footer = typeof(cm.config[i].footer) == "function" ? cm.config[i].footer(ds, cm.config[i]) : cm.config[i].footer;
+                var td = {
+                    tag: 'td',
+                    cls : ' x-fcol-' + i,
+                    html: footer
+                };
+
+                tr.cn.push(td);
+                
+            }
+            
+            tfoot.dom.innerHTML = '';
+
+            tfoot.createChild(tr);
+        }
         
         Roo.each(this.el.select('tbody td', true).elements, function(e){
             e.on('mouseover', _this.onMouseover, _this);
@@ -9860,7 +10338,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
             var id = false;
             
             if(typeof(renderer) !== 'undefined'){
-                value = renderer(d.data[cm.getDataIndex(i)], false, d);
+                value = renderer.call(config, d.data[cm.getDataIndex(i)], false, d);
             }
             // if object are returned, then they are expected to be Roo.bootstrap.Component instances
             // and are rendered into the cells after the row is rendered - using the id for the element.
@@ -9957,7 +10435,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     
     onBeforeLoad : function()
     {
-        
+        this.el.unmask(); // if needed.
     },
      /**
      * Remove all rows
@@ -10067,6 +10545,9 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
      */
     autoSize : function()
     {
+        if(this.disableAutoSize) {
+            return;
+        }
         //var ctr = Roo.get(this.container.dom.parentElement);
         var ctr = Roo.get(this.el.dom);
         
@@ -10277,7 +10758,10 @@ Roo.bootstrap.Table.RowSelectionModel = Roo.grid.RowSelectionModel;
 /**
  * @class Roo.bootstrap.TableCell
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
+ * @parent Roo.bootstrap.TableRow
  * Bootstrap TableCell class
+ * 
  * @cfg {String} html cell contain text
  * @cfg {String} cls cell class
  * @cfg {String} tag cell tag (td|th) default td
@@ -10399,6 +10883,8 @@ Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.TableRow
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.TableCell
+ * @parent Roo.bootstrap.TableBody
  * Bootstrap TableRow class
  * @cfg {String} cls row class
  * @cfg {String} align Aligns the content in a table row
@@ -10463,6 +10949,8 @@ Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.TableBody
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.TableRow
+ * @parent Roo.bootstrap.Table
  * Bootstrap TableBody class
  * @cfg {String} cls element class
  * @cfg {String} tag element tag (thead|tbody|tfoot) default tbody
@@ -10830,7 +11318,13 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
         }
         var ret = false;
         try {
-            ret = Roo.decode(response.responseText);
+            var rt = response.responseText;
+            if (rt.match(/^\<!--\[CDATA\[/)) {
+                rt = rt.replace(/^\<!--\[CDATA\[/,'');
+                rt = rt.replace(/\]\]--\>$/,'');
+            }
+            
+            ret = Roo.decode(rt);
         } catch (e) {
             ret = {
                 success: false,
@@ -10899,8 +11393,9 @@ Roo.form.Action.ACTION_TYPES = {
  */
 
 /**
- * @class Roo.bootstrap.Form
+ * @class Roo.bootstrap.form.Form
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
  * Bootstrap Form class
  * @cfg {String} method  GET | POST (default POST)
  * @cfg {String} labelAlign top | left (default top)
@@ -10914,11 +11409,11 @@ Roo.form.Action.ACTION_TYPES = {
  */
 
 
-Roo.bootstrap.Form = function(config){
+Roo.bootstrap.form.Form = function(config){
     
-    Roo.bootstrap.Form.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.Form.superclass.constructor.call(this, config);
     
-    Roo.bootstrap.Form.popover.apply();
+    Roo.bootstrap.form.Form.popover.apply();
     
     this.addEvents({
         /**
@@ -10952,7 +11447,7 @@ Roo.bootstrap.Form = function(config){
     });
 };
 
-Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.form.Form, Roo.bootstrap.Component,  {
 
      /**
      * @cfg {String} method
@@ -11082,7 +11577,7 @@ Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
         });
         
         if(this.errorMask && !valid){
-            Roo.bootstrap.Form.popover.mask(this, target);
+            Roo.bootstrap.form.Form.popover.mask(this, target);
         }
         
         return valid;
@@ -11499,7 +11994,7 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
 
 });
 
-Roo.apply(Roo.bootstrap.Form, {
+Roo.apply(Roo.bootstrap.form.Form, {
     
     popover : {
         
@@ -11635,7 +12130,7 @@ Roo.apply(Roo.bootstrap.Form, {
             this.toolTip.show(tip);
 
             this.intervalID = window.setInterval(function() {
-                Roo.bootstrap.Form.popover.unmask();
+                Roo.bootstrap.form.Form.popover.unmask();
             }, 10000);
 
             window.onwheel = function(){ return false;};
@@ -11698,7 +12193,7 @@ Roo.apply(Roo.bootstrap.Form, {
 /**
  * @class Roo.form.VTypes
  * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
- * @singleton
+ * @static
  */
 Roo.form.VTypes = function(){
     // closure these in so they are only created once.
@@ -11713,68 +12208,68 @@ Roo.form.VTypes = function(){
          * The function used to validate email addresses
          * @param {String} value The email address
          */
-        'email' : function(v){
+        email : function(v){
             return email.test(v);
         },
         /**
          * The error text to display when the email validation function returns false
          * @type String
          */
-        'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
+        emailText : 'This field should be an e-mail address in the format "user@domain.com"',
         /**
          * The keystroke filter mask to be applied on email input
          * @type RegExp
          */
-        'emailMask' : /[a-z0-9_\.\-@]/i,
+        emailMask : /[a-z0-9_\.\-@]/i,
 
         /**
          * The function used to validate URLs
          * @param {String} value The URL
          */
-        'url' : function(v){
+        url : function(v){
             return url.test(v);
         },
         /**
          * The error text to display when the url validation function returns false
          * @type String
          */
-        'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
+        urlText : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
         
         /**
          * The function used to validate alpha values
          * @param {String} value The value
          */
-        'alpha' : function(v){
+        alpha : function(v){
             return alpha.test(v);
         },
         /**
          * The error text to display when the alpha validation function returns false
          * @type String
          */
-        'alphaText' : 'This field should only contain letters and _',
+        alphaText : 'This field should only contain letters and _',
         /**
          * The keystroke filter mask to be applied on alpha input
          * @type RegExp
          */
-        'alphaMask' : /[a-z_]/i,
+        alphaMask : /[a-z_]/i,
 
         /**
          * The function used to validate alphanumeric values
          * @param {String} value The value
          */
-        'alphanum' : function(v){
+        alphanum : function(v){
             return alphanum.test(v);
         },
         /**
          * The error text to display when the alphanumeric validation function returns false
          * @type String
          */
-        'alphanumText' : 'This field should only contain letters, numbers and _',
+        alphanumText : 'This field should only contain letters, numbers and _',
         /**
          * The keystroke filter mask to be applied on alphanumeric input
          * @type RegExp
          */
-        'alphanumMask' : /[a-z0-9_]/i
+        alphanumMask : /[a-z0-9_]/i
     };
 }();/*
  * - LGPL
@@ -11784,15 +12279,15 @@ Roo.form.VTypes = function(){
  */
 
 /**
- * @class Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.Input
  * @extends Roo.bootstrap.Component
  * Bootstrap Input class
  * @cfg {Boolean} disabled is it disabled
- * @cfg {String} (button|checkbox|email|file|hidden|image|number|password|radio|range|reset|search|submit|text) inputType 
+ * @cfg {String} inputType (button|checkbox|email|file|hidden|image|number|password|radio|range|reset|search|submit|text)  
  * @cfg {String} name name of the input
  * @cfg {string} fieldLabel - the label associated
  * @cfg {string} placeholder - placeholder to put in text.
- * @cfg {string}  before - input group add on before
+ * @cfg {string} before - input group add on before
  * @cfg {string} after - input group add on after
  * @cfg {string} size - (lg|sm) or leave empty..
  * @cfg {Number} xs colspan out of 12 for mobile-sized screens
@@ -11812,7 +12307,8 @@ Roo.form.VTypes = function(){
  * @cfg {String} capture (user|camera) use for file input only. (default empty)
  * @cfg {String} accept (image|video|audio) use for file input only. (default empty)
  * @cfg {Boolean} preventMark Do not show tick or cross if error/success
-
+ * @cfg {Roo.bootstrap.Button} before Button to show before
+ * @cfg {Roo.bootstrap.Button} afterButton to show before
  * @cfg {String} align (left|center|right) Default left
  * @cfg {Boolean} forceFeedback (true|false) Default false
  * 
@@ -11821,9 +12317,9 @@ Roo.form.VTypes = function(){
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.Input = function(config){
+Roo.bootstrap.form.Input = function(config){
     
-    Roo.bootstrap.Input.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.Input.superclass.constructor.call(this, config);
     
     this.addEvents({
         /**
@@ -11884,7 +12380,7 @@ Roo.bootstrap.Input = function(config){
     });
 };
 
-Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.form.Input, Roo.bootstrap.Component,  {
      /**
      * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
       automatic validation (defaults to "keyup").
@@ -12050,7 +12546,6 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
     
     getAutoCreate : function()
     {
-        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
         
         var id = Roo.id();
         
@@ -12179,6 +12674,34 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 inputblock.cn.push(feedback);
             }
         };
+        
+        
+        
+        cfg = this.getAutoCreateLabel( cfg, inputblock );
+        
+       
+         
+        
+        if (this.parentType === 'Navbar' &&  this.parent().bar) {
+           cfg.cls += ' navbar-form';
+        }
+        
+        if (this.parentType === 'NavGroup' && !(Roo.bootstrap.version == 4 && this.parent().form)) {
+            // on BS4 we do this only if not form 
+            cfg.cls += ' navbar-form';
+            cfg.tag = 'li';
+        }
+        
+        return cfg;
+        
+    },
+    /**
+     * autocreate the label - also used by textara... ?? and others?
+     */
+    getAutoCreateLabel : function( cfg, inputblock )
+    {
+        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
+       
         var indicator = {
             tag : 'i',
             cls : 'roo-required-indicator ' + (this.indicatorpos == 'right'  ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star',
@@ -12322,20 +12845,10 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 
                 
         };
-        
-        if (this.parentType === 'Navbar' &&  this.parent().bar) {
-           cfg.cls += ' navbar-form';
-        }
-        
-        if (this.parentType === 'NavGroup' && !(Roo.bootstrap.version == 4 && this.parent().form)) {
-            // on BS4 we do this only if not form 
-            cfg.cls += ' navbar-form';
-            cfg.tag = 'li';
-        }
-        
         return cfg;
-        
     },
+    
+    
     /**
      * return the real input element.
      */
@@ -12484,12 +12997,12 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         }
         if(typeof this.validator == "function"){
             var msg = this.validator(value);
-            if(msg !== true){
-                return false;
-            }
             if (typeof(msg) == 'string') {
                 this.invalidText = msg;
             }
+            if(msg !== true){
+                return false;
+            }
         }
         
         if(this.regex && !this.regex.test(value)){
@@ -12890,8 +13403,8 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
  */
 
 /**
- * @class Roo.bootstrap.TextArea
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.TextArea
+ * @extends Roo.bootstrap.form.Input
  * Bootstrap TextArea class
  * @cfg {Number} cols Specifies the visible width of a text area
  * @cfg {Number} rows Specifies the visible number of lines in a text area
@@ -12904,12 +13417,12 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.TextArea = function(config){
-    Roo.bootstrap.TextArea.superclass.constructor.call(this, config);
+Roo.bootstrap.form.TextArea = function(config){
+    Roo.bootstrap.form.TextArea.superclass.constructor.call(this, config);
    
 };
 
-Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.TextArea, Roo.bootstrap.form.Input,  {
      
     cols : false,
     rows : 5,
@@ -13024,74 +13537,10 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
             
         }
         
-        if (align ==='left' && this.fieldLabel.length) {
-            cfg.cn = [
-                {
-                    tag: 'label',
-                    'for' :  id,
-                    cls : 'control-label',
-                    html : this.fieldLabel
-                },
-                {
-                    cls : "",
-                    cn: [
-                        inputblock
-                    ]
-                }
-
-            ];
-            
-            if(this.labelWidth > 12){
-                cfg.cn[0].style = "width: " + this.labelWidth + 'px';
-            }
-
-            if(this.labelWidth < 13 && this.labelmd == 0){
-                this.labelmd = this.labelWidth;
-            }
-
-            if(this.labellg > 0){
-                cfg.cn[0].cls += ' col-lg-' + this.labellg;
-                cfg.cn[1].cls += ' col-lg-' + (12 - this.labellg);
-            }
-
-            if(this.labelmd > 0){
-                cfg.cn[0].cls += ' col-md-' + this.labelmd;
-                cfg.cn[1].cls += ' col-md-' + (12 - this.labelmd);
-            }
-
-            if(this.labelsm > 0){
-                cfg.cn[0].cls += ' col-sm-' + this.labelsm;
-                cfg.cn[1].cls += ' col-sm-' + (12 - this.labelsm);
-            }
-
-            if(this.labelxs > 0){
-                cfg.cn[0].cls += ' col-xs-' + this.labelxs;
-                cfg.cn[1].cls += ' col-xs-' + (12 - this.labelxs);
-            }
-            
-        } else if ( this.fieldLabel.length) {
-            cfg.cn = [
-
-               {
-                   tag: 'label',
-                   //cls : 'input-group-addon',
-                   html : this.fieldLabel
-
-               },
-
-               inputblock
-
-           ];
-
-        } else {
-
-            cfg.cn = [
-
-                inputblock
+        
+        cfg = this.getAutoCreateLabel( cfg, inputblock );
 
-            ];
-                
-        }
+         
         
         if (this.disabled) {
             input.disabled=true;
@@ -13119,11 +13568,11 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
         }
         
         var label = this.el.select('label', true).first();
-        var icon = this.el.select('i.fa-star', true).first();
+        //var icon = this.el.select('i.fa-star', true).first();
         
-        if(label && icon){
-            icon.remove();
-        }
+        //if(label && icon){
+        //    icon.remove();
+        //}
         this.el.removeClass( this.validClass);
         this.inputEl().removeClass('is-invalid');
          
@@ -13165,9 +13614,9 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
         var label = this.el.select('label', true).first();
         var icon = this.el.select('i.fa-star', true).first();
         
-        if(label && icon){
-            icon.remove();
-        }
+        //if(label && icon){
+        //    icon.remove();
+        //}
         if (Roo.bootstrap.version == 3) {
             this.el.addClass(this.validClass);
         } else {
@@ -13213,16 +13662,17 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
         }
         
         var label = this.el.select('label', true).first();
-        var icon = this.el.select('i.fa-star', true).first();
+        //var icon = this.el.select('i.fa-star', true).first();
         
-        if(!this.getValue().length && label && !icon){
-            this.el.createChild({
+        //if(!this.getValue().length && label && !icon){
+          /*  this.el.createChild({
                 tag : 'i',
                 cls : 'text-danger fa fa-lg fa-star',
                 tooltip : 'This field is required',
                 style : 'margin-right:5px;'
             }, label, true);
-        }
+            */
+        //}
         
         if (Roo.bootstrap.version == 3) {
             this.el.addClass(this.invalidClass);
@@ -13259,35 +13709,35 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
  */
  
 /**
- * @class Roo.bootstrap.TriggerField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.TriggerField
+ * @extends Roo.bootstrap.form.Input
  * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
  * The trigger has no default action, so you must assign a function to implement the trigger click handler by
  * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox
  * for which you can provide a custom implementation.  For example:
  * <pre><code>
-var trigger = new Roo.bootstrap.TriggerField();
+var trigger = new Roo.bootstrap.form.TriggerField();
 trigger.onTriggerClick = myTriggerFn;
 trigger.applyTo('my-field');
 </code></pre>
  *
  * However, in general you will most likely want to use TriggerField as the base class for a reusable component.
- * {@link Roo.bootstrap.DateField} and {@link Roo.bootstrap.ComboBox} are perfect examples of this.
+ * {@link Roo.bootstrap.form.DateField} and {@link Roo.bootstrap.form.ComboBox} are perfect examples of this.
  * @cfg {String} triggerClass An additional CSS class used to style the trigger button.  The trigger will always get the
  * class 'x-form-trigger' by default and triggerClass will be <b>appended</b> if specified.
  * @cfg {String} caret (search|calendar) BS3 only - carat fa name
 
  * @constructor
  * Create a new TriggerField.
- * @param {Object} config Configuration options (valid {@Roo.bootstrap.Input} config options will also be applied
+ * @param {Object} config Configuration options (valid {@Roo.bootstrap.form.Input} config options will also be applied
  * to the base TextField)
  */
-Roo.bootstrap.TriggerField = function(config){
+Roo.bootstrap.form.TriggerField = function(config){
     this.mimicing = false;
-    Roo.bootstrap.TriggerField.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.TriggerField.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.TriggerField, Roo.bootstrap.form.Input,  {
     /**
      * @cfg {String} triggerClass A CSS class to apply to the trigger
      */
@@ -13507,12 +13957,14 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             cls : 'roo-required-indicator ' + (this.indicatorpos == 'right'  ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star',
             tooltip : 'This field is required'
         };
-        if (Roo.bootstrap.version == 4) {
+      
+        if (this.allowBlank) {
             indicator = {
                 tag : 'i',
                 style : 'display:none'
             };
         }
+         
         
         
         if (align ==='left' && this.fieldLabel.length) {
@@ -13653,7 +14105,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
     
     // private
     onResize : function(w, h){
-//        Roo.bootstrap.TriggerField.superclass.onResize.apply(this, arguments);
+//        Roo.bootstrap.form.TriggerField.superclass.onResize.apply(this, arguments);
 //        if(typeof w == 'number'){
 //            var x = w - this.trigger.getWidth();
 //            this.inputEl().setWidth(this.adjustWidth('input', x));
@@ -13684,7 +14136,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
         
         this.createList();
         
-        Roo.bootstrap.TriggerField.superclass.initEvents.call(this);
+        Roo.bootstrap.form.TriggerField.superclass.initEvents.call(this);
         //this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
         if(!this.multiple && this.showToggleBtn){
             this.trigger = this.el.select('span.dropdown-toggle',true).first();
@@ -13757,12 +14209,12 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
         //if(this.wrap){
         //    this.wrap.remove();
         //}
-        Roo.bootstrap.TriggerField.superclass.onDestroy.call(this);
+        Roo.bootstrap.form.TriggerField.superclass.onDestroy.call(this);
     },
 
     // private
     onFocus : function(){
-        Roo.bootstrap.TriggerField.superclass.onFocus.call(this);
+        Roo.bootstrap.form.TriggerField.superclass.onFocus.call(this);
         /*
         if(!this.mimicing){
             this.wrap.addClass('x-trigger-wrap-focus');
@@ -13804,7 +14256,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             this.el.un("keydown", this.checkTab, this);
         }
         //this.wrap.removeClass('x-trigger-wrap-focus');
-        Roo.bootstrap.TriggerField.superclass.onBlur.call(this);
+        Roo.bootstrap.form.TriggerField.superclass.onBlur.call(this);
     },
 
     // private
@@ -13816,7 +14268,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
     // private
     onDisable : function(){
         this.inputEl().dom.disabled = true;
-        //Roo.bootstrap.TriggerField.superclass.onDisable.call(this);
+        //Roo.bootstrap.form.TriggerField.superclass.onDisable.call(this);
         //if(this.wrap){
         //    this.wrap.addClass('x-item-disabled');
         //}
@@ -13825,7 +14277,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
     // private
     onEnable : function(){
         this.inputEl().dom.disabled = false;
-        //Roo.bootstrap.TriggerField.superclass.onEnable.call(this);
+        //Roo.bootstrap.form.TriggerField.superclass.onEnable.call(this);
         //if(this.wrap){
         //    this.el.removeClass('x-item-disabled');
         //}
@@ -13862,7 +14314,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
 */
 
 /**
- * @class Roo.bootstrap.CardUploader
+ * @class Roo.bootstrap.form.CardUploader
  * @extends Roo.bootstrap.Button
  * Bootstrap Card Uploader class - it's a button which when you add files to it, adds cards below with preview and the name...
  * @cfg {Number} errorTimeout default 3000
@@ -13875,11 +14327,11 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.CardUploader = function(config){
+Roo.bootstrap.form.CardUploader = function(config){
     
  
     
-    Roo.bootstrap.CardUploader.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.CardUploader.superclass.constructor.call(this, config);
     
     
     this.fileCollection   = new Roo.util.MixedCollection(false,function(r) {
@@ -13907,7 +14359,7 @@ Roo.bootstrap.CardUploader = function(config){
     });
 };
  
-Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.CardUploader, Roo.bootstrap.form.Input,  {
     
      
     errorTimeout : 3000,
@@ -13973,7 +14425,7 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input,  {
     initEvents : function()
     {
         
-        Roo.bootstrap.Input.prototype.initEvents.call(this);
+        Roo.bootstrap.form.Input.prototype.initEvents.call(this);
         
         var t = this;
         this.addxtype({
@@ -14063,7 +14515,7 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input,  {
         var url = _this.urlAPI.createObjectURL( file);
            
         this.addCard({
-            id : Roo.bootstrap.CardUploader.ID--,
+            id : Roo.bootstrap.form.CardUploader.ID--,
             is_uploaded : false,
             src : url,
             srcfile : file,
@@ -14241,7 +14693,7 @@ Roo.extend(Roo.bootstrap.CardUploader, Roo.bootstrap.Input,  {
 });
 
 
-Roo.bootstrap.CardUploader.ID = -1;/*
+Roo.bootstrap.form.CardUploader.ID = -1;/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -14255,7 +14707,7 @@ Roo.bootstrap.CardUploader.ID = -1;/*
 
 /**
  * @class Roo.data.SortTypes
- * @singleton
+ * @static
  * Defines the default sorting (casting?) comparison functions used when sorting data.
  */
 Roo.data.SortTypes = {
@@ -14724,8 +15176,8 @@ Roo.data.Store = function(config){
          * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
          * 
          * @param {Proxy} 
-         * @param {Object} return from JsonData.reader() - success, totalRecords, records
-         * @param {Object} load options 
+         * @param {Object} ret return data from JsonData.reader() - success, totalRecords, records
+         * @param {Object} opts - load Options
          * @param {Object} jsonData from your request (normally this contains the Exception)
          */
         loadexception : true
@@ -14754,13 +15206,13 @@ Roo.extend(Roo.data.Store, Roo.util.Observable, {
     */
     
     /**
-    * @cfg {Roo.data.DataProxy} proxy The Proxy object which provides access to a data object.
+    * @cfg {Roo.data.DataProxy} proxy [required] The Proxy object which provides access to a data object.
     */
     /**
     * @cfg {Array} data Inline data to be loaded when the store is initialized.
     */
     /**
-    * @cfg {Roo.data.Reader} reader The Reader object which processes the data object and returns
+    * @cfg {Roo.data.DataReader} reader [required]  The Reader object which processes the data object and returns
     * an Array of Roo.data.record objects which are cached keyed by their <em>id</em> property.
     */
     /**
@@ -14909,6 +15361,16 @@ Roo.extend(Roo.data.Store, Roo.util.Observable, {
      * <p>
      * @param {Object} options An object containing properties which control loading options:<ul>
      * <li>params {Object} An object containing properties to pass as HTTP parameters to a remote data source.</li>
+     * <li>params.data {Object} if you are using a MemoryProxy / JsonReader, use this as the data to load stuff..
+     * <pre>
+                {
+                    data : data,  // array of key=>value data like JsonReader
+                    total : data.length,
+                    success : true
+                    
+                }
+        </pre>
+            }.</li>
      * <li>callback {Function} A function to be called after the Records have been loaded. The callback is
      * passed the following arguments:<ul>
      * <li>r : Roo.data.Record[]</li>
@@ -14955,7 +15417,8 @@ Roo.extend(Roo.data.Store, Roo.util.Observable, {
     // private
     // Called as a callback by the Reader during a load operation.
     loadRecords : function(o, options, success){
-        if(!o || success === false){
+         
+        if(!o){
             if(success !== false){
                 this.fireEvent("load", this, [], options, o);
             }
@@ -15343,6 +15806,8 @@ Roo.extend(Roo.data.Store, Roo.util.Observable, {
  * @cfg {Array} fields An array of field definition objects, or field name strings.
  * @cfg {Object} an existing reader (eg. copied from another store)
  * @cfg {Array} data The multi-dimensional array of data
+ * @cfg {Roo.data.DataProxy} proxy [not-required]  
+ * @cfg {Roo.data.Reader} reader  [not-required] 
  * @constructor
  * @param {Object} config
  */
@@ -15514,6 +15979,7 @@ Roo.data.Field.prototype = {
 
 /**
  * @class Roo.data.DataReader
+ * @abstract
  * Base class for reading structured data from a data source.  This class is intended to be
  * extended (see {Roo.data.ArrayReader}, {Roo.data.JsonReader} and {Roo.data.XmlReader}) and should not be created directly.
  */
@@ -15564,7 +16030,8 @@ Roo.data.DataReader.prototype = {
 
 /**
  * @class Roo.data.DataProxy
- * @extends Roo.data.Observable
+ * @extends Roo.util.Observable
+ * @abstract
  * This class is an abstract base class for implementations which provide retrieval of
  * unformatted data objects.<br>
  * <p>
@@ -15622,14 +16089,16 @@ Roo.extend(Roo.data.DataProxy, Roo.util.Observable);
  */
 /**
  * @class Roo.data.MemoryProxy
+ * @extends Roo.data.DataProxy
  * An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
  * to the Reader when its load method is called.
  * @constructor
- * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+ * @param {Object} config  A config object containing the objects needed for the Store to access data,
  */
-Roo.data.MemoryProxy = function(data){
-    if (data.data) {
-        data = data.data;
+Roo.data.MemoryProxy = function(config){
+    var data = config;
+    if (typeof(config) != 'undefined' && typeof(config.data) != 'undefined') {
+        data = config.data;
     }
     Roo.data.MemoryProxy.superclass.constructor.call(this);
     this.data = data;
@@ -15637,6 +16106,9 @@ Roo.data.MemoryProxy = function(data){
 
 Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
     
+    /**
+     *  @cfg {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+     */
     /**
      * Load data from the requested source (in this case an in-memory
      * data object passed to the constructor), read the data object into
@@ -15711,24 +16183,24 @@ Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
     // thse are take from connection...
     
     /**
-     * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
+     * @cfg {String} url  The default URL to be used for requests to the server. (defaults to undefined)
      */
     /**
-     * @cfg {Object} extraParams (Optional) An object containing properties which are used as
+     * @cfg {Object} extraParams  An object containing properties which are used as
      * extra parameters to each request made by this object. (defaults to undefined)
      */
     /**
-     * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
+     * @cfg {Object} defaultHeaders   An object containing request headers which are added
      *  to each request made by this object. (defaults to undefined)
      */
     /**
-     * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
+     * @cfg {String} method (GET|POST)  The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
      */
     /**
-     * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
+     * @cfg {Number} timeout The timeout in milliseconds to be used for requests. (defaults to 30000)
      */
      /**
-     * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
+     * @cfg {Boolean} autoAbort Whether this request should abort any pending requests. (defaults to false)
      * @type Boolean
      */
   
@@ -15802,8 +16274,10 @@ Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
         try {
             result = o.reader.read(response);
         }catch(e){
+            o.success = false;
+            o.raw = { errorMsg : response.responseText };
             this.fireEvent("loadexception", this, o, response, e);
-            o.request.callback.call(o.request.scope, null, o.request.arg, false);
+            o.request.callback.call(o.request.scope, o, o.request.arg, false);
             return;
         }
         
@@ -16209,19 +16683,27 @@ Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
         }
         var records = [];
         for(var i = 0; i < c; i++){
-                var n = root[i];
+            var n = root[i];
             var values = {};
             var id = this.getId(n);
             for(var j = 0; j < fl; j++){
                 f = fi[j];
-            var v = this.ef[j](n);
-            if (!f.convert) {
-                Roo.log('missing convert for ' + f.name);
-                Roo.log(f);
-                continue;
-            }
-            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
-            }
+                               var v = this.ef[j](n);
+                               if (!f.convert) {
+                                       Roo.log('missing convert for ' + f.name);
+                                       Roo.log(f);
+                                       continue;
+                               }
+                               values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
+            }
+                       if (!Record) {
+                               return {
+                                       raw : { errorMsg : "JSON Reader Error: fields or metadata not available to create Record" },
+                                       success : false,
+                                       records : [],
+                                       totalRecords : 0
+                               };
+                       }
             var record = new Record(values, id);
             record.json = n;
             records[i] = record;
@@ -16343,8 +16825,8 @@ Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
  */
 
 /**
- * @class Roo.bootstrap.ComboBox
- * @extends Roo.bootstrap.TriggerField
+ * @class Roo.bootstrap.form.ComboBox
+ * @extends Roo.bootstrap.form.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
@@ -16361,25 +16843,25 @@ Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
  * Create a new ComboBox.
  * @param {Object} config Configuration options
  */
-Roo.bootstrap.ComboBox = function(config){
-    Roo.bootstrap.ComboBox.superclass.constructor.call(this, config);
+Roo.bootstrap.form.ComboBox = function(config){
+    Roo.bootstrap.form.ComboBox.superclass.constructor.call(this, config);
     this.addEvents({
         /**
          * @event expand
          * Fires when the dropdown list is expanded
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         */
         'expand' : true,
         /**
          * @event collapse
          * Fires when the dropdown list is collapsed
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         */
         'collapse' : true,
         /**
          * @event beforeselect
          * Fires before a list item is selected. Return false to cancel the selection.
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         * @param {Roo.data.Record} record The data record returned from the underlying store
         * @param {Number} index The index of the selected item in the dropdown list
         */
@@ -16387,7 +16869,7 @@ Roo.bootstrap.ComboBox = function(config){
         /**
          * @event select
          * Fires when a list item is selected
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         * @param {Roo.data.Record} record The data record returned from the underlying store (or false on clear)
         * @param {Number} index The index of the selected item in the dropdown list
         */
@@ -16396,7 +16878,7 @@ Roo.bootstrap.ComboBox = function(config){
          * @event beforequery
          * Fires before all queries are processed. Return false to cancel the query or set cancel to true.
          * The event object passed has these properties:
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         * @param {String} query The query
         * @param {Boolean} forceAll true to force "all" query
         * @param {Boolean} cancel true to cancel the query
@@ -16406,44 +16888,44 @@ Roo.bootstrap.ComboBox = function(config){
          /**
          * @event add
          * Fires when the 'add' icon is pressed (add a listener to enable add button)
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         */
         'add' : true,
         /**
          * @event edit
          * Fires when the 'edit' icon is pressed (add a listener to enable add button)
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         * @param {Roo.data.Record|false} record The data record returned from the underlying store (or false on nothing selected)
         */
         'edit' : true,
         /**
          * @event remove
          * Fires when the remove value from the combobox array
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         */
         'remove' : true,
         /**
          * @event afterremove
          * Fires when the remove value from the combobox array
-        * @param {Roo.bootstrap.ComboBox} combo This combo box
+        * @param {Roo.bootstrap.form.ComboBox} combo This combo box
         */
         'afterremove' : true,
         /**
          * @event specialfilter
          * Fires when specialfilter
-            * @param {Roo.bootstrap.ComboBox} combo This combo box
+            * @param {Roo.bootstrap.form.ComboBox} combo This combo box
             */
         'specialfilter' : true,
         /**
          * @event tick
          * Fires when tick the element
-            * @param {Roo.bootstrap.ComboBox} combo This combo box
+            * @param {Roo.bootstrap.form.ComboBox} combo This combo box
             */
         'tick' : true,
         /**
          * @event touchviewdisplay
          * Fires when touch view require special display (default is using displayField)
-            * @param {Roo.bootstrap.ComboBox} combo This combo box
+            * @param {Roo.bootstrap.form.ComboBox} combo This combo box
             * @param {Object} cfg set html .
             */
         'touchviewdisplay' : true
@@ -16464,7 +16946,7 @@ Roo.bootstrap.ComboBox = function(config){
     }
 };
 
-Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
+Roo.extend(Roo.bootstrap.form.ComboBox, Roo.bootstrap.form.TriggerField, {
      
     /**
      * @cfg {Boolean} lazyRender True to prevent the ComboBox from rendering until requested (should always be used when
@@ -16713,7 +17195,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
          *  Normal ComboBox
          */
         if(!this.tickable){
-            cfg = Roo.bootstrap.ComboBox.superclass.getAutoCreate.call(this);
+            cfg = Roo.bootstrap.form.ComboBox.superclass.getAutoCreate.call(this);
             return cfg;
         }
         
@@ -16841,12 +17323,13 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             cls : 'roo-required-indicator ' + (this.indicatorpos == 'right'  ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star',
             tooltip : 'This field is required'
         };
-        if (Roo.bootstrap.version == 4) {
+         
+        if (this.allowBlank) {
             indicator = {
                 tag : 'i',
                 style : 'display:none'
             };
-        }
+        } 
         if (align ==='left' && this.fieldLabel.length) {
             
             cfg.cls += ' roo-form-group-label-left'  + (Roo.bootstrap.version == 4 ? ' row' : '');
@@ -17033,7 +17516,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             return;
         }
         
-        Roo.bootstrap.ComboBox.superclass.initEvents.call(this);
+        Roo.bootstrap.form.ComboBox.superclass.initEvents.call(this);
         
         if(this.hiddenName){
             
@@ -17413,7 +17896,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             this.store.un('load', this.onLoad, this);
             this.store.un('loadexception', this.onLoadException, this);
         }
-        Roo.bootstrap.ComboBox.superclass.onDestroy.call(this);
+        Roo.bootstrap.form.ComboBox.superclass.onDestroy.call(this);
     },
 
     // private
@@ -17428,7 +17911,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     {
         
         
-//        Roo.bootstrap.ComboBox.superclass.onResize.apply(this, arguments);
+//        Roo.bootstrap.form.ComboBox.superclass.onResize.apply(this, arguments);
 //        
 //        if(typeof w != 'number'){
 //            // we do not handle it!?!?
@@ -17601,7 +18084,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         if(this.valueField){
             return typeof this.value != 'undefined' ? this.value : '';
         }else{
-            return Roo.bootstrap.ComboBox.superclass.getValue.call(this);
+            return Roo.bootstrap.form.ComboBox.superclass.getValue.call(this);
         }
     },
     
@@ -17671,7 +18154,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         if(this.hiddenField){
             this.hiddenField.dom.value = v;
         }
-        Roo.bootstrap.ComboBox.superclass.setValue.call(this, text);
+        Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, text);
         this.value = v;
         
         var close = this.closeTriggerEl();
@@ -17727,14 +18210,14 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             this.hiddenField.dom.value = vv;
             
             this.lastSelectionText = dv;
-            Roo.bootstrap.ComboBox.superclass.setValue.call(this, dv);
+            Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, dv);
             this.value = vv;
             return;
         }
         // no hidden field.. - we store the value in 'value', but still display
         // display field!!!!
         this.lastSelectionText = dv;
-        Roo.bootstrap.ComboBox.superclass.setValue.call(this, dv);
+        Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, dv);
         this.value = vv;
         
         
@@ -18875,7 +19358,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     
     renderTouchView : function()
     {
-        this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.ComboBox.touchViewTemplate);
+        this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.form.ComboBox.touchViewTemplate);
         this.touchViewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
         this.touchViewHeaderEl = this.touchViewEl.select('.modal-header', true).first();
@@ -19010,7 +19493,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         
         var rawValue = this.getRawValue();
         
-        var template = (this.multiple) ? Roo.bootstrap.ComboBox.listItemCheckbox : Roo.bootstrap.ComboBox.listItemRadio;
+        var template = (this.multiple) ? Roo.bootstrap.form.ComboBox.listItemCheckbox : Roo.bootstrap.form.ComboBox.listItemRadio;
         
         this.tickItems = [];
         
@@ -19084,7 +19567,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     {
         this.clearTouchView();
         
-        this.touchViewListGroup.createChild(Roo.bootstrap.ComboBox.emptyResult);
+        this.touchViewListGroup.createChild(Roo.bootstrap.form.ComboBox.emptyResult);
         
         this.touchViewListGroup.select('.roo-combobox-touch-view-empty-result', true).first().dom.innerHTML = this.emptyResultText;
         
@@ -19302,7 +19785,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
      */
 });
 
-Roo.apply(Roo.bootstrap.ComboBox,  {
+Roo.apply(Roo.bootstrap.form.ComboBox,  {
     
     header : {
         tag: 'div',
@@ -19412,7 +19895,7 @@ Roo.apply(Roo.bootstrap.ComboBox,  {
     }
 });
 
-Roo.apply(Roo.bootstrap.ComboBox,  {
+Roo.apply(Roo.bootstrap.form.ComboBox,  {
     
     touchViewTemplate : {
         tag: 'div',
@@ -19427,9 +19910,9 @@ Roo.apply(Roo.bootstrap.ComboBox,  {
                         tag: 'div',
                         cls: 'modal-content',
                         cn: [
-                            Roo.bootstrap.ComboBox.header,
-                            Roo.bootstrap.ComboBox.body,
-                            Roo.bootstrap.ComboBox.footer
+                            Roo.bootstrap.form.ComboBox.header,
+                            Roo.bootstrap.form.ComboBox.body,
+                            Roo.bootstrap.form.ComboBox.footer
                         ]
                     }
                 ]
@@ -20199,6 +20682,11 @@ Roo.bootstrap.Calendar = function(config){
 
 Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
     
+         /**
+     * @cfg {Roo.data.Store} store
+     * The data source for the calendar
+     */
+       store : false,
      /**
      * @cfg {Number} startDay
      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
@@ -21048,6 +21536,8 @@ Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
 /**
  * @class Roo.bootstrap.Popover
  * @extends Roo.bootstrap.Component
+ * @parent none builder
+ * @children Roo.bootstrap.Component
  * Bootstrap Popover class
  * @cfg {String} html contents of the popover   (or false to use children..)
  * @cfg {String} title of popover (or false to hide)
@@ -21302,6 +21792,35 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
             }
         }, this.delay.hide)
     },
+    
+    /**
+     * update the position of the dialog
+     * normally this is needed if the popover get's bigger - due to a Table reload etc..
+     * 
+     *
+     */
+    
+    doAlign : function()
+    {
+        
+        if (this.alignEl) {
+            this.updatePosition(this.placement, true);
+             
+        } else {
+            // this is usually just done by the builder = to show the popoup in the middle of the scren.
+            var es = this.el.getSize();
+            var x = Roo.lib.Dom.getViewWidth()/2;
+            var y = Roo.lib.Dom.getViewHeight()/2;
+            this.el.setXY([ x-(es.width/2),  y-(es.height/2)] );
+            
+        }
+
+         
+         
+        
+        
+    },
+    
     /**
      * Show the popover
      * @param {Roo.Element|string|Boolean} - element to align and point to. (set align to [ pos, offset ])
@@ -21338,19 +21857,7 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
         this.el.show();
         this.el.dom.style.display = 'block';
          
-        if (this.alignEl) {
-            this.updatePosition(this.placement, true);
-             
-        } else {
-            // this is usually just done by the builder = to show the popoup in the middle of the scren.
-            var es = this.el.getSize();
-            var x = Roo.lib.Dom.getViewWidth()/2;
-            var y = Roo.lib.Dom.getViewHeight()/2;
-            this.el.setXY([ x-(es.width/2),  y-(es.height/2)] );
-            
-        }
-
+        this.doAlign();
         
         //var arrow = this.el.select('.arrow',true).first();
         //arrow.set(align[2], 
@@ -21522,17 +22029,17 @@ Roo.apply(Roo.bootstrap.Popover, {
         Roo.bootstrap.Popover.popups.remove(this);
     } 
 
-});/*
- * - LGPL
- *
- * Card header - holder for the card header elements.
- * 
- */
-
+});
 /**
  * @class Roo.bootstrap.PopoverNav
- * @extends Roo.bootstrap.NavGroup
+ * @extends Roo.bootstrap.nav.Simplebar
+ * @parent Roo.bootstrap.Popover
+ * @children Roo.bootstrap.nav.Group Roo.bootstrap.Container
+ * @licence LGPL
  * Bootstrap Popover header navigation class
+ * FIXME? should this go under nav?
+ *
+ * 
  * @constructor
  * Create a new Popover Header Navigation 
  * @param {Object} config The config object
@@ -21542,7 +22049,7 @@ Roo.bootstrap.PopoverNav = function(config){
     Roo.bootstrap.PopoverNav.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.PopoverNav, Roo.bootstrap.NavSimplebar,  {
+Roo.extend(Roo.bootstrap.PopoverNav, Roo.bootstrap.nav.Simplebar,  {
     
     
     container_method : 'getPopoverHeader' 
@@ -21565,6 +22072,7 @@ Roo.extend(Roo.bootstrap.PopoverNav, Roo.bootstrap.NavSimplebar,  {
 /**
  * @class Roo.bootstrap.Progress
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.ProgressBar
  * Bootstrap Progress class
  * @cfg {Boolean} striped striped of the progress bar
  * @cfg {Boolean} active animated of the progress bar
@@ -21701,16 +22209,10 @@ Roo.extend(Roo.bootstrap.ProgressBar, Roo.bootstrap.Component,  {
 
  
 
- /*
- * - LGPL
- *
- * column
- * 
- */
-
-/**
+ /**
  * @class Roo.bootstrap.TabGroup
  * @extends Roo.bootstrap.Column
+ * @children Roo.bootstrap.TabPanel
  * Bootstrap Column class
  * @cfg {String} navId the navigation id (for use with navbars) - will be auto generated if it does not exist..
  * @cfg {Boolean} carousel true to make the group behave like a carousel
@@ -21850,7 +22352,7 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
     
     /**
     * register a Navigation item
-    * @param {Roo.bootstrap.NavItem} the navitem to add
+    * @param {Roo.bootstrap.nav.Item} the navitem to add
     */
     register : function(item)
     {
@@ -22070,7 +22572,7 @@ Roo.apply(Roo.bootstrap.TabGroup, {
     groups: {},
      /**
     * register a Navigation Group
-    * @param {Roo.bootstrap.NavGroup} the navgroup to add
+    * @param {Roo.bootstrap.nav.Group} the navgroup to add
     */
     register : function(navgrp)
     {
@@ -22081,7 +22583,7 @@ Roo.apply(Roo.bootstrap.TabGroup, {
     * fetch a Navigation Group based on the navigation ID
     * if one does not exist , it will get created.
     * @param {string} the navgroup to add
-    * @returns {Roo.bootstrap.NavGroup} the navgroup 
+    * @returns {Roo.bootstrap.nav.Group} the navgroup 
     */
     get: function(navId) {
         if (typeof(this.groups[navId]) == 'undefined') {
@@ -22104,11 +22606,12 @@ Roo.apply(Roo.bootstrap.TabGroup, {
 /**
  * @class Roo.bootstrap.TabPanel
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Component
  * Bootstrap TabPanel class
  * @cfg {Boolean} active panel active
  * @cfg {String} html panel content
  * @cfg {String} tabId  unique tab ID (will be autogenerated if not set. - used to match TabItem to Panel)
- * @cfg {String} navId The Roo.bootstrap.NavGroup which triggers show hide ()
+ * @cfg {String} navId The Roo.bootstrap.nav.Group which triggers show hide ()
  * @cfg {String} href click to link..
  * @cfg {Boolean} touchSlide if swiping slides tab to next panel (default off)
  * 
@@ -22290,8 +22793,8 @@ Roo.extend(Roo.bootstrap.TabPanel, Roo.bootstrap.Component,  {
  */
 
 /**
- * @class Roo.bootstrap.DateField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.DateField
+ * @extends Roo.bootstrap.form.Input
  * Bootstrap DateField class
  * @cfg {Number} weekStart default 0
  * @cfg {String} viewMode default empty, (months|years)
@@ -22312,41 +22815,41 @@ Roo.extend(Roo.bootstrap.TabPanel, Roo.bootstrap.Component,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.DateField = function(config){
-    Roo.bootstrap.DateField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.DateField = function(config){
+    Roo.bootstrap.form.DateField.superclass.constructor.call(this, config);
      this.addEvents({
             /**
              * @event show
              * Fires when this field show.
-             * @param {Roo.bootstrap.DateField} this
+             * @param {Roo.bootstrap.form.DateField} this
              * @param {Mixed} date The date value
              */
             show : true,
             /**
              * @event show
              * Fires when this field hide.
-             * @param {Roo.bootstrap.DateField} this
+             * @param {Roo.bootstrap.form.DateField} this
              * @param {Mixed} date The date value
              */
             hide : true,
             /**
              * @event select
              * Fires when select a date.
-             * @param {Roo.bootstrap.DateField} this
+             * @param {Roo.bootstrap.form.DateField} this
              * @param {Mixed} date The date value
              */
             select : true,
             /**
              * @event beforeselect
              * Fires when before select a date.
-             * @param {Roo.bootstrap.DateField} this
+             * @param {Roo.bootstrap.form.DateField} this
              * @param {Mixed} date The date value
              */
             beforeselect : true
         });
 };
 
-Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     
     /**
      * @cfg {String} format
@@ -22419,13 +22922,13 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     onRender: function(ct, position)
     {
         
-        Roo.bootstrap.DateField.superclass.onRender.call(this, ct, position);
+        Roo.bootstrap.form.DateField.superclass.onRender.call(this, ct, position);
         
         this.language = this.language || 'en';
-        this.language = this.language in Roo.bootstrap.DateField.dates ? this.language : this.language.split('-')[0];
-        this.language = this.language in Roo.bootstrap.DateField.dates ? this.language : "en";
+        this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : this.language.split('-')[0];
+        this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : "en";
         
-        this.isRTL = Roo.bootstrap.DateField.dates[this.language].rtl || false;
+        this.isRTL = Roo.bootstrap.form.DateField.dates[this.language].rtl || false;
         this.format = this.format || 'm/d/y';
         this.isInline = false;
         this.isInput = true;
@@ -22461,9 +22964,9 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
             }
         }
                 
-        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.DateField.template);
+        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.DateField.template);
         
-//        this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.DateField.template);
+//        this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.form.DateField.template);
         
         this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
@@ -22491,7 +22994,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                 return;
             }
             
-            v.dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
+            v.dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
             v.attr('colspan', function(i, val){
                 return parseInt(val) + 1;
             });
@@ -22544,7 +23047,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
             dow.cn.push({
                 tag: 'th',
                 cls: 'dow',
-                html: Roo.bootstrap.DateField.dates[this.language].daysMin[(dowCnt++)%7]
+                html: Roo.bootstrap.form.DateField.dates[this.language].daysMin[(dowCnt++)%7]
             });
         }
         
@@ -22562,7 +23065,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
             var month = {
                 tag: 'span',
                 cls: 'month',
-                html: Roo.bootstrap.DateField.dates[this.language].monthsShort[i++]
+                html: Roo.bootstrap.form.DateField.dates[this.language].monthsShort[i++]
             };
             
             months.createChild(month);
@@ -22597,9 +23100,9 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                 currentDate = this.date && this.date.valueOf(),
                 today = this.UTCToday();
         
-        this.picker().select('>.datepicker-days thead th.switch', true).first().dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].months[month]+' '+year;
+        this.picker().select('>.datepicker-days thead th.switch', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].months[month]+' '+year;
         
-//        this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
+//        this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
         
 //        this.picker.select('>tfoot th.today').
 //                                             .text(dates[this.language].today)
@@ -22737,7 +23240,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
             v.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
             v.hide();
         });
-        this.picker().select('>.datepicker-'+Roo.bootstrap.DateField.modes[this.viewMode].clsName, true).first().show();
+        this.picker().select('>.datepicker-'+Roo.bootstrap.form.DateField.modes[this.viewMode].clsName, true).first().show();
     },
     
     place: function()
@@ -22793,13 +23296,13 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     
     onFocus : function()
     {
-        Roo.bootstrap.DateField.superclass.onFocus.call(this);
+        Roo.bootstrap.form.DateField.superclass.onFocus.call(this);
         this.showPopup();
     },
     
     onBlur : function()
     {
-        Roo.bootstrap.DateField.superclass.onBlur.call(this);
+        Roo.bootstrap.form.DateField.superclass.onBlur.call(this);
         
         var d = this.inputEl().getValue();
         
@@ -22838,7 +23341,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     
     keyup: function(e)
     {
-        Roo.bootstrap.DateField.superclass.keyup.call(this);
+        Roo.bootstrap.form.DateField.superclass.keyup.call(this);
         this.update();
     },
 
@@ -22849,13 +23352,13 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
         
             if(isNaN(d.getTime())){
                 this.date = this.viewDate = '';
-                Roo.bootstrap.DateField.superclass.setValue.call(this, '');
+                Roo.bootstrap.form.DateField.superclass.setValue.call(this, '');
                 return;
             }
 
             v = this.formatDate(d);
 
-            Roo.bootstrap.DateField.superclass.setValue.call(this, v);
+            Roo.bootstrap.form.DateField.superclass.setValue.call(this, v);
 
             this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
 
@@ -22987,7 +23490,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                         break;
                     case 'prev':
                     case 'next':
-                        var dir = Roo.bootstrap.DateField.modes[this.viewMode].navStep * (className == 'prev' ? -1 : 1);
+                        var dir = Roo.bootstrap.form.DateField.modes[this.viewMode].navStep * (className == 'prev' ? -1 : 1);
                         switch(this.viewMode){
                                 case 0:
                                         this.viewDate = this.moveMonth(this.viewDate, dir);
@@ -23016,7 +23519,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                 }
                 this.viewDate.setUTCDate(1);
                     if (className.indexOf('month') > -1) {
-                        this.viewDate.setUTCMonth(Roo.bootstrap.DateField.dates[this.language].monthsShort.indexOf(html));
+                        this.viewDate.setUTCMonth(Roo.bootstrap.form.DateField.dates[this.language].monthsShort.indexOf(html));
                     } else {
                         var year = parseInt(html, 10) || 0;
                         this.viewDate.setUTCFullYear(year);
@@ -23271,12 +23774,12 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     {
         this.date = this.viewDate = '';
         
-        Roo.bootstrap.DateField.superclass.setValue.call(this, '');
+        Roo.bootstrap.form.DateField.superclass.setValue.call(this, '');
     }
    
 });
 
-Roo.apply(Roo.bootstrap.DateField,  {
+Roo.apply(Roo.bootstrap.form.DateField,  {
     
     head : {
         tag: 'thead',
@@ -23366,7 +23869,7 @@ Roo.apply(Roo.bootstrap.DateField,  {
     }]
 });
 
-Roo.apply(Roo.bootstrap.DateField,  {
+Roo.apply(Roo.bootstrap.form.DateField,  {
   
     template : {
         tag: 'div',
@@ -23380,11 +23883,11 @@ Roo.apply(Roo.bootstrap.DateField,  {
                 tag: 'table',
                 cls: 'table-condensed',
                 cn:[
-                Roo.bootstrap.DateField.head,
+                Roo.bootstrap.form.DateField.head,
                 {
                     tag: 'tbody'
                 },
-                Roo.bootstrap.DateField.footer
+                Roo.bootstrap.form.DateField.footer
                 ]
             }
             ]
@@ -23397,9 +23900,9 @@ Roo.apply(Roo.bootstrap.DateField,  {
                 tag: 'table',
                 cls: 'table-condensed',
                 cn:[
-                Roo.bootstrap.DateField.head,
-                Roo.bootstrap.DateField.content,
-                Roo.bootstrap.DateField.footer
+                Roo.bootstrap.form.DateField.head,
+                Roo.bootstrap.form.DateField.content,
+                Roo.bootstrap.form.DateField.footer
                 ]
             }
             ]
@@ -23412,9 +23915,9 @@ Roo.apply(Roo.bootstrap.DateField,  {
                 tag: 'table',
                 cls: 'table-condensed',
                 cn:[
-                Roo.bootstrap.DateField.head,
-                Roo.bootstrap.DateField.content,
-                Roo.bootstrap.DateField.footer
+                Roo.bootstrap.form.DateField.head,
+                Roo.bootstrap.form.DateField.content,
+                Roo.bootstrap.form.DateField.footer
                 ]
             }
             ]
@@ -23433,9 +23936,10 @@ Roo.apply(Roo.bootstrap.DateField,  {
  */
 
 /**
- * @class Roo.bootstrap.TimeField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.TimeField
+ * @extends Roo.bootstrap.form.Input
  * Bootstrap DateField class
+ * @cfg {Number} minuteStep the minutes is always the multiple of a fixed number, default 1
  * 
  * 
  * @constructor
@@ -23443,34 +23947,34 @@ Roo.apply(Roo.bootstrap.DateField,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.TimeField = function(config){
-    Roo.bootstrap.TimeField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.TimeField = function(config){
+    Roo.bootstrap.form.TimeField.superclass.constructor.call(this, config);
     this.addEvents({
             /**
              * @event show
              * Fires when this field show.
-             * @param {Roo.bootstrap.DateField} thisthis
+             * @param {Roo.bootstrap.form.DateField} thisthis
              * @param {Mixed} date The date value
              */
             show : true,
             /**
              * @event show
              * Fires when this field hide.
-             * @param {Roo.bootstrap.DateField} this
+             * @param {Roo.bootstrap.form.DateField} this
              * @param {Mixed} date The date value
              */
             hide : true,
             /**
              * @event select
              * Fires when select a date.
-             * @param {Roo.bootstrap.DateField} this
+             * @param {Roo.bootstrap.form.DateField} this
              * @param {Mixed} date The date value
              */
             select : true
         });
 };
 
-Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
     
     /**
      * @cfg {String} format
@@ -23478,20 +23982,21 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
      * valid according to {@link Date#parseDate} (defaults to 'H:i').
      */
     format : "H:i",
+    minuteStep : 1,
 
     getAutoCreate : function()
     {
         this.after = '<i class="fa far fa-clock"></i>';
-        return Roo.bootstrap.TimeField.superclass.getAutoCreate.call(this);
+        return Roo.bootstrap.form.TimeField.superclass.getAutoCreate.call(this);
         
          
     },
     onRender: function(ct, position)
     {
         
-        Roo.bootstrap.TimeField.superclass.onRender.call(this, ct, position);
+        Roo.bootstrap.form.TimeField.superclass.onRender.call(this, ct, position);
                 
-        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.TimeField.template);
+        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.TimeField.template);
         
         this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
@@ -23797,13 +24302,13 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
   
     onFocus : function()
     {
-        Roo.bootstrap.TimeField.superclass.onFocus.call(this);
+        Roo.bootstrap.form.TimeField.superclass.onFocus.call(this);
         this.show();
     },
     
     onBlur : function()
     {
-        Roo.bootstrap.TimeField.superclass.onBlur.call(this);
+        Roo.bootstrap.form.TimeField.superclass.onBlur.call(this);
         this.hide();
     },
     
@@ -23858,14 +24363,16 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
     onIncrementMinutes: function()
     {
         Roo.log('onIncrementMinutes');
-        this.time = this.time.add(Date.MINUTE, 1);
+        var minutesToAdd = Math.round((parseInt(this.time.format('i')) + this.minuteStep) / this.minuteStep) * this.minuteStep - parseInt(this.time.format('i'));
+        this.time = this.time.add(Date.MINUTE, minutesToAdd);
         this.update();
     },
     
     onDecrementMinutes: function()
     {
         Roo.log('onDecrementMinutes');
-        this.time = this.time.add(Date.MINUTE, -1);
+        var minutesToSubtract = parseInt(this.time.format('i')) - Math.round((parseInt(this.time.format('i')) - this.minuteStep) / this.minuteStep) * this.minuteStep;
+        this.time = this.time.add(Date.MINUTE, -1 * minutesToSubtract);
         this.update();
     },
     
@@ -23880,7 +24387,7 @@ Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
 });
  
 
-Roo.apply(Roo.bootstrap.TimeField,  {
+Roo.apply(Roo.bootstrap.form.TimeField,  {
   
     template : {
         tag: 'div',
@@ -23949,8 +24456,8 @@ Roo.apply(Roo.bootstrap.TimeField,  {
  */
 
 /**
- * @class Roo.bootstrap.MonthField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.MonthField
+ * @extends Roo.bootstrap.form.Input
  * Bootstrap MonthField class
  * 
  * @cfg {String} language default en
@@ -23960,28 +24467,28 @@ Roo.apply(Roo.bootstrap.TimeField,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.MonthField = function(config){
-    Roo.bootstrap.MonthField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.MonthField = function(config){
+    Roo.bootstrap.form.MonthField.superclass.constructor.call(this, config);
     
     this.addEvents({
         /**
          * @event show
          * Fires when this field show.
-         * @param {Roo.bootstrap.MonthField} this
+         * @param {Roo.bootstrap.form.MonthField} this
          * @param {Mixed} date The date value
          */
         show : true,
         /**
          * @event show
          * Fires when this field hide.
-         * @param {Roo.bootstrap.MonthField} this
+         * @param {Roo.bootstrap.form.MonthField} this
          * @param {Mixed} date The date value
          */
         hide : true,
         /**
          * @event select
          * Fires when select a date.
-         * @param {Roo.bootstrap.MonthField} this
+         * @param {Roo.bootstrap.form.MonthField} this
          * @param {String} oldvalue The old value
          * @param {String} newvalue The new value
          */
@@ -23989,25 +24496,25 @@ Roo.bootstrap.MonthField = function(config){
     });
 };
 
-Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.MonthField, Roo.bootstrap.form.Input,  {
     
     onRender: function(ct, position)
     {
         
-        Roo.bootstrap.MonthField.superclass.onRender.call(this, ct, position);
+        Roo.bootstrap.form.MonthField.superclass.onRender.call(this, ct, position);
         
         this.language = this.language || 'en';
-        this.language = this.language in Roo.bootstrap.MonthField.dates ? this.language : this.language.split('-')[0];
-        this.language = this.language in Roo.bootstrap.MonthField.dates ? this.language : "en";
+        this.language = this.language in Roo.bootstrap.form.MonthField.dates ? this.language : this.language.split('-')[0];
+        this.language = this.language in Roo.bootstrap.form.MonthField.dates ? this.language : "en";
         
-        this.isRTL = Roo.bootstrap.MonthField.dates[this.language].rtl || false;
+        this.isRTL = Roo.bootstrap.form.MonthField.dates[this.language].rtl || false;
         this.isInline = false;
         this.isInput = true;
         this.component = this.el.select('.add-on', true).first() || false;
         this.component = (this.component && this.component.length === 0) ? false : this.component;
         this.hasInput = this.component && this.inputEL().length;
         
-        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.MonthField.template);
+        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.MonthField.template);
         
         this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
@@ -24034,7 +24541,7 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
     {   
         var o = this.getValue();
         
-        Roo.bootstrap.MonthField.superclass.setValue.call(this, v);
+        Roo.bootstrap.form.MonthField.superclass.setValue.call(this, v);
         
         this.update();
 
@@ -24068,9 +24575,9 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
             return;
         }
         
-        this.vIndex = Roo.bootstrap.MonthField.dates[this.language].monthsShort.indexOf(html);
+        this.vIndex = Roo.bootstrap.form.MonthField.dates[this.language].monthsShort.indexOf(html);
         
-        this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+        this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
         
         this.hide();
                         
@@ -24092,7 +24599,7 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
             var month = {
                 tag: 'span',
                 cls: 'month',
-                html: Roo.bootstrap.MonthField.dates[this.language].monthsShort[i++]
+                html: Roo.bootstrap.form.MonthField.dates[this.language].monthsShort[i++]
             };
             
             months.createChild(month);
@@ -24105,7 +24612,7 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
         var _this = this;
         
         if(typeof(this.vIndex) == 'undefined' && this.value.length){
-            this.vIndex = Roo.bootstrap.MonthField.dates[this.language].months.indexOf(this.value);
+            this.vIndex = Roo.bootstrap.form.MonthField.dates[this.language].months.indexOf(this.value);
         }
         
         Roo.each(this.pickerEl.select('> .datepicker-months tbody > tr > td > span', true).elements, function(e, k){
@@ -24144,13 +24651,13 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
     
     onFocus : function()
     {
-        Roo.bootstrap.MonthField.superclass.onFocus.call(this);
+        Roo.bootstrap.form.MonthField.superclass.onFocus.call(this);
         this.show();
     },
     
     onBlur : function()
     {
-        Roo.bootstrap.MonthField.superclass.onBlur.call(this);
+        Roo.bootstrap.form.MonthField.superclass.onBlur.call(this);
         
         var d = this.inputEl().getValue();
         
@@ -24187,7 +24694,7 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
     
     keyup: function(e)
     {
-        Roo.bootstrap.MonthField.superclass.keyup.call(this);
+        Roo.bootstrap.form.MonthField.superclass.keyup.call(this);
         this.update();
     },
 
@@ -24225,7 +24732,7 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
                     this.vIndex = 0;
                 }
                 
-                this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+                this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
                 
                 break;
             case 38: // up
@@ -24247,13 +24754,13 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
                     this.vIndex = 0;
                 }
                 
-                this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+                this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
                 break;
                 
             case 13: // enter
                 
                 if(typeof(this.vIndex) != 'undefined' && !isNaN(this.vIndex)){
-                    this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+                    this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
                 }
                 
                 this.hide();
@@ -24261,7 +24768,7 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
                 break;
             case 9: // tab
                 if(typeof(this.vIndex) != 'undefined' && !isNaN(this.vIndex)){
-                    this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+                    this.setValue(Roo.bootstrap.form.MonthField.dates[this.language].months[this.vIndex]);
                 }
                 this.hide();
                 break;
@@ -24282,7 +24789,7 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
    
 });
 
-Roo.apply(Roo.bootstrap.MonthField,  {
+Roo.apply(Roo.bootstrap.form.MonthField,  {
     
     content : {
         tag: 'tbody',
@@ -24307,7 +24814,7 @@ Roo.apply(Roo.bootstrap.MonthField,  {
     }
 });
 
-Roo.apply(Roo.bootstrap.MonthField,  {
+Roo.apply(Roo.bootstrap.form.MonthField,  {
   
     template : {
         tag: 'div',
@@ -24321,7 +24828,7 @@ Roo.apply(Roo.bootstrap.MonthField,  {
                     tag: 'table',
                     cls: 'table-condensed',
                     cn:[
-                        Roo.bootstrap.DateField.content
+                        Roo.bootstrap.form.DateField.content
                     ]
                 }
                 ]
@@ -24341,8 +24848,8 @@ Roo.apply(Roo.bootstrap.MonthField,  {
  */
 
 /**
- * @class Roo.bootstrap.CheckBox
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.CheckBox
+ * @extends Roo.bootstrap.form.Input
  * Bootstrap CheckBox class
  * 
  * @cfg {String} valueOff The value that should go into the generated input element's value when unchecked.
@@ -24359,28 +24866,28 @@ Roo.apply(Roo.bootstrap.MonthField,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.CheckBox = function(config){
-    Roo.bootstrap.CheckBox.superclass.constructor.call(this, config);
+Roo.bootstrap.form.CheckBox = function(config){
+    Roo.bootstrap.form.CheckBox.superclass.constructor.call(this, config);
    
     this.addEvents({
         /**
         * @event check
         * Fires when the element is checked or unchecked.
-        * @param {Roo.bootstrap.CheckBox} this This input
+        * @param {Roo.bootstrap.form.CheckBox} this This input
         * @param {Boolean} checked The new checked value
         */
        check : true,
        /**
         * @event click
         * Fires when the element is click.
-        * @param {Roo.bootstrap.CheckBox} this This input
+        * @param {Roo.bootstrap.form.CheckBox} this This input
         */
        click : true
     });
     
 };
 
-Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.CheckBox, Roo.bootstrap.form.Input,  {
   
     inputType: 'checkbox',
     inputValue: 1,
@@ -24632,7 +25139,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
     
     initEvents : function()
     {
-//        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
+//        Roo.bootstrap.form.CheckBox.superclass.initEvents.call(this);
         
         this.inputEl().on('click', this.onClick,  this);
         
@@ -24643,7 +25150,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
         this.startValue = this.getValue();
         
         if(this.groupId){
-            Roo.bootstrap.CheckBox.register(this);
+            Roo.bootstrap.form.CheckBox.register(this);
         }
     },
     
@@ -24795,7 +25302,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
             //return (this.getValue() == this.inputValue) ? true : false;
         }
         
-        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+        var group = Roo.bootstrap.form.CheckBox.get(this.groupId);
         
         if(!group){
             return false;
@@ -24832,10 +25339,10 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
         
         this.fireEvent('valid', this);
         
-        var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+        var label = Roo.bootstrap.form.FieldLabel.get(this.name + '-group');
         
         if(this.groupId){
-            label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
+            label = Roo.bootstrap.form.FieldLabel.get(this.groupId + '-group');
         }
         
         if(label){
@@ -24869,7 +25376,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
             return;
         }
         
-        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+        var group = Roo.bootstrap.form.CheckBox.get(this.groupId);
         
         if(!group){
             return;
@@ -24901,10 +25408,10 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
         
         this.fireEvent('invalid', this, msg);
         
-        var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+        var label = Roo.bootstrap.form.FieldLabel.get(this.name + '-group');
         
         if(this.groupId){
-            label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
+            label = Roo.bootstrap.form.FieldLabel.get(this.groupId + '-group');
         }
         
         if(label){
@@ -24939,7 +25446,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
             return;
         }
         
-        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+        var group = Roo.bootstrap.form.CheckBox.get(this.groupId);
         
         if(!group){
             return;
@@ -24960,11 +25467,11 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
     
     clearInvalid : function()
     {
-        Roo.bootstrap.Input.prototype.clearInvalid.call(this);
+        Roo.bootstrap.form.Input.prototype.clearInvalid.call(this);
         
         // this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
         
-        var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+        var label = Roo.bootstrap.form.FieldLabel.get(this.name + '-group');
         
         if (label && label.iconEl) {
             label.iconEl.removeClass([ label.validClass, label.invalidClass ]);
@@ -24975,7 +25482,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
     disable : function()
     {
         if(this.inputType != 'radio'){
-            Roo.bootstrap.CheckBox.superclass.disable.call(this);
+            Roo.bootstrap.form.CheckBox.superclass.disable.call(this);
             return;
         }
         
@@ -24996,7 +25503,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
     enable : function()
     {
         if(this.inputType != 'radio'){
-            Roo.bootstrap.CheckBox.superclass.enable.call(this);
+            Roo.bootstrap.form.CheckBox.superclass.enable.call(this);
             return;
         }
         
@@ -25025,13 +25532,13 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
 
 });
 
-Roo.apply(Roo.bootstrap.CheckBox, {
+Roo.apply(Roo.bootstrap.form.CheckBox, {
     
     groups: {},
     
      /**
     * register a CheckBox Group
-    * @param {Roo.bootstrap.CheckBox} the CheckBox to add
+    * @param {Roo.bootstrap.form.CheckBox} the CheckBox to add
     */
     register : function(checkbox)
     {
@@ -25049,7 +25556,7 @@ Roo.apply(Roo.bootstrap.CheckBox, {
     /**
     * fetch a CheckBox Group based on the group ID
     * @param {string} the group ID
-    * @returns {Roo.bootstrap.CheckBox} the CheckBox group
+    * @returns {Roo.bootstrap.form.CheckBox} the CheckBox group
     */
     get: function(groupId) {
         if (typeof(this.groups[groupId]) == 'undefined') {
@@ -25069,7 +25576,7 @@ Roo.apply(Roo.bootstrap.CheckBox, {
  */
 
 /**
- * @class Roo.bootstrap.Radio
+ * @class Roo.bootstrap.form.Radio
  * @extends Roo.bootstrap.Component
  * Bootstrap Radio class
  * @cfg {String} boxLabel - the label associated
@@ -25079,12 +25586,12 @@ Roo.apply(Roo.bootstrap.CheckBox, {
  * Create a new Radio
  * @param {Object} config The config object
  */
-Roo.bootstrap.Radio = function(config){
-    Roo.bootstrap.Radio.superclass.constructor.call(this, config);
+Roo.bootstrap.form.Radio = function(config){
+    Roo.bootstrap.form.Radio.superclass.constructor.call(this, config);
     
 };
 
-Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.form.Radio, Roo.bootstrap.Component, {
     
     boxLabel : '',
     
@@ -25148,8 +25655,8 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.Component, {
  */
 
 /**
- * @class Roo.bootstrap.SecurePass
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.SecurePass
+ * @extends Roo.bootstrap.form.Input
  * Bootstrap SecurePass class
  *
  * 
@@ -25158,7 +25665,7 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.Component, {
  * @param {Object} config The config object
  */
  
-Roo.bootstrap.SecurePass = function (config) {
+Roo.bootstrap.form.SecurePass = function (config) {
     // these go here, so the translation tool can replace them..
     this.errors = {
         PwdEmpty: "Please type a password, and then retype it to confirm.",
@@ -25182,10 +25689,10 @@ Roo.bootstrap.SecurePass = function (config) {
     
     this.errors = {};
     
-    Roo.bootstrap.SecurePass.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.SecurePass.superclass.constructor.call(this, config);
 }
 
-Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.SecurePass, Roo.bootstrap.form.Input, {
     /**
      * @cfg {String/Object} errors A Error spec, or true for a default spec (defaults to
      * {
@@ -25230,7 +25737,7 @@ Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
     // private
     initEvents: function ()
     {
-        Roo.bootstrap.SecurePass.superclass.initEvents.call(this);
+        Roo.bootstrap.form.SecurePass.superclass.initEvents.call(this);
 
         if (this.el.is('input[type=password]') && Roo.isSafari) {
             this.el.on('keydown', this.SafariOnKeyDown, this);
@@ -25241,7 +25748,7 @@ Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
     // private
     onRender: function (ct, position)
     {
-        Roo.bootstrap.SecurePass.superclass.onRender.call(this, ct, position);
+        Roo.bootstrap.form.SecurePass.superclass.onRender.call(this, ct, position);
         this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
         this.trigger = this.wrap.createChild({tag: 'div', cls: 'StrengthMeter ' + this.triggerClass});
 
@@ -25278,7 +25785,7 @@ Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
         if (this.wrap) {
             this.wrap.remove();
         }
-        Roo.bootstrap.TriggerField.superclass.onDestroy.call(this);
+        Roo.bootstrap.form.TriggerField.superclass.onDestroy.call(this);
     },
     // private
     checkStrength: function ()
@@ -25315,7 +25822,7 @@ Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
     },
     reset: function ()
     {
-        Roo.bootstrap.SecurePass.superclass.reset.call(this);
+        Roo.bootstrap.form.SecurePass.superclass.reset.call(this);
         
         this._lastPwd = '';
         
@@ -25332,7 +25839,7 @@ Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
     // private
     validateValue: function (value)
     {
-        if (!Roo.bootstrap.SecurePass.superclass.validateValue.call(this, value)) {
+        if (!Roo.bootstrap.form.SecurePass.superclass.validateValue.call(this, value)) {
             return false;
         }
         if (value.length == 0) {
@@ -25493,351 +26000,5208 @@ Roo.extend(Roo.bootstrap.SecurePass, Roo.bootstrap.Input, {
         return this.IsLongEnough(pwd, 6) || !this.IsLongEnough(pwd, 0);
     }
           
-})//<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.rtf = {}; // namespace
+Roo.rtf.Hex = function(hex)
+{
+    this.hexstr = hex;
+};
+Roo.rtf.Paragraph = function(opts)
+{
+    this.content = []; ///??? is that used?
+};Roo.rtf.Span = function(opts)
+{
+    this.value = opts.value;
+};
 
-Roo.HtmlEditorCore = function(config){
-    
-    
-    Roo.HtmlEditorCore.superclass.constructor.call(this, config);
-    
+Roo.rtf.Group = function(parent)
+{
+    // we dont want to acutally store parent - it will make debug a nightmare..
+    this.content = [];
+    this.cn  = [];
+     
+       
     
-    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,
+};
+
+Roo.rtf.Group.prototype = {
+    ignorable : false,
+    content: false,
+    cn: false,
+    addContent : function(node) {
+        // could set styles...
+        this.content.push(node);
+    },
+    addChild : function(cn)
+    {
+        this.cn.push(cn);
+    },
+    // only for images really...
+    toDataURL : function()
+    {
+        var mimetype = false;
+        switch(true) {
+            case this.content.filter(function(a) { return a.value == 'pngblip' } ).length > 0: 
+                mimetype = "image/png";
+                break;
+             case this.content.filter(function(a) { return a.value == 'jpegblip' } ).length > 0:
+                mimetype = "image/jpeg";
+                break;
+            default :
+                return 'about:blank'; // ?? error?
+        }
         
-        /**
-         * @event editorevent
-         * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
-         * @param {Roo.HtmlEditorCore} this
-         */
-        editorevent: true
         
-    });
-    
-    // at this point this.owner is set, so we can start working out the whitelisted / blacklisted elements
+        var hexstring = this.content[this.content.length-1].value;
+        
+        return 'data:' + mimetype + ';base64,' + btoa(hexstring.match(/\w{2}/g).map(function(a) {
+            return String.fromCharCode(parseInt(a, 16));
+        }).join(""));
+    }
     
-    // defaults : white / black...
-    this.applyBlacklists();
+};
+// this looks like it's normally the {rtf{ .... }}
+Roo.rtf.Document = function()
+{
+    // we dont want to acutally store parent - it will make debug a nightmare..
+    this.rtlch  = [];
+    this.content = [];
+    this.cn = [];
     
+};
+Roo.extend(Roo.rtf.Document, Roo.rtf.Group, { 
+    addChild : function(cn)
+    {
+        this.cn.push(cn);
+        switch(cn.type) {
+            case 'rtlch': // most content seems to be inside this??
+            case 'listtext':
+            case 'shpinst':
+                this.rtlch.push(cn);
+                return;
+            default:
+                this[cn.type] = cn;
+        }
+        
+    },
     
+    getElementsByType : function(type)
+    {
+        var ret =  [];
+        this._getElementsByType(type, ret, this.cn, 'rtf');
+        return ret;
+    },
+    _getElementsByType : function (type, ret, search_array, path)
+    {
+        search_array.forEach(function(n,i) {
+            if (n.type == type) {
+                n.path = path + '/' + n.type + ':' + i;
+                ret.push(n);
+            }
+            if (n.cn.length > 0) {
+                this._getElementsByType(type, ret, n.cn, path + '/' + n.type+':'+i);
+            }
+        },this);
+    }
     
+});
+Roo.rtf.Ctrl = function(opts)
+{
+    this.value = opts.value;
+    this.param = opts.param;
 };
+/**
+ *
+ *
+ * based on this https://github.com/iarna/rtf-parser
+ * it's really only designed to extract pict from pasted RTF 
+ *
+ * usage:
+ *
+ *  var images = new Roo.rtf.Parser().parse(a_string).filter(function(g) { return g.type == 'pict'; });
+ *  
+ *
+ */
 
 
-Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
 
-     /**
-     * @cfg {Roo.form.HtmlEditor|Roo.bootstrap.HtmlEditor} the owner field 
-     */
+Roo.rtf.Parser = function(text) {
+    //super({objectMode: true})
+    this.text = '';
+    this.parserState = this.parseText;
     
-    owner : false,
+    // these are for interpeter...
+    this.doc = {};
+    ///this.parserState = this.parseTop
+    this.groupStack = [];
+    this.hexStore = [];
+    this.doc = 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,
+    this.groups = []; // where we put the return.
     
-    /**
-     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
-     * 
-     */
-    stylesheets: false,
+    for (var ii = 0; ii < text.length; ++ii) {
+        ++this.cpos;
+        
+        if (text[ii] === '\n') {
+            ++this.row;
+            this.col = 1;
+        } else {
+            ++this.col;
+        }
+        this.parserState(text[ii]);
+    }
     
-    /**
-     * @cfg {boolean} allowComments - default false - allow comments in HTML source - by default they are stripped - if you are editing email you may need this.
-     */
-    allowComments: 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,
+};
+Roo.rtf.Parser.prototype = {
+    text : '', // string being parsed..
+    controlWord : '',
+    controlWordParam :  '',
+    hexChar : '',
+    doc : false,
+    group: false,
+    groupStack : false,
+    hexStore : false,
     
-    // blacklist + whitelisted elements..
-    black: false,
-    white: false,
-     
-    bodyCls : '',
+    
+    cpos : 0, 
+    row : 1, // reportin?
+    col : 1, //
 
-    /**
-     * 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 = '';
-        
-        // 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 {
-            for (var i in this.stylesheets) { 
-                st += '<link rel="stylesheet" href="' + this.stylesheets[i] +'" type="text/css">';
-            }
-            
+     
+    push : function (el)
+    {
+        var m = 'cmd'+ el.type;
+        if (typeof(this[m]) == 'undefined') {
+            Roo.log('invalid cmd:' + el.type);
+            return;
         }
+        this[m](el);
+        //Roo.log(el);
+    },
+    flushHexStore : function()
+    {
+        if (this.hexStore.length < 1) {
+            return;
+        }
+        var hexstr = this.hexStore.map(
+            function(cmd) {
+                return cmd.value;
+        }).join('');
         
-        st +=  '<style type="text/css">' +
-            'IMG { cursor: pointer } ' +
-        '</style>';
-
-        var cls = 'roo-htmleditor-body';
+        this.group.addContent( new Roo.rtf.Hex( hexstr ));
+              
+            
+        this.hexStore.splice(0)
         
-        if(this.bodyCls.length){
-            cls += ' ' + this.bodyCls;
+    },
+    
+    cmdgroupstart : function()
+    {
+        this.flushHexStore();
+        if (this.group) {
+            this.groupStack.push(this.group);
         }
-        
-        return '<html><head>' + st  +
-            //<style type="text/css">' +
-            //'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
-            //'</style>' +
-            ' </head><body contenteditable="true" data-enable-grammerly="true" class="' +  cls + '"></body></html>';
+         // parent..
+        if (this.doc === false) {
+            this.group = this.doc = new Roo.rtf.Document();
+            return;
+            
+        }
+        this.group = new Roo.rtf.Group(this.group);
     },
-
-    // private
-    onRender : function(ct, position)
+    cmdignorable : function()
     {
-        var _t = this;
-        //Roo.HtmlEditorCore.superclass.onRender.call(this, ct, position);
-        this.el = this.owner.inputEl ? this.owner.inputEl() : this.owner.el;
-        
-        
-        this.el.dom.style.border = '0 none';
-        this.el.dom.setAttribute('tabIndex', -1);
-        this.el.addClass('x-hidden hide');
-        
+        this.flushHexStore();
+        this.group.ignorable = true;
+    },
+    cmdendparagraph : function()
+    {
+        this.flushHexStore();
+        this.group.addContent(new Roo.rtf.Paragraph());
+    },
+    cmdgroupend : function ()
+    {
+        this.flushHexStore();
+        var endingGroup = this.group;
         
         
-        if(Roo.isIE){ // fix IE 1px bogus margin
-            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
+        this.group = this.groupStack.pop();
+        if (this.group) {
+            this.group.addChild(endingGroup);
         }
-       
-        
-        this.frameId = Roo.id();
-        
-         
-        
-        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
-        );
         
         
-        this.iframe = iframe.dom;
-
-         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);
-
+        var doc = this.group || this.doc;
+        //if (endingGroup instanceof FontTable) {
+        //  doc.fonts = endingGroup.table
+        //} else if (endingGroup instanceof ColorTable) {
+        //  doc.colors = endingGroup.table
+        //} else if (endingGroup !== this.doc && !endingGroup.get('ignorable')) {
+        if (endingGroup.ignorable === false) {
+            //code
+            this.groups.push(endingGroup);
+           // Roo.log( endingGroup );
+        }
+            //Roo.each(endingGroup.content, function(item)) {
+            //    doc.addContent(item);
+            //}
+            //process.emit('debug', 'GROUP END', endingGroup.type, endingGroup.get('ignorable'))
+        //}
     },
-
-    // private
-    onResize : function(w, h)
+    cmdtext : function (cmd)
     {
-         Roo.log('resize: ' +w + ',' + h );
-        //Roo.HtmlEditorCore.superclass.onResize.apply(this, arguments);
-        if(!this.iframe){
+        this.flushHexStore();
+        if (!this.group) { // an RTF fragment, missing the {\rtf1 header
+            //this.group = this.doc
+            return;  // we really don't care about stray text...
+        }
+        this.group.addContent(new Roo.rtf.Span(cmd));
+    },
+    cmdcontrolword : function (cmd)
+    {
+        this.flushHexStore();
+        if (!this.group.type) {
+            this.group.type = cmd.value;
             return;
         }
-        if(typeof w == 'number'){
-            
-            this.iframe.style.width = w + 'px';
+        this.group.addContent(new Roo.rtf.Ctrl(cmd));
+        // we actually don't care about ctrl words...
+        return ;
+        /*
+        var method = 'ctrl$' + cmd.value.replace(/-(.)/g, (_, char) => char.toUpperCase())
+        if (this[method]) {
+            this[method](cmd.param)
+        } else {
+            if (!this.group.get('ignorable')) process.emit('debug', method, cmd.param)
         }
-        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';
+        */
+    },
+    cmdhexchar : function(cmd) {
+        this.hexStore.push(cmd);
+    },
+    cmderror : function(cmd) {
+        throw cmd.value;
+    },
+    
+    /*
+      _flush (done) {
+        if (this.text !== '\u0000') this.emitText()
+        done()
+      }
+      */
+      
+      
+    parseText : function(c)
+    {
+        if (c === '\\') {
+            this.parserState = this.parseEscapes;
+        } else if (c === '{') {
+            this.emitStartGroup();
+        } else if (c === '}') {
+            this.emitEndGroup();
+        } else if (c === '\x0A' || c === '\x0D') {
+            // cr/lf are noise chars
+        } else {
+            this.text += c;
+        }
+    },
+    
+    parseEscapes: function (c)
+    {
+        if (c === '\\' || c === '{' || c === '}') {
+            this.text += c;
+            this.parserState = this.parseText;
+        } else {
+            this.parserState = this.parseControlSymbol;
+            this.parseControlSymbol(c);
+        }
+    },
+    parseControlSymbol: function(c)
+    {
+        if (c === '~') {
+            this.text += '\u00a0'; // nbsp
+            this.parserState = this.parseText
+        } else if (c === '-') {
+             this.text += '\u00ad'; // soft hyphen
+        } else if (c === '_') {
+            this.text += '\u2011'; // non-breaking hyphen
+        } else if (c === '*') {
+            this.emitIgnorable();
+            this.parserState = this.parseText;
+        } else if (c === "'") {
+            this.parserState = this.parseHexChar;
+        } else if (c === '|') { // formula cacter
+            this.emitFormula();
+            this.parserState = this.parseText;
+        } else if (c === ':') { // subentry in an index entry
+            this.emitIndexSubEntry();
+            this.parserState = this.parseText;
+        } else if (c === '\x0a') {
+            this.emitEndParagraph();
+            this.parserState = this.parseText;
+        } else if (c === '\x0d') {
+            this.emitEndParagraph();
+            this.parserState = this.parseText;
+        } else {
+            this.parserState = this.parseControlWord;
+            this.parseControlWord(c);
+        }
+    },
+    parseHexChar: function (c)
+    {
+        if (/^[A-Fa-f0-9]$/.test(c)) {
+            this.hexChar += c;
+            if (this.hexChar.length >= 2) {
+              this.emitHexChar();
+              this.parserState = this.parseText;
             }
+            return;
         }
+        this.emitError("Invalid character \"" + c + "\" in hex literal.");
+        this.parserState = this.parseText;
         
     },
-
-    /**
-     * 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;
-        
-        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();
+    parseControlWord : function(c)
+    {
+        if (c === ' ') {
+            this.emitControlWord();
+            this.parserState = this.parseText;
+        } else if (/^[-\d]$/.test(c)) {
+            this.parserState = this.parseControlWordParam;
+            this.controlWordParam += c;
+        } else if (/^[A-Za-z]$/.test(c)) {
+          this.controlWord += c;
+        } else {
+          this.emitControlWord();
+          this.parserState = this.parseText;
+          this.parseText(c);
+        }
+    },
+    parseControlWordParam : function (c) {
+        if (/^\d$/.test(c)) {
+          this.controlWordParam += c;
+        } else if (c === ' ') {
+          this.emitControlWord();
+          this.parserState = this.parseText;
+        } else {
+          this.emitControlWord();
+          this.parserState = this.parseText;
+          this.parseText(c);
         }
-        //this.setSize(this.owner.wrap.getSize());
-        //this.fireEvent('editmodechange', this, this.sourceEditMode);
     },
-
     
-  
-
-    /**
-     * 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, '');
-            }
+    
+    
+    
+    emitText : function () {
+        if (this.text === '') {
+            return;
         }
-        if(html == '&nbsp;'){
-            html = '';
+        this.push({
+            type: 'text',
+            value: this.text,
+            pos: this.cpos,
+            row: this.row,
+            col: this.col
+        });
+        this.text = ''
+    },
+    emitControlWord : function ()
+    {
+        this.emitText();
+        if (this.controlWord === '') {
+            // do we want to track this - it seems just to cause problems.
+            //this.emitError('empty control word');
+        } else {
+            this.push({
+                  type: 'controlword',
+                  value: this.controlWord,
+                  param: this.controlWordParam !== '' && Number(this.controlWordParam),
+                  pos: this.cpos,
+                  row: this.row,
+                  col: this.col
+            });
         }
-        return html;
+        this.controlWord = '';
+        this.controlWordParam = '';
+    },
+    emitStartGroup : function ()
+    {
+        this.emitText();
+        this.push({
+            type: 'groupstart',
+            pos: this.cpos,
+            row: this.row,
+            col: this.col
+        });
+    },
+    emitEndGroup : function ()
+    {
+        this.emitText();
+        this.push({
+            type: 'groupend',
+            pos: this.cpos,
+            row: this.row,
+            col: this.col
+        });
+    },
+    emitIgnorable : function ()
+    {
+        this.emitText();
+        this.push({
+            type: 'ignorable',
+            pos: this.cpos,
+            row: this.row,
+            col: this.col
+        });
+    },
+    emitHexChar : function ()
+    {
+        this.emitText();
+        this.push({
+            type: 'hexchar',
+            value: this.hexChar,
+            pos: this.cpos,
+            row: this.row,
+            col: this.col
+        });
+        this.hexChar = ''
+    },
+    emitError : function (message)
+    {
+      this.emitText();
+      this.push({
+            type: 'error',
+            value: message,
+            row: this.row,
+            col: this.col,
+            char: this.cpos //,
+            //stack: new Error().stack
+        });
     },
+    emitEndParagraph : function () {
+        this.emitText();
+        this.push({
+            type: 'endparagraph',
+            pos: this.cpos,
+            row: this.row,
+            col: this.col
+        });
+    }
+     
+} ; 
+/**
+ * @class Roo.htmleditor.Filter
+ * Base Class for filtering htmleditor stuff. - do not use this directly - extend it.
+ * @cfg {DomElement} node The node to iterate and filter
+ * @cfg {boolean|String|Array} tag Tags to replace 
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
 
-    /**
-     * 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(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0080-\uFFFF]/g, function(match) {
-                
-                var cc = match.charCodeAt();
+
+
+Roo.htmleditor.Filter = function(cfg) {
+    Roo.apply(this.cfg);
+    // this does not actually call walk as it's really just a abstract class
+}
+
+
+Roo.htmleditor.Filter.prototype = {
+    
+    node: false,
+    
+    tag: false,
+
+    // overrride to do replace comments.
+    replaceComment : false,
+    
+    // overrride to do replace or do stuff with tags..
+    replaceTag : false,
+    
+    walk : function(dom)
+    {
+        Roo.each( Array.from(dom.childNodes), function( e ) {
+            switch(true) {
+                
+                case e.nodeType == 8 &&  this.replaceComment  !== false: // comment
+                    this.replaceComment(e);
+                    return;
+                
+                case e.nodeType != 1: //not a node.
+                    return;
+                
+                case this.tag === true: // everything
+                case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1:
+                case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'string' && this.tag == ":":
+                case typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1: // array and it matches.
+                case typeof(this.tag) == 'string' && this.tag == e.tagName: // array and it matches.
+                    if (this.replaceTag && false === this.replaceTag(e)) {
+                        return;
+                    }
+                    if (e.hasChildNodes()) {
+                        this.walk(e);
+                    }
+                    return;
+                
+                default:    // tags .. that do not match.
+                    if (e.hasChildNodes()) {
+                        this.walk(e);
+                    }
+            }
+            
+        }, this);
+        
+    },
+    
+    
+    removeNodeKeepChildren : function( node)
+    {
+    
+        ar = Array.from(node.childNodes);
+        for (var i = 0; i < ar.length; i++) {
+         
+            node.removeChild(ar[i]);
+            // what if we need to walk these???
+            node.parentNode.insertBefore(ar[i], node);
+           
+        }
+        node.parentNode.removeChild(node);
+    }
+}; 
+
+/**
+ * @class Roo.htmleditor.FilterAttributes
+ * clean attributes and  styles including http:// etc.. in attribute
+ * @constructor
+* Run a new Attribute Filter
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterAttributes = function(cfg)
+{
+    Roo.apply(this, cfg);
+    this.attrib_black = this.attrib_black || [];
+    this.attrib_white = this.attrib_white || [];
+
+    this.attrib_clean = this.attrib_clean || [];
+    this.style_white = this.style_white || [];
+    this.style_black = this.style_black || [];
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterAttributes, Roo.htmleditor.Filter,
+{
+    tag: true, // all tags
+    
+    attrib_black : false, // array
+    attrib_clean : false,
+    attrib_white : false,
+
+    style_white : false,
+    style_black : false,
+     
+     
+    replaceTag : function(node)
+    {
+        if (!node.attributes || !node.attributes.length) {
+            return true;
+        }
+        
+        for (var i = node.attributes.length-1; i > -1 ; i--) {
+            var a = node.attributes[i];
+            //console.log(a);
+            if (this.attrib_white.length && this.attrib_white.indexOf(a.name.toLowerCase()) < 0) {
+                node.removeAttribute(a.name);
+                continue;
+            }
+            
+            
+            
+            if (a.name.toLowerCase().substr(0,2)=='on')  {
+                node.removeAttribute(a.name);
+                continue;
+            }
+            
+            
+            if (this.attrib_black.indexOf(a.name.toLowerCase()) > -1) {
+                node.removeAttribute(a.name);
+                continue;
+            }
+            if (this.attrib_clean.indexOf(a.name.toLowerCase()) > -1) {
+                this.cleanAttr(node,a.name,a.value); // fixme..
+                continue;
+            }
+            if (a.name == 'style') {
+                this.cleanStyle(node,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.removeAttribute('class');
+                }
+                
+                if (a.value.match(/^body$/)) {
+                    node.removeAttribute('class');
+                }
+                continue;
+            }
+            
+            
+            // style cleanup!?
+            // class cleanup?
+            
+        }
+        return true; // clean children
+    },
+        
+    cleanAttr: function(node, n,v)
+    {
+        
+        if (v.match(/^\./) || v.match(/^\//)) {
+            return;
+        }
+        if (v.match(/^(http|https):\/\//)
+            || v.match(/^mailto:/) 
+            || v.match(/^ftp:/)
+            || v.match(/^data:/)
+            ) {
+            return;
+        }
+        if (v.match(/^#/)) {
+            return;
+        }
+        if (v.match(/^\{/)) { // allow template editing.
+            return;
+        }
+//            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
+        node.removeAttribute(n);
+        
+    },
+    cleanStyle : function(node,  n,v)
+    {
+        if (v.match(/expression/)) { //XSS?? should we even bother..
+            node.removeAttribute(n);
+            return;
+        }
+        
+        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 ( this.style_black.length && (this.style_black.indexOf(l) > -1 || this.style_black.indexOf(l.toLowerCase()) > -1)) {
+                return true;
+            }
+            //Roo.log()
+            // only allow 'c whitelisted system attributes'
+            if ( this.style_white.length &&  style_white.indexOf(l) < 0 && style_white.indexOf(l.toLowerCase()) < 0 ) {
+                return true;
+            }
+            
+            
+            clean.push(p);
+            return true;
+        },this);
+        if (clean.length) { 
+            node.setAttribute(n, clean.join(';'));
+        } else {
+            node.removeAttribute(n);
+        }
+        
+    }
+        
+        
+        
+    
+});/**
+ * @class Roo.htmleditor.FilterBlack
+ * remove blacklisted elements.
+ * @constructor
+ * Run a new Blacklisted Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterBlack = function(cfg)
+{
+    Roo.apply(this, cfg);
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterBlack, Roo.htmleditor.Filter,
+{
+    tag : true, // all elements.
+   
+    replaceTag : function(n)
+    {
+        n.parentNode.removeChild(n);
+    }
+});
+/**
+ * @class Roo.htmleditor.FilterComment
+ * remove comments.
+ * @constructor
+* Run a new Comments Filter
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterComment = function(cfg)
+{
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterComment, Roo.htmleditor.Filter,
+{
+  
+    replaceComment : function(n)
+    {
+        n.parentNode.removeChild(n);
+    }
+});/**
+ * @class Roo.htmleditor.FilterKeepChildren
+ * remove tags but keep children
+ * @constructor
+ * Run a new Keep Children Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterKeepChildren = function(cfg)
+{
+    Roo.apply(this, cfg);
+    if (this.tag === false) {
+        return; // dont walk.. (you can use this to use this just to do a child removal on a single tag )
+    }
+    // hacky?
+    if ((typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1)) {
+        this.cleanNamespace = true;
+    }
+        
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterKeepChildren, Roo.htmleditor.FilterBlack,
+{
+    cleanNamespace : false, // should really be an option, rather than using ':' inside of this tag.
+  
+    replaceTag : function(node)
+    {
+        // walk children...
+        //Roo.log(node.tagName);
+        var ar = Array.from(node.childNodes);
+        //remove first..
+        
+        for (var i = 0; i < ar.length; i++) {
+            var e = ar[i];
+            if (e.nodeType == 1) {
+                if (
+                    (typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1)
+                    || // array and it matches
+                    (typeof(this.tag) == 'string' && this.tag == e.tagName)
+                    ||
+                    (e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1)
+                    ||
+                    (e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'string' && this.tag == ":")
+                ) {
+                    this.replaceTag(ar[i]); // child is blacklisted as well...
+                    continue;
+                }
+            }
+        }  
+        ar = Array.from(node.childNodes);
+        for (var i = 0; i < ar.length; i++) {
+         
+            node.removeChild(ar[i]);
+            // what if we need to walk these???
+            node.parentNode.insertBefore(ar[i], node);
+            if (this.tag !== false) {
+                this.walk(ar[i]);
+                
+            }
+        }
+        //Roo.log("REMOVE:" + node.tagName);
+        node.parentNode.removeChild(node);
+        return false; // don't walk children
+        
+        
+    }
+});/**
+ * @class Roo.htmleditor.FilterParagraph
+ * paragraphs cause a nightmare for shared content - this filter is designed to be called ? at various points when editing
+ * like on 'push' to remove the <p> tags and replace them with line breaks.
+ * @constructor
+ * Run a new Paragraph Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterParagraph = function(cfg)
+{
+    // no need to apply config.
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterParagraph, Roo.htmleditor.Filter,
+{
+    
+     
+    tag : 'P',
+    
+     
+    replaceTag : function(node)
+    {
+        
+        if (node.childNodes.length == 1 &&
+            node.childNodes[0].nodeType == 3 &&
+            node.childNodes[0].textContent.trim().length < 1
+            ) {
+            // remove and replace with '<BR>';
+            node.parentNode.replaceChild(node.ownerDocument.createElement('BR'),node);
+            return false; // no need to walk..
+        }
+        var ar = Array.from(node.childNodes);
+        for (var i = 0; i < ar.length; i++) {
+            node.removeChild(ar[i]);
+            // what if we need to walk these???
+            node.parentNode.insertBefore(ar[i], node);
+        }
+        // now what about this?
+        // <p> &nbsp; </p>
+        
+        // double BR.
+        node.parentNode.insertBefore(node.ownerDocument.createElement('BR'), node);
+        node.parentNode.insertBefore(node.ownerDocument.createElement('BR'), node);
+        node.parentNode.removeChild(node);
+        
+        return false;
+
+    }
+    
+});/**
+ * @class Roo.htmleditor.FilterSpan
+ * filter span's with no attributes out..
+ * @constructor
+ * Run a new Span Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterSpan = function(cfg)
+{
+    // no need to apply config.
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterSpan, Roo.htmleditor.FilterKeepChildren,
+{
+     
+    tag : 'SPAN',
+     
+    replaceTag : function(node)
+    {
+        if (node.attributes && node.attributes.length > 0) {
+            return true; // walk if there are any.
+        }
+        Roo.htmleditor.FilterKeepChildren.prototype.replaceTag.call(this, node);
+        return false;
+     
+    }
+    
+});/**
+ * @class Roo.htmleditor.FilterTableWidth
+  try and remove table width data - as that frequently messes up other stuff.
+ * 
+ *      was cleanTableWidths.
+ *
+ * Quite often pasting from word etc.. results in tables with column and widths.
+ * This does not work well on fluid HTML layouts - like emails. - so this code should hunt an destroy them..
+ *
+ * @constructor
+ * Run a new Table Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterTableWidth = function(cfg)
+{
+    // no need to apply config.
+    this.tag = ['TABLE', 'TD', 'TR', 'TH', 'THEAD', 'TBODY' ];
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterTableWidth, Roo.htmleditor.Filter,
+{
+     
+     
+    
+    replaceTag: function(node) {
+        
+        
+      
+        if (node.hasAttribute('width')) {
+            node.removeAttribute('width');
+        }
+        
+         
+        if (node.hasAttribute("style")) {
+            // pretty basic...
+            
+            var styles = node.getAttribute("style").split(";");
+            var nstyle = [];
+            Roo.each(styles, function(s) {
+                if (!s.match(/:/)) {
+                    return;
+                }
+                var kv = s.split(":");
+                if (kv[0].match(/^\s*(width|min-width)\s*$/)) {
+                    return;
+                }
+                // what ever is left... we allow.
+                nstyle.push(s);
+            });
+            node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
+            if (!nstyle.length) {
+                node.removeAttribute('style');
+            }
+        }
+        
+        return true; // continue doing children..
+    }
+});/**
+ * @class Roo.htmleditor.FilterWord
+ * try and clean up all the mess that Word generates.
+ * 
+ * This is the 'nice version' - see 'Heavy' that white lists a very short list of elements, and multi-filters 
+ * @constructor
+ * Run a new Span Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterWord = function(cfg)
+{
+    // no need to apply config.
+    this.replaceDocBullets(cfg.node);
+    
+    this.replaceAname(cfg.node);
+    // this is disabled as the removal is done by other filters;
+   // this.walk(cfg.node);
+    this.replaceImageTable(cfg.node);
+    
+}
+
+Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
+{
+    tag: true,
+     
+    
+    /**
+     * Clean up MS wordisms...
+     */
+    replaceTag : function(node)
+    {
+         
+        // no idea what this does - span with text, replaceds with just text.
+        if(
+                node.nodeName == 'SPAN' &&
+                !node.hasAttributes() &&
+                node.childNodes.length == 1 &&
+                node.firstChild.nodeName == "#text"  
+        ) {
+            var textNode = node.firstChild;
+            node.removeChild(textNode);
+            if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
+                node.parentNode.insertBefore(node.ownerDocument.createTextNode(" "), node);
+            }
+            node.parentNode.insertBefore(textNode, node);
+            if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
+                node.parentNode.insertBefore(node.ownerDocument.createTextNode(" ") , node);
+            }
+            
+            node.parentNode.removeChild(node);
+            return false; // dont do chidren - we have remove our node - so no need to do chdhilren?
+        }
+        
+   
+        
+        if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
+            node.parentNode.removeChild(node);
+            return false; // dont do chidlren
+        }
+        //Roo.log(node.tagName);
+        // remove - but keep children..
+        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)) {
+            //Roo.log('-- removed');
+            while (node.childNodes.length) {
+                var cn = node.childNodes[0];
+                node.removeChild(cn);
+                node.parentNode.insertBefore(cn, node);
+                // move node to parent - and clean it..
+                if (cn.nodeType == 1) {
+                    this.replaceTag(cn);
+                }
+                
+            }
+            node.parentNode.removeChild(node);
+            /// no need to iterate chidlren = it's got none..
+            //this.iterateChildren(node, this.cleanWord);
+            return false; // no need to iterate children.
+        }
+        // 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");
+            }
+        }
+        
+        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(/:/)) {
+                    return;
+                }
+                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');
+            }
+        }
+        return true; // do children
+        
+        
+        
+    },
+    
+    styleToObject: function(node)
+    {
+        var styles = (node.getAttribute("style") || '').split(";");
+        var ret = {};
+        Roo.each(styles, function(s) {
+            if (!s.match(/:/)) {
+                return;
+            }
+            var kv = s.split(":");
+             
+            // what ever is left... we allow.
+            ret[kv[0].trim()] = kv[1];
+        });
+        return ret;
+    },
+    
+    
+    replaceAname : function (doc)
+    {
+        // replace all the a/name without..
+        var aa = Array.from(doc.getElementsByTagName('a'));
+        for (var i = 0; i  < aa.length; i++) {
+            var a = aa[i];
+            if (a.hasAttribute("name")) {
+                a.removeAttribute("name");
+            }
+            if (a.hasAttribute("href")) {
+                continue;
+            }
+            // reparent children.
+            this.removeNodeKeepChildren(a);
+            
+        }
+        
+        
+        
+    },
+
+    
+    
+    replaceDocBullets : function(doc)
+    {
+        // this is a bit odd - but it appears some indents use ql-indent-1
+         //Roo.log(doc.innerHTML);
+        
+        var listpara = Array.from(doc.getElementsByClassName('MsoListParagraphCxSpFirst'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        
+        listpara =  Array.from(doc.getElementsByClassName('MsoListParagraphCxSpMiddle'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        listpara =  Array.from(doc.getElementsByClassName('MsoListParagraphCxSpLast'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        listpara =  Array.from(doc.getElementsByClassName('ql-indent-1'));
+        for( var i = 0; i < listpara.length; i ++) {
+            listpara[i].className = "MsoListParagraph";
+        }
+        
+        // this is a bit hacky - we had one word document where h2 had a miso-list attribute.
+        var htwo =  Array.from(doc.getElementsByTagName('h2'));
+        for( var i = 0; i < htwo.length; i ++) {
+            if (htwo[i].hasAttribute('style') && htwo[i].getAttribute('style').match(/mso-list:/)) {
+                htwo[i].className = "MsoListParagraph";
+            }
+        }
+        listpara =  Array.from(doc.getElementsByClassName('MsoNormal'));
+        for( var i = 0; i < listpara.length; i ++) {
+            if (listpara[i].hasAttribute('style') && listpara[i].getAttribute('style').match(/mso-list:/)) {
+                listpara[i].className = "MsoListParagraph";
+            } else {
+                listpara[i].className = "MsoNormalx";
+            }
+        }
+       
+        listpara = doc.getElementsByClassName('MsoListParagraph');
+        // Roo.log(doc.innerHTML);
+        
+        
+        
+        while(listpara.length) {
+            
+            this.replaceDocBullet(listpara.item(0));
+        }
+      
+    },
+    
+     
+    
+    replaceDocBullet : function(p)
+    {
+        // gather all the siblings.
+        var ns = p,
+            parent = p.parentNode,
+            doc = parent.ownerDocument,
+            items = [];
+         
+        //Roo.log("Parsing: " + p.innerText)    ;
+        var listtype = 'ul';   
+        while (ns) {
+            if (ns.nodeType != 1) {
+                ns = ns.nextSibling;
+                continue;
+            }
+            if (!ns.className.match(/(MsoListParagraph|ql-indent-1)/i)) {
+                //Roo.log("Missing para r q1indent - got:" + ns.className);
+                break;
+            }
+            var spans = ns.getElementsByTagName('span');
+            
+            if (ns.hasAttribute('style') && ns.getAttribute('style').match(/mso-list/)) {
+                items.push(ns);
+                ns = ns.nextSibling;
+                has_list = true;
+                if (!spans.length) {
+                    continue;
+                }
+                var ff = '';
+                var se = spans[0];
+                for (var i = 0; i < spans.length;i++) {
+                    se = spans[i];
+                    if (se.hasAttribute('style')  && se.hasAttribute('style') && se.style.fontFamily != '') {
+                        ff = se.style.fontFamily;
+                        break;
+                    }
+                }
+                 
+                    
+                //Roo.log("got font family: " + ff);
+                if (typeof(ff) != 'undefined' && !ff.match(/(Symbol|Wingdings)/) && "·o".indexOf(se.innerText.trim()) < 0) {
+                    listtype = 'ol';
+                }
+                
+                continue;
+            }
+            //Roo.log("no mso-list?");
+            
+            var spans = ns.getElementsByTagName('span');
+            if (!spans.length) {
+                break;
+            }
+            var has_list  = false;
+            for(var i = 0; i < spans.length; i++) {
+                if (spans[i].hasAttribute('style') && spans[i].getAttribute('style').match(/mso-list/)) {
+                    has_list = true;
+                    break;
+                }
+            }
+            if (!has_list) {
+                break;
+            }
+            items.push(ns);
+            ns = ns.nextSibling;
+            
+            
+        }
+        if (!items.length) {
+            ns.className = "";
+            return;
+        }
+        
+        var ul = parent.ownerDocument.createElement(listtype); // what about number lists...
+        parent.insertBefore(ul, p);
+        var lvl = 0;
+        var stack = [ ul ];
+        var last_li = false;
+        
+        var margin_to_depth = {};
+        max_margins = -1;
+        
+        items.forEach(function(n, ipos) {
+            //Roo.log("got innertHMLT=" + n.innerHTML);
+            
+            var spans = n.getElementsByTagName('span');
+            if (!spans.length) {
+                //Roo.log("No spans found");
+                 
+                parent.removeChild(n);
+                
+                
+                return; // skip it...
+            }
+           
+                
+            var num = 1;
+            var style = {};
+            for(var i = 0; i < spans.length; i++) {
+            
+                style = this.styleToObject(spans[i]);
+                if (typeof(style['mso-list']) == 'undefined') {
+                    continue;
+                }
+                if (listtype == 'ol') {
+                   num = spans[i].innerText.replace(/[^0-9]+]/g,'')  * 1;
+                }
+                spans[i].parentNode.removeChild(spans[i]); // remove the fake bullet.
+                break;
+            }
+            //Roo.log("NOW GOT innertHMLT=" + n.innerHTML);
+            style = this.styleToObject(n); // mo-list is from the parent node.
+            if (typeof(style['mso-list']) == 'undefined') {
+                //Roo.log("parent is missing level");
+                  
+                parent.removeChild(n);
+                 
+                return;
+            }
+            
+            var margin = style['margin-left'];
+            if (typeof(margin_to_depth[margin]) == 'undefined') {
+                max_margins++;
+                margin_to_depth[margin] = max_margins;
+            }
+            nlvl = margin_to_depth[margin] ;
+             
+            if (nlvl > lvl) {
+                //new indent
+                var nul = doc.createElement(listtype); // what about number lists...
+                if (!last_li) {
+                    last_li = doc.createElement('li');
+                    stack[lvl].appendChild(last_li);
+                }
+                last_li.appendChild(nul);
+                stack[nlvl] = nul;
+                
+            }
+            lvl = nlvl;
+            
+            // not starting at 1..
+            if (!stack[nlvl].hasAttribute("start") && listtype == "ol") {
+                stack[nlvl].setAttribute("start", num);
+            }
+            
+            var nli = stack[nlvl].appendChild(doc.createElement('li'));
+            last_li = nli;
+            nli.innerHTML = n.innerHTML;
+            //Roo.log("innerHTML = " + n.innerHTML);
+            parent.removeChild(n);
+            
+             
+             
+            
+        },this);
+        
+        
+        
+        
+    },
+    
+    replaceImageTable : function(doc)
+    {
+         /*
+          <table cellpadding=0 cellspacing=0 align=left>
+  <tr>
+   <td width=423 height=0></td>
+  </tr>
+  <tr>
+   <td></td>
+   <td><img width=601 height=401
+   src="file:///C:/Users/Alan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg"
+   v:shapes="Picture_x0020_2"></td>
+  </tr>
+ </table>
+ */
+        var imgs = Array.from(doc.getElementsByTagName('img'));
+        Roo.each(imgs, function(img) {
+            var td = img.parentNode;
+            if (td.nodeName !=  'TD') {
+                return;
+            }
+            var tr = td.parentNode;
+            if (tr.nodeName !=  'TR') {
+                return;
+            }
+            var tbody = tr.parentNode;
+            if (tbody.nodeName !=  'TBODY') {
+                return;
+            }
+            var table = tbody.parentNode;
+            if (table.nodeName !=  'TABLE') {
+                return;
+            }
+            // first row..
+            
+            if (table.getElementsByTagName('tr').length != 2) {
+                return;
+            }
+            if (table.getElementsByTagName('td').length != 3) {
+                return;
+            }
+            if (table.innerText.trim() != '') {
+                return;
+            }
+            var p = table.parentNode;
+            img.parentNode.removeChild(img);
+            p.insertBefore(img, table);
+            p.removeChild(table);
+            
+            
+            
+        });
+        
+      
+    }
+    
+});
+/**
+ * @class Roo.htmleditor.FilterStyleToTag
+ * part of the word stuff... - certain 'styles' should be converted to tags.
+ * eg.
+ *   font-weight: bold -> bold
+ *   ?? super / subscrit etc..
+ * 
+ * @constructor
+* Run a new style to tag filter.
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterStyleToTag = function(cfg)
+{
+    
+    this.tags = {
+        B  : [ 'fontWeight' , 'bold'],
+        I :  [ 'fontStyle' , 'italic'],
+        //pre :  [ 'font-style' , 'italic'],
+        // h1.. h6 ?? font-size?
+        SUP : [ 'verticalAlign' , 'super' ],
+        SUB : [ 'verticalAlign' , 'sub' ]
+        
+        
+    };
+    
+    Roo.apply(this, cfg);
+     
+    
+    this.walk(cfg.node);
+    
+    
+    
+}
+
+
+Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
+{
+    tag: true, // all tags
+    
+    tags : false,
+    
+    
+    replaceTag : function(node)
+    {
+        
+        
+        if (node.getAttribute("style") === null) {
+            return true;
+        }
+        var inject = [];
+        for (var k in this.tags) {
+            if (node.style[this.tags[k][0]] == this.tags[k][1]) {
+                inject.push(k);
+                node.style.removeProperty(this.tags[k][0]);
+            }
+        }
+        if (!inject.length) {
+            return true; 
+        }
+        var cn = Array.from(node.childNodes);
+        var nn = node;
+        Roo.each(inject, function(t) {
+            var nc = node.ownerDocument.createElement(t);
+            nn.appendChild(nc);
+            nn = nc;
+        });
+        for(var i = 0;i < cn.length;cn++) {
+            node.removeChild(cn[i]);
+            nn.appendChild(cn[i]);
+        }
+        return true /// iterate thru
+    }
+    
+})/**
+ * @class Roo.htmleditor.FilterLongBr
+ * BR/BR/BR - keep a maximum of 2...
+ * @constructor
+ * Run a new Long BR Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterLongBr = function(cfg)
+{
+    // no need to apply config.
+    this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterLongBr, Roo.htmleditor.Filter,
+{
+    
+     
+    tag : 'BR',
+    
+     
+    replaceTag : function(node)
+    {
+        
+        var ps = node.nextSibling;
+        while (ps && ps.nodeType == 3 && ps.nodeValue.trim().length < 1) {
+            ps = ps.nextSibling;
+        }
+        
+        if (!ps &&  [ 'TD', 'TH', 'LI', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ].indexOf(node.parentNode.tagName) > -1) { 
+            node.parentNode.removeChild(node); // remove last BR inside one fo these tags
+            return false;
+        }
+        
+        if (!ps || ps.nodeType != 1) {
+            return false;
+        }
+        
+        if (!ps || ps.tagName != 'BR') {
+           
+            return false;
+        }
+        
+        
+        
+        
+        
+        if (!node.previousSibling) {
+            return false;
+        }
+        var ps = node.previousSibling;
+        
+        while (ps && ps.nodeType == 3 && ps.nodeValue.trim().length < 1) {
+            ps = ps.previousSibling;
+        }
+        if (!ps || ps.nodeType != 1) {
+            return false;
+        }
+        // if header or BR before.. then it's a candidate for removal.. - as we only want '2' of these..
+        if (!ps || [ 'BR', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6' ].indexOf(ps.tagName) < 0) {
+            return false;
+        }
+        
+        node.parentNode.removeChild(node); // remove me...
+        
+        return false; // no need to do children
+
+    }
+    
+}); 
+
+/**
+ * @class Roo.htmleditor.FilterBlock
+ * removes id / data-block and contenteditable that are associated with blocks
+ * usage should be done on a cloned copy of the dom
+ * @constructor
+* Run a new Attribute Filter { node : xxxx }}
+* @param {Object} config Configuration options
+ */
+Roo.htmleditor.FilterBlock = function(cfg)
+{
+    Roo.apply(this, cfg);
+    var qa = cfg.node.querySelectorAll;
+    this.removeAttributes('data-block');
+    this.removeAttributes('contenteditable');
+    this.removeAttributes('id');
+    
+}
+
+Roo.apply(Roo.htmleditor.FilterBlock.prototype,
+{
+    node: true, // all tags
+     
+     
+    removeAttributes : function(attr)
+    {
+        var ar = this.node.querySelectorAll('*[' + attr + ']');
+        for (var i =0;i<ar.length;i++) {
+            ar[i].removeAttribute(attr);
+        }
+    }
+        
+        
+        
+    
+});
+/***
+ * This is based loosely on tinymce 
+ * @class Roo.htmleditor.TidySerializer
+ * https://github.com/thorn0/tinymce.html/blob/master/tinymce.html.js
+ * @constructor
+ * @method Serializer
+ * @param {Object} settings Name/value settings object.
+ */
+
+
+Roo.htmleditor.TidySerializer = function(settings)
+{
+    Roo.apply(this, settings);
+    
+    this.writer = new Roo.htmleditor.TidyWriter(settings);
+    
+    
+
+};
+Roo.htmleditor.TidySerializer.prototype = {
+    
+    /**
+     * @param {boolean} inner do the inner of the node.
+     */
+    inner : false,
+    
+    writer : false,
+    
+    /**
+    * Serializes the specified node into a string.
+    *
+    * @example
+    * new tinymce.html.Serializer().serialize(new tinymce.html.DomParser().parse('<p>text</p>'));
+    * @method serialize
+    * @param {DomElement} node Node instance to serialize.
+    * @return {String} String with HTML based on DOM tree.
+    */
+    serialize : function(node) {
+        
+        // = settings.validate;
+        var writer = this.writer;
+        var self  = this;
+        this.handlers = {
+            // #text
+            3: function(node) {
+                
+                writer.text(node.nodeValue, node);
+            },
+            // #comment
+            8: function(node) {
+                writer.comment(node.nodeValue);
+            },
+            // Processing instruction
+            7: function(node) {
+                writer.pi(node.name, node.nodeValue);
+            },
+            // Doctype
+            10: function(node) {
+                writer.doctype(node.nodeValue);
+            },
+            // CDATA
+            4: function(node) {
+                writer.cdata(node.nodeValue);
+            },
+            // Document fragment
+            11: function(node) {
+                node = node.firstChild;
+                if (!node) {
+                    return;
+                }
+                while(node) {
+                    self.walk(node);
+                    node = node.nextSibling
+                }
+            }
+        };
+        writer.reset();
+        1 != node.nodeType || this.inner ? this.handlers[11](node) : this.walk(node);
+        return writer.getContent();
+    },
+
+    walk: function(node)
+    {
+        var attrName, attrValue, sortedAttrs, i, l, elementRule,
+            handler = this.handlers[node.nodeType];
+            
+        if (handler) {
+            handler(node);
+            return;
+        }
+    
+        var name = node.nodeName;
+        var isEmpty = node.childNodes.length < 1;
+      
+        var writer = this.writer;
+        var attrs = node.attributes;
+        // Sort attributes
+        
+        writer.start(node.nodeName, attrs, isEmpty, node);
+        if (isEmpty) {
+            return;
+        }
+        node = node.firstChild;
+        if (!node) {
+            writer.end(name);
+            return;
+        }
+        while (node) {
+            this.walk(node);
+            node = node.nextSibling;
+        }
+        writer.end(name);
+        
+    
+    }
+    // Serialize element and treat all non elements as fragments
+   
+}; 
+
+/***
+ * This is based loosely on tinymce 
+ * @class Roo.htmleditor.TidyWriter
+ * https://github.com/thorn0/tinymce.html/blob/master/tinymce.html.js
+ *
+ * Known issues?
+ * - not tested much with 'PRE' formated elements.
+ * 
+ *
+ *
+ */
+
+Roo.htmleditor.TidyWriter = function(settings)
+{
+    
+    // indent, indentBefore, indentAfter, encode, htmlOutput, html = [];
+    Roo.apply(this, settings);
+    this.html = [];
+    this.state = [];
+     
+    this.encode = Roo.htmleditor.TidyEntities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
+  
+}
+Roo.htmleditor.TidyWriter.prototype = {
+
+    state : false,
+    
+    indent :  '  ',
+    
+    // part of state...
+    indentstr : '',
+    in_pre: false,
+    in_inline : false,
+    last_inline : false,
+    encode : false,
+     
+    
+            /**
+    * Writes the a start element such as <p id="a">.
+    *
+    * @method start
+    * @param {String} name Name of the element.
+    * @param {Array} attrs Optional attribute array or undefined if it hasn't any.
+    * @param {Boolean} empty Optional empty state if the tag should end like <br />.
+    */
+    start: function(name, attrs, empty, node)
+    {
+        var i, l, attr, value;
+        
+        // there are some situations where adding line break && indentation will not work. will not work.
+        // <span / b / i ... formating?
+        
+        var in_inline = this.in_inline || Roo.htmleditor.TidyWriter.inline_elements.indexOf(name) > -1;
+        var in_pre    = this.in_pre    || Roo.htmleditor.TidyWriter.whitespace_elements.indexOf(name) > -1;
+        
+        var is_short   = empty ? Roo.htmleditor.TidyWriter.shortend_elements.indexOf(name) > -1 : false;
+        
+        var add_lb = name == 'BR' ? false : in_inline;
+        
+        if (!add_lb && !this.in_pre && this.lastElementEndsWS()) {
+            i_inline = false;
+        }
+
+        var indentstr =  this.indentstr;
+        
+        // e_inline = elements that can be inline, but still allow \n before and after?
+        // only 'BR' ??? any others?
+        
+        // ADD LINE BEFORE tage
+        if (!this.in_pre) {
+            if (in_inline) {
+                //code
+                if (name == 'BR') {
+                    this.addLine();
+                } else if (this.lastElementEndsWS()) {
+                    this.addLine();
+                } else{
+                    // otherwise - no new line. (and dont indent.)
+                    indentstr = '';
+                }
+                
+            } else {
+                this.addLine();
+            }
+        } else {
+            indentstr = '';
+        }
+        
+        this.html.push(indentstr + '<', name.toLowerCase());
+        
+        if (attrs) {
+            for (i = 0, l = attrs.length; i < l; i++) {
+                attr = attrs[i];
+                this.html.push(' ', attr.name, '="', this.encode(attr.value, true), '"');
+            }
+        }
+     
+        if (empty) {
+            if (is_short) {
+                this.html[this.html.length] = '/>';
+            } else {
+                this.html[this.html.length] = '></' + name.toLowerCase() + '>';
+            }
+            var e_inline = name == 'BR' ? false : this.in_inline;
+            
+            if (!e_inline && !this.in_pre) {
+                this.addLine();
+            }
+            return;
+        
+        }
+        // not empty..
+        this.html[this.html.length] = '>';
+        
+        // there is a special situation, where we need to turn on in_inline - if any of the imediate chidlren are one of these.
+        /*
+        if (!in_inline && !in_pre) {
+            var cn = node.firstChild;
+            while(cn) {
+                if (Roo.htmleditor.TidyWriter.inline_elements.indexOf(cn.nodeName) > -1) {
+                    in_inline = true
+                    break;
+                }
+                cn = cn.nextSibling;
+            }
+             
+        }
+        */
+        
+        
+        this.pushState({
+            indentstr : in_pre   ? '' : (this.indentstr + this.indent),
+            in_pre : in_pre,
+            in_inline :  in_inline
+        });
+        // add a line after if we are not in a
+        
+        if (!in_inline && !in_pre) {
+            this.addLine();
+        }
+        
+            
+         
+        
+    },
+    
+    lastElementEndsWS : function()
+    {
+        var value = this.html.length > 0 ? this.html[this.html.length-1] : false;
+        if (value === false) {
+            return true;
+        }
+        return value.match(/\s+$/);
+        
+    },
+    
+    /**
+     * Writes the a end element such as </p>.
+     *
+     * @method end
+     * @param {String} name Name of the element.
+     */
+    end: function(name) {
+        var value;
+        this.popState();
+        var indentstr = '';
+        var in_inline = this.in_inline || Roo.htmleditor.TidyWriter.inline_elements.indexOf(name) > -1;
+        
+        if (!this.in_pre && !in_inline) {
+            this.addLine();
+            indentstr  = this.indentstr;
+        }
+        this.html.push(indentstr + '</', name.toLowerCase(), '>');
+        this.last_inline = in_inline;
+        
+        // pop the indent state..
+    },
+    /**
+     * Writes a text node.
+     *
+     * In pre - we should not mess with the contents.
+     * 
+     *
+     * @method text
+     * @param {String} text String to write out.
+     * @param {Boolean} raw Optional raw state if true the contents wont get encoded.
+     */
+    text: function(in_text, node)
+    {
+        // if not in whitespace critical
+        if (in_text.length < 1) {
+            return;
+        }
+        var text = new XMLSerializer().serializeToString(document.createTextNode(in_text)); // escape it properly?
+        
+        if (this.in_pre) {
+            this.html[this.html.length] =  text;
+            return;   
+        }
+        
+        if (this.in_inline) {
+            text = text.replace(/\s+/g,' '); // all white space inc line breaks to a slingle' '
+            if (text != ' ') {
+                text = text.replace(/\s+/,' ');  // all white space to single white space
+                
+                    
+                // if next tag is '<BR>', then we can trim right..
+                if (node.nextSibling &&
+                    node.nextSibling.nodeType == 1 &&
+                    node.nextSibling.nodeName == 'BR' )
+                {
+                    text = text.replace(/\s+$/g,'');
+                }
+                // if previous tag was a BR, we can also trim..
+                if (node.previousSibling &&
+                    node.previousSibling.nodeType == 1 &&
+                    node.previousSibling.nodeName == 'BR' )
+                {
+                    text = this.indentstr +  text.replace(/^\s+/g,'');
+                }
+                if (text.match(/\n/)) {
+                    text = text.replace(
+                        /(?![^\n]{1,64}$)([^\n]{1,64})\s/g, '$1\n' + this.indentstr
+                    );
+                    // remoeve the last whitespace / line break.
+                    text = text.replace(/\n\s+$/,'');
+                }
+                // repace long lines
+                
+            }
+             
+            this.html[this.html.length] =  text;
+            return;   
+        }
+        // see if previous element was a inline element.
+        var indentstr = this.indentstr;
+   
+        text = text.replace(/\s+/g," "); // all whitespace into single white space.
+        
+        // should trim left?
+        if (node.previousSibling &&
+            node.previousSibling.nodeType == 1 &&
+            Roo.htmleditor.TidyWriter.inline_elements.indexOf(node.previousSibling.nodeName) > -1)
+        {
+            indentstr = '';
+            
+        } else {
+            this.addLine();
+            text = text.replace(/^\s+/,''); // trim left
+          
+        }
+        // should trim right?
+        if (node.nextSibling &&
+            node.nextSibling.nodeType == 1 &&
+            Roo.htmleditor.TidyWriter.inline_elements.indexOf(node.nextSibling.nodeName) > -1)
+        {
+          // noop
+            
+        }  else {
+            text = text.replace(/\s+$/,''); // trim right
+        }
+         
+              
+        
+        
+        
+        if (text.length < 1) {
+            return;
+        }
+        if (!text.match(/\n/)) {
+            this.html.push(indentstr + text);
+            return;
+        }
+        
+        text = this.indentstr + text.replace(
+            /(?![^\n]{1,64}$)([^\n]{1,64})\s/g, '$1\n' + this.indentstr
+        );
+        // remoeve the last whitespace / line break.
+        text = text.replace(/\s+$/,''); 
+        
+        this.html.push(text);
+        
+        // split and indent..
+        
+        
+    },
+    /**
+     * Writes a cdata node such as <![CDATA[data]]>.
+     *
+     * @method cdata
+     * @param {String} text String to write out inside the cdata.
+     */
+    cdata: function(text) {
+        this.html.push('<![CDATA[', text, ']]>');
+    },
+    /**
+    * Writes a comment node such as <!-- Comment -->.
+    *
+    * @method cdata
+    * @param {String} text String to write out inside the comment.
+    */
+   comment: function(text) {
+       this.html.push('<!--', text, '-->');
+   },
+    /**
+     * Writes a PI node such as <?xml attr="value" ?>.
+     *
+     * @method pi
+     * @param {String} name Name of the pi.
+     * @param {String} text String to write out inside the pi.
+     */
+    pi: function(name, text) {
+        text ? this.html.push('<?', name, ' ', this.encode(text), '?>') : this.html.push('<?', name, '?>');
+        this.indent != '' && this.html.push('\n');
+    },
+    /**
+     * Writes a doctype node such as <!DOCTYPE data>.
+     *
+     * @method doctype
+     * @param {String} text String to write out inside the doctype.
+     */
+    doctype: function(text) {
+        this.html.push('<!DOCTYPE', text, '>', this.indent != '' ? '\n' : '');
+    },
+    /**
+     * Resets the internal buffer if one wants to reuse the writer.
+     *
+     * @method reset
+     */
+    reset: function() {
+        this.html.length = 0;
+        this.state = [];
+        this.pushState({
+            indentstr : '',
+            in_pre : false, 
+            in_inline : false
+        })
+    },
+    /**
+     * Returns the contents that got serialized.
+     *
+     * @method getContent
+     * @return {String} HTML contents that got written down.
+     */
+    getContent: function() {
+        return this.html.join('').replace(/\n$/, '');
+    },
+    
+    pushState : function(cfg)
+    {
+        this.state.push(cfg);
+        Roo.apply(this, cfg);
+    },
+    
+    popState : function()
+    {
+        if (this.state.length < 1) {
+            return; // nothing to push
+        }
+        var cfg = {
+            in_pre: false,
+            indentstr : ''
+        };
+        this.state.pop();
+        if (this.state.length > 0) {
+            cfg = this.state[this.state.length-1]; 
+        }
+        Roo.apply(this, cfg);
+    },
+    
+    addLine: function()
+    {
+        if (this.html.length < 1) {
+            return;
+        }
+        
+        
+        var value = this.html[this.html.length - 1];
+        if (value.length > 0 && '\n' !== value) {
+            this.html.push('\n');
+        }
+    }
+    
+    
+//'pre script noscript style textarea video audio iframe object code'
+// shortended... 'area base basefont br col frame hr img input isindex link  meta param embed source wbr track');
+// inline 
+};
+
+Roo.htmleditor.TidyWriter.inline_elements = [
+        'SPAN','STRONG','B','EM','I','FONT','STRIKE','U','VAR',
+        'CITE','DFN','CODE','MARK','Q','SUP','SUB','SAMP', 'A'
+];
+Roo.htmleditor.TidyWriter.shortend_elements = [
+    'AREA','BASE','BASEFONT','BR','COL','FRAME','HR','IMG','INPUT',
+    'ISINDEX','LINK','','META','PARAM','EMBED','SOURCE','WBR','TRACK'
+];
+
+Roo.htmleditor.TidyWriter.whitespace_elements = [
+    'PRE','SCRIPT','NOSCRIPT','STYLE','TEXTAREA','VIDEO','AUDIO','IFRAME','OBJECT','CODE'
+];/***
+ * This is based loosely on tinymce 
+ * @class Roo.htmleditor.TidyEntities
+ * @static
+ * https://github.com/thorn0/tinymce.html/blob/master/tinymce.html.js
+ *
+ * Not 100% sure this is actually used or needed.
+ */
+
+Roo.htmleditor.TidyEntities = {
+    
+    /**
+     * initialize data..
+     */
+    init : function (){
+     
+        this.namedEntities = this.buildEntitiesLookup(this.namedEntitiesData, 32);
+       
+    },
+
+
+    buildEntitiesLookup: function(items, radix) {
+        var i, chr, entity, lookup = {};
+        if (!items) {
+            return {};
+        }
+        items = typeof(items) == 'string' ? items.split(',') : items;
+        radix = radix || 10;
+        // Build entities lookup table
+        for (i = 0; i < items.length; i += 2) {
+            chr = String.fromCharCode(parseInt(items[i], radix));
+            // Only add non base entities
+            if (!this.baseEntities[chr]) {
+                entity = '&' + items[i + 1] + ';';
+                lookup[chr] = entity;
+                lookup[entity] = chr;
+            }
+        }
+        return lookup;
+        
+    },
+    
+    asciiMap : {
+            128: '€',
+            130: '‚',
+            131: 'ƒ',
+            132: '„',
+            133: '…',
+            134: '†',
+            135: '‡',
+            136: 'ˆ',
+            137: '‰',
+            138: 'Š',
+            139: '‹',
+            140: 'Œ',
+            142: 'Ž',
+            145: '‘',
+            146: '’',
+            147: '“',
+            148: '”',
+            149: '•',
+            150: '–',
+            151: '—',
+            152: '˜',
+            153: '™',
+            154: 'š',
+            155: '›',
+            156: 'œ',
+            158: 'ž',
+            159: 'Ÿ'
+    },
+    // Raw entities
+    baseEntities : {
+        '"': '&quot;',
+        // Needs to be escaped since the YUI compressor would otherwise break the code
+        '\'': '&#39;',
+        '<': '&lt;',
+        '>': '&gt;',
+        '&': '&amp;',
+        '`': '&#96;'
+    },
+    // Reverse lookup table for raw entities
+    reverseEntities : {
+        '&lt;': '<',
+        '&gt;': '>',
+        '&amp;': '&',
+        '&quot;': '"',
+        '&apos;': '\''
+    },
+    
+    attrsCharsRegExp : /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+    textCharsRegExp : /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+    rawCharsRegExp : /[<>&\"\']/g,
+    entityRegExp : /&#([a-z0-9]+);?|&([a-z0-9]+);/gi,
+    namedEntities  : false,
+    namedEntitiesData : [ 
+        '50',
+        'nbsp',
+        '51',
+        'iexcl',
+        '52',
+        'cent',
+        '53',
+        'pound',
+        '54',
+        'curren',
+        '55',
+        'yen',
+        '56',
+        'brvbar',
+        '57',
+        'sect',
+        '58',
+        'uml',
+        '59',
+        'copy',
+        '5a',
+        'ordf',
+        '5b',
+        'laquo',
+        '5c',
+        'not',
+        '5d',
+        'shy',
+        '5e',
+        'reg',
+        '5f',
+        'macr',
+        '5g',
+        'deg',
+        '5h',
+        'plusmn',
+        '5i',
+        'sup2',
+        '5j',
+        'sup3',
+        '5k',
+        'acute',
+        '5l',
+        'micro',
+        '5m',
+        'para',
+        '5n',
+        'middot',
+        '5o',
+        'cedil',
+        '5p',
+        'sup1',
+        '5q',
+        'ordm',
+        '5r',
+        'raquo',
+        '5s',
+        'frac14',
+        '5t',
+        'frac12',
+        '5u',
+        'frac34',
+        '5v',
+        'iquest',
+        '60',
+        'Agrave',
+        '61',
+        'Aacute',
+        '62',
+        'Acirc',
+        '63',
+        'Atilde',
+        '64',
+        'Auml',
+        '65',
+        'Aring',
+        '66',
+        'AElig',
+        '67',
+        'Ccedil',
+        '68',
+        'Egrave',
+        '69',
+        'Eacute',
+        '6a',
+        'Ecirc',
+        '6b',
+        'Euml',
+        '6c',
+        'Igrave',
+        '6d',
+        'Iacute',
+        '6e',
+        'Icirc',
+        '6f',
+        'Iuml',
+        '6g',
+        'ETH',
+        '6h',
+        'Ntilde',
+        '6i',
+        'Ograve',
+        '6j',
+        'Oacute',
+        '6k',
+        'Ocirc',
+        '6l',
+        'Otilde',
+        '6m',
+        'Ouml',
+        '6n',
+        'times',
+        '6o',
+        'Oslash',
+        '6p',
+        'Ugrave',
+        '6q',
+        'Uacute',
+        '6r',
+        'Ucirc',
+        '6s',
+        'Uuml',
+        '6t',
+        'Yacute',
+        '6u',
+        'THORN',
+        '6v',
+        'szlig',
+        '70',
+        'agrave',
+        '71',
+        'aacute',
+        '72',
+        'acirc',
+        '73',
+        'atilde',
+        '74',
+        'auml',
+        '75',
+        'aring',
+        '76',
+        'aelig',
+        '77',
+        'ccedil',
+        '78',
+        'egrave',
+        '79',
+        'eacute',
+        '7a',
+        'ecirc',
+        '7b',
+        'euml',
+        '7c',
+        'igrave',
+        '7d',
+        'iacute',
+        '7e',
+        'icirc',
+        '7f',
+        'iuml',
+        '7g',
+        'eth',
+        '7h',
+        'ntilde',
+        '7i',
+        'ograve',
+        '7j',
+        'oacute',
+        '7k',
+        'ocirc',
+        '7l',
+        'otilde',
+        '7m',
+        'ouml',
+        '7n',
+        'divide',
+        '7o',
+        'oslash',
+        '7p',
+        'ugrave',
+        '7q',
+        'uacute',
+        '7r',
+        'ucirc',
+        '7s',
+        'uuml',
+        '7t',
+        'yacute',
+        '7u',
+        'thorn',
+        '7v',
+        'yuml',
+        'ci',
+        'fnof',
+        'sh',
+        'Alpha',
+        'si',
+        'Beta',
+        'sj',
+        'Gamma',
+        'sk',
+        'Delta',
+        'sl',
+        'Epsilon',
+        'sm',
+        'Zeta',
+        'sn',
+        'Eta',
+        'so',
+        'Theta',
+        'sp',
+        'Iota',
+        'sq',
+        'Kappa',
+        'sr',
+        'Lambda',
+        'ss',
+        'Mu',
+        'st',
+        'Nu',
+        'su',
+        'Xi',
+        'sv',
+        'Omicron',
+        't0',
+        'Pi',
+        't1',
+        'Rho',
+        't3',
+        'Sigma',
+        't4',
+        'Tau',
+        't5',
+        'Upsilon',
+        't6',
+        'Phi',
+        't7',
+        'Chi',
+        't8',
+        'Psi',
+        't9',
+        'Omega',
+        'th',
+        'alpha',
+        'ti',
+        'beta',
+        'tj',
+        'gamma',
+        'tk',
+        'delta',
+        'tl',
+        'epsilon',
+        'tm',
+        'zeta',
+        'tn',
+        'eta',
+        'to',
+        'theta',
+        'tp',
+        'iota',
+        'tq',
+        'kappa',
+        'tr',
+        'lambda',
+        'ts',
+        'mu',
+        'tt',
+        'nu',
+        'tu',
+        'xi',
+        'tv',
+        'omicron',
+        'u0',
+        'pi',
+        'u1',
+        'rho',
+        'u2',
+        'sigmaf',
+        'u3',
+        'sigma',
+        'u4',
+        'tau',
+        'u5',
+        'upsilon',
+        'u6',
+        'phi',
+        'u7',
+        'chi',
+        'u8',
+        'psi',
+        'u9',
+        'omega',
+        'uh',
+        'thetasym',
+        'ui',
+        'upsih',
+        'um',
+        'piv',
+        '812',
+        'bull',
+        '816',
+        'hellip',
+        '81i',
+        'prime',
+        '81j',
+        'Prime',
+        '81u',
+        'oline',
+        '824',
+        'frasl',
+        '88o',
+        'weierp',
+        '88h',
+        'image',
+        '88s',
+        'real',
+        '892',
+        'trade',
+        '89l',
+        'alefsym',
+        '8cg',
+        'larr',
+        '8ch',
+        'uarr',
+        '8ci',
+        'rarr',
+        '8cj',
+        'darr',
+        '8ck',
+        'harr',
+        '8dl',
+        'crarr',
+        '8eg',
+        'lArr',
+        '8eh',
+        'uArr',
+        '8ei',
+        'rArr',
+        '8ej',
+        'dArr',
+        '8ek',
+        'hArr',
+        '8g0',
+        'forall',
+        '8g2',
+        'part',
+        '8g3',
+        'exist',
+        '8g5',
+        'empty',
+        '8g7',
+        'nabla',
+        '8g8',
+        'isin',
+        '8g9',
+        'notin',
+        '8gb',
+        'ni',
+        '8gf',
+        'prod',
+        '8gh',
+        'sum',
+        '8gi',
+        'minus',
+        '8gn',
+        'lowast',
+        '8gq',
+        'radic',
+        '8gt',
+        'prop',
+        '8gu',
+        'infin',
+        '8h0',
+        'ang',
+        '8h7',
+        'and',
+        '8h8',
+        'or',
+        '8h9',
+        'cap',
+        '8ha',
+        'cup',
+        '8hb',
+        'int',
+        '8hk',
+        'there4',
+        '8hs',
+        'sim',
+        '8i5',
+        'cong',
+        '8i8',
+        'asymp',
+        '8j0',
+        'ne',
+        '8j1',
+        'equiv',
+        '8j4',
+        'le',
+        '8j5',
+        'ge',
+        '8k2',
+        'sub',
+        '8k3',
+        'sup',
+        '8k4',
+        'nsub',
+        '8k6',
+        'sube',
+        '8k7',
+        'supe',
+        '8kl',
+        'oplus',
+        '8kn',
+        'otimes',
+        '8l5',
+        'perp',
+        '8m5',
+        'sdot',
+        '8o8',
+        'lceil',
+        '8o9',
+        'rceil',
+        '8oa',
+        'lfloor',
+        '8ob',
+        'rfloor',
+        '8p9',
+        'lang',
+        '8pa',
+        'rang',
+        '9ea',
+        'loz',
+        '9j0',
+        'spades',
+        '9j3',
+        'clubs',
+        '9j5',
+        'hearts',
+        '9j6',
+        'diams',
+        'ai',
+        'OElig',
+        'aj',
+        'oelig',
+        'b0',
+        'Scaron',
+        'b1',
+        'scaron',
+        'bo',
+        'Yuml',
+        'm6',
+        'circ',
+        'ms',
+        'tilde',
+        '802',
+        'ensp',
+        '803',
+        'emsp',
+        '809',
+        'thinsp',
+        '80c',
+        'zwnj',
+        '80d',
+        'zwj',
+        '80e',
+        'lrm',
+        '80f',
+        'rlm',
+        '80j',
+        'ndash',
+        '80k',
+        'mdash',
+        '80o',
+        'lsquo',
+        '80p',
+        'rsquo',
+        '80q',
+        'sbquo',
+        '80s',
+        'ldquo',
+        '80t',
+        'rdquo',
+        '80u',
+        'bdquo',
+        '810',
+        'dagger',
+        '811',
+        'Dagger',
+        '81g',
+        'permil',
+        '81p',
+        'lsaquo',
+        '81q',
+        'rsaquo',
+        '85c',
+        'euro'
+    ],
+
+         
+    /**
+     * Encodes the specified string using raw entities. This means only the required XML base entities will be encoded.
+     *
+     * @method encodeRaw
+     * @param {String} text Text to encode.
+     * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+     * @return {String} Entity encoded text.
+     */
+    encodeRaw: function(text, attr)
+    {
+        var t = this;
+        return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
+            return t.baseEntities[chr] || chr;
+        });
+    },
+    /**
+     * Encoded the specified text with both the attributes and text entities. This function will produce larger text contents
+     * since it doesn't know if the context is within a attribute or text node. This was added for compatibility
+     * and is exposed as the DOMUtils.encode function.
+     *
+     * @method encodeAllRaw
+     * @param {String} text Text to encode.
+     * @return {String} Entity encoded text.
+     */
+    encodeAllRaw: function(text) {
+        var t = this;
+        return ('' + text).replace(this.rawCharsRegExp, function(chr) {
+            return t.baseEntities[chr] || chr;
+        });
+    },
+    /**
+     * Encodes the specified string using numeric entities. The core entities will be
+     * encoded as named ones but all non lower ascii characters will be encoded into numeric entities.
+     *
+     * @method encodeNumeric
+     * @param {String} text Text to encode.
+     * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+     * @return {String} Entity encoded text.
+     */
+    encodeNumeric: function(text, attr) {
+        var t = this;
+        return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
+            // Multi byte sequence convert it to a single entity
+            if (chr.length > 1) {
+                return '&#' + (1024 * (chr.charCodeAt(0) - 55296) + (chr.charCodeAt(1) - 56320) + 65536) + ';';
+            }
+            return t.baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
+        });
+    },
+    /**
+     * Encodes the specified string using named entities. The core entities will be encoded
+     * as named ones but all non lower ascii characters will be encoded into named entities.
+     *
+     * @method encodeNamed
+     * @param {String} text Text to encode.
+     * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+     * @param {Object} entities Optional parameter with entities to use.
+     * @return {String} Entity encoded text.
+     */
+    encodeNamed: function(text, attr, entities) {
+        var t = this;
+        entities = entities || this.namedEntities;
+        return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
+            return t.baseEntities[chr] || entities[chr] || chr;
+        });
+    },
+    /**
+     * Returns an encode function based on the name(s) and it's optional entities.
+     *
+     * @method getEncodeFunc
+     * @param {String} name Comma separated list of encoders for example named,numeric.
+     * @param {String} entities Optional parameter with entities to use instead of the built in set.
+     * @return {function} Encode function to be used.
+     */
+    getEncodeFunc: function(name, entities) {
+        entities = this.buildEntitiesLookup(entities) || this.namedEntities;
+        var t = this;
+        function encodeNamedAndNumeric(text, attr) {
+            return text.replace(attr ? t.attrsCharsRegExp : t.textCharsRegExp, function(chr) {
+                return t.baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr;
+            });
+        }
+
+        function encodeCustomNamed(text, attr) {
+            return t.encodeNamed(text, attr, entities);
+        }
+        // Replace + with , to be compatible with previous TinyMCE versions
+        name = this.makeMap(name.replace(/\+/g, ','));
+        // Named and numeric encoder
+        if (name.named && name.numeric) {
+            return this.encodeNamedAndNumeric;
+        }
+        // Named encoder
+        if (name.named) {
+            // Custom names
+            if (entities) {
+                return encodeCustomNamed;
+            }
+            return this.encodeNamed;
+        }
+        // Numeric
+        if (name.numeric) {
+            return this.encodeNumeric;
+        }
+        // Raw encoder
+        return this.encodeRaw;
+    },
+    /**
+     * Decodes the specified string, this will replace entities with raw UTF characters.
+     *
+     * @method decode
+     * @param {String} text Text to entity decode.
+     * @return {String} Entity decoded string.
+     */
+    decode: function(text)
+    {
+        var  t = this;
+        return text.replace(this.entityRegExp, function(all, numeric) {
+            if (numeric) {
+                numeric = 'x' === numeric.charAt(0).toLowerCase() ? parseInt(numeric.substr(1), 16) : parseInt(numeric, 10);
+                // Support upper UTF
+                if (numeric > 65535) {
+                    numeric -= 65536;
+                    return String.fromCharCode(55296 + (numeric >> 10), 56320 + (1023 & numeric));
+                }
+                return t.asciiMap[numeric] || String.fromCharCode(numeric);
+            }
+            return t.reverseEntities[all] || t.namedEntities[all] || t.nativeDecode(all);
+        });
+    },
+    nativeDecode : function (text) {
+        return text;
+    },
+    makeMap : function (items, delim, map) {
+               var i;
+               items = items || [];
+               delim = delim || ',';
+               if (typeof items == "string") {
+                       items = items.split(delim);
+               }
+               map = map || {};
+               i = items.length;
+               while (i--) {
+                       map[items[i]] = {};
+               }
+               return map;
+       }
+};
+    
+    
+    
+Roo.htmleditor.TidyEntities.init();
+/**
+ * @class Roo.htmleditor.KeyEnter
+ * Handle Enter press..
+ * @cfg {Roo.HtmlEditorCore} core the editor.
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+
+
+
+
+Roo.htmleditor.KeyEnter = function(cfg) {
+    Roo.apply(this, cfg);
+    // this does not actually call walk as it's really just a abstract class
+    Roo.get(this.core.doc.body).on('keypress', this.keypress, this);
+}
+
+//Roo.htmleditor.KeyEnter.i = 0;
+
+
+Roo.htmleditor.KeyEnter.prototype = {
+    
+    core : false,
+    
+    keypress : function(e)
+    {
+        if (e.charCode != 13 && e.charCode != 10) {
+            Roo.log([e.charCode,e]);
+            return true;
+        }
+        e.preventDefault();
+        // https://stackoverflow.com/questions/18552336/prevent-contenteditable-adding-div-on-enter-chrome
+        var doc = this.core.doc;
+          //add a new line
+       
+    
+        var sel = this.core.getSelection();
+        var range = sel.getRangeAt(0);
+        var n = range.commonAncestorContainer;
+        var pc = range.closest([ 'ol', 'ul']);
+        var pli = range.closest('li');
+        if (!pc || e.ctrlKey) {
+            // on it list, or ctrl pressed.
+            if (!e.ctrlKey) {
+                sel.insertNode('br', 'after'); 
+            } else {
+                // only do this if we have ctrl key..
+                var br = doc.createElement('br');
+                br.className = 'clear';
+                br.setAttribute('style', 'clear: both');
+                sel.insertNode(br, 'after'); 
+            }
+            
+         
+            this.core.undoManager.addEvent();
+            this.core.fireEditorEvent(e);
+            return false;
+        }
+        
+        // deal with <li> insetion
+        if (pli.innerText.trim() == '' &&
+            pli.previousSibling &&
+            pli.previousSibling.nodeName == 'LI' &&
+            pli.previousSibling.innerText.trim() ==  '') {
+            pli.parentNode.removeChild(pli.previousSibling);
+            sel.cursorAfter(pc);
+            this.core.undoManager.addEvent();
+            this.core.fireEditorEvent(e);
+            return false;
+        }
+    
+        var li = doc.createElement('LI');
+        li.innerHTML = '&nbsp;';
+        if (!pli || !pli.firstSibling) {
+            pc.appendChild(li);
+        } else {
+            pli.parentNode.insertBefore(li, pli.firstSibling);
+        }
+        sel.cursorText (li.firstChild);
+      
+        this.core.undoManager.addEvent();
+        this.core.fireEditorEvent(e);
+
+        return false;
+        
+    
+        
+        
+         
+    }
+};
+     
+/**
+ * @class Roo.htmleditor.Block
+ * Base class for html editor blocks - do not use it directly .. extend it..
+ * @cfg {DomElement} node The node to apply stuff to.
+ * @cfg {String} friendly_name the name that appears in the context bar about this block
+ * @cfg {Object} Context menu - see Roo.form.HtmlEditor.ToolbarContext
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.Block  = function(cfg)
+{
+    // do nothing .. should not be called really.
+}
+/**
+ * factory method to get the block from an element (using cache if necessary)
+ * @static
+ * @param {HtmlElement} the dom element
+ */
+Roo.htmleditor.Block.factory = function(node)
+{
+    var cc = Roo.htmleditor.Block.cache;
+    var id = Roo.get(node).id;
+    if (typeof(cc[id]) != 'undefined' && (!cc[id].node || cc[id].node.closest('body'))) {
+        Roo.htmleditor.Block.cache[id].readElement(node);
+        return Roo.htmleditor.Block.cache[id];
+    }
+    var db  = node.getAttribute('data-block');
+    if (!db) {
+        db = node.nodeName.toLowerCase().toUpperCaseFirst();
+    }
+    var cls = Roo.htmleditor['Block' + db];
+    if (typeof(cls) == 'undefined') {
+        //Roo.log(node.getAttribute('data-block'));
+        Roo.log("OOps missing block : " + 'Block' + db);
+        return false;
+    }
+    Roo.htmleditor.Block.cache[id] = new cls({ node: node });
+    return Roo.htmleditor.Block.cache[id];  /// should trigger update element
+};
+
+/**
+ * initalize all Elements from content that are 'blockable'
+ * @static
+ * @param the body element
+ */
+Roo.htmleditor.Block.initAll = function(body, type)
+{
+    if (typeof(type) == 'undefined') {
+        var ia = Roo.htmleditor.Block.initAll;
+        ia(body,'table');
+        ia(body,'td');
+        ia(body,'figure');
+        return;
+    }
+    Roo.each(Roo.get(body).query(type), function(e) {
+        Roo.htmleditor.Block.factory(e);    
+    },this);
+};
+// question goes here... do we need to clear out this cache sometimes?
+// or show we make it relivant to the htmleditor.
+Roo.htmleditor.Block.cache = {};
+
+Roo.htmleditor.Block.prototype = {
+    
+    node : false,
+    
+     // used by context menu
+    friendly_name : 'Based Block',
+    
+    // text for button to delete this element
+    deleteTitle : false,
+    
+    context : false,
+    /**
+     * Update a node with values from this object
+     * @param {DomElement} node
+     */
+    updateElement : function(node)
+    {
+        Roo.DomHelper.update(node === undefined ? this.node : node, this.toObject());
+    },
+     /**
+     * convert to plain HTML for calling insertAtCursor..
+     */
+    toHTML : function()
+    {
+        return Roo.DomHelper.markup(this.toObject());
+    },
+    /**
+     * used by readEleemnt to extract data from a node
+     * may need improving as it's pretty basic
+     
+     * @param {DomElement} node
+     * @param {String} tag - tag to find, eg. IMG ?? might be better to use DomQuery ?
+     * @param {String} attribute (use html - for contents, style for using next param as style, or false to return the node)
+     * @param {String} style the style property - eg. text-align
+     */
+    getVal : function(node, tag, attr, style)
+    {
+        var n = node;
+        if (tag !== true && n.tagName != tag.toUpperCase()) {
+            // in theory we could do figure[3] << 3rd figure? or some more complex search..?
+            // but kiss for now.
+            n = node.getElementsByTagName(tag).item(0);
+        }
+        if (!n) {
+            return '';
+        }
+        if (attr === false) {
+            return n;
+        }
+        if (attr == 'html') {
+            return n.innerHTML;
+        }
+        if (attr == 'style') {
+            return n.style[style]; 
+        }
+        
+        return n.hasAttribute(attr) ? n.getAttribute(attr) : '';
+            
+    },
+    /**
+     * create a DomHelper friendly object - for use with 
+     * Roo.DomHelper.markup / overwrite / etc..
+     * (override this)
+     */
+    toObject : function()
+    {
+        return {};
+    },
+      /**
+     * Read a node that has a 'data-block' property - and extract the values from it.
+     * @param {DomElement} node - the node
+     */
+    readElement : function(node)
+    {
+        
+    } 
+    
+    
+};
+
+
+/**
+ * @class Roo.htmleditor.BlockFigure
+ * Block that has an image and a figcaption
+ * @cfg {String} image_src the url for the image
+ * @cfg {String} align (left|right) alignment for the block default left
+ * @cfg {String} caption the text to appear below  (and in the alt tag)
+ * @cfg {String} caption_display (block|none) display or not the caption
+ * @cfg {String|number} image_width the width of the image number or %?
+ * @cfg {String|number} image_height the height of the image number or %?
+ * 
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.BlockFigure = function(cfg)
+{
+    if (cfg.node) {
+        this.readElement(cfg.node);
+        this.updateElement(cfg.node);
+    }
+    Roo.apply(this, cfg);
+}
+Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
+    
+    // setable values.
+    image_src: '',
+    align: 'center',
+    caption : '',
+    caption_display : 'block',
+    width : '100%',
+    cls : '',
+    href: '',
+    video_url : '',
+    
+    // margin: '2%', not used
+    
+    text_align: 'left', //   (left|right) alignment for the text caption default left. - not used at present
+
+    
+    // used by context menu
+    friendly_name : 'Image with caption',
+    deleteTitle : "Delete Image and Caption",
+    
+    contextMenu : function(toolbar)
+    {
+        
+        var block = function() {
+            return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+        };
+        
+        
+        var rooui =  typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+        
+        var syncValue = toolbar.editorcore.syncValue;
+        
+        var fields = {};
+        
+        return [
+             {
+                xtype : 'TextItem',
+                text : "Source: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'Button',
+                text: 'Change Image URL',
+                 
+                listeners : {
+                    click: function (btn, state)
+                    {
+                        var b = block();
+                        
+                        Roo.MessageBox.show({
+                            title : "Image Source URL",
+                            msg : "Enter the url for the image",
+                            buttons: Roo.MessageBox.OKCANCEL,
+                            fn: function(btn, val){
+                                if (btn != 'ok') {
+                                    return;
+                                }
+                                b.image_src = val;
+                                b.updateElement();
+                                syncValue();
+                                toolbar.editorcore.onEditorEvent();
+                            },
+                            minWidth:250,
+                            prompt:true,
+                            //multiline: multiline,
+                            modal : true,
+                            value : b.image_src
+                        });
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+         
+            {
+                xtype : 'Button',
+                text: 'Change Link URL',
+                 
+                listeners : {
+                    click: function (btn, state)
+                    {
+                        var b = block();
+                        
+                        Roo.MessageBox.show({
+                            title : "Link URL",
+                            msg : "Enter the url for the link - leave blank to have no link",
+                            buttons: Roo.MessageBox.OKCANCEL,
+                            fn: function(btn, val){
+                                if (btn != 'ok') {
+                                    return;
+                                }
+                                b.href = val;
+                                b.updateElement();
+                                syncValue();
+                                toolbar.editorcore.onEditorEvent();
+                            },
+                            minWidth:250,
+                            prompt:true,
+                            //multiline: multiline,
+                            modal : true,
+                            value : b.href
+                        });
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            {
+                xtype : 'Button',
+                text: 'Show Video URL',
+                 
+                listeners : {
+                    click: function (btn, state)
+                    {
+                        Roo.MessageBox.alert("Video URL",
+                            block().video_url == '' ? 'This image is not linked ot a video' :
+                                'The image is linked to: <a target="_new" href="' + block().video_url + '">' + block().video_url + '</a>');
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            
+            
+            {
+                xtype : 'TextItem',
+                text : "Width: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'width',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.width = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['100%'],
+                        ['80%'],
+                        ['50%'],
+                        ['20%'],
+                        ['10%']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            {
+                xtype : 'TextItem',
+                text : "Align: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'align',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.align = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['left'],
+                        ['right'],
+                        ['center']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            
+             
+            {
+                xtype : 'Button',
+                text: 'Hide Caption',
+                name : 'caption_display',
+                pressed : false,
+                enableToggle : true,
+                setValue : function(v) {
+                    // this trigger toggle.
+                     
+                    this.setText(v ? "Hide Caption" : "Show Caption");
+                    this.setPressed(v != 'block');
+                },
+                listeners : {
+                    toggle: function (btn, state)
+                    {
+                        var b  = block();
+                        b.caption_display = b.caption_display == 'block' ? 'none' : 'block';
+                        this.setText(b.caption_display == 'block' ? "Hide Caption" : "Show Caption");
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            }
+        ];
+        
+    },
+    /**
+     * create a DomHelper friendly object - for use with
+     * Roo.DomHelper.markup / overwrite / etc..
+     */
+    toObject : function()
+    {
+        var d = document.createElement('div');
+        d.innerHTML = this.caption;
+        
+        var m = this.width != '100%' && this.align == 'center' ? '0 auto' : 0; 
+        
+        var iw = this.align == 'center' ? this.width : '100%';
+        var img =   {
+            tag : 'img',
+            contenteditable : 'false',
+            src : this.image_src,
+            alt : d.innerText.replace(/\n/g, " ").replace(/\s+/g, ' ').trim(), // removeHTML and reduce spaces..
+            style: {
+                width : iw,
+                maxWidth : iw + ' !important', // this is not getting rendered?
+                margin : m  
+                
+            }
+        };
+        /*
+        '<div class="{0}" width="420" height="315" src="{1}" frameborder="0" allowfullscreen>' +
+                    '<a href="{2}">' + 
+                        '<img class="{0}-thumbnail" src="{3}/Images/{4}/{5}#image-{4}" />' + 
+                    '</a>' + 
+                '</div>',
+        */
+                
+        if (this.href.length > 0) {
+            img = {
+                tag : 'a',
+                href: this.href,
+                contenteditable : 'true',
+                cn : [
+                    img
+                ]
+            };
+        }
+        
+        
+        if (this.video_url.length > 0) {
+            img = {
+                tag : 'div',
+                cls : this.cls,
+                frameborder : 0,
+                allowfullscreen : true,
+                width : 420,  // these are for video tricks - that we replace the outer
+                height : 315,
+                src : this.video_url,
+                cn : [
+                    img
+                ]
+            };
+        }
+        // we remove caption totally if its hidden... - will delete data.. but otherwise we end up with fake caption
+        var captionhtml = this.caption_display == 'none' ? '' : (this.caption.length ? this.caption : "Caption");
+        
+  
+        var ret =   {
+            tag: 'figure',
+            'data-block' : 'Figure',
+            'data-width' : this.width, 
+            contenteditable : 'false',
+            
+            style : {
+                display: 'block',
+                float :  this.align ,
+                maxWidth :  this.align == 'center' ? '100% !important' : (this.width + ' !important'),
+                width : this.align == 'center' ? '100%' : this.width,
+                margin:  '0px',
+                padding: this.align == 'center' ? '0' : '0 10px' ,
+                textAlign : this.align   // seems to work for email..
+                
+            },
+           
+            
+            align : this.align,
+            cn : [
+                img,
+              
+                {
+                    tag: 'figcaption',
+                    'data-display' : this.caption_display,
+                    style : {
+                        textAlign : 'left',
+                        fontSize : '16px',
+                        lineHeight : '24px',
+                        display : this.caption_display,
+                        maxWidth : (this.align == 'center' ?  this.width : '100%' ) + ' !important',
+                        margin: m,
+                        width: this.align == 'center' ?  this.width : '100%' 
+                    
+                         
+                    },
+                    cls : this.cls.length > 0 ? (this.cls  + '-thumbnail' ) : '',
+                    cn : [
+                        {
+                            tag: 'div',
+                            style  : {
+                                marginTop : '16px',
+                                textAlign : 'left'
+                            },
+                            align: 'left',
+                            cn : [
+                                {
+                                    // we can not rely on yahoo syndication to use CSS elements - so have to use  '<i>' to encase stuff.
+                                    tag : 'i',
+                                    contenteditable : true,
+                                    html : captionhtml
+                                }
+                                
+                            ]
+                        }
+                        
+                    ]
+                    
+                }
+            ]
+        };
+        return ret;
+         
+    },
+    
+    readElement : function(node)
+    {
+        // this should not really come from the link...
+        this.video_url = this.getVal(node, 'div', 'src');
+        this.cls = this.getVal(node, 'div', 'class');
+        this.href = this.getVal(node, 'a', 'href');
+        
+        
+        this.image_src = this.getVal(node, 'img', 'src');
+         
+        this.align = this.getVal(node, 'figure', 'align');
+        var figcaption = this.getVal(node, 'figcaption', false);
+        if (figcaption !== '') {
+            this.caption = this.getVal(figcaption, 'i', 'html');
+        }
+        
+
+        this.caption_display = this.getVal(node, 'figcaption', 'data-display');
+        //this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
+        this.width = this.getVal(node, true, 'data-width');
+        //this.margin = this.getVal(node, 'figure', 'style', 'margin');
+        
+    },
+    removeNode : function()
+    {
+        return this.node;
+    }
+    
+  
+   
+     
+    
+    
+    
+    
+})
+
+
+/**
+ * @class Roo.htmleditor.BlockTable
+ * Block that manages a table
+ * 
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.BlockTable = function(cfg)
+{
+    if (cfg.node) {
+        this.readElement(cfg.node);
+        this.updateElement(cfg.node);
+    }
+    Roo.apply(this, cfg);
+    if (!cfg.node) {
+        this.rows = [];
+        for(var r = 0; r < this.no_row; r++) {
+            this.rows[r] = [];
+            for(var c = 0; c < this.no_col; c++) {
+                this.rows[r][c] = this.emptyCell();
+            }
+        }
+    }
+    
+    
+}
+Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
+    rows : false,
+    no_col : 1,
+    no_row : 1,
+    
+    
+    width: '100%',
+    
+    // used by context menu
+    friendly_name : 'Table',
+    deleteTitle : 'Delete Table',
+    // context menu is drawn once..
+    
+    contextMenu : function(toolbar)
+    {
+        
+        var block = function() {
+            return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+        };
+        
+        
+        var rooui =  typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+        
+        var syncValue = toolbar.editorcore.syncValue;
+        
+        var fields = {};
+        
+        return [
+            {
+                xtype : 'TextItem',
+                text : "Width: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 100,
+                name : 'width',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.width = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['100%'],
+                        ['auto']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            // -------- Cols
+            
+            {
+                xtype : 'TextItem',
+                text : "Columns: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+         
+            {
+                xtype : 'Button',
+                text: '-',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        block().removeColumn();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            {
+                xtype : 'Button',
+                text: '+',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        block().addColumn();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            // -------- ROWS
+            {
+                xtype : 'TextItem',
+                text : "Rows: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+         
+            {
+                xtype : 'Button',
+                text: '-',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        block().removeRow();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            {
+                xtype : 'Button',
+                text: '+',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        block().addRow();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            // -------- ROWS
+            {
+                xtype : 'Button',
+                text: 'Reset Column Widths',
+                listeners : {
+                    
+                    click : function (_self, e)
+                    {
+                        block().resetWidths();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            } 
+            
+            
+            
+        ];
+        
+    },
+    
+    
+  /**
+     * create a DomHelper friendly object - for use with
+     * Roo.DomHelper.markup / overwrite / etc..
+     * ?? should it be called with option to hide all editing features?
+     */
+    toObject : function()
+    {
+        
+        var ret = {
+            tag : 'table',
+            contenteditable : 'false', // this stops cell selection from picking the table.
+            'data-block' : 'Table',
+            style : {
+                width:  this.width,
+                border : 'solid 1px #000', // ??? hard coded?
+                'border-collapse' : 'collapse' 
+            },
+            cn : [
+                { tag : 'tbody' , cn : [] }
+            ]
+        };
+        
+        // do we have a head = not really 
+        var ncols = 0;
+        Roo.each(this.rows, function( row ) {
+            var tr = {
+                tag: 'tr',
+                style : {
+                    margin: '6px',
+                    border : 'solid 1px #000',
+                    textAlign : 'left' 
+                },
+                cn : [ ]
+            };
+            
+            ret.cn[0].cn.push(tr);
+            // does the row have any properties? ?? height?
+            var nc = 0;
+            Roo.each(row, function( cell ) {
+                
+                var td = {
+                    tag : 'td',
+                    contenteditable :  'true',
+                    'data-block' : 'Td',
+                    html : cell.html,
+                    style : cell.style
+                };
+                if (cell.colspan > 1) {
+                    td.colspan = cell.colspan ;
+                    nc += cell.colspan;
+                } else {
+                    nc++;
+                }
+                if (cell.rowspan > 1) {
+                    td.rowspan = cell.rowspan ;
+                }
+                
+                
+                // widths ?
+                tr.cn.push(td);
+                    
+                
+            }, this);
+            ncols = Math.max(nc, ncols);
+            
+            
+        }, this);
+        // add the header row..
+        
+        ncols++;
+         
+        
+        return ret;
+         
+    },
+    
+    readElement : function(node)
+    {
+        node  = node ? node : this.node ;
+        this.width = this.getVal(node, true, 'style', 'width') || '100%';
+        
+        this.rows = [];
+        this.no_row = 0;
+        var trs = Array.from(node.rows);
+        trs.forEach(function(tr) {
+            var row =  [];
+            this.rows.push(row);
+            
+            this.no_row++;
+            var no_column = 0;
+            Array.from(tr.cells).forEach(function(td) {
+                
+                var add = {
+                    colspan : td.hasAttribute('colspan') ? td.getAttribute('colspan')*1 : 1,
+                    rowspan : td.hasAttribute('rowspan') ? td.getAttribute('rowspan')*1 : 1,
+                    style : td.hasAttribute('style') ? td.getAttribute('style') : '',
+                    html : td.innerHTML
+                };
+                no_column += add.colspan;
+                     
+                
+                row.push(add);
+                
+                
+            },this);
+            this.no_col = Math.max(this.no_col, no_column);
+            
+            
+        },this);
+        
+        
+    },
+    normalizeRows: function()
+    {
+        var ret= [];
+        var rid = -1;
+        this.rows.forEach(function(row) {
+            rid++;
+            ret[rid] = [];
+            row = this.normalizeRow(row);
+            var cid = 0;
+            row.forEach(function(c) {
+                while (typeof(ret[rid][cid]) != 'undefined') {
+                    cid++;
+                }
+                if (typeof(ret[rid]) == 'undefined') {
+                    ret[rid] = [];
+                }
+                ret[rid][cid] = c;
+                c.row = rid;
+                c.col = cid;
+                if (c.rowspan < 2) {
+                    return;
+                }
+                
+                for(var i = 1 ;i < c.rowspan; i++) {
+                    if (typeof(ret[rid+i]) == 'undefined') {
+                        ret[rid+i] = [];
+                    }
+                    ret[rid+i][cid] = c;
+                }
+            });
+        }, this);
+        return ret;
+    
+    },
+    
+    normalizeRow: function(row)
+    {
+        var ret= [];
+        row.forEach(function(c) {
+            if (c.colspan < 2) {
+                ret.push(c);
+                return;
+            }
+            for(var i =0 ;i < c.colspan; i++) {
+                ret.push(c);
+            }
+        });
+        return ret;
+    
+    },
+    
+    deleteColumn : function(sel)
+    {
+        if (!sel || sel.type != 'col') {
+            return;
+        }
+        if (this.no_col < 2) {
+            return;
+        }
+        
+        this.rows.forEach(function(row) {
+            var cols = this.normalizeRow(row);
+            var col = cols[sel.col];
+            if (col.colspan > 1) {
+                col.colspan --;
+            } else {
+                row.remove(col);
+            }
+            
+        }, this);
+        this.no_col--;
+        
+    },
+    removeColumn : function()
+    {
+        this.deleteColumn({
+            type: 'col',
+            col : this.no_col-1
+        });
+        this.updateElement();
+    },
+    
+     
+    addColumn : function()
+    {
+        
+        this.rows.forEach(function(row) {
+            row.push(this.emptyCell());
+           
+        }, this);
+        this.updateElement();
+    },
+    
+    deleteRow : function(sel)
+    {
+        if (!sel || sel.type != 'row') {
+            return;
+        }
+        
+        if (this.no_row < 2) {
+            return;
+        }
+        
+        var rows = this.normalizeRows();
+        
+        
+        rows[sel.row].forEach(function(col) {
+            if (col.rowspan > 1) {
+                col.rowspan--;
+            } else {
+                col.remove = 1; // flage it as removed.
+            }
+            
+        }, this);
+        var newrows = [];
+        this.rows.forEach(function(row) {
+            newrow = [];
+            row.forEach(function(c) {
+                if (typeof(c.remove) == 'undefined') {
+                    newrow.push(c);
+                }
+                
+            });
+            if (newrow.length > 0) {
+                newrows.push(row);
+            }
+        });
+        this.rows =  newrows;
+        
+        
+        
+        this.no_row--;
+        this.updateElement();
+        
+    },
+    removeRow : function()
+    {
+        this.deleteRow({
+            type: 'row',
+            row : this.no_row-1
+        });
+        
+    },
+    
+     
+    addRow : function()
+    {
+        
+        var row = [];
+        for (var i = 0; i < this.no_col; i++ ) {
+            
+            row.push(this.emptyCell());
+           
+        }
+        this.rows.push(row);
+        this.updateElement();
+        
+    },
+     
+    // the default cell object... at present...
+    emptyCell : function() {
+        return (new Roo.htmleditor.BlockTd({})).toObject();
+        
+     
+    },
+    
+    removeNode : function()
+    {
+        return this.node;
+    },
+    
+    
+    
+    resetWidths : function()
+    {
+        Array.from(this.node.getElementsByTagName('td')).forEach(function(n) {
+            var nn = Roo.htmleditor.Block.factory(n);
+            nn.width = '';
+            nn.updateElement(n);
+        });
+    }
+    
+    
+    
+    
+})
+
+/**
+ *
+ * editing a TD?
+ *
+ * since selections really work on the table cell, then editing really should work from there
+ *
+ * The original plan was to support merging etc... - but that may not be needed yet..
+ *
+ * So this simple version will support:
+ *   add/remove cols
+ *   adjust the width +/-
+ *   reset the width...
+ *   
+ *
+ */
+
+
+
+/**
+ * @class Roo.htmleditor.BlockTable
+ * Block that manages a table
+ * 
+ * @constructor
+ * Create a new Filter.
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.BlockTd = function(cfg)
+{
+    if (cfg.node) {
+        this.readElement(cfg.node);
+        this.updateElement(cfg.node);
+    }
+    Roo.apply(this, cfg);
+     
+    
+    
+}
+Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
+    node : false,
+    
+    width: '',
+    textAlign : 'left',
+    valign : 'top',
+    
+    colspan : 1,
+    rowspan : 1,
+    
+    
+    // used by context menu
+    friendly_name : 'Table Cell',
+    deleteTitle : false, // use our customer delete
+    
+    // context menu is drawn once..
+    
+    contextMenu : function(toolbar)
+    {
+        
+        var cell = function() {
+            return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+        };
+        
+        var table = function() {
+            return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode.closest('table'));
+        };
+        
+        var lr = false;
+        var saveSel = function()
+        {
+            lr = toolbar.editorcore.getSelection().getRangeAt(0);
+        }
+        var restoreSel = function()
+        {
+            if (lr) {
+                (function() {
+                    toolbar.editorcore.focus();
+                    var cr = toolbar.editorcore.getSelection();
+                    cr.removeAllRanges();
+                    cr.addRange(lr);
+                    toolbar.editorcore.onEditorEvent();
+                }).defer(10, this);
+                
+                
+            }
+        }
+        
+        var rooui =  typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+        
+        var syncValue = toolbar.editorcore.syncValue;
+        
+        var fields = {};
+        
+        return [
+            {
+                xtype : 'Button',
+                text : 'Edit Table',
+                listeners : {
+                    click : function() {
+                        var t = toolbar.tb.selectedNode.closest('table');
+                        toolbar.editorcore.selectNode(t);
+                        toolbar.editorcore.onEditorEvent();                        
+                    }
+                }
+                
+            },
+              
+           
+             
+            {
+                xtype : 'TextItem',
+                text : "Column Width: ",
+                 xns : rooui.Toolbar 
+               
+            },
+            {
+                xtype : 'Button',
+                text: '-',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        cell().shrinkColumn();
+                        syncValue();
+                         toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            {
+                xtype : 'Button',
+                text: '+',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        cell().growColumn();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            
+            {
+                xtype : 'TextItem',
+                text : "Vertical Align: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 100,
+                name : 'valign',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = cell();
+                        b.valign = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['top'],
+                        ['middle'],
+                        ['bottom'] // there are afew more... 
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            
+            {
+                xtype : 'TextItem',
+                text : "Merge Cells: ",
+                 xns : rooui.Toolbar 
+               
+            },
+            
+            
+            {
+                xtype : 'Button',
+                text: 'Right',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        cell().mergeRight();
+                        //block().growColumn();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+             
+            {
+                xtype : 'Button',
+                text: 'Below',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        cell().mergeBelow();
+                        //block().growColumn();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            {
+                xtype : 'TextItem',
+                text : "| ",
+                 xns : rooui.Toolbar 
+               
+            },
+            
+            {
+                xtype : 'Button',
+                text: 'Split',
+                listeners : {
+                    click : function (_self, e)
+                    {
+                        //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        cell().split();
+                        syncValue();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        toolbar.editorcore.onEditorEvent();
+                                             
+                    }
+                },
+                xns : rooui.Toolbar
+            },
+            {
+                xtype : 'Fill',
+                xns : rooui.Toolbar 
+               
+            },
+        
+          
+            {
+                xtype : 'Button',
+                text: 'Delete',
+                 
+                xns : rooui.Toolbar,
+                menu : {
+                    xtype : 'Menu',
+                    xns : rooui.menu,
+                    items : [
+                        {
+                            xtype : 'Item',
+                            html: 'Column',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    
+                                    cell().deleteColumn();
+                                    syncValue();
+                                    toolbar.editorcore.selectNode(t.node);
+                                    toolbar.editorcore.onEditorEvent();   
+                                }
+                            },
+                            xns : rooui.menu
+                        },
+                        {
+                            xtype : 'Item',
+                            html: 'Row',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    cell().deleteRow();
+                                    syncValue();
+                                    
+                                    toolbar.editorcore.selectNode(t.node);
+                                    toolbar.editorcore.onEditorEvent();   
+                                                         
+                                }
+                            },
+                            xns : rooui.menu
+                        },
+                       {
+                            xtype : 'Separator',
+                            xns : rooui.menu
+                        },
+                        {
+                            xtype : 'Item',
+                            html: 'Table',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    var nn = t.node.nextSibling || t.node.previousSibling;
+                                    t.node.parentNode.removeChild(t.node);
+                                    if (nn) { 
+                                        toolbar.editorcore.selectNode(nn, true);
+                                    }
+                                    toolbar.editorcore.onEditorEvent();   
+                                                         
+                                }
+                            },
+                            xns : rooui.menu
+                        }
+                    ]
+                }
+            }
+            
+            // align... << fixme
+            
+        ];
+        
+    },
+    
+    
+  /**
+     * create a DomHelper friendly object - for use with
+     * Roo.DomHelper.markup / overwrite / etc..
+     * ?? should it be called with option to hide all editing features?
+     */
+ /**
+     * create a DomHelper friendly object - for use with
+     * Roo.DomHelper.markup / overwrite / etc..
+     * ?? should it be called with option to hide all editing features?
+     */
+    toObject : function()
+    {
+        var ret = {
+            tag : 'td',
+            contenteditable : 'true', // this stops cell selection from picking the table.
+            'data-block' : 'Td',
+            valign : this.valign,
+            style : {  
+                'text-align' :  this.textAlign,
+                border : 'solid 1px rgb(0, 0, 0)', // ??? hard coded?
+                'border-collapse' : 'collapse',
+                padding : '6px', // 8 for desktop / 4 for mobile
+                'vertical-align': this.valign
+            },
+            html : this.html
+        };
+        if (this.width != '') {
+            ret.width = this.width;
+            ret.style.width = this.width;
+        }
+        
+        
+        if (this.colspan > 1) {
+            ret.colspan = this.colspan ;
+        } 
+        if (this.rowspan > 1) {
+            ret.rowspan = this.rowspan ;
+        }
+        
+           
+        
+        return ret;
+         
+    },
+    
+    readElement : function(node)
+    {
+        node  = node ? node : this.node ;
+        this.width = node.style.width;
+        this.colspan = Math.max(1,1*node.getAttribute('colspan'));
+        this.rowspan = Math.max(1,1*node.getAttribute('rowspan'));
+        this.html = node.innerHTML;
+        if (node.style.textAlign != '') {
+            this.textAlign = node.style.textAlign;
+        }
+        
+        
+    },
+     
+    // the default cell object... at present...
+    emptyCell : function() {
+        return {
+            colspan :  1,
+            rowspan :  1,
+            textAlign : 'left',
+            html : "&nbsp;" // is this going to be editable now?
+        };
+     
+    },
+    
+    removeNode : function()
+    {
+        return this.node.closest('table');
+         
+    },
+    
+    cellData : false,
+    
+    colWidths : false,
+    
+    toTableArray  : function()
+    {
+        var ret = [];
+        var tab = this.node.closest('tr').closest('table');
+        Array.from(tab.rows).forEach(function(r, ri){
+            ret[ri] = [];
+        });
+        var rn = 0;
+        this.colWidths = [];
+        var all_auto = true;
+        Array.from(tab.rows).forEach(function(r, ri){
+            
+            var cn = 0;
+            Array.from(r.cells).forEach(function(ce, ci){
+                var c =  {
+                    cell : ce,
+                    row : rn,
+                    col: cn,
+                    colspan : ce.colSpan,
+                    rowspan : ce.rowSpan
+                };
+                if (ce.isEqualNode(this.node)) {
+                    this.cellData = c;
+                }
+                // if we have been filled up by a row?
+                if (typeof(ret[rn][cn]) != 'undefined') {
+                    while(typeof(ret[rn][cn]) != 'undefined') {
+                        cn++;
+                    }
+                    c.col = cn;
+                }
+                
+                if (typeof(this.colWidths[cn]) == 'undefined' && c.colspan < 2) {
+                    this.colWidths[cn] =   ce.style.width;
+                    if (this.colWidths[cn] != '') {
+                        all_auto = false;
+                    }
+                }
+                
+                
+                if (c.colspan < 2 && c.rowspan < 2 ) {
+                    ret[rn][cn] = c;
+                    cn++;
+                    return;
+                }
+                for(var j = 0; j < c.rowspan; j++) {
+                    if (typeof(ret[rn+j]) == 'undefined') {
+                        continue; // we have a problem..
+                    }
+                    ret[rn+j][cn] = c;
+                    for(var i = 0; i < c.colspan; i++) {
+                        ret[rn+j][cn+i] = c;
+                    }
+                }
+                
+                cn += c.colspan;
+            }, this);
+            rn++;
+        }, this);
+        
+        // initalize widths.?
+        // either all widths or no widths..
+        if (all_auto) {
+            this.colWidths[0] = false; // no widths flag.
+        }
+        
+        
+        return ret;
+        
+    },
+    
+    
+    
+    
+    mergeRight: function()
+    {
+         
+        // get the contents of the next cell along..
+        var tr = this.node.closest('tr');
+        var i = Array.prototype.indexOf.call(tr.childNodes, this.node);
+        if (i >= tr.childNodes.length - 1) {
+            return; // no cells on right to merge with.
+        }
+        var table = this.toTableArray();
+        
+        if (typeof(table[this.cellData.row][this.cellData.col+this.cellData.colspan]) == 'undefined') {
+            return; // nothing right?
+        }
+        var rc = table[this.cellData.row][this.cellData.col+this.cellData.colspan];
+        // right cell - must be same rowspan and on the same row.
+        if (rc.rowspan != this.cellData.rowspan || rc.row != this.cellData.row) {
+            return; // right hand side is not same rowspan.
+        }
+        
+        
+        
+        this.node.innerHTML += ' ' + rc.cell.innerHTML;
+        tr.removeChild(rc.cell);
+        this.colspan += rc.colspan;
+        this.node.setAttribute('colspan', this.colspan);
+
+        var table = this.toTableArray();
+        this.normalizeWidths(table);
+        this.updateWidths(table);
+    },
+    
+    
+    mergeBelow : function()
+    {
+        var table = this.toTableArray();
+        if (typeof(table[this.cellData.row+this.cellData.rowspan]) == 'undefined') {
+            return; // no row below
+        }
+        if (typeof(table[this.cellData.row+this.cellData.rowspan][this.cellData.col]) == 'undefined') {
+            return; // nothing right?
+        }
+        var rc = table[this.cellData.row+this.cellData.rowspan][this.cellData.col];
+        
+        if (rc.colspan != this.cellData.colspan || rc.col != this.cellData.col) {
+            return; // right hand side is not same rowspan.
+        }
+        this.node.innerHTML =  this.node.innerHTML + rc.cell.innerHTML ;
+        rc.cell.parentNode.removeChild(rc.cell);
+        this.rowspan += rc.rowspan;
+        this.node.setAttribute('rowspan', this.rowspan);
+    },
+    
+    split: function()
+    {
+        if (this.node.rowSpan < 2 && this.node.colSpan < 2) {
+            return;
+        }
+        var table = this.toTableArray();
+        var cd = this.cellData;
+        this.rowspan = 1;
+        this.colspan = 1;
+        
+        for(var r = cd.row; r < cd.row + cd.rowspan; r++) {
+             
+            
+            for(var c = cd.col; c < cd.col + cd.colspan; c++) {
+                if (r == cd.row && c == cd.col) {
+                    this.node.removeAttribute('rowspan');
+                    this.node.removeAttribute('colspan');
+                }
+                 
+                var ntd = this.node.cloneNode(); // which col/row should be 0..
+                ntd.removeAttribute('id'); 
+                ntd.style.width  = this.colWidths[c];
+                ntd.innerHTML = '';
+                table[r][c] = { cell : ntd, col : c, row: r , colspan : 1 , rowspan : 1   };
+            }
+            
+        }
+        this.redrawAllCells(table);
+        
+    },
+    
+    
+    
+    redrawAllCells: function(table)
+    {
+        
+         
+        var tab = this.node.closest('tr').closest('table');
+        var ctr = tab.rows[0].parentNode;
+        Array.from(tab.rows).forEach(function(r, ri){
+            
+            Array.from(r.cells).forEach(function(ce, ci){
+                ce.parentNode.removeChild(ce);
+            });
+            r.parentNode.removeChild(r);
+        });
+        for(var r = 0 ; r < table.length; r++) {
+            var re = tab.rows[r];
+            
+            var re = tab.ownerDocument.createElement('tr');
+            ctr.appendChild(re);
+            for(var c = 0 ; c < table[r].length; c++) {
+                if (table[r][c].cell === false) {
+                    continue;
+                }
+                
+                re.appendChild(table[r][c].cell);
+                 
+                table[r][c].cell = false;
+            }
+        }
+        
+    },
+    updateWidths : function(table)
+    {
+        for(var r = 0 ; r < table.length; r++) {
+           
+            for(var c = 0 ; c < table[r].length; c++) {
+                if (table[r][c].cell === false) {
+                    continue;
+                }
+                
+                if (this.colWidths[0] != false && table[r][c].colspan < 2) {
+                    var el = Roo.htmleditor.Block.factory(table[r][c].cell);
+                    el.width = Math.floor(this.colWidths[c])  +'%';
+                    el.updateElement(el.node);
+                }
+                if (this.colWidths[0] != false && table[r][c].colspan > 1) {
+                    var el = Roo.htmleditor.Block.factory(table[r][c].cell);
+                    var width = 0;
+                    for(var i = 0; i < table[r][c].colspan; i ++) {
+                        width += Math.floor(this.colWidths[c + i]);
+                    }
+                    el.width = width  +'%';
+                    el.updateElement(el.node);
+                }
+                table[r][c].cell = false; // done
+            }
+        }
+    },
+    normalizeWidths : function(table)
+    {
+        if (this.colWidths[0] === false) {
+            var nw = 100.0 / this.colWidths.length;
+            this.colWidths.forEach(function(w,i) {
+                this.colWidths[i] = nw;
+            },this);
+            return;
+        }
+    
+        var t = 0, missing = [];
+        
+        this.colWidths.forEach(function(w,i) {
+            //if you mix % and
+            this.colWidths[i] = this.colWidths[i] == '' ? 0 : (this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;
+            var add =  this.colWidths[i];
+            if (add > 0) {
+                t+=add;
+                return;
+            }
+            missing.push(i);
+            
+            
+        },this);
+        var nc = this.colWidths.length;
+        if (missing.length) {
+            var mult = (nc - missing.length) / (1.0 * nc);
+            var t = mult * t;
+            var ew = (100 -t) / (1.0 * missing.length);
+            this.colWidths.forEach(function(w,i) {
+                if (w > 0) {
+                    this.colWidths[i] = w * mult;
+                    return;
+                }
+                
+                this.colWidths[i] = ew;
+            }, this);
+            // have to make up numbers..
+             
+        }
+        // now we should have all the widths..
+        
+    
+    },
+    
+    shrinkColumn : function()
+    {
+        var table = this.toTableArray();
+        this.normalizeWidths(table);
+        var col = this.cellData.col;
+        var nw = this.colWidths[col] * 0.8;
+        if (nw < 5) {
+            return;
+        }
+        var otherAdd = (this.colWidths[col]  * 0.2) / (this.colWidths.length -1);
+        this.colWidths.forEach(function(w,i) {
+            if (i == col) {
+                 this.colWidths[i] = nw;
+                return;
+            }
+            this.colWidths[i] += otherAdd
+        }, this);
+        this.updateWidths(table);
+         
+    },
+    growColumn : function()
+    {
+        var table = this.toTableArray();
+        this.normalizeWidths(table);
+        var col = this.cellData.col;
+        var nw = this.colWidths[col] * 1.2;
+        if (nw > 90) {
+            return;
+        }
+        var otherSub = (this.colWidths[col]  * 0.2) / (this.colWidths.length -1);
+        this.colWidths.forEach(function(w,i) {
+            if (i == col) {
+                this.colWidths[i] = nw;
+                return;
+            }
+            this.colWidths[i] -= otherSub
+        }, this);
+        this.updateWidths(table);
+         
+    },
+    deleteRow : function()
+    {
+        // delete this rows 'tr'
+        // if any of the cells in this row have a rowspan > 1 && row!= this row..
+        // then reduce the rowspan.
+        var table = this.toTableArray();
+        // this.cellData.row;
+        for (var i =0;i< table[this.cellData.row].length ; i++) {
+            var c = table[this.cellData.row][i];
+            if (c.row != this.cellData.row) {
+                
+                c.rowspan--;
+                c.cell.setAttribute('rowspan', c.rowspan);
+                continue;
+            }
+            if (c.rowspan > 1) {
+                c.rowspan--;
+                c.cell.setAttribute('rowspan', c.rowspan);
+            }
+        }
+        table.splice(this.cellData.row,1);
+        this.redrawAllCells(table);
+        
+    },
+    deleteColumn : function()
+    {
+        var table = this.toTableArray();
+        
+        for (var i =0;i< table.length ; i++) {
+            var c = table[i][this.cellData.col];
+            if (c.col != this.cellData.col) {
+                table[i][this.cellData.col].colspan--;
+            } else if (c.colspan > 1) {
+                c.colspan--;
+                c.cell.setAttribute('colspan', c.colspan);
+            }
+            table[i].splice(this.cellData.col,1);
+        }
+        
+        this.redrawAllCells(table);
+    }
+    
+    
+    
+    
+})
+
+//<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 
+         
+        
+    });
+    
+    // at this point this.owner is set, so we can start working out the whitelisted / blacklisted elements
+    
+    // defaults : white / black...
+    this.applyBlacklists();
+    
+    
+    
+};
+
+
+Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
+
+
+     /**
+     * @cfg {Roo.form.HtmlEditor|Roo.bootstrap.HtmlEditor} the owner field 
+     */
+    
+    owner : false,
+    
+     /**
+     * @cfg {String} css styling for resizing. (used on bootstrap only)
+     */
+    resize : false,
+     /**
+     * @cfg {Number} height (in pixels)
+     */   
+    height: 300,
+   /**
+     * @cfg {Number} width (in pixels)
+     */   
+    width: 500,
+     /**
+     * @cfg {boolean} autoClean - default true - loading and saving will remove quite a bit of formating,
+     *         if you are doing an email editor, this probably needs disabling, it's designed
+     */
+    autoClean: true,
+    
+    /**
+     * @cfg {boolean} enableBlocks - default true - if the block editor (table and figure should be enabled)
+     */
+    enableBlocks : true,
+    /**
+     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
+     * 
+     */
+    stylesheets: false,
+     /**
+     * @cfg {String} language default en - language of text (usefull for rtl languages)
+     * 
+     */
+    language: 'en',
+    
+    /**
+     * @cfg {boolean} allowComments - default false - allow comments in HTML source
+     *          - by default they are stripped - if you are editing email you may need this.
+     */
+    allowComments: 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,
+    
+    // blacklist + whitelisted elements..
+    black: false,
+    white: false,
+     
+    bodyCls : '',
+
+    
+    undoManager : false,
+    /**
+     * 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 = '';
+        
+        // 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 {
+            for (var i in this.stylesheets) {
+                if (typeof(this.stylesheets[i]) != 'string') {
+                    continue;
+                }
+                st += '<link rel="stylesheet" href="' + this.stylesheets[i] +'" type="text/css">';
+            }
+            
+        }
+        
+        st +=  '<style type="text/css">' +
+            'IMG { cursor: pointer } ' +
+        '</style>';
+        
+        st += '<meta name="google" content="notranslate">';
+        
+        var cls = 'notranslate roo-htmleditor-body';
+        
+        if(this.bodyCls.length){
+            cls += ' ' + this.bodyCls;
+        }
+        
+        return '<html  class="notranslate" translate="no"><head>' + st  +
+            //<style type="text/css">' +
+            //'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
+            //'</style>' +
+            ' </head><body contenteditable="true" data-enable-grammerly="true" class="' +  cls + '"></body></html>';
+    },
+
+    // private
+    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;
+        
+        
+        this.el.dom.style.border = '0 none';
+        this.el.dom.setAttribute('tabIndex', -1);
+        this.el.addClass('x-hidden hide');
+        
+        
+        
+        if(Roo.isIE){ // fix IE 1px bogus margin
+            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
+        }
+       
+        
+        this.frameId = Roo.id();
+        
+        var ifcfg = {
+            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"
+        };
+        if (this.resize) {
+            ifcfg.style = { resize : this.resize };
+        }
+        
+        var iframe = this.owner.wrap.createChild(ifcfg, this.el); 
+        
+        
+        this.iframe = iframe.dom;
+
+        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);
+
+    },
+
+    // private
+    onResize : function(w, h)
+    {
+         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';
+            }
+        }
+        
+    },
+
+    /**
+     * 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;
+        
+        if(this.sourceEditMode){
+            Roo.get(this.iframe).addClass(['x-hidden','hide', 'd-none']);     //FIXME - what's the BS styles for these
+            
+        }else{
+            Roo.get(this.iframe).removeClass(['x-hidden','hide', 'd-none']);
+            //this.iframe.className = '';
+            this.deferFocus();
+        }
+        //this.setSize(this.owner.wrap.getSize());
+        //this.fireEvent('editmodechange', this, this.sourceEditMode);
+    },
+
+    
+  
+
+    /**
+     * 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()
+    {
+        //Roo.log("HtmlEditorCore:syncValue (EDITOR->TEXT)");
+        if(this.initialized){
+            
+            if (this.undoManager) {
+                this.undoManager.addEvent();
+            }
+
+            
+            var bd = (this.doc.body || this.doc.documentElement);
+           
+            
+            var sel = this.win.getSelection();
+            
+            var div = document.createElement('div');
+            div.innerHTML = bd.innerHTML;
+            var gtx = div.getElementsByClassName('gtx-trans-icon'); // google translate - really annoying and difficult to get rid of.
+            if (gtx.length > 0) {
+                var rm = gtx.item(0).parentNode;
+                rm.parentNode.removeChild(rm);
+            }
+            
+           
+            if (this.enableBlocks) {
+                new Roo.htmleditor.FilterBlock({ node : div });
+            }
+            
+            var html = div.innerHTML;
+            
+            //?? tidy?
+            if (this.autoClean) {
+                
+                new Roo.htmleditor.FilterAttributes({
+                    node : div,
+                    attrib_white : [
+                            'href',
+                            'src',
+                            'name',
+                            'align',
+                            'colspan',
+                            'rowspan',
+                            'data-display',
+                            'data-width',
+                            'start' ,
+                            'style',
+                            // youtube embed.
+                            'class',
+                            'allowfullscreen',
+                            'frameborder',
+                            'width',
+                            'height',
+                            'alt'
+                            ],
+                    attrib_clean : ['href', 'src' ] 
+                });
+                
+                var tidy = new Roo.htmleditor.TidySerializer({
+                    inner:  true
+                });
+                html  = tidy.serialize(div);
+                
+            }
+            
+            
+            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(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0080-\uFFFF]/g, function(match) {
+                
+                var cc = match.charCodeAt();
 
                 // Get the character value, handling surrogate pairs
                 if (match.length == 2) {
@@ -25869,24 +31233,41 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     },
 
     /**
+     * TEXTAREA -> EDITABLE
      * Protected method that will not generally be called directly. Pushes the value of the textarea
      * into the iframe editor.
      */
-    pushValue : function(){
+    pushValue : function()
+    {
+        //Roo.log("HtmlEditorCore:pushValue (TEXT->EDITOR)");
         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);
             }
+            if (this.autoClean) {
+                new Roo.htmleditor.FilterParagraph({node : this.doc.body}); // paragraphs
+                new Roo.htmleditor.FilterSpan({node : this.doc.body}); // empty spans
+            }
+            if (this.enableBlocks) {
+                Roo.htmleditor.Block.initAll(this.doc.body);
+            }
+            
+            this.updateLanguage();
+            
+            var lc = this.doc.body.lastChild;
+            if (lc && lc.nodeType == 1 && lc.getAttribute("contenteditable") == "false") {
+                // add an extra line at the end.
+                this.doc.body.appendChild(this.doc.createElement('br'));
+            }
+            
+            
         }
     },
 
@@ -25948,28 +31329,182 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         //var ss = this.el.getStyles( 'background-image', 'background-repeat');
         //ss['background-attachment'] = 'fixed'; // w3c
         dbody.bgProperties = 'fixed'; // ie
+        dbody.setAttribute("translate", "no");
+        
         //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
         });
+        Roo.EventManager.on(this.doc, {
+            'paste': this.onPasteEvent,
+            scope : this
+        });
         if(Roo.isGecko){
             Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
         }
+        //??? needed???
         if(Roo.isIE || Roo.isSafari || Roo.isOpera){
             Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
         }
         this.initialized = true;
 
+        
+        // initialize special key events - enter
+        new Roo.htmleditor.KeyEnter({core : this});
+        
+         
+        
         this.owner.fireEvent('initialize', this);
         this.pushValue();
     },
-
+    // this is to prevent a href clicks resulting in a redirect?
+   
+    onPasteEvent : function(e,v)
+    {
+        // I think we better assume paste is going to be a dirty load of rubish from word..
+        
+        // even pasting into a 'email version' of this widget will have to clean up that mess.
+        var cd = (e.browserEvent.clipboardData || window.clipboardData);
+        
+        // check what type of paste - if it's an image, then handle it differently.
+        if (cd.files && cd.files.length > 0) {
+            // pasting images?
+            var urlAPI = (window.createObjectURL && window) || 
+                (window.URL && URL.revokeObjectURL && URL) || 
+                (window.webkitURL && webkitURL);
+            
+            var r = new FileReader();
+            var t = this;
+            r.addEventListener('load',function()
+            {
+                
+                var d = (new DOMParser().parseFromString('<img src="' + r.result+ '">', 'text/html')).body;
+                // is insert asycn?
+                if (t.enableBlocks) {
+                    
+                    Array.from(d.getElementsByTagName('img')).forEach(function(img) {
+                        if (img.closest('figure')) { // assume!! that it's aready
+                            return;
+                        }
+                        var fig  = new Roo.htmleditor.BlockFigure({
+                            image_src  : img.src
+                        });
+                        fig.updateElement(img); // replace it..
+                        
+                    });
+                }
+                t.insertAtCursor(d.innerHTML.replace(/&nbsp;/g,' '));
+                t.owner.fireEvent('paste', this);
+            });
+            r.readAsDataURL(cd.files[0]);
+            
+            e.preventDefault();
+            
+            return false;
+        }
+        if (cd.types.indexOf('text/html') < 0 ) {
+            return false;
+        }
+        var images = [];
+        var html = cd.getData('text/html'); // clipboard event
+        if (cd.types.indexOf('text/rtf') > -1) {
+            var parser = new Roo.rtf.Parser(cd.getData('text/rtf'));
+            images = parser.doc ? parser.doc.getElementsByType('pict') : [];
+        }
+        //Roo.log(images);
+        //Roo.log(imgs);
+        // fixme..
+        images = images.filter(function(g) { return !g.path.match(/^rtf\/(head|pgdsctbl|listtable|footerf)/); }) // ignore headers/footers etc.
+                       .map(function(g) { return g.toDataURL(); })
+                       .filter(function(g) { return g != 'about:blank'; });
+        
+        //Roo.log(html);
+        html = this.cleanWordChars(html);
+        
+        var d = (new DOMParser().parseFromString(html, 'text/html')).body;
+        
+        
+        var sn = this.getParentElement();
+        // check if d contains a table, and prevent nesting??
+        //Roo.log(d.getElementsByTagName('table'));
+        //Roo.log(sn);
+        //Roo.log(sn.closest('table'));
+        if (d.getElementsByTagName('table').length && sn && sn.closest('table')) {
+            e.preventDefault();
+            this.insertAtCursor("You can not nest tables");
+            //Roo.log("prevent?"); // fixme - 
+            return false;
+        }
+        
+        
+        
+        if (images.length > 0) {
+            // replace all v:imagedata - with img.
+            var ar = Array.from(d.getElementsByTagName('v:imagedata'));
+            Roo.each(ar, function(node) {
+                node.parentNode.insertBefore(d.ownerDocument.createElement('img'), node );
+                node.parentNode.removeChild(node);
+            });
+            
+            
+            Roo.each(d.getElementsByTagName('img'), function(img, i) {
+                img.setAttribute('src', images[i]);
+            });
+        }
+        if (this.autoClean) {
+            new Roo.htmleditor.FilterWord({ node : d });
+            
+            new Roo.htmleditor.FilterStyleToTag({ node : d });
+            new Roo.htmleditor.FilterAttributes({
+                node : d,
+                attrib_white : ['href', 'src', 'name', 'align', 'colspan', 'rowspan', 'data-display', 'data-width', 'start'],
+                attrib_clean : ['href', 'src' ] 
+            });
+            new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
+            // should be fonts..
+            new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT', ':' ]} );
+            new Roo.htmleditor.FilterParagraph({ node : d });
+            new Roo.htmleditor.FilterSpan({ node : d });
+            new Roo.htmleditor.FilterLongBr({ node : d });
+            new Roo.htmleditor.FilterComment({ node : d });
+            
+            
+        }
+        if (this.enableBlocks) {
+                
+            Array.from(d.getElementsByTagName('img')).forEach(function(img) {
+                if (img.closest('figure')) { // assume!! that it's aready
+                    return;
+                }
+                var fig  = new Roo.htmleditor.BlockFigure({
+                    image_src  : img.src
+                });
+                fig.updateElement(img); // replace it..
+                
+            });
+        }
+        
+        
+        this.insertAtCursor(d.innerHTML.replace(/&nbsp;/g,' '));
+        if (this.enableBlocks) {
+            Roo.htmleditor.Block.initAll(this.doc.body);
+        }
+         
+        
+        e.preventDefault();
+        this.owner.fireEvent('paste', this);
+        return false;
+        // default behaveiour should be our local cleanup paste? (optional?)
+        // for simple editor - we want to hammer the paste and get rid of everything... - so over-rideable..
+        //this.owner.fireEvent('paste', e, v);
+    },
     // private
     onDestroy : function(){
         
@@ -25991,7 +31526,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     onFirstFocus : function(){
         
         this.assignDocWin();
-        
+        this.undoManager = new Roo.lib.UndoManager(100,(this.doc.body || this.doc.documentElement));
         
         this.activated = true;
          
@@ -26036,10 +31571,50 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
     onEditorEvent : function(e)
     {
-        this.owner.fireEvent('editorevent', this, e);
+         
+        
+        if (e && (e.ctrlKey || e.metaKey) && e.keyCode === 90) {
+            return; // we do not handle this.. (undo manager does..)
+        }
+        // clicking a 'block'?
+        
+        // in theory this detects if the last element is not a br, then we try and do that.
+        // its so clicking in space at bottom triggers adding a br and moving the cursor.
+        if (e &&
+            e.target.nodeName == 'BODY' &&
+            e.type == "mouseup" &&
+            this.doc.body.lastChild
+           ) {
+            var lc = this.doc.body.lastChild;
+            // gtx-trans is google translate plugin adding crap.
+            while ((lc.nodeType == 3 && lc.nodeValue == '') || lc.id == 'gtx-trans') {
+                lc = lc.previousSibling;
+            }
+            if (lc.nodeType == 1 && lc.nodeName != 'BR') {
+            // if last element is <BR> - then dont do anything.
+            
+                var ns = this.doc.createElement('br');
+                this.doc.body.appendChild(ns);
+                range = this.doc.createRange();
+                range.setStartAfter(ns);
+                range.collapse(true);
+                var sel = this.win.getSelection();
+                sel.removeAllRanges();
+                sel.addRange(range);
+            }
+        }
+        
+        
+        
+        this.fireEditorEvent(e);
       //  this.updateToolbar();
         this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
     },
+    
+    fireEditorEvent: function(e)
+    {
+        this.owner.fireEvent('editorevent', this, e);
+    },
 
     insertTag : function(tg)
     {
@@ -26061,7 +31636,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             
         }
         this.execCmd("formatblock",   tg);
-        
+        this.undoManager.addEvent(); 
     },
     
     insertText : function(txt)
@@ -26073,6 +31648,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                //alert(Sender.getAttribute('label'));
                
         range.insertNode(this.doc.createTextNode(txt));
+        this.undoManager.addEvent();
     } ,
     
      
@@ -26083,7 +31659,38 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
      * @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){
+    relayCmd : function(cmd, value)
+    {
+        
+        switch (cmd) {
+            case 'justifyleft':
+            case 'justifyright':
+            case 'justifycenter':
+                // if we are in a cell, then we will adjust the
+                var n = this.getParentElement();
+                var td = n.closest('td');
+                if (td) {
+                    var bl = Roo.htmleditor.Block.factory(td);
+                    bl.textAlign = cmd.replace('justify','');
+                    bl.updateElement();
+                    this.owner.fireEvent('editorevent', this);
+                    return;
+                }
+                this.execCmd('styleWithCSS', true); // 
+                break;
+            case 'bold':
+            case 'italic':
+            case 'underline':                
+                // if there is no selection, then we insert, and set the curson inside it..
+                this.execCmd('styleWithCSS', false); 
+                break;
+                
+        
+            default:
+                break;
+        }
+        
+        
         this.win.focus();
         this.execCmd(cmd, value);
         this.owner.fireEvent('editorevent', this);
@@ -26116,20 +31723,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         if(!this.activated){
             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();
-            
-            }
-            return;
-        }
-        */
+         
         if(Roo.isGecko || Roo.isOpera || Roo.isSafari){
             this.win.focus();
             
@@ -26139,19 +31733,31 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             var win = this.win;
             
             if (win.getSelection && win.getSelection().getRangeAt) {
+                
+                // delete the existing?
+                
+                this.createRange(this.getSelection()).deleteContents();
                 range = win.getSelection().getRangeAt(0);
                 node = typeof(text) == 'string' ? range.createContextualFragment(text) : text;
                 range.insertNode(node);
+                range = range.cloneRange();
+                range.collapse(false);
+                 
+                win.getSelection().removeAllRanges();
+                win.getSelection().addRange(range);
+                
+                
+                
             } 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();
@@ -26176,15 +31782,17 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                         cmd = 'underline';
                         break;
                     
-                    case 'v':
-                        this.cleanUpPaste.defer(100, this);
-                        return;
+                    //case 'v':
+                      //  this.cleanUpPaste.defer(100, this);
+                      //  return;
                         
                 }
                 if(cmd){
-                    this.win.focus();
-                    this.execCmd(cmd);
-                    this.deferFocus();
+                    
+                    this.relayCmd(cmd);
+                    //this.win.focus();
+                    //this.execCmd(cmd);
+                    //this.deferFocus();
                     e.preventDefault();
                 }
                 
@@ -26194,6 +31802,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
     // private
     fixKeys : function(){ // load time branching for fastest keydown performance
+        
+        
         if(Roo.isIE){
             return function(e){
                 var k = e.getKey(), r;
@@ -26207,23 +31817,25 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                     }
                     return;
                 }
-                
+                /// this is handled by Roo.htmleditor.KeyEnter
+                 /*
                 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.pasteHTML('<br/>');
                             r.collapse(false);
                             r.select();
                         }
                     }
                 }
-                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
+                */
+                //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                //    this.cleanUpPaste.defer(100, this);
+                //    return;
+                //}
                 
                 
             };
@@ -26236,10 +31848,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                     this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
                     this.deferFocus();
                 }
-                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
+               
+                //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                //    this.cleanUpPaste.defer(100, this);
+                 //   return;
+                //}
                 
             };
         }else if(Roo.isSafari){
@@ -26252,10 +31865,12 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                     this.deferFocus();
                     return;
                 }
-               if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
+                 this.mozKeyPress(e);
+                
+               //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                 //   this.cleanUpPaste.defer(100, this);
+                 //   return;
+               // }
                 
              };
         }
@@ -26285,7 +31900,27 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     getSelection : function() 
     {
         this.assignDocWin();
-        return Roo.isIE ? this.doc.selection : this.win.getSelection();
+        return Roo.lib.Selection.wrap(Roo.isIE ? this.doc.selection : this.win.getSelection(), this.doc);
+    },
+    /**
+     * Select a dom node
+     * @param {DomElement} node the node to select
+     */
+    selectNode : function(node, collapse)
+    {
+        var nodeRange = node.ownerDocument.createRange();
+        try {
+            nodeRange.selectNode(node);
+        } catch (e) {
+            nodeRange.selectNodeContents(node);
+        }
+        if (collapse === true) {
+            nodeRange.collapse(true);
+        }
+        //
+        var s = this.win.getSelection();
+        s.removeAllRanges();
+        s.addRange(nodeRange);
     },
     
     getSelectedNode: function() 
@@ -26294,8 +31929,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         // should we cache this!!!!
         
-        
-        
+         
          
         var range = this.createRange(this.getSelection()).cloneRange();
         
@@ -26359,6 +31993,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         return nodes[0];
     },
+    
+    
     createRange: function(sel)
     {
         // this has strange effects when using with 
@@ -26476,26 +32112,21 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         // 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;
-        }
-        
-    },
-    
     cleanWordChars : function(input) {// change the chars to hex code
-        var he = Roo.HtmlEditorCore;
         
+       var swapCodes  = [ 
+            [    8211, "&#8211;" ], 
+            [    8212, "&#8212;" ], 
+            [    8216,  "'" ],  
+            [    8217, "'" ],  
+            [    8220, '"' ],  
+            [    8221, '"' ],  
+            [    8226, "*" ],  
+            [    8230, "..." ]
+        ]; 
         var output = input;
-        Roo.each(he.swapCodes, function(sw) { 
+        Roo.each(swapCodes, function(sw) { 
             var swapper = new RegExp("\\u" + sw[0].toString(16), "g"); // hex codes
             
             output = output.replace(swapper, sw[1]);
@@ -26504,487 +32135,61 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         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]);
-        }
-    },
-    
+     
     
         
     
     cleanUpChild : function (node)
     {
-        var ed = this;
-        //console.log(node);
-        if (node.nodeName == "#text") {
-            // clean up silly Windows -- stuff?
-            return; 
-        }
-        if (node.nodeName == "#comment") {
-            if (!this.allowComments) {
-                node.parentNode.removeChild(node);
-            }
-            // clean up silly Windows -- stuff?
-            return; 
-        }
-        var lcname = node.tagName.toLowerCase();
-        // we ignore whitelists... ?? = not really the way to go, but we probably have not got a full
-        // whitelist of tags..
-        
-        if (this.black.indexOf(lcname) > -1 && this.clearUp ) {
-            // remove node.
-            node.parentNode.removeChild(node);
-            return;
-            
-        }
-        
-        var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
-        
-        // spans with no attributes - just remove them..
-        if ((!node.attributes || !node.attributes.length) && lcname == 'span') { 
-            remove_keep_children = true;
-        }
-        
-        // remove <a name=....> as rendering on yahoo mailer is borked with this.
-        // this will have to be flaged elsewhere - perhaps ablack=name... on the mailer..
-        
-        //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:/) || v.match(/^ftp:/)) {
-                return;
-            }
-            if (v.match(/^#/)) {
-                return;
-            }
-            if (v.match(/^\{/)) { // allow template editing.
-                return;
-            }
-//            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
-            node.removeAttribute(n);
-            
-        }
-        
-        var cwhite = this.cwhite;
-        var cblack = this.cblack;
-            
-        function cleanStyle(n,v)
-        {
-            if (v.match(/expression/)) { //XSS?? should we even bother..
-                node.removeAttribute(n);
-                return;
-            }
-            
-            var 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 ( cwhite.length && 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.removeAttribute('class');
-                }
-                
-                if (a.value.match(/^body$/)) {
-                    node.removeAttribute('class');
-                }
-                continue;
-            }
-            
-            // style cleanup!?
-            // class cleanup?
-            
-        }
-        
-        
-        this.cleanUpChildren(node);
         
+        new Roo.htmleditor.FilterComment({node : node});
+        new Roo.htmleditor.FilterAttributes({
+                node : node,
+                attrib_black : this.ablack,
+                attrib_clean : this.aclean,
+                style_white : this.cwhite,
+                style_black : this.cblack
+        });
+        new Roo.htmleditor.FilterBlack({ node : node, tag : this.black});
+        new Roo.htmleditor.FilterKeepChildren({node : node, tag : this.tag_remove} );
+         
         
     },
     
     /**
      * Clean up MS wordisms...
+     * @deprecated - use filter directly
      */
     cleanWord : function(node)
     {
-        if (!node) {
-            this.cleanWord(this.doc.body);
-            return;
-        }
-        
-        if(
-                node.nodeName == 'SPAN' &&
-                !node.hasAttributes() &&
-                node.childNodes.length == 1 &&
-                node.firstChild.nodeName == "#text"  
-        ) {
-            var textNode = node.firstChild;
-            node.removeChild(textNode);
-            if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
-                node.parentNode.insertBefore(node.ownerDocument.createTextNode(" "), node);
-            }
-            node.parentNode.insertBefore(textNode, node);
-            if (node.getAttribute('lang') != 'zh-CN') {   // do not space pad on chinese characters..
-                node.parentNode.insertBefore(node.ownerDocument.createTextNode(" ") , node);
-            }
-            node.parentNode.removeChild(node);
-        }
-        
-        if (node.nodeName == "#text") {
-            // clean up silly Windows -- stuff?
-            return; 
-        }
-        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;
-        }
-        //Roo.log(node.tagName);
-        // remove - but keep children..
-        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)) {
-            //Roo.log('-- removed');
-            while (node.childNodes.length) {
-                var cn = node.childNodes[0];
-                node.removeChild(cn);
-                node.parentNode.insertBefore(cn, node);
-                // move node to parent - and clean it..
-                this.cleanWord(cn);
-            }
-            node.parentNode.removeChild(node);
-            /// no need to iterate chidlren = it's got none..
-            //this.iterateChildren(node, this.cleanWord);
-            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");
-            }
-        }
-        
-        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(/:/)) {
-                    return;
-                }
-                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');
-            }
-        }
-        this.iterateChildren(node, this.cleanWord);
-        
-        
+        new Roo.htmleditor.FilterWord({ node : node ? node : this.doc.body });
+        new Roo.htmleditor.FilterKeepChildren({node : node ? node : this.doc.body, tag : [ 'FONT', ':' ]} );
         
     },
-    /**
-     * iterateChildren of a Node, calling fn each time, using this as the scole..
-     * @param {DomNode} node node to iterate children of.
-     * @param {Function} fn method of this class to call on each item.
-     */
-    iterateChildren : function(node, fn)
-    {
-        if (!node.childNodes.length) {
-                return;
-        }
-        for (var i = node.childNodes.length-1; i > -1 ; i--) {
-           fn.call(this, node.childNodes[i])
-        }
-    },
-    
+   
     
     /**
-     * cleanTableWidths.
-     *
-     * Quite often pasting from word etc.. results in tables with column and widths.
-     * This does not work well on fluid HTML layouts - like emails. - so this code should hunt an destroy them..
-     *
+
+     * @deprecated - use filters
      */
     cleanTableWidths : function(node)
     {
-         
-         
-        if (!node) {
-            this.cleanTableWidths(this.doc.body);
-            return;
-        }
-        
-        // ignore list...
-        if (node.nodeName == "#text" || node.nodeName == "#comment") {
-            return; 
-        }
-        Roo.log(node.tagName);
-        if (!node.tagName.toLowerCase().match(/^(table|td|tr)$/)) {
-            this.iterateChildren(node, this.cleanTableWidths);
-            return;
-        }
-        if (node.hasAttribute('width')) {
-            node.removeAttribute('width');
-        }
-        
-         
-        if (node.hasAttribute("style")) {
-            // pretty basic...
-            
-            var styles = node.getAttribute("style").split(";");
-            var nstyle = [];
-            Roo.each(styles, function(s) {
-                if (!s.match(/:/)) {
-                    return;
-                }
-                var kv = s.split(":");
-                if (kv[0].match(/^\s*(width|min-width)\s*$/)) {
-                    return;
-                }
-                // what ever is left... we allow.
-                nstyle.push(s);
-            });
-            node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
-            if (!nstyle.length) {
-                node.removeAttribute('style');
-            }
-        }
-        
-        this.iterateChildren(node, this.cleanTableWidths);
-        
+        new Roo.htmleditor.FilterTableWidth({ node : node ? node : this.doc.body});
         
     },
     
-    
-    
-    
-    domToHTML : function(currentElement, depth, nopadtext) {
-        
-        depth = depth || 0;
-        nopadtext = nopadtext || false;
-    
-        if (!currentElement) {
-            return this.domToHTML(this.doc.body);
-        }
-        
-        //Roo.log(currentElement);
-        var j;
-        var allText = false;
-        var nodeName = currentElement.nodeName;
-        var tagName = Roo.util.Format.htmlEncode(currentElement.tagName);
-        
-        if  (nodeName == '#text') {
-            
-            return nopadtext ? currentElement.nodeValue : currentElement.nodeValue.trim();
-        }
-        
-        
-        var ret = '';
-        if (nodeName != 'BODY') {
-             
-            var i = 0;
-            // Prints the node tagName, such as <A>, <IMG>, etc
-            if (tagName) {
-                var attr = [];
-                for(i = 0; i < currentElement.attributes.length;i++) {
-                    // quoting?
-                    var aname = currentElement.attributes.item(i).name;
-                    if (!currentElement.attributes.item(i).value.length) {
-                        continue;
-                    }
-                    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);
-                toadd = nopadtext ? toadd : toadd.trim();
-                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;
-        
-    },
+     
         
     applyBlacklists : function()
     {
         var w = typeof(this.owner.white) != 'undefined' && this.owner.white ? this.owner.white  : [];
         var b = typeof(this.owner.black) != 'undefined' && this.owner.black ? this.owner.black :  [];
         
+        this.aclean = typeof(this.owner.aclean) != 'undefined' && this.owner.aclean ? this.owner.aclean :  Roo.HtmlEditorCore.aclean;
+        this.ablack = typeof(this.owner.ablack) != 'undefined' && this.owner.ablack ? this.owner.ablack :  Roo.HtmlEditorCore.ablack;
+        this.tag_remove = typeof(this.owner.tag_remove) != 'undefined' && this.owner.tag_remove ? this.owner.tag_remove :  Roo.HtmlEditorCore.tag_remove;
+        
         this.white = [];
         this.black = [];
         Roo.each(Roo.HtmlEditorCore.white, function(tag) {
@@ -27102,6 +32307,16 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
     },
     
+    
+    updateLanguage : function()
+    {
+        if (!this.iframe || !this.iframe.contentDocument) {
+            return;
+        }
+        Roo.get(this.iframe.contentDocument.body).attr("lang", this.language);
+    },
+    
+    
     removeStylesheets : function()
     {
         var _this = this;
@@ -27166,36 +32381,40 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 });
 
 Roo.HtmlEditorCore.white = [
-        'area', 'br', 'img', 'input', 'hr', 'wbr',
+        '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', 
+       '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', 
+       'CAPTION', 'COL', 'COLGROUP', 'TBODY', 'TD', 'TFOOT', 'TH', 
+      'THEAD',   'TR', 
      
-      'dir', 'menu', 'ol', 'ul', 'dl',
+      'DIR', 'MENU', 'OL', 'UL', 'DL',
        
-      'embed',  'object'
+      '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..
+        'APPLET', // 
+        'BASE',   'BASEFONT', 'BGSOUND', 'BLINK',  'BODY', 
+        'FRAME',  'FRAMESET', 'HEAD',    'HTML',   'ILAYER', 
+        'IFRAME', 'LAYER',  'LINK',     'META',    'OBJECT',   
+        'SCRIPT', 'STYLE' ,'TITLE',  'XML',
+        //'FONT' // CLEAN LATER..
+        'COLGROUP', 'COL'   // messy tables.
+        
+        
 ];
-Roo.HtmlEditorCore.clean = [
-    'script', 'style', 'title', 'xml'
+Roo.HtmlEditorCore.clean = [ // ?? needed???
+     'SCRIPT', 'STYLE', 'TITLE', 'XML'
 ];
-Roo.HtmlEditorCore.remove = [
-    'font'
+Roo.HtmlEditorCore.tag_remove = [
+    'FONT', 'TBODY'  
 ];
 // attributes..
 
@@ -27226,16 +32445,7 @@ Roo.HtmlEditorCore.cblack= [
 ];
 
 
-Roo.HtmlEditorCore.swapCodes   =[ 
-    [    8211, "&#8211;" ], 
-    [    8212, "&#8212;" ], 
-    [    8216,  "'" ],  
-    [    8217, "'" ],  
-    [    8220, '"' ],  
-    [    8221, '"' ],  
-    [    8226, "*" ],  
-    [    8230, "..." ]
-]; 
+
 
     /*
  * - LGPL
@@ -27245,8 +32455,8 @@ Roo.HtmlEditorCore.swapCodes   =[
  */
 
 /**
- * @class Roo.bootstrap.HtmlEditor
- * @extends Roo.bootstrap.TextArea
+ * @class Roo.bootstrap.form.HtmlEditor
+ * @extends Roo.bootstrap.form.TextArea
  * Bootstrap HtmlEditor class
 
  * @constructor
@@ -27254,8 +32464,8 @@ Roo.HtmlEditorCore.swapCodes   =[
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.HtmlEditor = function(config){
-    Roo.bootstrap.HtmlEditor.superclass.constructor.call(this, config);
+Roo.bootstrap.form.HtmlEditor = function(config){
+    Roo.bootstrap.form.HtmlEditor.superclass.constructor.call(this, config);
     if (!this.toolbars) {
         this.toolbars = [];
     }
@@ -27340,13 +32550,13 @@ Roo.bootstrap.HtmlEditor = function(config){
 };
 
 
-Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
+Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea,  {
     
     
       /**
-     * @cfg {Array} toolbars Array of toolbars. - defaults to just the Standard one
+     * @cfg {Array|boolean} toolbars Array of toolbars, or names of toolbars. - true for standard, and false for none.
      */
-    toolbars : false,
+    toolbars : true,
     
      /**
     * @cfg {Array} buttons Array of toolbar's buttons. - defaults to empty
@@ -27354,10 +32564,9 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
     btns : [],
    
      /**
-     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
-     *                        Roo.resizable.
+     * @cfg {String} resize  (none|both|horizontal|vertical) - css resize of element
      */
-    resizable : false,
+    resize : false,
      /**
      * @cfg {Number} height (in pixels)
      */   
@@ -27400,26 +32609,35 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
      * add custom toolbar buttons.
      * @param {HtmlEditor} editor
      */
-    createToolbar : function(){
-        Roo.log('renewing');
-        Roo.log("create toolbars");
+    createToolbar : function()
+    {
+        //Roo.log('renewing');
+        //Roo.log("create toolbars");
+        if (this.toolbars === false) {
+            return;
+        }
+        if (this.toolbars === true) {
+            this.toolbars = [ 'Standard' ];
+        }
         
-        this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
-        this.toolbars[0].render(this.toolbarContainer());
+        var ar = Array.from(this.toolbars);
+        this.toolbars = [];
+        ar.forEach(function(t,i) {
+            if (typeof(t) == 'string') {
+                t = {
+                    xtype : t
+                };
+            }
+            if (typeof(t) == 'object' && typeof(t.xtype) == 'string') {
+                t.editor = this;
+                t.xns = t.xns || Roo.bootstrap.form.HtmlEditorToolbar;
+                t = Roo.factory(t);
+            }
+            this.toolbars[i] = t;
+            this.toolbars[i].render(this.toolbarContainer());
+        }, this);
         
-        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);
-//        }
     },
 
      
@@ -27428,7 +32646,7 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
     {
        // Roo.log("Call onRender: " + this.xtype);
         var _t = this;
-        Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
+        Roo.bootstrap.form.HtmlEditor.superclass.onRender.call(this, ct, position);
       
         this.wrap = this.inputEl().wrap({
             cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
@@ -27436,33 +32654,11 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
         
         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
-                    }
-                }
-            });
-            
-        }
+         
         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..
-        }
+          
         
     },
 
@@ -27470,7 +32666,7 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
     onResize : function(w, h)
     {
         Roo.log('resize: ' +w + ',' + h );
-        Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
+        Roo.bootstrap.form.HtmlEditor.superclass.onResize.apply(this, arguments);
         var ew = false;
         var eh = false;
         
@@ -27533,9 +32729,9 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
             //this.deferFocus();
         }
          
-        if(this.resizable){
-            this.setSize(this.wrap.getSize());
-        }
+        //if(this.resizable){
+        //    this.setSize(this.wrap.getSize());
+        //}
         
         this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
     },
@@ -27570,7 +32766,7 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
 //    clearInvalid : Roo.emptyFn,
 
     setValue : function(v){
-        Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
+        Roo.bootstrap.form.HtmlEditor.superclass.setValue.call(this, v);
         this.editorcore.pushValue();
     },
 
@@ -27672,18 +32868,19 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
    
    
       
-Roo.namespace('Roo.bootstrap.htmleditor');
 /**
- * @class Roo.bootstrap.HtmlEditorToolbar1
+ * @class Roo.bootstrap.form.HtmlEditorToolbar.Standard
+ * @parent Roo.bootstrap.form.HtmlEditor
+ * @extends Roo.bootstrap.nav.Simplebar
  * Basic Toolbar
  * 
  * @example
  * Usage:
  *
- new Roo.bootstrap.HtmlEditor({
+ new Roo.bootstrap.form.HtmlEditor({
     ....
     toolbars : [
-        new Roo.bootstrap.HtmlEditorToolbar1({
+        new Roo.bootstrap.form.HtmlEditorToolbar.Standard({
             disable : { fonts: 1 , format: 1, ..., ... , ...],
             btns : [ .... ]
         })
@@ -27698,7 +32895,7 @@ Roo.namespace('Roo.bootstrap.htmleditor');
  * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
  */
  
-Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
+Roo.bootstrap.form.HtmlEditorToolbar.Standard = function(config)
 {
     
     Roo.apply(this, config);
@@ -27710,17 +32907,17 @@ Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
         colors : true,
         specialElements : true
     });
-    Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.constructor.call(this, config);
     
     this.editor = config.editor;
     this.editorcore = config.editor.editorcore;
     
-    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
+    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.btnid; });
     
     //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,  {
+Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simplebar,  {
      
     bar : true,
     
@@ -27736,11 +32933,14 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
         'div','span'
     ],
     
+    
+    deleteBtn: false,
+    
     onRender : function(ct, position)
     {
        // Roo.log("Call onRender: " + this.xtype);
         
-       Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
+       Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.onRender.call(this, ct, position);
        Roo.log(this.el);
        this.el.dom.style.marginBottom = '0';
        var _this = this;
@@ -27748,7 +32948,7 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
        var editor= this.editor;
        
        var children = [];
-       var btn = function(id,cmd , toggle, handler, html){
+       var btn = function(id, cmd , toggle, handler, html){
        
             var  event = toggle ? 'toggle' : 'click';
        
@@ -27757,9 +32957,11 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
                 xtype: 'Button',
                 xns: Roo.bootstrap,
                 //glyphicon : id,
+                btnid : id,
                 fa: id,
-                cmd : id || cmd,
-                enableToggle:toggle !== false,
+                cls : 'roo-html-editor-btn-' + id,
+                cmd : cmd, // why id || cmd
+                enableToggle: toggle !== false,
                 html : html || '',
                 pressed : toggle ? false : null,
                 listeners : {}
@@ -27778,6 +32980,7 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
                 size : 'sm',
                 xns: Roo.bootstrap,
                 fa : 'font',
+                cls : 'roo-html-editor-font-chooser',
                 //html : 'submit'
                 menu : {
                     xtype: 'Menu',
@@ -27803,19 +33006,19 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
         });
         children.push(style);   
         
-        btn('bold',false,true);
-        btn('italic',false,true);
-        btn('align-left', 'justifyleft',true);
+        btn('bold',         'bold',true);
+        btn('italic',       'italic',true);
+        btn('underline',     'underline',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('link', false, true, this.onLinkClick);
+        
+        
+        btn('image', false, true, this.onImageClick);
         btn('list','insertunorderedlist',true);
+        btn('list-ol','insertorderedlist',true);
+
         btn('pencil', false,true, function(btn){
                 Roo.log(this);
                 this.toggleSourceEdit(btn.pressed);
@@ -27827,58 +33030,166 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
             }
         }
         
-        /*
-        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.xtype = 'NavSimplebar'; // why?
         
         for(var i=0;i< children.length;i++) {
             
             this.buttons.add(this.addxtypeChild(children[i]));
             
         }
-        
+        this.buildToolbarDelete();
+
         editor.on('editorevent', this.updateToolbar, this);
     },
+    
+    buildToolbarDelete : function()
+    {
+        
+       /* this.addxtypeChild({
+            xtype : 'Element',
+            xns : Roo.bootstrap,
+            cls : 'roo-htmleditor-fill'
+        });
+        */
+        this.deleteBtn = this.addxtypeChild({
+            size : 'sm',
+            xtype: 'Button',
+            xns: Roo.bootstrap,
+            fa: 'eraser',
+            tooltip : "Clear Formating / Delete",
+            listeners : {
+                click : this.onDelete.createDelegate(this)
+            }
+        });
+        this.deleteBtn.hide();     
+        
+    },
+    
+    onImageClick : function()
+    {
+        if (this.input) {
+            this.input.un('change', this.onFileSelected, this);
+        }
+        this.input = Roo.get(document.body).createChild({ 
+          tag: 'input', 
+          type : 'file', 
+          style : 'display:none', 
+          multiple: 'multiple'
+       });
+        this.input.on('change', this.onFileSelected, this);
+        this.input.dom.click();
+    },
+    
+    onFileSelected : function(e)
+    {
+         e.preventDefault();
+        
+        if(typeof(this.input.dom.files) == 'undefined' || !this.input.dom.files.length){
+            return;
+        }
+    
+         
+        this.addFiles(Array.prototype.slice.call(this.input.dom.files));
+    },
+    
+    addFiles : function(far) {
+
+        if (!far.length) {
+            return;
+        }
+        
+        var f = far.pop();
+        
+        if (!f.type.match(/^image/)) {
+            this.addFiles(far);
+            return;
+        }
+         
+        var sn = this.selectedNode;
+        
+        var bl = sn  && this.editorcore.enableBlocks ? Roo.htmleditor.Block.factory(sn) : false;
+        
+        var editor =  this.editorcore;
+        
+        var reader = new FileReader();
+        reader.addEventListener('load', (function() {
+            if (bl) {
+                bl.image_src = reader.result;
+                //bl.caption = f.name;
+                bl.updateElement(sn);
+                editor.owner.fireEvent('editorevent', editor, false);
+                // we only do the first file!! and replace.
+                return;
+            }
+            if (this.editorcore.enableBlocks) {
+                var fig = new Roo.htmleditor.BlockFigure({
+                    image_src :  reader.result,
+                    caption : '',
+                    caption_display : 'none'  //default to hide captions..
+                 });
+                editor.insertAtCursor(fig.toHTML());
+                editor.owner.fireEvent('editorevent', editor, false);
+                return;
+            }
+            // just a standard img..
+            if (sn && sn.tagName.toUpperCase() == 'IMG') {
+                sn.src = reader.result;
+                editor.owner.fireEvent('editorevent', editor, false);
+                return;
+            }
+            editor.insertAtCursor('<img src="' + reader.result +'">');
+            editor.owner.fireEvent('editorevent', editor, false);
+            
+        }).createDelegate(this));
+        reader.readAsDataURL(f);
+        
+    
+     },
+    
+    
     onBtnClick : function(id)
     {
        this.editorcore.relayCmd(id);
        this.editorcore.focus();
     },
     
+    onLinkClick : function(btn) {
+        var url = this.selectedNode && this.selectedNode.tagName.toUpperCase() == 'A' ?
+                this.selectedNode.getAttribute('href') : '';
+            
+        Roo.bootstrap.MessageBox.show({
+            title : "Add / Edit Link URL",
+            msg : "Enter the URL for the link",
+            buttons: Roo.bootstrap.MessageBox.OKCANCEL,
+            minWidth: 250,
+            scope : this,
+            prompt:true,
+            multiline: false,
+            modal : true,
+            value : url,
+            fn:  function(pressed, newurl) {
+                if (pressed != 'ok') {
+                    this.editorcore.focus();
+                    return;
+                }
+                if (url != '') {
+                    this.selectedNode.setAttribute('href', newurl);
+                    return;
+                }
+                if(newurl && newurl .match(/http(s):\/\/.+/)) {
+                    this.editorcore.relayCmd('createlink', newurl);
+                }
+                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(){
+    updateToolbar: function(editor ,ev, sel){
 
         if(!this.editorcore.activated){
             this.editor.onFirstFocus(); // is this neeed?
@@ -27887,39 +33198,89 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
 
         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'));
+        var hasToggle  = false;
+        btns.each(function(e) {
+            if (e.enableToggle && e.cmd) {
+                hasToggle = hasToggle  || (['align-left', 'align-right', 'align-center', 'image' , 'link', 'underline'].indexOf(e.btnid) < 0 && doc.queryCommandState(e.cmd));
+                e.setActive(doc.queryCommandState(e.cmd));
+            }
+        }, this);
         
-        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'));
-         /*
+        if (ev &&
+            (ev.type == 'mouseup' || ev.type == 'click' ) &&
+            ev.target && ev.target.tagName != 'BODY' ) { // && ev.target.tagName == 'IMG') {
+            // they have click on an image...
+            // let's see if we can change the selection...
+            sel = ev.target;
+            
+        }
         
         var ans = this.editorcore.getAllAncestors();
-        if (this.formatCombo) {
+        if (!sel) { 
+            sel = ans.length ? (ans[0] ?  ans[0]  : ans[1]) : this.editorcore.doc.body;
+            sel = sel ? sel : this.editorcore.doc.body;
+            sel = sel.tagName.length ? sel : this.editorcore.doc.body;
             
+        }
+        
+        var lastSel = this.selectedNode;
+        this.selectedNode = sel;
+         
+        // ok see if we are editing a block?
+        
+        var db = false;
+        // you are not actually selecting the block.
+        if (sel && sel.hasAttribute('data-block')) {
+            db = sel;
+        } else if (sel && sel.closest('[data-block]')) {
+            db = sel.closest('[data-block]');
+        }
+        
+        Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e) {
+            e.classList.remove('roo-ed-selection');
+        });
+        
+        var block = false;
+        if (db && this.editorcore.enableBlocks) {
+            block = Roo.htmleditor.Block.factory(db);
             
-            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 (block) {
+                db.className =  (db.classList.length > 0  ? db.className + ' ' : '') +
+                    ' roo-ed-selection';
+                sel = this.selectedNode = db;
             }
         }
         
+        // highlight the 'a'..
+        var tn = sel && sel.tagName.toUpperCase() || '';
+        if (!block && sel && tn != 'A') {
+            var asel = sel.closest('A');
+            if (asel) {
+                sel = asel;
+            }
+        }
+       
+        btns.get('link').setActive(tn == 'A' && this.selectedNode.hasAttribute('href'));
+        btns.get('image').setActive(tn == 'IMG' || this.editorcore.enableBlocks && tn == 'FIGURE');
+        btns.get('underline').setActive(tn == 'U' || sel.closest('u') ? true : false);
+        
+        Roo.bootstrap.menu.Manager.hideAll();
+         
+        
+        
+        
+        
+        // handle delete button..
+        if (hasToggle || (tn.length && tn == 'BODY')) {
+            this.deleteBtn.hide();
+            return;
+            
+        }
+        this.deleteBtn.show();
+        
         
         
-        // hides menus... - so this cant be on a menu...
-        Roo.bootstrap.MenuMgr.hideAll();
-        */
-        Roo.bootstrap.MenuMgr.hideAll();
         //this.editorsyncValue();
     },
     onFirstFocus: function() {
@@ -27927,6 +33288,49 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
            item.enable();
         });
     },
+    
+    onDelete : function()
+    {
+        var range = this.editorcore.createRange();
+        var selection = this.editorcore.getSelection();
+        var sn = this.selectedNode;
+        range.setStart(sn,0);
+        range.setEnd(sn,0); 
+        
+        
+        if (sn.hasAttribute('data-block')) {
+            var block = Roo.htmleditor.Block.factory(this.selectedNode);
+            if (block) {
+                sn = block.removeNode();
+                sn.parentNode.removeChild(sn);
+                selection.removeAllRanges();
+                selection.addRange(range);
+                this.updateToolbar(null, null, null);
+                this.editorcore.fireEditorEvent(false);
+                return;
+            }   
+             
+        }
+        if (!sn) {
+            return; // should not really happen..
+        }
+        if (sn && sn.tagName == 'BODY') {
+            return;
+        }
+        var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
+        
+        // remove and keep parents.
+        a = new Roo.htmleditor.FilterKeepChildren({tag : false});
+        a.replaceTag(sn);
+        
+        selection.removeAllRanges();
+        selection.addRange(range);
+        this.editorcore.fireEditorEvent(false);
+        
+        
+    },
+    
+    
     toggleSourceEdit : function(sourceEditMode){
         
           
@@ -27963,8 +33367,8 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
  */
 
 /**
- * @class Roo.bootstrap.Markdown
- * @extends Roo.bootstrap.TextArea
+ * @class Roo.bootstrap.form.Markdown
+ * @extends Roo.bootstrap.form.TextArea
  * Bootstrap Showdown editable area
  * @cfg {string} content
  * 
@@ -27972,19 +33376,19 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
  * Create a new Showdown
  */
 
-Roo.bootstrap.Markdown = function(config){
-    Roo.bootstrap.Markdown.superclass.constructor.call(this, config);
+Roo.bootstrap.form.Markdown = function(config){
+    Roo.bootstrap.form.Markdown.superclass.constructor.call(this, config);
    
 };
 
-Roo.extend(Roo.bootstrap.Markdown, Roo.bootstrap.TextArea,  {
+Roo.extend(Roo.bootstrap.form.Markdown, Roo.bootstrap.form.TextArea,  {
     
     editing :false,
     
     initEvents : function()
     {
         
-        Roo.bootstrap.TextArea.prototype.initEvents.call(this);
+        Roo.bootstrap.form.TextArea.prototype.initEvents.call(this);
         this.markdownEl = this.el.createChild({
             cls : 'roo-markdown-area'
         });
@@ -28037,7 +33441,7 @@ Roo.extend(Roo.bootstrap.Markdown, Roo.bootstrap.TextArea,  {
     },
     setValue : function(val)
     {
-        Roo.bootstrap.TextArea.prototype.setValue.call(this,val);
+        Roo.bootstrap.form.TextArea.prototype.setValue.call(this,val);
         if (!this.editing) {
             this.updateMarkdown();
         }
@@ -28065,7 +33469,7 @@ Roo.extend(Roo.bootstrap.Markdown, Roo.bootstrap.TextArea,  {
  
 /**
  * @class Roo.bootstrap.PagingToolbar
- * @extends Roo.bootstrap.NavSimplebar
+ * @extends Roo.bootstrap.nav.Simplebar
  * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
  * @constructor
  * Create a new PagingToolbar
@@ -28101,14 +33505,18 @@ Roo.bootstrap.PagingToolbar = function(config)
     if (Roo.bootstrap.version == 4) {
         this.navgroup = new Roo.bootstrap.ButtonGroup({ cls: 'pagination' });
     } else {
-        this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
+        this.navgroup = new Roo.bootstrap.nav.Group({ cls: 'pagination' });
     }
     
 };
 
-Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
+Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.nav.Simplebar, {
     /**
-     * @cfg {Roo.data.Store} dataSource
+     * @cfg {Roo.bootstrap.Button} buttons[]
+     * Buttons for the toolbar
+     */
+     /**
+     * @cfg {Roo.data.Store} store
      * The underlying data store providing the paged data
      */
     /**
@@ -28308,8 +33716,14 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
     },
 
     // private
-    onLoadError : function(){
+    onLoadError : function(proxy, o){
         this.loading.enable();
+        if (this.ds.events.loadexception.listeners.length  < 2) {
+            // nothing has been assigned to loadexception except this...
+            // so 
+            Roo.MessageBox.alert("Error loading",o.raw.errorMsg);
+
+        }
     },
 
     // private
@@ -28755,7 +34169,7 @@ Roo.extend(Roo.bootstrap.Graph, Roo.bootstrap.Component,  {
 });
 
  
-/*
+Roo.bootstrap.dash = {};/*
  * - LGPL
  *
  * numberBox
@@ -28893,6 +34307,7 @@ Roo.bootstrap.dash = Roo.bootstrap.dash || {};
 /**
  * @class Roo.bootstrap.dash.TabBox
  * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.dash.TabPane
  * Bootstrap TabBox class
  * @cfg {String} title Title of the TabBox
  * @cfg {String} icon Icon of the TabBox
@@ -29093,6 +34508,7 @@ Roo.bootstrap.dash = Roo.bootstrap.dash || {};
 /**
  * @class Roo.bootstrap.TabPane
  * @extends Roo.bootstrap.Component
+ * @children  Roo.bootstrap.Graph Roo.bootstrap.Column
  * Bootstrap TabPane class
  * @cfg {Boolean} active (false | true) Default false
  * @cfg {String} title title of panel
@@ -29166,409 +34582,6 @@ Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component,  {
  
 
 
- /*
- * - LGPL
- *
- * menu
- * 
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Menu
- * @extends Roo.bootstrap.Component
- * Bootstrap Menu class - container for Menu
- * @cfg {String} html Text of the menu
- * @cfg {String} weight (default | primary | success | info | warning | danger | inverse)
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Menu align to (top | bottom) default bottom
- * 
- * 
- * @constructor
- * Create a new Menu
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Menu = function(config){
-    Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
-    
-    this.addEvents({
-        /**
-         * @event beforeshow
-         * Fires before this menu is displayed
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        beforeshow : true,
-        /**
-         * @event beforehide
-         * Fires before this menu is hidden
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        beforehide : true,
-        /**
-         * @event show
-         * Fires after this menu is displayed
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        show : true,
-        /**
-         * @event hide
-         * Fires after this menu is hidden
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        hide : true,
-        /**
-         * @event click
-         * Fires when this menu is clicked (or when the enter key is pressed while it is active)
-         * @param {Roo.bootstrap.menu.Menu} this
-         * @param {Roo.EventObject} e
-         */
-        click : true
-    });
-    
-};
-
-Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component,  {
-    
-    submenu : false,
-    html : '',
-    weight : 'default',
-    icon : false,
-    pos : 'bottom',
-    
-    
-    getChildContainer : function() {
-        if(this.isSubMenu){
-            return this.el;
-        }
-        
-        return this.el.select('ul.dropdown-menu', true).first();  
-    },
-    
-    getAutoCreate : function()
-    {
-        var text = [
-            {
-                tag : 'span',
-                cls : 'roo-menu-text',
-                html : this.html
-            }
-        ];
-        
-        if(this.icon){
-            text.unshift({
-                tag : 'i',
-                cls : 'fa ' + this.icon
-            })
-        }
-        
-        
-        var cfg = {
-            tag : 'div',
-            cls : 'btn-group',
-            cn : [
-                {
-                    tag : 'button',
-                    cls : 'dropdown-button btn btn-' + this.weight,
-                    cn : text
-                },
-                {
-                    tag : 'button',
-                    cls : 'dropdown-toggle btn btn-' + this.weight,
-                    cn : [
-                        {
-                            tag : 'span',
-                            cls : 'caret'
-                        }
-                    ]
-                },
-                {
-                    tag : 'ul',
-                    cls : 'dropdown-menu'
-                }
-            ]
-            
-        };
-        
-        if(this.pos == 'top'){
-            cfg.cls += ' dropup';
-        }
-        
-        if(this.isSubMenu){
-            cfg = {
-                tag : 'ul',
-                cls : 'dropdown-menu'
-            }
-        }
-       
-        return cfg;
-    },
-    
-    onRender : function(ct, position)
-    {
-        this.isSubMenu = ct.hasClass('dropdown-submenu');
-        
-        Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
-    },
-    
-    initEvents : function() 
-    {
-        if(this.isSubMenu){
-            return;
-        }
-        
-        this.hidden = true;
-        
-        this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
-        this.triggerEl.on('click', this.onTriggerPress, this);
-        
-        this.buttonEl = this.el.select('button.dropdown-button', true).first();
-        this.buttonEl.on('click', this.onClick, this);
-        
-    },
-    
-    list : function()
-    {
-        if(this.isSubMenu){
-            return this.el;
-        }
-        
-        return this.el.select('ul.dropdown-menu', true).first();
-    },
-    
-    onClick : function(e)
-    {
-        this.fireEvent("click", this, e);
-    },
-    
-    onTriggerPress  : function(e)
-    {   
-        if (this.isVisible()) {
-            this.hide();
-        } else {
-            this.show();
-        }
-    },
-    
-    isVisible : function(){
-        return !this.hidden;
-    },
-    
-    show : function()
-    {
-        this.fireEvent("beforeshow", this);
-        
-        this.hidden = false;
-        this.el.addClass('open');
-        
-        Roo.get(document).on("mouseup", this.onMouseUp, this);
-        
-        this.fireEvent("show", this);
-        
-        
-    },
-    
-    hide : function()
-    {
-        this.fireEvent("beforehide", this);
-        
-        this.hidden = true;
-        this.el.removeClass('open');
-        
-        Roo.get(document).un("mouseup", this.onMouseUp);
-        
-        this.fireEvent("hide", this);
-    },
-    
-    onMouseUp : function()
-    {
-        this.hide();
-    }
-    
-});
-
- /*
- * - LGPL
- *
- * menu item
- * 
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Item
- * @extends Roo.bootstrap.Component
- * Bootstrap MenuItem class
- * @cfg {Boolean} submenu (true | false) default false
- * @cfg {String} html text of the item
- * @cfg {String} href the link
- * @cfg {Boolean} disable (true | false) default false
- * @cfg {Boolean} preventDefault (true | false) default true
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Submenu align to (left | right) default right 
- * 
- * 
- * @constructor
- * Create a new Item
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Item = function(config){
-    Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
-    this.addEvents({
-        /**
-         * @event mouseover
-         * Fires when the mouse is hovering over this menu
-         * @param {Roo.bootstrap.menu.Item} this
-         * @param {Roo.EventObject} e
-         */
-        mouseover : true,
-        /**
-         * @event mouseout
-         * Fires when the mouse exits this menu
-         * @param {Roo.bootstrap.menu.Item} this
-         * @param {Roo.EventObject} e
-         */
-        mouseout : true,
-        // raw events
-        /**
-         * @event click
-         * The raw click event for the entire grid.
-         * @param {Roo.EventObject} e
-         */
-        click : true
-    });
-};
-
-Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component,  {
-    
-    submenu : false,
-    href : '',
-    html : '',
-    preventDefault: true,
-    disable : false,
-    icon : false,
-    pos : 'right',
-    
-    getAutoCreate : function()
-    {
-        var text = [
-            {
-                tag : 'span',
-                cls : 'roo-menu-item-text',
-                html : this.html
-            }
-        ];
-        
-        if(this.icon){
-            text.unshift({
-                tag : 'i',
-                cls : 'fa ' + this.icon
-            })
-        }
-        
-        var cfg = {
-            tag : 'li',
-            cn : [
-                {
-                    tag : 'a',
-                    href : this.href || '#',
-                    cn : text
-                }
-            ]
-        };
-        
-        if(this.disable){
-            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
-        }
-        
-        if(this.submenu){
-            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
-            
-            if(this.pos == 'left'){
-                cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
-            }
-        }
-        
-        return cfg;
-    },
-    
-    initEvents : function() 
-    {
-        this.el.on('mouseover', this.onMouseOver, this);
-        this.el.on('mouseout', this.onMouseOut, this);
-        
-        this.el.select('a', true).first().on('click', this.onClick, this);
-        
-    },
-    
-    onClick : function(e)
-    {
-        if(this.preventDefault){
-            e.preventDefault();
-        }
-        
-        this.fireEvent("click", this, e);
-    },
-    
-    onMouseOver : function(e)
-    {
-        if(this.submenu && this.pos == 'left'){
-            this.el.select('ul.dropdown-menu', true).first().setLeft(this.el.select('ul.dropdown-menu', true).first().getWidth() * -1);
-        }
-        
-        this.fireEvent("mouseover", this, e);
-    },
-    
-    onMouseOut : function(e)
-    {
-        this.fireEvent("mouseout", this, e);
-    }
-});
-
-
- /*
- * - LGPL
- *
- * menu separator
- * 
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Separator
- * @extends Roo.bootstrap.Component
- * Bootstrap Separator class
- * 
- * @constructor
- * Create a new Separator
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Separator = function(config){
-    Roo.bootstrap.menu.Separator.superclass.constructor.call(this, config);
-};
-
-Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component,  {
-    
-    getAutoCreate : function(){
-        var cfg = {
-            tag : 'li',
-            cls: 'dropdown-divider divider'
-        };
-        
-        return cfg;
-    }
-   
-});
-
-
  /*
  * - LGPL
  *
@@ -29816,10 +34829,18 @@ Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
         
         this.el.removeClass(['fade','top','bottom', 'left', 'right','in',
                              'bs-tooltip-top','bs-tooltip-bottom', 'bs-tooltip-left', 'bs-tooltip-right']);
+
+        if(this.bindEl.attr('tooltip-class')) {
+            this.el.addClass(this.bindEl.attr('tooltip-class'));
+        }
         
         var placement = typeof this.placement == 'function' ?
             this.placement.call(this, this.el, on_el) :
             this.placement;
+        
+        if(this.bindEl.attr('tooltip-placement')) {
+            placement = this.bindEl.attr('tooltip-placement');
+        }
             
         var autoToken = /\s?auto?\s?/i;
         var autoPlace = autoToken.test(placement);
@@ -29909,6 +34930,9 @@ Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
             return;
         }
         //this.el.setXY([0,0]);
+        if(this.bindEl.attr('tooltip-class')) {
+            this.el.removeClass(this.bindEl.attr('tooltip-class'));
+        }
         this.el.removeClass(['show', 'in']);
         //this.el.hide();
         
@@ -33296,405 +38320,6 @@ Roo.extend(Roo.bootstrap.DocumentViewer, Roo.bootstrap.Component,  {
     
 });
 /*
- * - LGPL
- *
- * nav progress bar
- * 
- */
-
-/**
- * @class Roo.bootstrap.NavProgressBar
- * @extends Roo.bootstrap.Component
- * Bootstrap NavProgressBar class
- * 
- * @constructor
- * Create a new nav progress bar
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.NavProgressBar = function(config){
-    Roo.bootstrap.NavProgressBar.superclass.constructor.call(this, config);
-
-    this.bullets = this.bullets || [];
-   
-//    Roo.bootstrap.NavProgressBar.register(this);
-     this.addEvents({
-        /**
-            * @event changed
-            * Fires when the active item changes
-            * @param {Roo.bootstrap.NavProgressBar} this
-            * @param {Roo.bootstrap.NavProgressItem} selected The item selected
-            * @param {Roo.bootstrap.NavProgressItem} prev The previously selected item 
-         */
-        'changed': true
-     });
-    
-};
-
-Roo.extend(Roo.bootstrap.NavProgressBar, Roo.bootstrap.Component,  {
-    
-    bullets : [],
-    barItems : [],
-    
-    getAutoCreate : function()
-    {
-        var cfg = Roo.apply({}, Roo.bootstrap.NavProgressBar.superclass.getAutoCreate.call(this));
-        
-        cfg = {
-            tag : 'div',
-            cls : 'roo-navigation-bar-group',
-            cn : [
-                {
-                    tag : 'div',
-                    cls : 'roo-navigation-top-bar'
-                },
-                {
-                    tag : 'div',
-                    cls : 'roo-navigation-bullets-bar',
-                    cn : [
-                        {
-                            tag : 'ul',
-                            cls : 'roo-navigation-bar'
-                        }
-                    ]
-                },
-                
-                {
-                    tag : 'div',
-                    cls : 'roo-navigation-bottom-bar'
-                }
-            ]
-            
-        };
-        
-        return cfg;
-        
-    },
-    
-    initEvents: function() 
-    {
-        
-    },
-    
-    onRender : function(ct, position) 
-    {
-        Roo.bootstrap.NavProgressBar.superclass.onRender.call(this, ct, position);
-        
-        if(this.bullets.length){
-            Roo.each(this.bullets, function(b){
-               this.addItem(b);
-            }, this);
-        }
-        
-        this.format();
-        
-    },
-    
-    addItem : function(cfg)
-    {
-        var item = new Roo.bootstrap.NavProgressItem(cfg);
-        
-        item.parentId = this.id;
-        item.render(this.el.select('.roo-navigation-bar', true).first(), null);
-        
-        if(cfg.html){
-            var top = new Roo.bootstrap.Element({
-                tag : 'div',
-                cls : 'roo-navigation-bar-text'
-            });
-            
-            var bottom = new Roo.bootstrap.Element({
-                tag : 'div',
-                cls : 'roo-navigation-bar-text'
-            });
-            
-            top.onRender(this.el.select('.roo-navigation-top-bar', true).first(), null);
-            bottom.onRender(this.el.select('.roo-navigation-bottom-bar', true).first(), null);
-            
-            var topText = new Roo.bootstrap.Element({
-                tag : 'span',
-                html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? cfg.html : ''
-            });
-            
-            var bottomText = new Roo.bootstrap.Element({
-                tag : 'span',
-                html : (typeof(cfg.position) != 'undefined' && cfg.position == 'top') ? '' : cfg.html
-            });
-            
-            topText.onRender(top.el, null);
-            bottomText.onRender(bottom.el, null);
-            
-            item.topEl = top;
-            item.bottomEl = bottom;
-        }
-        
-        this.barItems.push(item);
-        
-        return item;
-    },
-    
-    getActive : function()
-    {
-        var active = false;
-        
-        Roo.each(this.barItems, function(v){
-            
-            if (!v.isActive()) {
-                return;
-            }
-            
-            active = v;
-            return false;
-            
-        });
-        
-        return active;
-    },
-    
-    setActiveItem : function(item)
-    {
-        var prev = false;
-        
-        Roo.each(this.barItems, function(v){
-            if (v.rid == item.rid) {
-                return ;
-            }
-            
-            if (v.isActive()) {
-                v.setActive(false);
-                prev = v;
-            }
-        });
-
-        item.setActive(true);
-        
-        this.fireEvent('changed', this, item, prev);
-    },
-    
-    getBarItem: function(rid)
-    {
-        var ret = false;
-        
-        Roo.each(this.barItems, function(e) {
-            if (e.rid != rid) {
-                return;
-            }
-            
-            ret =  e;
-            return false;
-        });
-        
-        return ret;
-    },
-    
-    indexOfItem : function(item)
-    {
-        var index = false;
-        
-        Roo.each(this.barItems, function(v, i){
-            
-            if (v.rid != item.rid) {
-                return;
-            }
-            
-            index = i;
-            return false
-        });
-        
-        return index;
-    },
-    
-    setActiveNext : function()
-    {
-        var i = this.indexOfItem(this.getActive());
-        
-        if (i > this.barItems.length) {
-            return;
-        }
-        
-        this.setActiveItem(this.barItems[i+1]);
-    },
-    
-    setActivePrev : function()
-    {
-        var i = this.indexOfItem(this.getActive());
-        
-        if (i  < 1) {
-            return;
-        }
-        
-        this.setActiveItem(this.barItems[i-1]);
-    },
-    
-    format : function()
-    {
-        if(!this.barItems.length){
-            return;
-        }
-     
-        var width = 100 / this.barItems.length;
-        
-        Roo.each(this.barItems, function(i){
-            i.el.setStyle('width', width + '%');
-            i.topEl.el.setStyle('width', width + '%');
-            i.bottomEl.el.setStyle('width', width + '%');
-        }, this);
-        
-    }
-    
-});
-/*
- * - LGPL
- *
- * Nav Progress Item
- * 
- */
-
-/**
- * @class Roo.bootstrap.NavProgressItem
- * @extends Roo.bootstrap.Component
- * Bootstrap NavProgressItem class
- * @cfg {String} rid the reference id
- * @cfg {Boolean} active (true|false) Is item active default false
- * @cfg {Boolean} disabled (true|false) Is item active default false
- * @cfg {String} html
- * @cfg {String} position (top|bottom) text position default bottom
- * @cfg {String} icon show icon instead of number
- * 
- * @constructor
- * Create a new NavProgressItem
- * @param {Object} config The config object
- */
-Roo.bootstrap.NavProgressItem = function(config){
-    Roo.bootstrap.NavProgressItem.superclass.constructor.call(this, config);
-    this.addEvents({
-        // raw events
-        /**
-         * @event click
-         * The raw click event for the entire grid.
-         * @param {Roo.bootstrap.NavProgressItem} this
-         * @param {Roo.EventObject} e
-         */
-        "click" : true
-    });
-   
-};
-
-Roo.extend(Roo.bootstrap.NavProgressItem, Roo.bootstrap.Component,  {
-    
-    rid : '',
-    active : false,
-    disabled : false,
-    html : '',
-    position : 'bottom',
-    icon : false,
-    
-    getAutoCreate : function()
-    {
-        var iconCls = 'roo-navigation-bar-item-icon';
-        
-        iconCls += ((this.icon) ? (' ' + this.icon) : (' step-number')) ;
-        
-        var cfg = {
-            tag: 'li',
-            cls: 'roo-navigation-bar-item',
-            cn : [
-                {
-                    tag : 'i',
-                    cls : iconCls
-                }
-            ]
-        };
-        
-        if(this.active){
-            cfg.cls += ' active';
-        }
-        if(this.disabled){
-            cfg.cls += ' disabled';
-        }
-        
-        return cfg;
-    },
-    
-    disable : function()
-    {
-        this.setDisabled(true);
-    },
-    
-    enable : function()
-    {
-        this.setDisabled(false);
-    },
-    
-    initEvents: function() 
-    {
-        this.iconEl = this.el.select('.roo-navigation-bar-item-icon', true).first();
-        
-        this.iconEl.on('click', this.onClick, this);
-    },
-    
-    onClick : function(e)
-    {
-        e.preventDefault();
-        
-        if(this.disabled){
-            return;
-        }
-        
-        if(this.fireEvent('click', this, e) === false){
-            return;
-        };
-        
-        this.parent().setActiveItem(this);
-    },
-    
-    isActive: function () 
-    {
-        return this.active;
-    },
-    
-    setActive : function(state)
-    {
-        if(this.active == state){
-            return;
-        }
-        
-        this.active = state;
-        
-        if (state) {
-            this.el.addClass('active');
-            return;
-        }
-        
-        this.el.removeClass('active');
-        
-        return;
-    },
-    
-    setDisabled : function(state)
-    {
-        if(this.disabled == state){
-            return;
-        }
-        
-        this.disabled = state;
-        
-        if (state) {
-            this.el.addClass('disabled');
-            return;
-        }
-        
-        this.el.removeClass('disabled');
-    },
-    
-    tooltipEl : function()
-    {
-        return this.el.select('.roo-navigation-bar-item-icon', true).first();;
-    }
-});
-
- /*
  * - LGPL
  *
  * FieldLabel
@@ -33702,7 +38327,7 @@ Roo.extend(Roo.bootstrap.NavProgressItem, Roo.bootstrap.Component,  {
  */
 
 /**
- * @class Roo.bootstrap.FieldLabel
+ * @class Roo.bootstrap.form.FieldLabel
  * @extends Roo.bootstrap.Component
  * Bootstrap FieldLabel class
  * @cfg {String} html contents of the element
@@ -33720,7 +38345,7 @@ Roo.extend(Roo.bootstrap.NavProgressItem, Roo.bootstrap.Component,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.FieldLabel = function(config){
+Roo.bootstrap.form.FieldLabel = function(config){
     Roo.bootstrap.Element.superclass.constructor.call(this, config);
     
     this.addEvents({
@@ -33740,7 +38365,7 @@ Roo.bootstrap.FieldLabel = function(config){
         });
 };
 
-Roo.extend(Roo.bootstrap.FieldLabel, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.form.FieldLabel, Roo.bootstrap.Component,  {
     
     tag: 'label',
     cls: '',
@@ -33809,7 +38434,7 @@ Roo.extend(Roo.bootstrap.FieldLabel, Roo.bootstrap.Component,  {
             this.indicator.addClass('invisible');
         }
         
-        Roo.bootstrap.FieldLabel.register(this);
+        Roo.bootstrap.form.FieldLabel.register(this);
     },
     
     indicatorEl : function()
@@ -33870,13 +38495,13 @@ Roo.extend(Roo.bootstrap.FieldLabel, Roo.bootstrap.Component,  {
    
 });
 
-Roo.apply(Roo.bootstrap.FieldLabel, {
+Roo.apply(Roo.bootstrap.form.FieldLabel, {
     
     groups: {},
     
      /**
     * register a FieldLabel Group
-    * @param {Roo.bootstrap.FieldLabel} the FieldLabel to add
+    * @param {Roo.bootstrap.form.FieldLabel} the FieldLabel to add
     */
     register : function(label)
     {
@@ -33890,7 +38515,7 @@ Roo.apply(Roo.bootstrap.FieldLabel, {
     /**
     * fetch a FieldLabel Group based on the target
     * @param {string} target
-    * @returns {Roo.bootstrap.FieldLabel} the CheckBox group
+    * @returns {Roo.bootstrap.form.FieldLabel} the CheckBox group
     */
     get: function(target) {
         if (typeof(this.groups[target]) == 'undefined') {
@@ -33912,7 +38537,7 @@ Roo.apply(Roo.bootstrap.FieldLabel, {
 
 
 /**
- * @class Roo.bootstrap.DateSplitField
+ * @class Roo.bootstrap.form.DateSplitField
  * @extends Roo.bootstrap.Component
  * Bootstrap DateSplitField class
  * @cfg {string} fieldLabel - the label associated
@@ -33938,22 +38563,22 @@ Roo.apply(Roo.bootstrap.FieldLabel, {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.DateSplitField = function(config){
-    Roo.bootstrap.DateSplitField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.DateSplitField = function(config){
+    Roo.bootstrap.form.DateSplitField.superclass.constructor.call(this, config);
     
     this.addEvents({
         // raw events
          /**
          * @event years
          * getting the data of years
-         * @param {Roo.bootstrap.DateSplitField} this
+         * @param {Roo.bootstrap.form.DateSplitField} this
          * @param {Object} years
          */
         "years" : true,
         /**
          * @event days
          * getting the data of days
-         * @param {Roo.bootstrap.DateSplitField} this
+         * @param {Roo.bootstrap.form.DateSplitField} this
          * @param {Object} days
          */
         "days" : true,
@@ -33973,7 +38598,7 @@ Roo.bootstrap.DateSplitField = function(config){
     });
 };
 
-Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.form.DateSplitField, Roo.bootstrap.Component,  {
     
     fieldLabel : '',
     labelAlign : 'top',
@@ -34079,11 +38704,11 @@ Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component,  {
     {
         var _this = this;
         
-        Roo.bootstrap.NavProgressBar.superclass.onRender.call(this, ct, position);
+        Roo.bootstrap.DateSplitFiel.superclass.onRender.call(this, ct, position);
         
         this.inputEl = this.el.select('.roo-date-split-field-group-value', true).first();
         
-        this.dayField = new Roo.bootstrap.ComboBox({
+        this.dayField = new Roo.bootstrap.form.ComboBox({
             allowBlank : this.dayAllowBlank,
             alwaysQuery : true,
             displayField : 'value',
@@ -34115,7 +38740,7 @@ Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component,  {
 
         this.dayField.render(this.el.select('.roo-date-split-field-day', true).first(), null);
         
-        this.monthField = new Roo.bootstrap.MonthField({
+        this.monthField = new Roo.bootstrap.form.MonthField({
             after : '<i class=\"fa fa-calendar\"></i>',
             allowBlank : this.monthAllowBlank,
             placeholder : this.monthPlaceholder,
@@ -34137,7 +38762,7 @@ Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component,  {
         
         this.monthField.render(this.el.select('.roo-date-split-field-month', true).first(), null);
         
-        this.yearField = new Roo.bootstrap.ComboBox({
+        this.yearField = new Roo.bootstrap.form.ComboBox({
             allowBlank : this.yearAllowBlank,
             alwaysQuery : true,
             displayField : 'value',
@@ -34334,7 +38959,13 @@ Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component,  {
     
 });
 
- /**
+
+/**
+ * @class Roo.bootstrap.LayoutMasonry
+ * @extends Roo.bootstrap.Component
+ * @children Roo.bootstrap.Element Roo.bootstrap.Img Roo.bootstrap.MasonryBrick
+ * Bootstrap Layout Masonry class
  *
  * This is based on 
  * http://masonry.desandro.com
@@ -34342,15 +38973,7 @@ Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component,  {
  * The idea is to render all the bricks based on vertical width...
  *
  * The original code extends 'outlayer' - we might need to use that....
- * 
- */
 
-
-/**
- * @class Roo.bootstrap.LayoutMasonry
- * @extends Roo.bootstrap.Component
- * Bootstrap Layout Masonry class
- * 
  * @constructor
  * Create a new Element
  * @param {Object} config The config object
@@ -36921,8 +41544,8 @@ Roo.extend(Roo.bootstrap.Brick, Roo.bootstrap.Component,  {
  */
 
 /**
- * @class Roo.bootstrap.NumberField
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.NumberField
+ * @extends Roo.bootstrap.form.Input
  * Bootstrap NumberField class
  * 
  * 
@@ -36933,11 +41556,11 @@ Roo.extend(Roo.bootstrap.Brick, Roo.bootstrap.Component,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.NumberField = function(config){
-    Roo.bootstrap.NumberField.superclass.constructor.call(this, config);
+Roo.bootstrap.form.NumberField = function(config){
+    Roo.bootstrap.form.NumberField.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.NumberField, Roo.bootstrap.Input, {
+Roo.extend(Roo.bootstrap.form.NumberField, Roo.bootstrap.form.Input, {
     
     /**
      * @cfg {Boolean} allowDecimals False to disallow decimal values (defaults to true)
@@ -37005,7 +41628,7 @@ Roo.extend(Roo.bootstrap.NumberField, Roo.bootstrap.Input, {
         
         this.name = '';
         
-        var cfg = Roo.bootstrap.NumberField.superclass.getAutoCreate.call(this);
+        var cfg = Roo.bootstrap.form.NumberField.superclass.getAutoCreate.call(this);
         
         this.name = hiddenInput.name;
         
@@ -37019,7 +41642,7 @@ Roo.extend(Roo.bootstrap.NumberField, Roo.bootstrap.Input, {
     // private
     initEvents : function()
     {   
-        Roo.bootstrap.NumberField.superclass.initEvents.call(this);
+        Roo.bootstrap.form.NumberField.superclass.initEvents.call(this);
         
         var allowed = "0123456789";
         
@@ -37066,7 +41689,7 @@ Roo.extend(Roo.bootstrap.NumberField, Roo.bootstrap.Input, {
     validateValue : function(value)
     {
         
-        if(!Roo.bootstrap.NumberField.superclass.validateValue.call(this, value)){
+        if(!Roo.bootstrap.form.NumberField.superclass.validateValue.call(this, value)){
             return false;
         }
         
@@ -37373,8 +41996,9 @@ Roo.extend(Roo.bootstrap.DocumentSlider, Roo.bootstrap.Component,  {
  */
 
 /**
- * @class Roo.bootstrap.RadioSet
- * @extends Roo.bootstrap.Input
+ * @class Roo.bootstrap.form.RadioSet
+ * @extends Roo.bootstrap.form.Input
+ * @children Roo.bootstrap.form.Radio
  * Bootstrap RadioSet class
  * @cfg {String} indicatorpos (left|right) default left
  * @cfg {Boolean} inline (true|false) inline the element (default true)
@@ -37384,27 +42008,27 @@ Roo.extend(Roo.bootstrap.DocumentSlider, Roo.bootstrap.Component,  {
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.RadioSet = function(config){
+Roo.bootstrap.form.RadioSet = function(config){
     
-    Roo.bootstrap.RadioSet.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.RadioSet.superclass.constructor.call(this, config);
     
     this.radioes = [];
     
-    Roo.bootstrap.RadioSet.register(this);
+    Roo.bootstrap.form.RadioSet.register(this);
     
     this.addEvents({
         /**
         * @event check
         * Fires when the element is checked or unchecked.
-        * @param {Roo.bootstrap.RadioSet} this This radio
-        * @param {Roo.bootstrap.Radio} item The checked item
+        * @param {Roo.bootstrap.form.RadioSet} this This radio
+        * @param {Roo.bootstrap.form.Radio} item The checked item
         */
        check : true,
        /**
         * @event click
         * Fires when the element is click.
-        * @param {Roo.bootstrap.RadioSet} this This radio set
-        * @param {Roo.bootstrap.Radio} item The checked item
+        * @param {Roo.bootstrap.form.RadioSet} this This radio set
+        * @param {Roo.bootstrap.form.Radio} item The checked item
         * @param {Roo.EventObject} e The event object
         */
        click : true
@@ -37412,7 +42036,7 @@ Roo.bootstrap.RadioSet = function(config){
     
 };
 
-Roo.extend(Roo.bootstrap.RadioSet, Roo.bootstrap.Input,  {
+Roo.extend(Roo.bootstrap.form.RadioSet, Roo.bootstrap.form.Input,  {
 
     radioes : false,
     
@@ -37688,7 +42312,7 @@ Roo.extend(Roo.bootstrap.RadioSet, Roo.bootstrap.Input,  {
     
 });
 
-Roo.apply(Roo.bootstrap.RadioSet, {
+Roo.apply(Roo.bootstrap.form.RadioSet, {
     
     groups: {},
     
@@ -38158,7 +42782,7 @@ Roo.bootstrap.SplitBar.TOP = 3;
  * @type Number
  */
 Roo.bootstrap.SplitBar.BOTTOM = 4;
-Roo.namespace("Roo.bootstrap.layout");/*
+/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -38172,10 +42796,13 @@ Roo.namespace("Roo.bootstrap.layout");/*
 /**
  * @class Roo.bootstrap.layout.Manager
  * @extends Roo.bootstrap.Component
+ * @abstract
  * Base class for layout managers.
  */
 Roo.bootstrap.layout.Manager = function(config)
 {
+    this.monitorWindowResize = true; // do this before we apply configuration.
+    
     Roo.bootstrap.layout.Manager.superclass.constructor.call(this,config);
 
 
@@ -38183,7 +42810,7 @@ Roo.bootstrap.layout.Manager = function(config)
 
 
     /** false to disable window resize monitoring @type Boolean */
-    this.monitorWindowResize = true;
+    
     this.regions = {};
     this.addEvents({
         /**
@@ -38360,6 +42987,8 @@ Roo.extend(Roo.bootstrap.layout.Manager, Roo.bootstrap.Component, {
 /**
  * @class Roo.bootstrap.layout.Border
  * @extends Roo.bootstrap.layout.Manager
+ * @children Roo.bootstrap.panel.Content Roo.bootstrap.panel.Nest Roo.bootstrap.panel.Grid
+ * @parent builder Roo.bootstrap.panel.Nest Roo.bootstrap.panel.Nest Roo.bootstrap.Modal
  * This class represents a common layout manager used in desktop applications. For screenshots and more details,
  * please see: examples/bootstrap/nested.html<br><br>
  
@@ -38391,6 +43020,25 @@ Roo.bootstrap.layout.Border.regions =  ["center", "north","south","east","west"]
 
 Roo.extend(Roo.bootstrap.layout.Border, Roo.bootstrap.layout.Manager, {
     
+       /**
+        * @cfg {Roo.bootstrap.layout.Region} center region to go in center
+        */
+       /**
+        * @cfg {Roo.bootstrap.layout.Region} west region to go in west
+        */
+       /**
+        * @cfg {Roo.bootstrap.layout.Region} east region to go in east
+        */
+       /**
+        * @cfg {Roo.bootstrap.layout.Region} south region to go in south
+        */
+       /**
+        * @cfg {Roo.bootstrap.layout.Region} north region to go in north
+        */
+       
+       
+       
+       
     parent : false, // this might point to a 'nest' or a ???
     
     /**
@@ -40525,7 +45173,7 @@ Roo.extend(Roo.bootstrap.layout.West, Roo.bootstrap.layout.Split, {
         }
         Roo.bootstrap.layout.Region.prototype.updateBox.call(this, box);
     }
-});Roo.namespace("Roo.bootstrap.panel");/*
+});/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -40536,9 +45184,11 @@ Roo.extend(Roo.bootstrap.layout.West, Roo.bootstrap.layout.Split, {
  * <script type="text/javascript">
  */
 /**
- * @class Roo.ContentPanel
+ * @class Roo.bootstrap.paenl.Content
  * @extends Roo.util.Observable
- * A basic ContentPanel element.
+ * @children Roo.bootstrap.Component
+ * @parent builder Roo.bootstrap.layout.Border
+ * A basic ContentPanel element. - a panel that contain any content (eg. forms etc.)
  * @cfg {Boolean}   fitToFrame    True for this panel to adjust its size to fit when the region resizes  (defaults to false)
  * @cfg {Boolean}   fitContainer   When using {@link #fitToFrame} and {@link #resizeEl}, you can also fit the parent container  (defaults to false)
  * @cfg {Boolean/Object} autoCreate True to auto generate the DOM element for this panel, or a {@link Roo.DomHelper} config of the element to create
@@ -40550,7 +45200,7 @@ Roo.extend(Roo.bootstrap.layout.West, Roo.bootstrap.layout.Split, {
  * @cfg {String} title          The title for this panel
  * @cfg {Array} adjustments     Values to <b>add</b> to the width/height when doing a {@link #fitToFrame} (default is [0, 0])
  * @cfg {String} url            Calls {@link #setUrl} with this value
- * @cfg {String} region         (center|north|south|east|west) which region to put this panel on (when used with xtype constructors)
+ * @cfg {String} region  [required] (center|north|south|east|west) which region to put this panel on (when used with xtype constructors)
  * @cfg {String/Object} params  When used with {@link #url}, calls {@link #setUrl} with this value
  * @cfg {Boolean} loadOnce      When used with {@link #url}, calls {@link #setUrl} with this value
  * @cfg {String}    content        Raw content to fill content panel with (uses setContent on construction.)
@@ -40558,13 +45208,11 @@ Roo.extend(Roo.bootstrap.layout.West, Roo.bootstrap.layout.Split, {
  * @cfg {Boolean} badges render the badges
  * @cfg {String} cls  extra classes to use  
  * @cfg {String} background (primary|secondary|success|info|warning|danger|light|dark)
-
  * @constructor
  * Create a new ContentPanel.
- * @param {String/HTMLElement/Roo.Element} el The container element for this panel
  * @param {String/Object} config A string to set only the title or a config object
- * @param {String} content (optional) Set the HTML content for this panel
- * @param {String} region (optional) Used by xtype constructors to add to regions. (values center,east,west,south,north)
  */
 Roo.bootstrap.panel.Content = function( config){
     
@@ -40812,7 +45460,9 @@ Roo.extend(Roo.bootstrap.panel.Content, Roo.bootstrap.Component, {
         this.el.update(content, loadScripts);
     },
 
-    ignoreResize : function(w, h){
+    ignoreResize : function(w, h)
+    {
+        //return false; // always resize?
         if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
             return true;
         }else{
@@ -41126,6 +45776,7 @@ layout.addxtype({
  * @constructor
  * Create a new GridPanel.
  * @cfg {Roo.bootstrap.Table} grid The grid for this panel
+ * @cfg {Roo.bootstrap.nav.Simplebar} toolbar the toolbar at the top of the grid.
  * @param {Object} config A the config object
   
  */
@@ -41216,7 +45867,9 @@ Roo.bootstrap.panel.Grid = function(config)
      
 };
 
-Roo.extend(Roo.bootstrap.panel.Grid, Roo.bootstrap.panel.Content, {
+Roo.extend(Roo.bootstrap.panel.Grid, Roo.bootstrap.panel.Content,
+{
+  
     getId : function(){
         return this.grid.id;
     },
@@ -41229,8 +45882,10 @@ Roo.extend(Roo.bootstrap.panel.Grid, Roo.bootstrap.panel.Content, {
         return this.grid;    
     },
     
-    setSize : function(width, height){
-        if(!this.ignoreResize(width, height)){
+    setSize : function(width, height)
+    {
+     
+        //if(!this.ignoreResize(width, height)){
             var grid = this.grid;
             var size = this.adjustForComponents(width, height);
             // tfoot is not a footer?
@@ -41258,7 +45913,8 @@ Roo.extend(Roo.bootstrap.panel.Grid, Roo.bootstrap.panel.Content, {
             //}
              
             grid.autoSize();
-        }
+        //}
+   
     },
      
     
@@ -41285,7 +45941,6 @@ Roo.extend(Roo.bootstrap.panel.Grid, Roo.bootstrap.panel.Content, {
  * Create a new Panel, that can contain a layout.Border.
  * 
  * 
- * @param {Roo.BorderLayout} layout The layout for this panel
  * @param {String/Object} config A string to set only the title or a config object
  */
 Roo.bootstrap.panel.Nest = function(config)
@@ -41318,6 +45973,10 @@ Roo.bootstrap.panel.Nest = function(config)
 };
 
 Roo.extend(Roo.bootstrap.panel.Nest, Roo.bootstrap.panel.Content, {
+    /**
+    * @cfg {Roo.BorderLayout} layout The layout for this panel
+    */
+    layout : false,
 
     setSize : function(width, height){
         if(!this.ignoreResize(width, height)){
@@ -42351,7 +47010,7 @@ Roo.extend(Roo.bootstrap.panel.TabItem, Roo.util.Observable,
 *    Availability: https://github.com/jackocnr/intl-tel-input.git
 **/
 
-Roo.bootstrap.PhoneInputData = function() {
+Roo.bootstrap.form.PhoneInputData = function() {
     var d = [
       [
         "Afghanistan (‫افغانستان‬‎)",
@@ -43611,8 +48270,8 @@ Roo.bootstrap.PhoneInputData = function() {
 **/
 
 /**
- * @class Roo.bootstrap.PhoneInput
- * @extends Roo.bootstrap.TriggerField
+ * @class Roo.bootstrap.form.PhoneInput
+ * @extends Roo.bootstrap.form.TriggerField
  * An input with International dial-code selection
  
  * @cfg {String} defaultDialCode default '+852'
@@ -43623,12 +48282,14 @@ Roo.bootstrap.PhoneInputData = function() {
  * @param {Object} config Configuration options
  */
 
-Roo.bootstrap.PhoneInput = function(config) {
-    Roo.bootstrap.PhoneInput.superclass.constructor.call(this, config);
+Roo.bootstrap.form.PhoneInput = function(config) {
+    Roo.bootstrap.form.PhoneInput.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
-        
+Roo.extend(Roo.bootstrap.form.PhoneInput, Roo.bootstrap.form.TriggerField, {
+        /**
+        * @cfg {Roo.data.Store} store [required] The data store to which this combo is bound (defaults to undefined)
+        */
         listWidth: undefined,
         
         selectedClass: 'active',
@@ -43653,7 +48314,7 @@ Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
         
         getAutoCreate : function()
         {
-            var data = Roo.bootstrap.PhoneInputData();
+            var data = Roo.bootstrap.form.PhoneInputData();
             var align = this.labelAlign || this.parentLabelAlign();
             var id = Roo.id();
             
@@ -43881,7 +48542,7 @@ Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
         initEvents : function()
         {
             this.createList();
-            Roo.bootstrap.PhoneInput.superclass.initEvents.call(this);
+            Roo.bootstrap.form.PhoneInput.superclass.initEvents.call(this);
             
             this.indicator = this.indicatorEl();
             this.flag = this.flagEl();
@@ -44163,8 +48824,8 @@ Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
         
 });
 /**
- * @class Roo.bootstrap.MoneyField
- * @extends Roo.bootstrap.ComboBox
+ * @class Roo.bootstrap.form.MoneyField
+ * @extends Roo.bootstrap.form.ComboBox
  * Bootstrap MoneyField class
  * 
  * @constructor
@@ -44172,13 +48833,13 @@ Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
  * @param {Object} config Configuration options
  */
 
-Roo.bootstrap.MoneyField = function(config) {
+Roo.bootstrap.form.MoneyField = function(config) {
     
-    Roo.bootstrap.MoneyField.superclass.constructor.call(this, config);
+    Roo.bootstrap.form.MoneyField.superclass.constructor.call(this, config);
     
 };
 
-Roo.extend(Roo.bootstrap.MoneyField, Roo.bootstrap.ComboBox, {
+Roo.extend(Roo.bootstrap.form.MoneyField, Roo.bootstrap.form.ComboBox, {
     
     /**
      * @cfg {Boolean} allowDecimals False to disallow decimal values (defaults to true)
@@ -44243,7 +48904,9 @@ Roo.extend(Roo.bootstrap.MoneyField, Roo.bootstrap.ComboBox, {
     inputmd : 9,
     inputsm : 9,
     inputxs : 6,
-    
+     /**
+     * @cfg {Roo.data.Store} store  Store to lookup currency??
+     */
     store : false,
     
     getAutoCreate : function()
@@ -44782,7 +49445,7 @@ Roo.extend(Roo.bootstrap.MoneyField, Roo.bootstrap.ComboBox, {
     
     validateValue : function(value)
     {
-        if(!Roo.bootstrap.MoneyField.superclass.validateValue.call(this, value)){
+        if(!Roo.bootstrap.form.MoneyField.superclass.validateValue.call(this, value)){
             return false;
         }
         
@@ -45477,4 +50140,42 @@ Roo.extend(Roo.bootstrap.BezierSignature, Roo.bootstrap.Component,
 
  
 
\ No newline at end of file
+ // old names for form elements
+Roo.bootstrap.Form          =   Roo.bootstrap.form.Form;
+Roo.bootstrap.Input         =   Roo.bootstrap.form.Input;
+Roo.bootstrap.TextArea      =   Roo.bootstrap.form.TextArea;
+Roo.bootstrap.TriggerField  =   Roo.bootstrap.form.TriggerField;
+Roo.bootstrap.ComboBox      =   Roo.bootstrap.form.ComboBox;
+Roo.bootstrap.DateField     =   Roo.bootstrap.form.DateField;
+Roo.bootstrap.TimeField     =   Roo.bootstrap.form.TimeField;
+Roo.bootstrap.MonthField    =   Roo.bootstrap.form.MonthField;
+Roo.bootstrap.CheckBox      =   Roo.bootstrap.form.CheckBox;
+Roo.bootstrap.Radio         =   Roo.bootstrap.form.Radio;
+Roo.bootstrap.RadioSet      =   Roo.bootstrap.form.RadioSet;
+Roo.bootstrap.SecurePass    =   Roo.bootstrap.form.SecurePass;
+Roo.bootstrap.FieldLabel    =   Roo.bootstrap.form.FieldLabel;
+Roo.bootstrap.DateSplitField=   Roo.bootstrap.form.DateSplitField;
+Roo.bootstrap.NumberField   =   Roo.bootstrap.form.NumberField;
+Roo.bootstrap.PhoneInput    =   Roo.bootstrap.form.PhoneInput;
+Roo.bootstrap.PhoneInputData=   Roo.bootstrap.form.PhoneInputData;
+Roo.bootstrap.MoneyField    =   Roo.bootstrap.form.MoneyField;
+Roo.bootstrap.HtmlEditor    =   Roo.bootstrap.form.HtmlEditor;
+Roo.bootstrap.HtmlEditor.ToolbarStandard =   Roo.bootstrap.form.HtmlEditorToolbarStandard;
+Roo.bootstrap.Markdown      = Roo.bootstrap.form.Markdown;
+Roo.bootstrap.CardUploader  = Roo.bootstrap.form.CardUploader;// depricated.
+Roo.bootstrap.Navbar            = Roo.bootstrap.nav.Bar;
+Roo.bootstrap.NavGroup          = Roo.bootstrap.nav.Group;
+Roo.bootstrap.NavHeaderbar      = Roo.bootstrap.nav.Headerbar;
+Roo.bootstrap.NavItem           = Roo.bootstrap.nav.Item;
+
+Roo.bootstrap.NavProgressBar     = Roo.bootstrap.nav.ProgressBar;
+Roo.bootstrap.NavProgressBarItem = Roo.bootstrap.nav.ProgressBarItem;
+
+Roo.bootstrap.NavSidebar        = Roo.bootstrap.nav.Sidebar;
+Roo.bootstrap.NavSidebarItem    = Roo.bootstrap.nav.SidebarItem;
+
+Roo.bootstrap.NavSimplebar      = Roo.bootstrap.nav.Simplebar;// deprciated 
+Roo.bootstrap.Menu = Roo.bootstrap.menu.Menu;
+Roo.bootstrap.MenuItem =  Roo.bootstrap.menu.Item;
+Roo.bootstrap.MenuSeparator = Roo.bootstrap.menu.Separator
+