docs/default.css
[roojs1] / roojs-bootstrap-debug.js
index 0c467ba..40493b7 100644 (file)
@@ -989,6 +989,7 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
  * @cfg {String} icon (info-sign|check|...) glyphicon name
  * @cfg {Boolean} hidden (true|false) hide the element
  * @cfg {Boolean} expandable (true|false) default false
+ * @cfg {Boolean} expanded (true|false) default true
  * @cfg {String} rheader contet on the right of header
 
  *     
@@ -1116,15 +1117,16 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
                     
                     h.push({
                         tag: 'i',
-                        cls: 'fa fa-minus'
+                        cls: (this.expanded ? 'fa fa-minus' : 'fa fa-plus') 
                     });
+                    
                 }
                 
                 h.push(
                     {
                         tag: 'span',
                         cls : 'panel-title',
-                        html : this.header
+                        html : (this.expandable ? ' ' : '') + this.header
                     },
                     {
                         tag: 'span',
@@ -1135,6 +1137,7 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
                 
                 cfg.cn.push({
                     cls : 'panel-heading',
+                    style : this.expandable ? 'cursor: pointer' : '',
                     cn : h
                 });
                 
@@ -1142,7 +1145,7 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             body = false;
             cfg.cn.push({
-                cls : 'panel-body',
+                cls : 'panel-body' + (this.expanded ? '' : ' hide'),
                 html : this.html
             });
             
@@ -1214,8 +1217,10 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             this.expanded = true;
             
-            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
-        
+            //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
+            
+            this.el.select('.panel-body',true).first().removeClass('hide');
+            
             var toggleEl = this.toggleEl();
 
             if(!toggleEl){
@@ -1233,7 +1238,8 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             this.expanded = false;
             
-            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+            //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+            this.el.select('.panel-body',true).first().addClass('hide');
         
             var toggleEl = this.toggleEl();
 
@@ -1392,7 +1398,9 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
             
             var s = ['xs', 'sm', 'md', 'lg'];
             
-            Roo.eac(ss.splice(ss.indexOf(size), 1), function(ss){
+            s.splice(s.indexOf(size), 1);
+            
+            Roo.each(s, function(ss){
                 img.cls += ' hidden-' + ss;
             });
             
@@ -2419,7 +2427,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
     
         if (this.buttons.length) {
             Roo.each(this.buttons, function(bb) {
-                b = Roo.apply({}, bb);
+                var b = Roo.apply({}, bb);
                 b.xns = b.xns || Roo.bootstrap;
                 b.xtype = b.xtype || 'Button';
                 if (typeof(b.listeners) == 'undefined') {
@@ -2453,6 +2461,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         //this.el.addClass([this.fieldClass, this.cls]);
         
     },
+    
     getAutoCreate : function(){
         
         
@@ -2539,8 +2548,18 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         if (this.allow_close) {
             this.closeEl.on('click', this.hide, this);
         }
+        
+        var _this = this;
+        
+        window.addEventListener("resize", function() { _this.resize(); } );
 
     },
+    
+    resize : function()
+    {
+        this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
+    },
+    
     show : function() {
         
         if (!this.rendered) {
@@ -4173,7 +4192,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     },
     setActive : function(state, fire, is_was_active)
     {
-        if (this.active && !state & this.navId) {
+        if (this.active && !state && this.navId) {
             this.was_active = true;
             var nv = Roo.bootstrap.NavGroup.get(this.navId);
             if (nv) {
@@ -5366,10 +5385,10 @@ Roo.LoadMask.prototype = {
  * @cfg {boolean} condensed Format condensed
  * @cfg {boolean} responsive Format condensed
  * @cfg {Boolean} loadMask (true|false) default false
- * @cfg {Boolean} tfoot (true|false) generate tfoot, default true
- * @cfg {Boolean} thead (true|false) generate thead, default true
- * @cfg {Boolean} RowSelection (true|false) default false
- * @cfg {Boolean} CellSelection (true|false) default false
+ * @cfg {Boolean} footerShow (true|false) generate tfoot, default true
+ * @cfg {Boolean} headerShow (true|false) generate thead, default true
+ * @cfg {Boolean} rowSelection (true|false) default false
+ * @cfg {Boolean} cellSelection (true|false) default false
  * @cfg {Roo.bootstrap.PagingToolbar} footer  a paging toolbar
  
  * 
@@ -5381,6 +5400,13 @@ Roo.LoadMask.prototype = {
 Roo.bootstrap.Table = function(config){
     Roo.bootstrap.Table.superclass.constructor.call(this, config);
     
+    // BC...
+    this.rowSelection = (typeof(config.RowSelection) != 'undefined') ? config.RowSelection : this.rowSelection;
+    this.cellSelection = (typeof(config.CellSelection) != 'undefined') ? config.CellSelection : this.cellSelection;
+    this.headerShow = (typeof(config.thead) != 'undefined') ? config.thead : this.headerShow;
+    this.footerShow = (typeof(config.tfoot) != 'undefined') ? config.tfoot : this.footerShow;
+    
+    
     if (this.sm) {
         this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table);
         this.sm = this.selModel;
@@ -5501,10 +5527,11 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     cm : false,
     store : false,
     loadMask : false,
-    tfoot : true,
-    thead : true,
-    RowSelection : false,
-    CellSelection : false,
+    footerShow : true,
+    headerShow : true,
+  
+    rowSelection : false,
+    cellSelection : false,
     layout : false,
     
     // Roo.Element - the tbody
@@ -5577,13 +5604,13 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
         }
         
         if(this.store || this.cm){
-            if(this.thead){
+            if(this.headerShow){
                 cfg.cn.push(this.renderHeader());
             }
             
             cfg.cn.push(this.renderBody());
             
-            if(this.tfoot){
+            if(this.footerShow){
                 cfg.cn.push(this.renderFooter());
             }
             
@@ -5675,7 +5702,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     {
         var cell = Roo.get(el);
         
-        if(!cell || (!this.CellSelection && !this.RowSelection)){
+        if(!cell || (!this.cellSelection && !this.rowSelection)){
             return;
         }
         
@@ -5696,11 +5723,12 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
         var cellIndex = cell.dom.cellIndex;
         var rowIndex = this.getRowIndex(row);
         
-        if(this.CellSelection){
+        // why??? - should these not be based on SelectionModel?
+        if(this.cellSelection){
             this.fireEvent('cellclick', this, cell, rowIndex, cellIndex, e);
         }
         
-        if(this.RowSelection){
+        if(this.rowSelection){
             this.fireEvent('rowclick', this, row, rowIndex, e);
         }
         
@@ -5779,13 +5807,35 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
         for(var i = 0, len = cm.getColumnCount(); i < len; i++){
             
             var config = cm.config[i];
-                    
+            
             var c = {
                 tag: 'th',
                 style : '',
                 html: cm.getColumnHeader(i)
             };
             
+            var hh = '';
+            
+            if(typeof(config.lgHeader) != 'undefined'){
+                hh += '<span class="hidden-xs hidden-sm hidden-md">' + config.lgHeader + '</span>';
+            }
+            
+            if(typeof(config.mdHeader) != 'undefined'){
+                hh += '<span class="hidden-xs hidden-sm hidden-lg">' + config.mdHeader + '</span>';
+            }
+            
+            if(typeof(config.smHeader) != 'undefined'){
+                hh += '<span class="hidden-xs hidden-md hidden-lg">' + config.smHeader + '</span>';
+            }
+            
+            if(typeof(config.xsHeader) != 'undefined'){
+                hh += '<span class="hidden-sm hidden-md hidden-lg">' + config.xsHeader + '</span>';
+            }
+            
+            if(hh.length){
+                c.html = hh;
+            }
+            
             if(typeof(config.tooltip) != 'undefined'){
                 c.tooltip = config.tooltip;
             }
@@ -7459,6 +7509,8 @@ Roo.form.VTypes = function(){
  * @cfg {String} autocomplete - default is new-password see: https://developers.google.com/web/fundamentals/input/form/label-and-name-inputs?hl=en
 
  * @cfg {String} align (left|center|right) Default left
+ * @cfg {Boolean} forceFeedback (true|false) Default false
+ * 
  * 
  * 
  * 
@@ -7654,6 +7706,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
     readOnly : false,
     align : false,
     formatedValue : false,
+    forceFeedback : false,
     
     parentLabelAlign : function()
     {
@@ -7874,7 +7927,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         this.inputEl().on("blur", this.onBlur,  this);
         
         this.inputEl().relayEvent('keyup', this);
-
         // reference to original value for reset
         this.originalValue = this.getValue();
         //Roo.form.TextField.superclass.initEvents.call(this);
@@ -8147,13 +8200,19 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         
         this.el.removeClass([this.invalidClass, this.validClass]);
         
+        var feedback = this.el.select('.form-control-feedback', true).first();
+            
+        if(feedback){
+            this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
+        }
+
         if(this.disabled || this.allowBlank){
             return;
         }
         
         this.el.addClass(this.validClass);
         
-        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && this.getValue().length){
+        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && (this.getValue().length || this.forceFeedback)){
             
             var feedback = this.el.select('.form-control-feedback', true).first();
             
@@ -8178,6 +8237,12 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         
         this.el.removeClass([this.invalidClass, this.validClass]);
         
+        var feedback = this.el.select('.form-control-feedback', true).first();
+            
+        if(feedback){
+            this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
+        }
+
         if(this.disabled || this.allowBlank){
             return;
         }
@@ -8191,7 +8256,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             if(feedback){
                 this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
                 
-                if(this.getValue().length){
+                if(this.getValue().length || this.forceFeedback){
                     this.el.select('.form-control-feedback', true).first().addClass([this.invalidFeedbackClass]);
                 }
                 
@@ -8585,7 +8650,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                     ] 
                 };
             }
-              
+
         } else {
             if(this.removable && !this.editable && !this.tickable){
                 inputblock = {
@@ -8774,7 +8839,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                 cfg.cls += ' col-' + size + '-' + settings[size];
             }
         });
-        
+        Roo.log(cfg);
         return cfg;
         
     },
@@ -8832,7 +8897,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             var close = this.closeTriggerEl();
             
             if(close){
-                close.setVisibilityMode(Roo.Element.DISPALY).hide();
+                close.setVisibilityMode(Roo.Element.DISPLAY).hide();
                 close.on('click', this.removeBtnClick, this, close);
             }
         }
@@ -8855,7 +8920,9 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
     {
         e.preventDefault();
         
-        this.fireEvent("remove", this);
+        if(this.fireEvent("remove", this) !== false){
+            this.reset();
+        }
     },
     
     createList : function()
@@ -11034,6 +11101,8 @@ Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
  * @cfg {Boolean} triggerList trigger show the list or not (true|false) default true
  * @cfg {Boolean} showToggleBtn show toggle button or not (true|false) default true
  * @cfg {String} btnPosition set the position of the trigger button (left | right) default right
+ * @cfg {Boolean} animate default true
+ * @cfg {Boolean} emptyResultText only for touch device
  * @constructor
  * Create a new ComboBox.
  * @param {Object} config Configuration options
@@ -11304,6 +11373,11 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
      */
     specialFilter : false,
     
+    /**
+     * @cfg {Boolean} mobileTouchView (true|false) show mobile touch view when using a mobile default true
+     */
+    mobileTouchView : true,
+    
     //private
     addicon : false,
     editicon: false,
@@ -11317,12 +11391,23 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     btnPosition : 'right',
     triggerList : true,
     showToggleBtn : true,
+    animate : true,
+    emptyResultText: 'Empty',
     // element that contains real text value.. (when hidden is used..)
     
     getAutoCreate : function()
     {
         var cfg = false;
         
+        /*
+         * Touch Devices
+         */
+        
+        if(Roo.isTouch && this.mobileTouchView){
+            cfg = this.getAutoCreateTouchView();
+            return cfg;;
+        }
+        
         /*
          *  Normal ComboBox
          */
@@ -11495,8 +11580,18 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         if (!this.store) {
             throw "can not find store for combo";
         }
+        
         this.store = Roo.factory(this.store, Roo.data);
         
+        /*
+         * Touch Devices
+         */
+        
+        if(Roo.isTouch && this.mobileTouchView){
+            this.initTouchView();
+            return;
+        }
+        
         if(this.tickable){
             this.initTickableEvents();
             return;
@@ -12106,7 +12201,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         var close = this.closeTriggerEl();
         
         if(close){
-            (v.length || v * 1 > 0) ? close.show() : close.hide();
+            (v && (v.length || v * 1 > 0)) ? close.show() : close.hide();
         }
     },
     /**
@@ -12849,13 +12944,22 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         this.syncValue();
         
         this.validate();
+        
+        if(this.tickable && !Roo.isTouch){
+            this.view.refresh();
+        }
     },
     
     inputEl: function ()
     {
+        if(Roo.isTouch && this.mobileTouchView){
+            return this.el.select('input.form-control',true).first();
+        }
+        
         if(this.tickable){
             return this.searchField;
         }
+        
         return this.el.select('input.form-control',true).first();
     },
     
@@ -12908,2016 +13012,4139 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         }
         
         return this.inputEl().select('.select2-search-field-input', true).first();
-    }
+    },
     
     
+    getAutoCreateTouchView : function()
+    {
+        var id = Roo.id();
+        
+        var cfg = {
+            cls: 'form-group' //input-group
+        };
+        
+        var input =  {
+            tag: 'input',
+            id : id,
+            type : this.inputType,
+            cls : 'form-control x-combo-noedit',
+            autocomplete: 'new-password',
+            placeholder : this.placeholder || '',
+            readonly : true
+        };
+        
+        if (this.name) {
+            input.name = this.name;
+        }
+        
+        if (this.size) {
+            input.cls += ' input-' + this.size;
+        }
+        
+        if (this.disabled) {
+            input.disabled = true;
+        }
+        
+        var inputblock = {
+            cls : '',
+            cn : [
+                input
+            ]
+        };
+        
+        if(this.before){
+            inputblock.cls += ' input-group';
+            
+            inputblock.cn.unshift({
+                tag :'span',
+                cls : 'input-group-addon',
+                html : this.before
+            });
+        }
+        
+        if(this.removable && !this.multiple){
+            inputblock.cls += ' roo-removable';
+            
+            inputblock.cn.push({
+                tag: 'button',
+                html : 'x',
+                cls : 'roo-combo-removable-btn close'
+            });
+        }
 
-    /** 
-    * @cfg {Boolean} grow 
-    * @hide 
-    */
-    /** 
-    * @cfg {Number} growMin 
-    * @hide 
-    */
-    /** 
-    * @cfg {Number} growMax 
-    * @hide 
-    */
-    /**
-     * @hide
-     * @method autoSize
-     */
-});
-/*
- * 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.View
- * @extends Roo.util.Observable
- * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template. 
- * This class also supports single and multi selection modes. <br>
- * Create a data model bound view:
- <pre><code>
- var store = new Roo.data.Store(...);
+        if(this.hasFeedback && !this.allowBlank){
+            
+            inputblock.cls += ' has-feedback';
+            
+            inputblock.cn.push({
+                tag: 'span',
+                cls: 'glyphicon form-control-feedback'
+            });
+            
+        }
+        
+        if (this.after) {
+            
+            inputblock.cls += (this.before) ? '' : ' input-group';
+            
+            inputblock.cn.push({
+                tag :'span',
+                cls : 'input-group-addon',
+                html : this.after
+            });
+        }
 
- var view = new Roo.View({
-    el : "my-element",
-    tpl : '&lt;div id="{0}"&gt;{2} - {1}&lt;/div&gt;', // auto create template
-    singleSelect: true,
-    selectedClass: "ydataview-selected",
-    store: store
- });
+        var box = {
+            tag: 'div',
+            cn: [
+                {
+                    tag: 'input',
+                    type : 'hidden',
+                    cls: 'form-hidden-field'
+                },
+                inputblock
+            ]
+            
+        };
+        
+        if(this.multiple){
+            box = {
+                tag: 'div',
+                cn: [
+                    {
+                        tag: 'input',
+                        type : 'hidden',
+                        cls: 'form-hidden-field'
+                    },
+                    {
+                        tag: 'ul',
+                        cls: 'select2-choices',
+                        cn:[
+                            {
+                                tag: 'li',
+                                cls: 'select2-search-field',
+                                cn: [
 
- // listen for node click?
- view.on("click", function(vw, index, node, e){
- alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
- });
+                                    inputblock
+                                ]
+                            }
+                        ]
+                    }
+                ]
+            }
+        };
+        
+        var combobox = {
+            cls: 'select2-container input-group',
+            cn: [
+                box
+            ]
+        };
+        
+        if(this.multiple){
+            combobox.cls += ' select2-container-multi';
+        }
+        
+        var align = this.labelAlign || this.parentLabelAlign();
+        
+        cfg.cn = combobox;
+        
+        if(this.fieldLabel.length){
+            
+            var lw = align === 'left' ? ('col-sm' + this.labelWidth) : '';
+            var cw = align === 'left' ? ('col-sm' + (12 - this.labelWidth)) : '';
+            
+            cfg.cn = [
+                {
+                    tag: 'label',
+                    cls : 'control-label ' + lw,
+                    html : this.fieldLabel
 
- // load XML data
- dataModel.load("foobar.xml");
- </code></pre>
- For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
- * <br><br>
- * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
- * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
- * 
- * Note: old style constructor is still suported (container, template, config)
- * 
- * @constructor
- * Create a new View
- * @param {Object} config The config object
- * 
- */
-Roo.View = function(config, depreciated_tpl, depreciated_config){
-    
-    this.parent = false;
-    
-    if (typeof(depreciated_tpl) == 'undefined') {
-        // new way.. - universal constructor.
-        Roo.apply(this, config);
-        this.el  = Roo.get(this.el);
-    } else {
-        // old format..
-        this.el  = Roo.get(config);
-        this.tpl = depreciated_tpl;
-        Roo.apply(this, depreciated_config);
-    }
-    this.wrapEl  = this.el.wrap().wrap();
-    ///this.el = this.wrapEla.appendChild(document.createElement("div"));
-    
-    
-    if(typeof(this.tpl) == "string"){
-        this.tpl = new Roo.Template(this.tpl);
-    } else {
-        // support xtype ctors..
-        this.tpl = new Roo.factory(this.tpl, Roo);
-    }
-    
+                },
+                {
+                    cls : cw, 
+                    cn: [
+                        combobox
+                    ]
+                }
+            ];
+        }
+        
+        var settings = this;
+        
+        ['xs','sm','md','lg'].map(function(size){
+            if (settings[size]) {
+                cfg.cls += ' col-' + size + '-' + settings[size];
+            }
+        });
+        
+        return cfg;
+    },
     
-    this.tpl.compile();
+    initTouchView : function()
+    {
+        this.renderTouchView();
+        
+        this.touchViewEl.on('scroll', function(){
+            this.el.dom.scrollTop = 0;
+        }, this);
+        
+        this.inputEl().on("click", this.showTouchView, this);
+        this.touchViewFooterEl.select('.roo-touch-view-cancel', true).first().on('click', this.hideTouchView, this);
+        this.touchViewFooterEl.select('.roo-touch-view-ok', true).first().on('click', this.setTouchViewValue, this);
+        
+        this.maskEl = new Roo.LoadMask(this.touchViewEl, { store : this.store, msgCls: 'roo-el-mask-msg' });
+        
+        this.store.on('beforeload', this.onTouchViewBeforeLoad, this);
+        this.store.on('load', this.onTouchViewLoad, this);
+        this.store.on('loadexception', this.onTouchViewLoadException, this);
+        
+        if(this.hiddenName){
+            
+            this.hiddenField = this.el.select('input.form-hidden-field',true).first();
+            
+            this.hiddenField.dom.value =
+                this.hiddenValue !== undefined ? this.hiddenValue :
+                this.value !== undefined ? this.value : '';
+        
+            this.el.dom.removeAttribute('name');
+            this.hiddenField.dom.setAttribute('name', this.hiddenName);
+        }
+        
+        if(this.multiple){
+            this.choices = this.el.select('ul.select2-choices', true).first();
+            this.searchField = this.el.select('ul li.select2-search-field', true).first();
+        }
+        
+        if(this.removable && !this.multiple){
+            var close = this.closeTriggerEl();
+            if(close){
+                close.setVisibilityMode(Roo.Element.DISPLAY).hide();
+                close.on('click', this.removeBtnClick, this, close);
+            }
+        }
+        
+        return;
+        
+        
+    },
     
-    /** @private */
-    this.addEvents({
-        /**
-         * @event beforeclick
-         * Fires before a click is processed. Returns false to cancel the default action.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "beforeclick" : true,
-        /**
-         * @event click
-         * Fires when a template node is clicked.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "click" : true,
-        /**
-         * @event dblclick
-         * Fires when a template node is double clicked.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "dblclick" : true,
-        /**
-         * @event contextmenu
-         * Fires when a template node is right clicked.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "contextmenu" : true,
-        /**
-         * @event selectionchange
-         * Fires when the selected nodes change.
-         * @param {Roo.View} this
-         * @param {Array} selections Array of the selected nodes
-         */
-            "selectionchange" : true,
+    renderTouchView : function()
+    {
+        this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.ComboBox.touchViewTemplate);
+        this.touchViewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.touchViewHeaderEl = this.touchViewEl.select('.modal-header', true).first();
+        this.touchViewHeaderEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.touchViewBodyEl = this.touchViewEl.select('.modal-body', true).first();
+        this.touchViewBodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.touchViewBodyEl.setStyle('overflow', 'auto');
+        
+        this.touchViewListGroup = this.touchViewBodyEl.select('.list-group', true).first();
+        this.touchViewListGroup.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.touchViewFooterEl = this.touchViewEl.select('.modal-footer', true).first();
+        this.touchViewFooterEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+    },
     
-        /**
-         * @event beforeselect
-         * Fires before a selection is made. If any handlers return false, the selection is cancelled.
-         * @param {Roo.View} this
-         * @param {HTMLElement} node The node to be selected
-         * @param {Array} selections Array of currently selected nodes
-         */
-            "beforeselect" : true,
-        /**
-         * @event preparedata
-         * Fires on every row to render, to allow you to change the data.
-         * @param {Roo.View} this
-         * @param {Object} data to be rendered (change this)
-         */
-          "preparedata" : true
-          
-          
-        });
+    showTouchView : function()
+    {
+        this.touchViewHeaderEl.hide();
 
+        if(this.fieldLabel.length){
+            this.touchViewHeaderEl.dom.innerHTML = this.fieldLabel;
+            this.touchViewHeaderEl.show();
+        }
 
+        this.touchViewEl.show();
 
-    this.el.on({
-        "click": this.onClick,
-        "dblclick": this.onDblClick,
-        "contextmenu": this.onContextMenu,
-        scope:this
-    });
+        this.touchViewEl.select('.modal-dialog', true).first().setStyle('margin', '0px');
+        this.touchViewEl.select('.modal-dialog > .modal-content', true).first().setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
 
-    this.selections = [];
-    this.nodes = [];
-    this.cmp = new Roo.CompositeElementLite([]);
-    if(this.store){
-        this.store = Roo.factory(this.store, Roo.data);
-        this.setStore(this.store, true);
-    }
-    
-    if ( this.footer && this.footer.xtype) {
-           
-         var fctr = this.wrapEl.appendChild(document.createElement("div"));
+        var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+        if(this.fieldLabel.length){
+            bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+        }
         
-        this.footer.dataSource = this.store
-        this.footer.container = fctr;
-        this.footer = Roo.factory(this.footer, Roo);
-        fctr.insertFirst(this.el);
+        this.touchViewBodyEl.setHeight(bodyHeight);
+
+        if(this.animate){
+            var _this = this;
+            (function(){ _this.touchViewEl.addClass('in'); }).defer(50);
+        }else{
+            this.touchViewEl.addClass('in');
+        }
+
+        this.doTouchViewQuery();
         
-        // this is a bit insane - as the paging toolbar seems to detach the el..
-//        dom.parentNode.parentNode.parentNode
-         // they get detached?
-    }
+    },
     
+    hideTouchView : function()
+    {
+        this.touchViewEl.removeClass('in');
+
+        if(this.animate){
+            var _this = this;
+            (function(){ _this.touchViewEl.setStyle('display', 'none'); }).defer(150);
+        }else{
+            this.touchViewEl.setStyle('display', 'none');
+        }
+        
+    },
     
-    Roo.View.superclass.constructor.call(this);
+    setTouchViewValue : function()
+    {
+        if(this.multiple){
+            this.clearItem();
+        
+            var _this = this;
+
+            Roo.each(this.tickItems, function(o){
+                this.addItem(o);
+            }, this);
+        }
+        
+        this.hideTouchView();
+    },
     
+    doTouchViewQuery : function()
+    {
+        var qe = {
+            query: '',
+            forceAll: true,
+            combo: this,
+            cancel:false
+        };
+        
+        if(this.fireEvent('beforequery', qe) ===false || qe.cancel){
+            return false;
+        }
+        
+        if(!this.alwaysQuery || this.mode == 'local'){
+            this.onTouchViewLoad();
+            return;
+        }
+        
+        this.store.load();
+    },
     
-};
+    onTouchViewBeforeLoad : function(combo,opts)
+    {
+        return;
+    },
 
-Roo.extend(Roo.View, Roo.util.Observable, {
+    // private
+    onTouchViewLoad : function()
+    {
+        if(this.store.getCount() < 1){
+            this.onTouchViewEmptyResults();
+            return;
+        }
+        
+        this.clearTouchView();
+        
+        var rawValue = this.getRawValue();
+        
+        var template = (this.multiple) ? Roo.bootstrap.ComboBox.listItemCheckbox : Roo.bootstrap.ComboBox.listItemRadio;
+        
+        this.tickItems = [];
+        
+        this.store.data.each(function(d, rowIndex){
+            var row = this.touchViewListGroup.createChild(template);
+            
+            if(this.displayField && typeof(d.data[this.displayField]) != 'undefined'){
+                row.select('.roo-combobox-list-group-item-value', true).first().dom.innerHTML = d.data[this.displayField];
+            }
+            
+            if(!this.multiple && this.valueField && typeof(d.data[this.valueField]) != 'undefined' && d.data[this.valueField] == this.getValue()){
+                row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+            }
+            
+            if(this.multiple && this.valueField && typeof(d.data[this.valueField]) != 'undefined' && this.getValue().indexOf(d.data[this.valueField]) != -1){
+                row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+                this.tickItems.push(d.data);
+            }
+            
+            row.on('click', this.onTouchViewClick, this, {row : row, rowIndex : rowIndex});
+            
+        }, this);
+        
+        var firstChecked = this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).first();
+        
+        var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+        if(this.fieldLabel.length){
+            bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+        }
+
+        var listHeight = this.touchViewListGroup.getHeight();
+        
+        var _this = this;
+        
+        if(firstChecked && listHeight > bodyHeight){
+            (function() { firstChecked.findParent('li').scrollIntoView(_this.touchViewListGroup.dom); }).defer(500);
+        }
+        
+    },
     
-     /**
-     * @cfg {Roo.data.Store} store Data store to load data from.
-     */
-    store : false,
+    onTouchViewLoadException : function()
+    {
+        this.hideTouchView();
+    },
     
-    /**
-     * @cfg {String|Roo.Element} el The container element.
-     */
-    el : '',
+    onTouchViewEmptyResults : function()
+    {
+        this.clearTouchView();
+        
+        this.touchViewListGroup.createChild(Roo.bootstrap.ComboBox.emptyResult);
+        
+        this.touchViewListGroup.select('.roo-combobox-touch-view-empty-result', true).first().dom.innerHTML = this.emptyResultText;
+        
+    },
     
-    /**
-     * @cfg {String|Roo.Template} tpl The template used by this View 
-     */
-    tpl : false,
-    /**
-     * @cfg {String} dataName the named area of the template to use as the data area
-     *                          Works with domtemplates roo-name="name"
-     */
-    dataName: false,
-    /**
-     * @cfg {String} selectedClass The css class to add to selected nodes
-     */
-    selectedClass : "x-view-selected",
-     /**
-     * @cfg {String} emptyText The empty text to show when nothing is loaded.
-     */
-    emptyText : "",
-    
-    /**
-     * @cfg {String} text to display on mask (default Loading)
-     */
-    mask : false,
-    /**
-     * @cfg {Boolean} multiSelect Allow multiple selection
-     */
-    multiSelect : false,
-    /**
-     * @cfg {Boolean} singleSelect Allow single selection
-     */
-    singleSelect:  false,
-    
-    /**
-     * @cfg {Boolean} toggleSelect - selecting 
-     */
-    toggleSelect : false,
-    
-    /**
-     * @cfg {Boolean} tickable - selecting 
-     */
-    tickable : false,
-    
-    /**
-     * Returns the element this view is bound to.
-     * @return {Roo.Element}
-     */
-    getEl : function(){
-        return this.wrapEl;
+    clearTouchView : function()
+    {
+        this.touchViewListGroup.dom.innerHTML = '';
     },
     
-    
-
-    /**
-     * Refreshes the view. - called by datachanged on the store. - do not call directly.
-     */
-    refresh : function(){
-        //Roo.log('refresh');
-        var t = this.tpl;
-        
-        // if we are using something like 'domtemplate', then
-        // the what gets used is:
-        // t.applySubtemplate(NAME, data, wrapping data..)
-        // the outer template then get' applied with
-        //     the store 'extra data'
-        // and the body get's added to the
-        //      roo-name="data" node?
-        //      <span class='roo-tpl-{name}'></span> ?????
+    onTouchViewClick : function(e, el, o)
+    {
+        e.preventDefault();
         
+        var row = o.row;
+        var rowIndex = o.rowIndex;
         
+        var r = this.store.getAt(rowIndex);
         
-        this.clearSelections();
-        this.el.update("");
-        var html = [];
-        var records = this.store.getRange();
-        if(records.length < 1) {
-            
-            // is this valid??  = should it render a template??
+        if(!this.multiple){
+            Roo.each(this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).elements, function(c){
+                c.dom.removeAttribute('checked');
+            }, this);
             
-            this.el.update(this.emptyText);
-            return;
-        }
-        var el = this.el;
-        if (this.dataName) {
-            this.el.update(t.apply(this.store.meta)); //????
-            el = this.el.child('.roo-tpl-' + this.dataName);
-        }
+            row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
         
-        for(var i = 0, len = records.length; i < len; i++){
-            var data = this.prepareData(records[i].data, i, records[i]);
-            this.fireEvent("preparedata", this, data, i, records[i]);
-            
-            var d = Roo.apply({}, data);
-            
-            if(this.tickable){
-                Roo.apply(d, {'roo-id' : Roo.id()});
-                
-                var _this = this;
+            this.setFromData(r.data);
             
-                Roo.each(this.parent.item, function(item){
-                    if(item[_this.parent.valueField] != data[_this.parent.valueField]){
-                        return;
-                    }
-                    Roo.apply(d, {'roo-data-checked' : 'checked'});
-                });
+            var close = this.closeTriggerEl();
+        
+            if(close){
+                close.show();
             }
+
+            this.hideTouchView();
             
-            html[html.length] = Roo.util.Format.trim(
-                this.dataName ?
-                    t.applySubtemplate(this.dataName, d, this.store.meta) :
-                    t.apply(d)
-            );
+            this.fireEvent('select', this, r, rowIndex);
+            
+            return;
         }
         
+        if(this.valueField && typeof(r.data[this.valueField]) != 'undefined' && this.getValue().indexOf(r.data[this.valueField]) != -1){
+            row.select('.roo-combobox-list-group-item-box > input', true).first().dom.removeAttribute('checked');
+            this.tickItems.splice(this.tickItems.indexOf(r.data), 1);
+            return;
+        }
         
+        row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+        this.addItem(r.data);
+        this.tickItems.push(r.data);
         
-        el.update(html.join(""));
-        this.nodes = el.dom.childNodes;
-        this.updateIndexes(0);
-    },
+    }
     
 
+    /** 
+    * @cfg {Boolean} grow 
+    * @hide 
+    */
+    /** 
+    * @cfg {Number} growMin 
+    * @hide 
+    */
+    /** 
+    * @cfg {Number} growMax 
+    * @hide 
+    */
     /**
-     * Function to override to reformat the data that is sent to
-     * the template for each node.
-     * DEPRICATED - use the preparedata event handler.
-     * @param {Array/Object} data The raw data (array of colData for a data model bound view or
-     * a JSON object for an UpdateManager bound view).
+     * @hide
+     * @method autoSize
      */
-    prepareData : function(data, index, record)
-    {
-        this.fireEvent("preparedata", this, data, index, record);
-        return data;
-    },
+});
 
-    onUpdate : function(ds, record){
-        // Roo.log('on update');   
-        this.clearSelections();
-        var index = this.store.indexOf(record);
-        var n = this.nodes[index];
-        this.tpl.insertBefore(n, this.prepareData(record.data, index, record));
-        n.parentNode.removeChild(n);
-        this.updateIndexes(index, index);
+Roo.apply(Roo.bootstrap.ComboBox,  {
+    
+    header : {
+        tag: 'div',
+        cls: 'modal-header',
+        cn: [
+            {
+                tag: 'h4',
+                cls: 'modal-title'
+            }
+        ]
     },
-
     
+    body : {
+        tag: 'div',
+        cls: 'modal-body',
+        cn: [
+            {
+                tag: 'ul',
+                cls: 'list-group'
+            }
+        ]
+    },
     
-// --------- FIXME     
-    onAdd : function(ds, records, index)
-    {
-        //Roo.log(['on Add', ds, records, index] );        
-        this.clearSelections();
-        if(this.nodes.length == 0){
-            this.refresh();
-            return;
-        }
-        var n = this.nodes[index];
-        for(var i = 0, len = records.length; i < len; i++){
-            var d = this.prepareData(records[i].data, i, records[i]);
-            if(n){
-                this.tpl.insertBefore(n, d);
-            }else{
-                
-                this.tpl.append(this.el, d);
+    listItemRadio : {
+        tag: 'li',
+        cls: 'list-group-item',
+        cn: [
+            {
+                tag: 'span',
+                cls: 'roo-combobox-list-group-item-value'
+            },
+            {
+                tag: 'div',
+                cls: 'roo-combobox-list-group-item-box pull-xs-right radio-inline radio radio-info',
+                cn: [
+                    {
+                        tag: 'input',
+                        type: 'radio'
+                    },
+                    {
+                        tag: 'label'
+                    }
+                ]
             }
-        }
-        this.updateIndexes(index);
+        ]
     },
-
-    onRemove : function(ds, record, index){
-       // Roo.log('onRemove');
-        this.clearSelections();
-        var el = this.dataName  ?
-            this.el.child('.roo-tpl-' + this.dataName) :
-            this.el; 
-        
-        el.dom.removeChild(this.nodes[index]);
-        this.updateIndexes(index);
+    
+    listItemCheckbox : {
+        tag: 'li',
+        cls: 'list-group-item',
+        cn: [
+            {
+                tag: 'span',
+                cls: 'roo-combobox-list-group-item-value'
+            },
+            {
+                tag: 'div',
+                cls: 'roo-combobox-list-group-item-box pull-xs-right checkbox-inline checkbox checkbox-info',
+                cn: [
+                    {
+                        tag: 'input',
+                        type: 'checkbox'
+                    },
+                    {
+                        tag: 'label'
+                    }
+                ]
+            }
+        ]
     },
-
-    /**
-     * Refresh an individual node.
-     * @param {Number} index
-     */
-    refreshNode : function(index){
-        this.onUpdate(this.store, this.store.getAt(index));
+    
+    emptyResult : {
+        tag: 'div',
+        cls: 'alert alert-danger roo-combobox-touch-view-empty-result'
     },
+    
+    footer : {
+        tag: 'div',
+        cls: 'modal-footer',
+        cn: [
+            {
+                tag: 'div',
+                cls: 'row',
+                cn: [
+                    {
+                        tag: 'div',
+                        cls: 'col-xs-6 text-left',
+                        cn: {
+                            tag: 'button',
+                            cls: 'btn btn-danger roo-touch-view-cancel',
+                            html: 'Cancel'
+                        }
+                    },
+                    {
+                        tag: 'div',
+                        cls: 'col-xs-6 text-right',
+                        cn: {
+                            tag: 'button',
+                            cls: 'btn btn-success roo-touch-view-ok',
+                            html: 'OK'
+                        }
+                    }
+                ]
+            }
+        ]
+        
+    }
+});
 
-    updateIndexes : function(startIndex, endIndex){
-        var ns = this.nodes;
-        startIndex = startIndex || 0;
-        endIndex = endIndex || ns.length - 1;
-        for(var i = startIndex; i <= endIndex; i++){
+Roo.apply(Roo.bootstrap.ComboBox,  {
+    
+    touchViewTemplate : {
+        tag: 'div',
+        cls: 'modal fade roo-combobox-touch-view',
+        cn: [
+            {
+                tag: 'div',
+                cls: 'modal-dialog',
+                cn: [
+                    {
+                        tag: 'div',
+                        cls: 'modal-content',
+                        cn: [
+                            Roo.bootstrap.ComboBox.header,
+                            Roo.bootstrap.ComboBox.body,
+                            Roo.bootstrap.ComboBox.footer
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+});/*
+ * 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.View
+ * @extends Roo.util.Observable
+ * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template. 
+ * This class also supports single and multi selection modes. <br>
+ * Create a data model bound view:
+ <pre><code>
+ var store = new Roo.data.Store(...);
+
+ var view = new Roo.View({
+    el : "my-element",
+    tpl : '&lt;div id="{0}"&gt;{2} - {1}&lt;/div&gt;', // auto create template
+    singleSelect: true,
+    selectedClass: "ydataview-selected",
+    store: store
+ });
+
+ // listen for node click?
+ view.on("click", function(vw, index, node, e){
+ alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
+ });
+
+ // load XML data
+ dataModel.load("foobar.xml");
+ </code></pre>
+ For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
+ * <br><br>
+ * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
+ * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
+ * 
+ * Note: old style constructor is still suported (container, template, config)
+ * 
+ * @constructor
+ * Create a new View
+ * @param {Object} config The config object
+ * 
+ */
+Roo.View = function(config, depreciated_tpl, depreciated_config){
+    
+    this.parent = false;
+    
+    if (typeof(depreciated_tpl) == 'undefined') {
+        // new way.. - universal constructor.
+        Roo.apply(this, config);
+        this.el  = Roo.get(this.el);
+    } else {
+        // old format..
+        this.el  = Roo.get(config);
+        this.tpl = depreciated_tpl;
+        Roo.apply(this, depreciated_config);
+    }
+    this.wrapEl  = this.el.wrap().wrap();
+    ///this.el = this.wrapEla.appendChild(document.createElement("div"));
+    
+    
+    if(typeof(this.tpl) == "string"){
+        this.tpl = new Roo.Template(this.tpl);
+    } else {
+        // support xtype ctors..
+        this.tpl = new Roo.factory(this.tpl, Roo);
+    }
+    
+    
+    this.tpl.compile();
+    
+    /** @private */
+    this.addEvents({
+        /**
+         * @event beforeclick
+         * Fires before a click is processed. Returns false to cancel the default action.
+         * @param {Roo.View} this
+         * @param {Number} index The index of the target node
+         * @param {HTMLElement} node The target node
+         * @param {Roo.EventObject} e The raw event object
+         */
+            "beforeclick" : true,
+        /**
+         * @event click
+         * Fires when a template node is clicked.
+         * @param {Roo.View} this
+         * @param {Number} index The index of the target node
+         * @param {HTMLElement} node The target node
+         * @param {Roo.EventObject} e The raw event object
+         */
+            "click" : true,
+        /**
+         * @event dblclick
+         * Fires when a template node is double clicked.
+         * @param {Roo.View} this
+         * @param {Number} index The index of the target node
+         * @param {HTMLElement} node The target node
+         * @param {Roo.EventObject} e The raw event object
+         */
+            "dblclick" : true,
+        /**
+         * @event contextmenu
+         * Fires when a template node is right clicked.
+         * @param {Roo.View} this
+         * @param {Number} index The index of the target node
+         * @param {HTMLElement} node The target node
+         * @param {Roo.EventObject} e The raw event object
+         */
+            "contextmenu" : true,
+        /**
+         * @event selectionchange
+         * Fires when the selected nodes change.
+         * @param {Roo.View} this
+         * @param {Array} selections Array of the selected nodes
+         */
+            "selectionchange" : true,
+    
+        /**
+         * @event beforeselect
+         * Fires before a selection is made. If any handlers return false, the selection is cancelled.
+         * @param {Roo.View} this
+         * @param {HTMLElement} node The node to be selected
+         * @param {Array} selections Array of currently selected nodes
+         */
+            "beforeselect" : true,
+        /**
+         * @event preparedata
+         * Fires on every row to render, to allow you to change the data.
+         * @param {Roo.View} this
+         * @param {Object} data to be rendered (change this)
+         */
+          "preparedata" : true
+          
+          
+        });
+
+
+
+    this.el.on({
+        "click": this.onClick,
+        "dblclick": this.onDblClick,
+        "contextmenu": this.onContextMenu,
+        scope:this
+    });
+
+    this.selections = [];
+    this.nodes = [];
+    this.cmp = new Roo.CompositeElementLite([]);
+    if(this.store){
+        this.store = Roo.factory(this.store, Roo.data);
+        this.setStore(this.store, true);
+    }
+    
+    if ( this.footer && this.footer.xtype) {
+           
+         var fctr = this.wrapEl.appendChild(document.createElement("div"));
+        
+        this.footer.dataSource = this.store
+        this.footer.container = fctr;
+        this.footer = Roo.factory(this.footer, Roo);
+        fctr.insertFirst(this.el);
+        
+        // this is a bit insane - as the paging toolbar seems to detach the el..
+//        dom.parentNode.parentNode.parentNode
+         // they get detached?
+    }
+    
+    
+    Roo.View.superclass.constructor.call(this);
+    
+    
+};
+
+Roo.extend(Roo.View, Roo.util.Observable, {
+    
+     /**
+     * @cfg {Roo.data.Store} store Data store to load data from.
+     */
+    store : false,
+    
+    /**
+     * @cfg {String|Roo.Element} el The container element.
+     */
+    el : '',
+    
+    /**
+     * @cfg {String|Roo.Template} tpl The template used by this View 
+     */
+    tpl : false,
+    /**
+     * @cfg {String} dataName the named area of the template to use as the data area
+     *                          Works with domtemplates roo-name="name"
+     */
+    dataName: false,
+    /**
+     * @cfg {String} selectedClass The css class to add to selected nodes
+     */
+    selectedClass : "x-view-selected",
+     /**
+     * @cfg {String} emptyText The empty text to show when nothing is loaded.
+     */
+    emptyText : "",
+    
+    /**
+     * @cfg {String} text to display on mask (default Loading)
+     */
+    mask : false,
+    /**
+     * @cfg {Boolean} multiSelect Allow multiple selection
+     */
+    multiSelect : false,
+    /**
+     * @cfg {Boolean} singleSelect Allow single selection
+     */
+    singleSelect:  false,
+    
+    /**
+     * @cfg {Boolean} toggleSelect - selecting 
+     */
+    toggleSelect : false,
+    
+    /**
+     * @cfg {Boolean} tickable - selecting 
+     */
+    tickable : false,
+    
+    /**
+     * Returns the element this view is bound to.
+     * @return {Roo.Element}
+     */
+    getEl : function(){
+        return this.wrapEl;
+    },
+    
+    
+
+    /**
+     * Refreshes the view. - called by datachanged on the store. - do not call directly.
+     */
+    refresh : function(){
+        //Roo.log('refresh');
+        var t = this.tpl;
+        
+        // if we are using something like 'domtemplate', then
+        // the what gets used is:
+        // t.applySubtemplate(NAME, data, wrapping data..)
+        // the outer template then get' applied with
+        //     the store 'extra data'
+        // and the body get's added to the
+        //      roo-name="data" node?
+        //      <span class='roo-tpl-{name}'></span> ?????
+        
+        
+        
+        this.clearSelections();
+        this.el.update("");
+        var html = [];
+        var records = this.store.getRange();
+        if(records.length < 1) {
+            
+            // is this valid??  = should it render a template??
+            
+            this.el.update(this.emptyText);
+            return;
+        }
+        var el = this.el;
+        if (this.dataName) {
+            this.el.update(t.apply(this.store.meta)); //????
+            el = this.el.child('.roo-tpl-' + this.dataName);
+        }
+        
+        for(var i = 0, len = records.length; i < len; i++){
+            var data = this.prepareData(records[i].data, i, records[i]);
+            this.fireEvent("preparedata", this, data, i, records[i]);
+            
+            var d = Roo.apply({}, data);
+            
+            if(this.tickable){
+                Roo.apply(d, {'roo-id' : Roo.id()});
+                
+                var _this = this;
+            
+                Roo.each(this.parent.item, function(item){
+                    if(item[_this.parent.valueField] != data[_this.parent.valueField]){
+                        return;
+                    }
+                    Roo.apply(d, {'roo-data-checked' : 'checked'});
+                });
+            }
+            
+            html[html.length] = Roo.util.Format.trim(
+                this.dataName ?
+                    t.applySubtemplate(this.dataName, d, this.store.meta) :
+                    t.apply(d)
+            );
+        }
+        
+        
+        
+        el.update(html.join(""));
+        this.nodes = el.dom.childNodes;
+        this.updateIndexes(0);
+    },
+    
+
+    /**
+     * Function to override to reformat the data that is sent to
+     * the template for each node.
+     * DEPRICATED - use the preparedata event handler.
+     * @param {Array/Object} data The raw data (array of colData for a data model bound view or
+     * a JSON object for an UpdateManager bound view).
+     */
+    prepareData : function(data, index, record)
+    {
+        this.fireEvent("preparedata", this, data, index, record);
+        return data;
+    },
+
+    onUpdate : function(ds, record){
+        // Roo.log('on update');   
+        this.clearSelections();
+        var index = this.store.indexOf(record);
+        var n = this.nodes[index];
+        this.tpl.insertBefore(n, this.prepareData(record.data, index, record));
+        n.parentNode.removeChild(n);
+        this.updateIndexes(index, index);
+    },
+
+    
+    
+// --------- FIXME     
+    onAdd : function(ds, records, index)
+    {
+        //Roo.log(['on Add', ds, records, index] );        
+        this.clearSelections();
+        if(this.nodes.length == 0){
+            this.refresh();
+            return;
+        }
+        var n = this.nodes[index];
+        for(var i = 0, len = records.length; i < len; i++){
+            var d = this.prepareData(records[i].data, i, records[i]);
+            if(n){
+                this.tpl.insertBefore(n, d);
+            }else{
+                
+                this.tpl.append(this.el, d);
+            }
+        }
+        this.updateIndexes(index);
+    },
+
+    onRemove : function(ds, record, index){
+       // Roo.log('onRemove');
+        this.clearSelections();
+        var el = this.dataName  ?
+            this.el.child('.roo-tpl-' + this.dataName) :
+            this.el; 
+        
+        el.dom.removeChild(this.nodes[index]);
+        this.updateIndexes(index);
+    },
+
+    /**
+     * Refresh an individual node.
+     * @param {Number} index
+     */
+    refreshNode : function(index){
+        this.onUpdate(this.store, this.store.getAt(index));
+    },
+
+    updateIndexes : function(startIndex, endIndex){
+        var ns = this.nodes;
+        startIndex = startIndex || 0;
+        endIndex = endIndex || ns.length - 1;
+        for(var i = startIndex; i <= endIndex; i++){
             ns[i].nodeIndex = i;
         }
     },
 
-    /**
-     * Changes the data store this view uses and refresh the view.
-     * @param {Store} store
-     */
-    setStore : function(store, initial){
-        if(!initial && this.store){
-            this.store.un("datachanged", this.refresh);
-            this.store.un("add", this.onAdd);
-            this.store.un("remove", this.onRemove);
-            this.store.un("update", this.onUpdate);
-            this.store.un("clear", this.refresh);
-            this.store.un("beforeload", this.onBeforeLoad);
-            this.store.un("load", this.onLoad);
-            this.store.un("loadexception", this.onLoad);
+    /**
+     * Changes the data store this view uses and refresh the view.
+     * @param {Store} store
+     */
+    setStore : function(store, initial){
+        if(!initial && this.store){
+            this.store.un("datachanged", this.refresh);
+            this.store.un("add", this.onAdd);
+            this.store.un("remove", this.onRemove);
+            this.store.un("update", this.onUpdate);
+            this.store.un("clear", this.refresh);
+            this.store.un("beforeload", this.onBeforeLoad);
+            this.store.un("load", this.onLoad);
+            this.store.un("loadexception", this.onLoad);
+        }
+        if(store){
+          
+            store.on("datachanged", this.refresh, this);
+            store.on("add", this.onAdd, this);
+            store.on("remove", this.onRemove, this);
+            store.on("update", this.onUpdate, this);
+            store.on("clear", this.refresh, this);
+            store.on("beforeload", this.onBeforeLoad, this);
+            store.on("load", this.onLoad, this);
+            store.on("loadexception", this.onLoad, this);
+        }
+        
+        if(store){
+            this.refresh();
+        }
+    },
+    /**
+     * onbeforeLoad - masks the loading area.
+     *
+     */
+    onBeforeLoad : function(store,opts)
+    {
+         //Roo.log('onBeforeLoad');   
+        if (!opts.add) {
+            this.el.update("");
+        }
+        this.el.mask(this.mask ? this.mask : "Loading" ); 
+    },
+    onLoad : function ()
+    {
+        this.el.unmask();
+    },
+    
+
+    /**
+     * Returns the template node the passed child belongs to or null if it doesn't belong to one.
+     * @param {HTMLElement} node
+     * @return {HTMLElement} The template node
+     */
+    findItemFromChild : function(node){
+        var el = this.dataName  ?
+            this.el.child('.roo-tpl-' + this.dataName,true) :
+            this.el.dom; 
+        
+        if(!node || node.parentNode == el){
+                   return node;
+           }
+           var p = node.parentNode;
+           while(p && p != el){
+            if(p.parentNode == el){
+               return p;
+            }
+            p = p.parentNode;
+        }
+           return null;
+    },
+
+    /** @ignore */
+    onClick : function(e){
+        var item = this.findItemFromChild(e.getTarget());
+        if(item){
+            var index = this.indexOf(item);
+            if(this.onItemClick(item, index, e) !== false){
+                this.fireEvent("click", this, index, item, e);
+            }
+        }else{
+            this.clearSelections();
+        }
+    },
+
+    /** @ignore */
+    onContextMenu : function(e){
+        var item = this.findItemFromChild(e.getTarget());
+        if(item){
+            this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
+        }
+    },
+
+    /** @ignore */
+    onDblClick : function(e){
+        var item = this.findItemFromChild(e.getTarget());
+        if(item){
+            this.fireEvent("dblclick", this, this.indexOf(item), item, e);
+        }
+    },
+
+    onItemClick : function(item, index, e)
+    {
+        if(this.fireEvent("beforeclick", this, index, item, e) === false){
+            return false;
+        }
+        if (this.toggleSelect) {
+            var m = this.isSelected(item) ? 'unselect' : 'select';
+            //Roo.log(m);
+            var _t = this;
+            _t[m](item, true, false);
+            return true;
+        }
+        if(this.multiSelect || this.singleSelect){
+            if(this.multiSelect && e.shiftKey && this.lastSelection){
+                this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
+            }else{
+                this.select(item, this.multiSelect && e.ctrlKey);
+                this.lastSelection = item;
+            }
+            
+            if(!this.tickable){
+                e.preventDefault();
+            }
+            
+        }
+        return true;
+    },
+
+    /**
+     * Get the number of selected nodes.
+     * @return {Number}
+     */
+    getSelectionCount : function(){
+        return this.selections.length;
+    },
+
+    /**
+     * Get the currently selected nodes.
+     * @return {Array} An array of HTMLElements
+     */
+    getSelectedNodes : function(){
+        return this.selections;
+    },
+
+    /**
+     * Get the indexes of the selected nodes.
+     * @return {Array}
+     */
+    getSelectedIndexes : function(){
+        var indexes = [], s = this.selections;
+        for(var i = 0, len = s.length; i < len; i++){
+            indexes.push(s[i].nodeIndex);
+        }
+        return indexes;
+    },
+
+    /**
+     * Clear all selections
+     * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange event
+     */
+    clearSelections : function(suppressEvent){
+        if(this.nodes && (this.multiSelect || this.singleSelect) && this.selections.length > 0){
+            this.cmp.elements = this.selections;
+            this.cmp.removeClass(this.selectedClass);
+            this.selections = [];
+            if(!suppressEvent){
+                this.fireEvent("selectionchange", this, this.selections);
+            }
+        }
+    },
+
+    /**
+     * Returns true if the passed node is selected
+     * @param {HTMLElement/Number} node The node or node index
+     * @return {Boolean}
+     */
+    isSelected : function(node){
+        var s = this.selections;
+        if(s.length < 1){
+            return false;
+        }
+        node = this.getNode(node);
+        return s.indexOf(node) !== -1;
+    },
+
+    /**
+     * Selects nodes.
+     * @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
+     * @param {Boolean} keepExisting (optional) true to keep existing selections
+     * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
+     */
+    select : function(nodeInfo, keepExisting, suppressEvent){
+        if(nodeInfo instanceof Array){
+            if(!keepExisting){
+                this.clearSelections(true);
+            }
+            for(var i = 0, len = nodeInfo.length; i < len; i++){
+                this.select(nodeInfo[i], true, true);
+            }
+            return;
+        } 
+        var node = this.getNode(nodeInfo);
+        if(!node || this.isSelected(node)){
+            return; // already selected.
+        }
+        if(!keepExisting){
+            this.clearSelections(true);
+        }
+        
+        if(this.fireEvent("beforeselect", this, node, this.selections) !== false){
+            Roo.fly(node).addClass(this.selectedClass);
+            this.selections.push(node);
+            if(!suppressEvent){
+                this.fireEvent("selectionchange", this, this.selections);
+            }
+        }
+        
+        
+    },
+      /**
+     * Unselects nodes.
+     * @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
+     * @param {Boolean} keepExisting (optional) true IGNORED (for campatibility with select)
+     * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
+     */
+    unselect : function(nodeInfo, keepExisting, suppressEvent)
+    {
+        if(nodeInfo instanceof Array){
+            Roo.each(this.selections, function(s) {
+                this.unselect(s, nodeInfo);
+            }, this);
+            return;
+        }
+        var node = this.getNode(nodeInfo);
+        if(!node || !this.isSelected(node)){
+            //Roo.log("not selected");
+            return; // not selected.
+        }
+        // fireevent???
+        var ns = [];
+        Roo.each(this.selections, function(s) {
+            if (s == node ) {
+                Roo.fly(node).removeClass(this.selectedClass);
+
+                return;
+            }
+            ns.push(s);
+        },this);
+        
+        this.selections= ns;
+        this.fireEvent("selectionchange", this, this.selections);
+    },
+
+    /**
+     * Gets a template node.
+     * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
+     * @return {HTMLElement} The node or null if it wasn't found
+     */
+    getNode : function(nodeInfo){
+        if(typeof nodeInfo == "string"){
+            return document.getElementById(nodeInfo);
+        }else if(typeof nodeInfo == "number"){
+            return this.nodes[nodeInfo];
+        }
+        return nodeInfo;
+    },
+
+    /**
+     * Gets a range template nodes.
+     * @param {Number} startIndex
+     * @param {Number} endIndex
+     * @return {Array} An array of nodes
+     */
+    getNodes : function(start, end){
+        var ns = this.nodes;
+        start = start || 0;
+        end = typeof end == "undefined" ? ns.length - 1 : end;
+        var nodes = [];
+        if(start <= end){
+            for(var i = start; i <= end; i++){
+                nodes.push(ns[i]);
+            }
+        } else{
+            for(var i = start; i >= end; i--){
+                nodes.push(ns[i]);
+            }
+        }
+        return nodes;
+    },
+
+    /**
+     * Finds the index of the passed node
+     * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
+     * @return {Number} The index of the node or -1
+     */
+    indexOf : function(node){
+        node = this.getNode(node);
+        if(typeof node.nodeIndex == "number"){
+            return node.nodeIndex;
+        }
+        var ns = this.nodes;
+        for(var i = 0, len = ns.length; i < len; i++){
+            if(ns[i] == node){
+                return i;
+            }
+        }
+        return -1;
+    }
+});
+/*
+ * - LGPL
+ *
+ * based on jquery fullcalendar
+ * 
+ */
+
+Roo.bootstrap = Roo.bootstrap || {};
+/**
+ * @class Roo.bootstrap.Calendar
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Calendar class
+ * @cfg {Boolean} loadMask (true|false) default false
+ * @cfg {Object} header generate the user specific header of the calendar, default false
+
+ * @constructor
+ * Create a new Container
+ * @param {Object} config The config object
+ */
+
+
+
+Roo.bootstrap.Calendar = function(config){
+    Roo.bootstrap.Calendar.superclass.constructor.call(this, config);
+     this.addEvents({
+        /**
+            * @event select
+            * Fires when a date is selected
+            * @param {DatePicker} this
+            * @param {Date} date The selected date
+            */
+        'select': true,
+        /**
+            * @event monthchange
+            * Fires when the displayed month changes 
+            * @param {DatePicker} this
+            * @param {Date} date The selected month
+            */
+        'monthchange': true,
+        /**
+            * @event evententer
+            * Fires when mouse over an event
+            * @param {Calendar} this
+            * @param {event} Event
+            */
+        'evententer': true,
+        /**
+            * @event eventleave
+            * Fires when the mouse leaves an
+            * @param {Calendar} this
+            * @param {event}
+            */
+        'eventleave': true,
+        /**
+            * @event eventclick
+            * Fires when the mouse click an
+            * @param {Calendar} this
+            * @param {event}
+            */
+        'eventclick': true
+        
+    });
+
+};
+
+Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
+    
+     /**
+     * @cfg {Number} startDay
+     * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
+     */
+    startDay : 0,
+    
+    loadMask : false,
+    
+    header : false,
+      
+    getAutoCreate : function(){
+        
+        
+        var fc_button = function(name, corner, style, content ) {
+            return Roo.apply({},{
+                tag : 'span',
+                cls : 'fc-button fc-button-'+name+' fc-state-default ' + 
+                         (corner.length ?
+                            'fc-corner-' + corner.split(' ').join(' fc-corner-') :
+                            ''
+                        ),
+                html : '<SPAN class="fc-text-'+style+ '">'+content +'</SPAN>',
+                unselectable: 'on'
+            });
+        };
+        
+        var header = {};
+        
+        if(!this.header){
+            header = {
+                tag : 'table',
+                cls : 'fc-header',
+                style : 'width:100%',
+                cn : [
+                    {
+                        tag: 'tr',
+                        cn : [
+                            {
+                                tag : 'td',
+                                cls : 'fc-header-left',
+                                cn : [
+                                    fc_button('prev', 'left', 'arrow', '&#8249;' ),
+                                    fc_button('next', 'right', 'arrow', '&#8250;' ),
+                                    { tag: 'span', cls: 'fc-header-space' },
+                                    fc_button('today', 'left right', '', 'today' )  // neds state disabled..
+
+
+                                ]
+                            },
+
+                            {
+                                tag : 'td',
+                                cls : 'fc-header-center',
+                                cn : [
+                                    {
+                                        tag: 'span',
+                                        cls: 'fc-header-title',
+                                        cn : {
+                                            tag: 'H2',
+                                            html : 'month / year'
+                                        }
+                                    }
+
+                                ]
+                            },
+                            {
+                                tag : 'td',
+                                cls : 'fc-header-right',
+                                cn : [
+                              /*      fc_button('month', 'left', '', 'month' ),
+                                    fc_button('week', '', '', 'week' ),
+                                    fc_button('day', 'right', '', 'day' )
+                                */    
+
+                                ]
+                            }
+
+                        ]
+                    }
+                ]
+            };
+        }
+        
+        header = this.header;
+        
+       
+        var cal_heads = function() {
+            var ret = [];
+            // fixme - handle this.
+            
+            for (var i =0; i < Date.dayNames.length; i++) {
+                var d = Date.dayNames[i];
+                ret.push({
+                    tag: 'th',
+                    cls : 'fc-day-header fc-' + d.substring(0,3).toLowerCase() + ' fc-widget-header',
+                    html : d.substring(0,3)
+                });
+                
+            }
+            ret[0].cls += ' fc-first';
+            ret[6].cls += ' fc-last';
+            return ret;
+        };
+        var cal_cell = function(n) {
+            return  {
+                tag: 'td',
+                cls : 'fc-day fc-'+n + ' fc-widget-content', ///fc-other-month fc-past
+                cn : [
+                    {
+                        cn : [
+                            {
+                                cls: 'fc-day-number',
+                                html: 'D'
+                            },
+                            {
+                                cls: 'fc-day-content',
+                             
+                                cn : [
+                                     {
+                                        style: 'position: relative;' // height: 17px;
+                                    }
+                                ]
+                            }
+                            
+                            
+                        ]
+                    }
+                ]
+                
+            }
+        };
+        var cal_rows = function() {
+            
+            var ret = [];
+            for (var r = 0; r < 6; r++) {
+                var row= {
+                    tag : 'tr',
+                    cls : 'fc-week',
+                    cn : []
+                };
+                
+                for (var i =0; i < Date.dayNames.length; i++) {
+                    var d = Date.dayNames[i];
+                    row.cn.push(cal_cell(d.substring(0,3).toLowerCase()));
+
+                }
+                row.cn[0].cls+=' fc-first';
+                row.cn[0].cn[0].style = 'min-height:90px';
+                row.cn[6].cls+=' fc-last';
+                ret.push(row);
+                
+            }
+            ret[0].cls += ' fc-first';
+            ret[4].cls += ' fc-prev-last';
+            ret[5].cls += ' fc-last';
+            return ret;
+            
+        };
+        
+        var cal_table = {
+            tag: 'table',
+            cls: 'fc-border-separate',
+            style : 'width:100%',
+            cellspacing  : 0,
+            cn : [
+                { 
+                    tag: 'thead',
+                    cn : [
+                        { 
+                            tag: 'tr',
+                            cls : 'fc-first fc-last',
+                            cn : cal_heads()
+                        }
+                    ]
+                },
+                { 
+                    tag: 'tbody',
+                    cn : cal_rows()
+                }
+                  
+            ]
+        };
+         
+         var cfg = {
+            cls : 'fc fc-ltr',
+            cn : [
+                header,
+                {
+                    cls : 'fc-content',
+                    style : "position: relative;",
+                    cn : [
+                        {
+                            cls : 'fc-view fc-view-month fc-grid',
+                            style : 'position: relative',
+                            unselectable : 'on',
+                            cn : [
+                                {
+                                    cls : 'fc-event-container',
+                                    style : 'position:absolute;z-index:8;top:0;left:0;'
+                                },
+                                cal_table
+                            ]
+                        }
+                    ]
+    
+                }
+           ] 
+            
+        };
+        
+         
+        
+        return cfg;
+    },
+    
+    
+    initEvents : function()
+    {
+        if(!this.store){
+            throw "can not find store for calendar";
+        }
+        
+        var mark = {
+            tag: "div",
+            cls:"x-dlg-mask",
+            style: "text-align:center",
+            cn: [
+                {
+                    tag: "div",
+                    style: "background-color:white;width:50%;margin:250 auto",
+                    cn: [
+                        {
+                            tag: "img",
+                            src: Roo.rootURL + '/images/ux/lightbox/loading.gif' 
+                        },
+                        {
+                            tag: "span",
+                            html: "Loading"
+                        }
+                        
+                    ]
+                }
+            ]
+        }
+        this.maskEl = Roo.DomHelper.append(this.el.select('.fc-content', true).first(), mark, true);
+        
+        var size = this.el.select('.fc-content', true).first().getSize();
+        this.maskEl.setSize(size.width, size.height);
+        this.maskEl.enableDisplayMode("block");
+        if(!this.loadMask){
+            this.maskEl.hide();
+        }
+        
+        this.store = Roo.factory(this.store, Roo.data);
+        this.store.on('load', this.onLoad, this);
+        this.store.on('beforeload', this.onBeforeLoad, this);
+        
+        this.resize();
+        
+        this.cells = this.el.select('.fc-day',true);
+        //Roo.log(this.cells);
+        this.textNodes = this.el.query('.fc-day-number');
+        this.cells.addClassOnOver('fc-state-hover');
+        
+        this.el.select('.fc-button-prev',true).on('click', this.showPrevMonth, this);
+        this.el.select('.fc-button-next',true).on('click', this.showNextMonth, this);
+        this.el.select('.fc-button-today',true).on('click', this.showToday, this);
+        this.el.select('.fc-button',true).addClassOnOver('fc-state-hover');
+        
+        this.on('monthchange', this.onMonthChange, this);
+        
+        this.update(new Date().clearTime());
+    },
+    
+    resize : function() {
+        var sz  = this.el.getSize();
+        
+        this.el.select('.fc-day-header',true).setWidth(sz.width / 7);
+        this.el.select('.fc-day-content div',true).setHeight(34);
+    },
+    
+    
+    // private
+    showPrevMonth : function(e){
+        this.update(this.activeDate.add("mo", -1));
+    },
+    showToday : function(e){
+        this.update(new Date().clearTime());
+    },
+    // private
+    showNextMonth : function(e){
+        this.update(this.activeDate.add("mo", 1));
+    },
+
+    // private
+    showPrevYear : function(){
+        this.update(this.activeDate.add("y", -1));
+    },
+
+    // private
+    showNextYear : function(){
+        this.update(this.activeDate.add("y", 1));
+    },
+
+    
+   // private
+    update : function(date)
+    {
+        var vd = this.activeDate;
+        this.activeDate = date;
+//        if(vd && this.el){
+//            var t = date.getTime();
+//            if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
+//                Roo.log('using add remove');
+//                
+//                this.fireEvent('monthchange', this, date);
+//                
+//                this.cells.removeClass("fc-state-highlight");
+//                this.cells.each(function(c){
+//                   if(c.dateValue == t){
+//                       c.addClass("fc-state-highlight");
+//                       setTimeout(function(){
+//                            try{c.dom.firstChild.focus();}catch(e){}
+//                       }, 50);
+//                       return false;
+//                   }
+//                   return true;
+//                });
+//                return;
+//            }
+//        }
+        
+        var days = date.getDaysInMonth();
+        
+        var firstOfMonth = date.getFirstDateOfMonth();
+        var startingPos = firstOfMonth.getDay()-this.startDay;
+        
+        if(startingPos < this.startDay){
+            startingPos += 7;
+        }
+        
+        var pm = date.add(Date.MONTH, -1);
+        var prevStart = pm.getDaysInMonth()-startingPos;
+//        
+        this.cells = this.el.select('.fc-day',true);
+        this.textNodes = this.el.query('.fc-day-number');
+        this.cells.addClassOnOver('fc-state-hover');
+        
+        var cells = this.cells.elements;
+        var textEls = this.textNodes;
+        
+        Roo.each(cells, function(cell){
+            cell.removeClass([ 'fc-past', 'fc-other-month', 'fc-future', 'fc-state-highlight', 'fc-state-disabled']);
+        });
+        
+        days += startingPos;
+
+        // convert everything to numbers so it's fast
+        var day = 86400000;
+        var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
+        //Roo.log(d);
+        //Roo.log(pm);
+        //Roo.log(prevStart);
+        
+        var today = new Date().clearTime().getTime();
+        var sel = date.clearTime().getTime();
+        var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
+        var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
+        var ddMatch = this.disabledDatesRE;
+        var ddText = this.disabledDatesText;
+        var ddays = this.disabledDays ? this.disabledDays.join("") : false;
+        var ddaysText = this.disabledDaysText;
+        var format = this.format;
+        
+        var setCellClass = function(cal, cell){
+            cell.row = 0;
+            cell.events = [];
+            cell.more = [];
+            //Roo.log('set Cell Class');
+            cell.title = "";
+            var t = d.getTime();
+            
+            //Roo.log(d);
+            
+            cell.dateValue = t;
+            if(t == today){
+                cell.className += " fc-today";
+                cell.className += " fc-state-highlight";
+                cell.title = cal.todayText;
+            }
+            if(t == sel){
+                // disable highlight in other month..
+                //cell.className += " fc-state-highlight";
+                
+            }
+            // disabling
+            if(t < min) {
+                cell.className = " fc-state-disabled";
+                cell.title = cal.minText;
+                return;
+            }
+            if(t > max) {
+                cell.className = " fc-state-disabled";
+                cell.title = cal.maxText;
+                return;
+            }
+            if(ddays){
+                if(ddays.indexOf(d.getDay()) != -1){
+                    cell.title = ddaysText;
+                    cell.className = " fc-state-disabled";
+                }
+            }
+            if(ddMatch && format){
+                var fvalue = d.dateFormat(format);
+                if(ddMatch.test(fvalue)){
+                    cell.title = ddText.replace("%0", fvalue);
+                    cell.className = " fc-state-disabled";
+                }
+            }
+            
+            if (!cell.initialClassName) {
+                cell.initialClassName = cell.dom.className;
+            }
+            
+            cell.dom.className = cell.initialClassName  + ' ' +  cell.className;
+        };
+
+        var i = 0;
+        
+        for(; i < startingPos; i++) {
+            textEls[i].innerHTML = (++prevStart);
+            d.setDate(d.getDate()+1);
+            
+            cells[i].className = "fc-past fc-other-month";
+            setCellClass(this, cells[i]);
+        }
+        
+        var intDay = 0;
+        
+        for(; i < days; i++){
+            intDay = i - startingPos + 1;
+            textEls[i].innerHTML = (intDay);
+            d.setDate(d.getDate()+1);
+            
+            cells[i].className = ''; // "x-date-active";
+            setCellClass(this, cells[i]);
+        }
+        var extraDays = 0;
+        
+        for(; i < 42; i++) {
+            textEls[i].innerHTML = (++extraDays);
+            d.setDate(d.getDate()+1);
+            
+            cells[i].className = "fc-future fc-other-month";
+            setCellClass(this, cells[i]);
+        }
+        
+        this.el.select('.fc-header-title h2',true).update(Date.monthNames[date.getMonth()] + " " + date.getFullYear());
+        
+        var totalRows = Math.ceil((date.getDaysInMonth() + date.getFirstDateOfMonth().getDay()) / 7);
+        
+        this.el.select('tr.fc-week.fc-prev-last',true).removeClass('fc-last');
+        this.el.select('tr.fc-week.fc-next-last',true).addClass('fc-last').show();
+        
+        if(totalRows != 6){
+            this.el.select('tr.fc-week.fc-last',true).removeClass('fc-last').addClass('fc-next-last').hide();
+            this.el.select('tr.fc-week.fc-prev-last',true).addClass('fc-last');
+        }
+        
+        this.fireEvent('monthchange', this, date);
+        
+        
+        /*
+        if(!this.internalRender){
+            var main = this.el.dom.firstChild;
+            var w = main.offsetWidth;
+            this.el.setWidth(w + this.el.getBorderWidth("lr"));
+            Roo.fly(main).setWidth(w);
+            this.internalRender = true;
+            // opera does not respect the auto grow header center column
+            // then, after it gets a width opera refuses to recalculate
+            // without a second pass
+            if(Roo.isOpera && !this.secondPass){
+                main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
+                this.secondPass = true;
+                this.update.defer(10, this, [date]);
+            }
+        }
+        */
+        
+    },
+    
+    findCell : function(dt) {
+        dt = dt.clearTime().getTime();
+        var ret = false;
+        this.cells.each(function(c){
+            //Roo.log("check " +c.dateValue + '?=' + dt);
+            if(c.dateValue == dt){
+                ret = c;
+                return false;
+            }
+            return true;
+        });
+        
+        return ret;
+    },
+    
+    findCells : function(ev) {
+        var s = ev.start.clone().clearTime().getTime();
+       // Roo.log(s);
+        var e= ev.end.clone().clearTime().getTime();
+       // Roo.log(e);
+        var ret = [];
+        this.cells.each(function(c){
+             ////Roo.log("check " +c.dateValue + '<' + e + ' > ' + s);
+            
+            if(c.dateValue > e){
+                return ;
+            }
+            if(c.dateValue < s){
+                return ;
+            }
+            ret.push(c);
+        });
+        
+        return ret;    
+    },
+    
+//    findBestRow: function(cells)
+//    {
+//        var ret = 0;
+//        
+//        for (var i =0 ; i < cells.length;i++) {
+//            ret  = Math.max(cells[i].rows || 0,ret);
+//        }
+//        return ret;
+//        
+//    },
+    
+    
+    addItem : function(ev)
+    {
+        // look for vertical location slot in
+        var cells = this.findCells(ev);
+        
+//        ev.row = this.findBestRow(cells);
+        
+        // work out the location.
+        
+        var crow = false;
+        var rows = [];
+        for(var i =0; i < cells.length; i++) {
+            
+            cells[i].row = cells[0].row;
+            
+            if(i == 0){
+                cells[i].row = cells[i].row + 1;
+            }
+            
+            if (!crow) {
+                crow = {
+                    start : cells[i],
+                    end :  cells[i]
+                };
+                continue;
+            }
+            if (crow.start.getY() == cells[i].getY()) {
+                // on same row.
+                crow.end = cells[i];
+                continue;
+            }
+            // different row.
+            rows.push(crow);
+            crow = {
+                start: cells[i],
+                end : cells[i]
+            };
+            
+        }
+        
+        rows.push(crow);
+        ev.els = [];
+        ev.rows = rows;
+        ev.cells = cells;
+        
+        cells[0].events.push(ev);
+        
+        this.calevents.push(ev);
+    },
+    
+    clearEvents: function() {
+        
+        if(!this.calevents){
+            return;
+        }
+        
+        Roo.each(this.cells.elements, function(c){
+            c.row = 0;
+            c.events = [];
+            c.more = [];
+        });
+        
+        Roo.each(this.calevents, function(e) {
+            Roo.each(e.els, function(el) {
+                el.un('mouseenter' ,this.onEventEnter, this);
+                el.un('mouseleave' ,this.onEventLeave, this);
+                el.remove();
+            },this);
+        },this);
+        
+        Roo.each(Roo.select('.fc-more-event', true).elements, function(e){
+            e.remove();
+        });
+        
+    },
+    
+    renderEvents: function()
+    {   
+        var _this = this;
+        
+        this.cells.each(function(c) {
+            
+            if(c.row < 5){
+                return;
+            }
+            
+            var ev = c.events;
+            
+            var r = 4;
+            if(c.row != c.events.length){
+                r = 4 - (4 - (c.row - c.events.length));
+            }
+            
+            c.events = ev.slice(0, r);
+            c.more = ev.slice(r);
+            
+            if(c.more.length && c.more.length == 1){
+                c.events.push(c.more.pop());
+            }
+            
+            c.row = (c.row - ev.length) + c.events.length + ((c.more.length) ? 1 : 0);
+            
+        });
+            
+        this.cells.each(function(c) {
+            
+            c.select('.fc-day-content div',true).first().setHeight(Math.max(34, c.row * 20));
+            
+            
+            for (var e = 0; e < c.events.length; e++){
+                var ev = c.events[e];
+                var rows = ev.rows;
+                
+                for(var i = 0; i < rows.length; i++) {
+                
+                    // how many rows should it span..
+
+                    var  cfg = {
+                        cls : 'roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable',
+                        style : 'position: absolute', // left: 387px; width: 121px; top: 359px;
+
+                        unselectable : "on",
+                        cn : [
+                            {
+                                cls: 'fc-event-inner',
+                                cn : [
+    //                                {
+    //                                  tag:'span',
+    //                                  cls: 'fc-event-time',
+    //                                  html : cells.length > 1 ? '' : ev.time
+    //                                },
+                                    {
+                                      tag:'span',
+                                      cls: 'fc-event-title',
+                                      html : String.format('{0}', ev.title)
+                                    }
+
+
+                                ]
+                            },
+                            {
+                                cls: 'ui-resizable-handle ui-resizable-e',
+                                html : '&nbsp;&nbsp;&nbsp'
+                            }
+
+                        ]
+                    };
+
+                    if (i == 0) {
+                        cfg.cls += ' fc-event-start';
+                    }
+                    if ((i+1) == rows.length) {
+                        cfg.cls += ' fc-event-end';
+                    }
+
+                    var ctr = _this.el.select('.fc-event-container',true).first();
+                    var cg = ctr.createChild(cfg);
+
+                    var sbox = rows[i].start.select('.fc-day-content',true).first().getBox();
+                    var ebox = rows[i].end.select('.fc-day-content',true).first().getBox();
+
+                    var r = (c.more.length) ? 1 : 0;
+                    cg.setXY([sbox.x +2, sbox.y + ((c.row - c.events.length - r + e) * 20)]);    
+                    cg.setWidth(ebox.right - sbox.x -2);
+
+                    cg.on('mouseenter' ,_this.onEventEnter, _this, ev);
+                    cg.on('mouseleave' ,_this.onEventLeave, _this, ev);
+                    cg.on('click', _this.onEventClick, _this, ev);
+
+                    ev.els.push(cg);
+                    
+                }
+                
+            }
+            
+            
+            if(c.more.length){
+                var  cfg = {
+                    cls : 'fc-more-event roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable fc-event-start fc-event-end',
+                    style : 'position: absolute',
+                    unselectable : "on",
+                    cn : [
+                        {
+                            cls: 'fc-event-inner',
+                            cn : [
+                                {
+                                  tag:'span',
+                                  cls: 'fc-event-title',
+                                  html : 'More'
+                                }
+
+
+                            ]
+                        },
+                        {
+                            cls: 'ui-resizable-handle ui-resizable-e',
+                            html : '&nbsp;&nbsp;&nbsp'
+                        }
+
+                    ]
+                };
+
+                var ctr = _this.el.select('.fc-event-container',true).first();
+                var cg = ctr.createChild(cfg);
+
+                var sbox = c.select('.fc-day-content',true).first().getBox();
+                var ebox = c.select('.fc-day-content',true).first().getBox();
+                //Roo.log(cg);
+                cg.setXY([sbox.x +2, sbox.y +((c.row - 1) * 20)]);    
+                cg.setWidth(ebox.right - sbox.x -2);
+
+                cg.on('click', _this.onMoreEventClick, _this, c.more);
+                
+            }
+            
+        });
+        
+        
+        
+    },
+    
+    onEventEnter: function (e, el,event,d) {
+        this.fireEvent('evententer', this, el, event);
+    },
+    
+    onEventLeave: function (e, el,event,d) {
+        this.fireEvent('eventleave', this, el, event);
+    },
+    
+    onEventClick: function (e, el,event,d) {
+        this.fireEvent('eventclick', this, el, event);
+    },
+    
+    onMonthChange: function () {
+        this.store.load();
+    },
+    
+    onMoreEventClick: function(e, el, more)
+    {
+        var _this = this;
+        
+        this.calpopover.placement = 'right';
+        this.calpopover.setTitle('More');
+        
+        this.calpopover.setContent('');
+        
+        var ctr = this.calpopover.el.select('.popover-content', true).first();
+        
+        Roo.each(more, function(m){
+            var cfg = {
+                cls : 'fc-event-hori fc-event-draggable',
+                html : m.title
+            }
+            var cg = ctr.createChild(cfg);
+            
+            cg.on('click', _this.onEventClick, _this, m);
+        });
+        
+        this.calpopover.show(el);
+        
+        
+    },
+    
+    onLoad: function () 
+    {   
+        this.calevents = [];
+        var cal = this;
+        
+        if(this.store.getCount() > 0){
+            this.store.data.each(function(d){
+               cal.addItem({
+                    id : d.data.id,
+                    start: (typeof(d.data.start_dt) === 'string') ? new Date.parseDate(d.data.start_dt, 'Y-m-d H:i:s') : d.data.start_dt,
+                    end : (typeof(d.data.end_dt) === 'string') ? new Date.parseDate(d.data.end_dt, 'Y-m-d H:i:s') : d.data.end_dt,
+                    time : d.data.start_time,
+                    title : d.data.title,
+                    description : d.data.description,
+                    venue : d.data.venue
+                });
+            });
+        }
+        
+        this.renderEvents();
+        
+        if(this.calevents.length && this.loadMask){
+            this.maskEl.hide();
+        }
+    },
+    
+    onBeforeLoad: function()
+    {
+        this.clearEvents();
+        if(this.loadMask){
+            this.maskEl.show();
+        }
+    }
+});
+
+ /*
+ * - LGPL
+ *
+ * element
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.Popover
+ * @extends 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)
+ * @cfg {String} placement how it is placed
+ * @cfg {String} trigger click || hover (or false to trigger manually)
+ * @cfg {String} over what (parent or false to trigger manually.)
+ * @cfg {Number} delay - delay before showing
+ * @constructor
+ * Create a new Popover
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Popover = function(config){
+    Roo.bootstrap.Popover.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
+    
+    title: 'Fill in a title',
+    html: false,
+    
+    placement : 'right',
+    trigger : 'hover', // hover
+    
+    delay : 0,
+    
+    over: 'parent',
+    
+    can_build_overlaid : false,
+    
+    getChildContainer : function()
+    {
+        return this.el.select('.popover-content',true).first();
+    },
+    
+    getAutoCreate : function(){
+         Roo.log('make popover?');
+        var cfg = {
+           cls : 'popover roo-dynamic',
+           style: 'display:block',
+           cn : [
+                {
+                    cls : 'arrow'
+                },
+                {
+                    cls : 'popover-inner',
+                    cn : [
+                        {
+                            tag: 'h3',
+                            cls: 'popover-title',
+                            html : this.title
+                        },
+                        {
+                            cls : 'popover-content',
+                            html : this.html
+                        }
+                    ]
+                    
+                }
+           ]
+        };
+        
+        return cfg;
+    },
+    setTitle: function(str)
+    {
+        this.title = str;
+        this.el.select('.popover-title',true).first().dom.innerHTML = str;
+    },
+    setContent: function(str)
+    {
+        this.html = str;
+        this.el.select('.popover-content',true).first().dom.innerHTML = str;
+    },
+    // as it get's added to the bottom of the page.
+    onRender : function(ct, position)
+    {
+        Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
+        if(!this.el){
+            var cfg = Roo.apply({},  this.getAutoCreate());
+            cfg.id = Roo.id();
+            
+            if (this.cls) {
+                cfg.cls += ' ' + this.cls;
+            }
+            if (this.style) {
+                cfg.style = this.style;
+            }
+            Roo.log("adding to ")
+            this.el = Roo.get(document.body).createChild(cfg, position);
+            Roo.log(this.el);
+        }
+        this.initEvents();
+    },
+    
+    initEvents : function()
+    {
+        this.el.select('.popover-title',true).setVisibilityMode(Roo.Element.DISPLAY);
+        this.el.enableDisplayMode('block');
+        this.el.hide();
+        if (this.over === false) {
+            return; 
+        }
+        if (this.triggers === false) {
+            return;
+        }
+        var on_el = (this.over == 'parent') ? this.parent().el : Roo.get(this.over);
+        var triggers = this.trigger ? this.trigger.split(' ') : [];
+        Roo.each(triggers, function(trigger) {
+        
+            if (trigger == 'click') {
+                on_el.on('click', this.toggle, this);
+            } else if (trigger != 'manual') {
+                var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin';
+                var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';
+      
+                on_el.on(eventIn  ,this.enter, this);
+                on_el.on(eventOut, this.leave, this);
+            }
+        }, this);
+        
+    },
+    
+    
+    // private
+    timeout : null,
+    hoverState : null,
+    
+    toggle : function () {
+        this.hoverState == 'in' ? this.leave() : this.enter();
+    },
+    
+    enter : function () {
+       
+    
+        clearTimeout(this.timeout);
+    
+        this.hoverState = 'in';
+    
+        if (!this.delay || !this.delay.show) {
+            this.show();
+            return;
+        }
+        var _t = this;
+        this.timeout = setTimeout(function () {
+            if (_t.hoverState == 'in') {
+                _t.show();
+            }
+        }, this.delay.show)
+    },
+    leave : function() {
+        clearTimeout(this.timeout);
+    
+        this.hoverState = 'out';
+    
+        if (!this.delay || !this.delay.hide) {
+            this.hide();
+            return;
+        }
+        var _t = this;
+        this.timeout = setTimeout(function () {
+            if (_t.hoverState == 'out') {
+                _t.hide();
+            }
+        }, this.delay.hide)
+    },
+    
+    show : function (on_el)
+    {
+        if (!on_el) {
+            on_el= (this.over == 'parent') ? this.parent().el : Roo.get(this.over);
+        }
+        // set content.
+        this.el.select('.popover-title',true).first().dom.innerHtml = this.title;
+        if (this.html !== false) {
+            this.el.select('.popover-content',true).first().dom.innerHtml = this.html;
+        }
+        this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
+        if (!this.title.length) {
+            this.el.select('.popover-title',true).hide();
+        }
+        
+        var placement = typeof this.placement == 'function' ?
+            this.placement.call(this, this.el, on_el) :
+            this.placement;
+            
+        var autoToken = /\s?auto?\s?/i;
+        var autoPlace = autoToken.test(placement);
+        if (autoPlace) {
+            placement = placement.replace(autoToken, '') || 'top';
+        }
+        
+        //this.el.detach()
+        //this.el.setXY([0,0]);
+        this.el.show();
+        this.el.dom.style.display='block';
+        this.el.addClass(placement);
+        
+        //this.el.appendTo(on_el);
+        
+        var p = this.getPosition();
+        var box = this.el.getBox();
+        
+        if (autoPlace) {
+            // fixme..
+        }
+        var align = Roo.bootstrap.Popover.alignment[placement];
+        this.el.alignTo(on_el, align[0],align[1]);
+        //var arrow = this.el.select('.arrow',true).first();
+        //arrow.set(align[2], 
+        
+        this.el.addClass('in');
+        
+        
+        if (this.el.hasClass('fade')) {
+            // fade it?
+        }
+        
+    },
+    hide : function()
+    {
+        this.el.setXY([0,0]);
+        this.el.removeClass('in');
+        this.el.hide();
+        this.hoverState = null;
+        
+    }
+    
+});
+
+Roo.bootstrap.Popover.alignment = {
+    'left' : ['r-l', [-10,0], 'right'],
+    'right' : ['l-r', [10,0], 'left'],
+    'bottom' : ['t-b', [0,10], 'top'],
+    'top' : [ 'b-t', [0,-10], 'bottom']
+};
+
+ /*
+ * - LGPL
+ *
+ * Progress
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.Progress
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Progress class
+ * @cfg {Boolean} striped striped of the progress bar
+ * @cfg {Boolean} active animated of the progress bar
+ * 
+ * 
+ * @constructor
+ * Create a new Progress
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Progress = function(config){
+    Roo.bootstrap.Progress.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.Progress, Roo.bootstrap.Component,  {
+    
+    striped : false,
+    active: false,
+    
+    getAutoCreate : function(){
+        var cfg = {
+            tag: 'div',
+            cls: 'progress'
+        };
+        
+        
+        if(this.striped){
+            cfg.cls += ' progress-striped';
+        }
+      
+        if(this.active){
+            cfg.cls += ' active';
+        }
+        
+        
+        return cfg;
+    }
+   
+});
+
+
+ /*
+ * - LGPL
+ *
+ * ProgressBar
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.ProgressBar
+ * @extends Roo.bootstrap.Component
+ * Bootstrap ProgressBar class
+ * @cfg {Number} aria_valuenow aria-value now
+ * @cfg {Number} aria_valuemin aria-value min
+ * @cfg {Number} aria_valuemax aria-value max
+ * @cfg {String} label label for the progress bar
+ * @cfg {String} panel (success | info | warning | danger )
+ * @cfg {String} role role of the progress bar
+ * @cfg {String} sr_only text
+ * 
+ * 
+ * @constructor
+ * Create a new ProgressBar
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.ProgressBar = function(config){
+    Roo.bootstrap.ProgressBar.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.ProgressBar, Roo.bootstrap.Component,  {
+    
+    aria_valuenow : 0,
+    aria_valuemin : 0,
+    aria_valuemax : 100,
+    label : false,
+    panel : false,
+    role : false,
+    sr_only: false,
+    
+    getAutoCreate : function()
+    {
+        
+        var cfg = {
+            tag: 'div',
+            cls: 'progress-bar',
+            style: 'width:' + Math.ceil((this.aria_valuenow / this.aria_valuemax) * 100) + '%'
+        };
+        
+        if(this.sr_only){
+            cfg.cn = {
+                tag: 'span',
+                cls: 'sr-only',
+                html: this.sr_only
+            }
+        }
+        
+        if(this.role){
+            cfg.role = this.role;
+        }
+        
+        if(this.aria_valuenow){
+            cfg['aria-valuenow'] = this.aria_valuenow;
+        }
+        
+        if(this.aria_valuemin){
+            cfg['aria-valuemin'] = this.aria_valuemin;
+        }
+        
+        if(this.aria_valuemax){
+            cfg['aria-valuemax'] = this.aria_valuemax;
+        }
+        
+        if(this.label && !this.sr_only){
+            cfg.html = this.label;
+        }
+        
+        if(this.panel){
+            cfg.cls += ' progress-bar-' + this.panel;
+        }
+        
+        return cfg;
+    },
+    
+    update : function(aria_valuenow)
+    {
+        this.aria_valuenow = aria_valuenow;
+        
+        this.el.setStyle('width', Math.ceil((this.aria_valuenow / this.aria_valuemax) * 100) + '%');
+    }
+   
+});
+
+
+ /*
+ * - LGPL
+ *
+ * column
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.TabGroup
+ * @extends Roo.bootstrap.Column
+ * 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
+ * @cfg {Number} bullets show the panel pointer.. default 0
+ * @cfg {Boolean} autoslide (true|false) auto slide .. default false
+ * @cfg {Boolean} slideOnTouch (true|false) slide on touch .. default false
+ * @cfg {Number} timer auto slide timer .. default 0 millisecond
+ * 
+ * @constructor
+ * Create a new TabGroup
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.TabGroup = function(config){
+    Roo.bootstrap.TabGroup.superclass.constructor.call(this, config);
+    if (!this.navId) {
+        this.navId = Roo.id();
+    }
+    this.tabs = [];
+    Roo.bootstrap.TabGroup.register(this);
+    
+};
+
+Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
+    
+    carousel : false,
+    transition : false,
+    bullets : 0,
+    timer : 0,
+    autoslide : false,
+    slideFn : false,
+    slideOnTouch : false,
+    
+    getAutoCreate : function()
+    {
+        var cfg = Roo.apply({}, Roo.bootstrap.TabGroup.superclass.getAutoCreate.call(this));
+        
+        cfg.cls += ' tab-content';
+        
+        Roo.log('get auto create...............');
+        
+        if (this.carousel) {
+            cfg.cls += ' carousel slide';
+            
+            cfg.cn = [{
+               cls : 'carousel-inner'
+            }];
+        
+            if(this.bullets > 0 && !Roo.isTouch){
+                
+                var bullets = {
+                    cls : 'carousel-bullets',
+                    cn : []
+                };
+                
+                if(this.bullets_cls){
+                    bullets.cls = bullets.cls + ' ' + this.bullets_cls;
+                }
+                
+                for (var i = 0; i < this.bullets; i++){
+                    bullets.cn.push({
+                        cls : 'bullet bullet-' + i
+                    });
+                }
+                
+                bullets.cn.push({
+                    cls : 'clear'
+                });
+                
+                cfg.cn[0].cn = bullets;
+            }
         }
-        if(store){
-          
-            store.on("datachanged", this.refresh, this);
-            store.on("add", this.onAdd, this);
-            store.on("remove", this.onRemove, this);
-            store.on("update", this.onUpdate, this);
-            store.on("clear", this.refresh, this);
-            store.on("beforeload", this.onBeforeLoad, this);
-            store.on("load", this.onLoad, this);
-            store.on("loadexception", this.onLoad, this);
+        
+        return cfg;
+    },
+    
+    initEvents:  function()
+    {
+        Roo.log('-------- init events on tab group ---------');
+        
+        if(this.bullets > 0 && !Roo.isTouch){
+            this.initBullet();
         }
         
-        if(store){
-            this.refresh();
+        Roo.log(this);
+        
+        if(Roo.isTouch && this.slideOnTouch){
+            this.el.on("touchstart", this.onTouchStart, this);
+        }
+        
+        if(this.autoslide){
+            var _this = this;
+            
+            this.slideFn = window.setInterval(function() {
+                _this.showPanelNext();
+            }, this.timer);
         }
+        
     },
-    /**
-     * onbeforeLoad - masks the loading area.
-     *
-     */
-    onBeforeLoad : function(store,opts)
+    
+    onTouchStart : function(e, el, o)
     {
-         //Roo.log('onBeforeLoad');   
-        if (!opts.add) {
-            this.el.update("");
+        if(!this.slideOnTouch || !Roo.isTouch || Roo.get(e.getTarget()).hasClass('roo-button-text')){
+            return;
         }
-        this.el.mask(this.mask ? this.mask : "Loading" ); 
+        
+        this.showPanelNext();
     },
-    onLoad : function ()
+    
+    getChildContainer : function()
     {
-        this.el.unmask();
+        return this.carousel ? this.el.select('.carousel-inner', true).first() : this.el;
     },
     
-
     /**
-     * Returns the template node the passed child belongs to or null if it doesn't belong to one.
-     * @param {HTMLElement} node
-     * @return {HTMLElement} The template node
-     */
-    findItemFromChild : function(node){
-        var el = this.dataName  ?
-            this.el.child('.roo-tpl-' + this.dataName,true) :
-            this.el.dom; 
-        
-        if(!node || node.parentNode == el){
-                   return node;
-           }
-           var p = node.parentNode;
-           while(p && p != el){
-            if(p.parentNode == el){
-               return p;
-            }
-            p = p.parentNode;
-        }
-           return null;
+    * register a Navigation item
+    * @param {Roo.bootstrap.NavItem} the navitem to add
+    */
+    register : function(item)
+    {
+        this.tabs.push( item);
+        item.navId = this.navId; // not really needed..
+    
     },
-
-    /** @ignore */
-    onClick : function(e){
-        var item = this.findItemFromChild(e.getTarget());
-        if(item){
-            var index = this.indexOf(item);
-            if(this.onItemClick(item, index, e) !== false){
-                this.fireEvent("click", this, index, item, e);
+    
+    getActivePanel : function()
+    {
+        var r = false;
+        Roo.each(this.tabs, function(t) {
+            if (t.active) {
+                r = t;
+                return false;
             }
-        }else{
-            this.clearSelections();
-        }
-    },
-
-    /** @ignore */
-    onContextMenu : function(e){
-        var item = this.findItemFromChild(e.getTarget());
-        if(item){
-            this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
-        }
-    },
-
-    /** @ignore */
-    onDblClick : function(e){
-        var item = this.findItemFromChild(e.getTarget());
-        if(item){
-            this.fireEvent("dblclick", this, this.indexOf(item), item, e);
-        }
+            return null;
+        });
+        return r;
+        
     },
-
-    onItemClick : function(item, index, e)
+    getPanelByName : function(n)
     {
-        if(this.fireEvent("beforeclick", this, index, item, e) === false){
-            return false;
-        }
-        if (this.toggleSelect) {
-            var m = this.isSelected(item) ? 'unselect' : 'select';
-            //Roo.log(m);
-            var _t = this;
-            _t[m](item, true, false);
-            return true;
-        }
-        if(this.multiSelect || this.singleSelect){
-            if(this.multiSelect && e.shiftKey && this.lastSelection){
-                this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
-            }else{
-                this.select(item, this.multiSelect && e.ctrlKey);
-                this.lastSelection = item;
-            }
-            
-            if(!this.tickable){
-                e.preventDefault();
+        var r = false;
+        Roo.each(this.tabs, function(t) {
+            if (t.tabId == n) {
+                r = t;
+                return false;
             }
-            
-        }
-        return true;
-    },
-
-    /**
-     * Get the number of selected nodes.
-     * @return {Number}
-     */
-    getSelectionCount : function(){
-        return this.selections.length;
+            return null;
+        });
+        return r;
     },
-
-    /**
-     * Get the currently selected nodes.
-     * @return {Array} An array of HTMLElements
-     */
-    getSelectedNodes : function(){
-        return this.selections;
+    indexOfPanel : function(p)
+    {
+        var r = false;
+        Roo.each(this.tabs, function(t,i) {
+            if (t.tabId == p.tabId) {
+                r = i;
+                return false;
+            }
+            return null;
+        });
+        return r;
     },
-
     /**
-     * Get the indexes of the selected nodes.
-     * @return {Array}
+     * show a specific panel
+     * @param {Roo.bootstrap.TabPanel|number|string} panel to change to (use the tabId to specify a specific one)
+     * @return {boolean} false if panel was not shown (invalid entry or beforedeactivate fails.)
      */
-    getSelectedIndexes : function(){
-        var indexes = [], s = this.selections;
-        for(var i = 0, len = s.length; i < len; i++){
-            indexes.push(s[i].nodeIndex);
+    showPanel : function (pan)
+    {
+        if(this.transition){
+            Roo.log("waiting for the transitionend");
+            return;
         }
-        return indexes;
-    },
-
-    /**
-     * Clear all selections
-     * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange event
-     */
-    clearSelections : function(suppressEvent){
-        if(this.nodes && (this.multiSelect || this.singleSelect) && this.selections.length > 0){
-            this.cmp.elements = this.selections;
-            this.cmp.removeClass(this.selectedClass);
-            this.selections = [];
-            if(!suppressEvent){
-                this.fireEvent("selectionchange", this, this.selections);
-            }
+        
+        if (typeof(pan) == 'number') {
+            pan = this.tabs[pan];
         }
-    },
-
-    /**
-     * Returns true if the passed node is selected
-     * @param {HTMLElement/Number} node The node or node index
-     * @return {Boolean}
-     */
-    isSelected : function(node){
-        var s = this.selections;
-        if(s.length < 1){
-            return false;
+        if (typeof(pan) == 'string') {
+            pan = this.getPanelByName(pan);
         }
-        node = this.getNode(node);
-        return s.indexOf(node) !== -1;
-    },
-
-    /**
-     * Selects nodes.
-     * @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
-     * @param {Boolean} keepExisting (optional) true to keep existing selections
-     * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
-     */
-    select : function(nodeInfo, keepExisting, suppressEvent){
-        if(nodeInfo instanceof Array){
-            if(!keepExisting){
-                this.clearSelections(true);
-            }
-            for(var i = 0, len = nodeInfo.length; i < len; i++){
-                this.select(nodeInfo[i], true, true);
-            }
-            return;
-        } 
-        var node = this.getNode(nodeInfo);
-        if(!node || this.isSelected(node)){
-            return; // already selected.
+        if (pan.tabId == this.getActivePanel().tabId) {
+            return true;
+        }
+        var cur = this.getActivePanel();
+        
+        if (false === cur.fireEvent('beforedeactivate')) {
+            return false;
         }
-        if(!keepExisting){
-            this.clearSelections(true);
+        
+        if(this.bullets > 0 && !Roo.isTouch){
+            this.setActiveBullet(this.indexOfPanel(pan));
         }
         
-        if(this.fireEvent("beforeselect", this, node, this.selections) !== false){
-            Roo.fly(node).addClass(this.selectedClass);
-            this.selections.push(node);
-            if(!suppressEvent){
-                this.fireEvent("selectionchange", this, this.selections);
-            }
+        if (this.carousel && typeof(Roo.get(document.body).dom.style.transition) != 'undefined') {
+            
+            this.transition = true;
+            var dir = this.indexOfPanel(pan) > this.indexOfPanel(cur)  ? 'next' : 'prev';
+            var lr = dir == 'next' ? 'left' : 'right';
+            pan.el.addClass(dir); // or prev
+            pan.el.dom.offsetWidth; // find the offset with - causing a reflow?
+            cur.el.addClass(lr); // or right
+            pan.el.addClass(lr);
+            
+            var _this = this;
+            cur.el.on('transitionend', function() {
+                Roo.log("trans end?");
+                
+                pan.el.removeClass([lr,dir]);
+                pan.setActive(true);
+                
+                cur.el.removeClass([lr]);
+                cur.setActive(false);
+                
+                _this.transition = false;
+                
+            }, this, { single:  true } );
+            
+            return true;
         }
         
+        cur.setActive(false);
+        pan.setActive(true);
+        
+        return true;
         
     },
-      /**
-     * Unselects nodes.
-     * @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
-     * @param {Boolean} keepExisting (optional) true IGNORED (for campatibility with select)
-     * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
-     */
-    unselect : function(nodeInfo, keepExisting, suppressEvent)
+    showPanelNext : function()
     {
-        if(nodeInfo instanceof Array){
-            Roo.each(this.selections, function(s) {
-                this.unselect(s, nodeInfo);
-            }, this);
+        var i = this.indexOfPanel(this.getActivePanel());
+        
+        if (i >= this.tabs.length - 1 && !this.autoslide) {
             return;
         }
-        var node = this.getNode(nodeInfo);
-        if(!node || !this.isSelected(node)){
-            //Roo.log("not selected");
-            return; // not selected.
-        }
-        // fireevent???
-        var ns = [];
-        Roo.each(this.selections, function(s) {
-            if (s == node ) {
-                Roo.fly(node).removeClass(this.selectedClass);
-
-                return;
-            }
-            ns.push(s);
-        },this);
         
-        this.selections= ns;
-        this.fireEvent("selectionchange", this, this.selections);
-    },
-
-    /**
-     * Gets a template node.
-     * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
-     * @return {HTMLElement} The node or null if it wasn't found
-     */
-    getNode : function(nodeInfo){
-        if(typeof nodeInfo == "string"){
-            return document.getElementById(nodeInfo);
-        }else if(typeof nodeInfo == "number"){
-            return this.nodes[nodeInfo];
-        }
-        return nodeInfo;
-    },
-
-    /**
-     * Gets a range template nodes.
-     * @param {Number} startIndex
-     * @param {Number} endIndex
-     * @return {Array} An array of nodes
-     */
-    getNodes : function(start, end){
-        var ns = this.nodes;
-        start = start || 0;
-        end = typeof end == "undefined" ? ns.length - 1 : end;
-        var nodes = [];
-        if(start <= end){
-            for(var i = start; i <= end; i++){
-                nodes.push(ns[i]);
-            }
-        } else{
-            for(var i = start; i >= end; i--){
-                nodes.push(ns[i]);
-            }
-        }
-        return nodes;
-    },
-
-    /**
-     * Finds the index of the passed node
-     * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
-     * @return {Number} The index of the node or -1
-     */
-    indexOf : function(node){
-        node = this.getNode(node);
-        if(typeof node.nodeIndex == "number"){
-            return node.nodeIndex;
-        }
-        var ns = this.nodes;
-        for(var i = 0, len = ns.length; i < len; i++){
-            if(ns[i] == node){
-                return i;
-            }
+        if (i >= this.tabs.length - 1 && this.autoslide) {
+            i = -1;
         }
-        return -1;
-    }
-});
-/*
- * - LGPL
- *
- * based on jquery fullcalendar
- * 
- */
-
-Roo.bootstrap = Roo.bootstrap || {};
-/**
- * @class Roo.bootstrap.Calendar
- * @extends Roo.bootstrap.Component
- * Bootstrap Calendar class
- * @cfg {Boolean} loadMask (true|false) default false
- * @cfg {Object} header generate the user specific header of the calendar, default false
-
- * @constructor
- * Create a new Container
- * @param {Object} config The config object
- */
-
-
-
-Roo.bootstrap.Calendar = function(config){
-    Roo.bootstrap.Calendar.superclass.constructor.call(this, config);
-     this.addEvents({
-        /**
-            * @event select
-            * Fires when a date is selected
-            * @param {DatePicker} this
-            * @param {Date} date The selected date
-            */
-        'select': true,
-        /**
-            * @event monthchange
-            * Fires when the displayed month changes 
-            * @param {DatePicker} this
-            * @param {Date} date The selected month
-            */
-        'monthchange': true,
-        /**
-            * @event evententer
-            * Fires when mouse over an event
-            * @param {Calendar} this
-            * @param {event} Event
-            */
-        'evententer': true,
-        /**
-            * @event eventleave
-            * Fires when the mouse leaves an
-            * @param {Calendar} this
-            * @param {event}
-            */
-        'eventleave': true,
-        /**
-            * @event eventclick
-            * Fires when the mouse click an
-            * @param {Calendar} this
-            * @param {event}
-            */
-        'eventclick': true
         
-    });
-
-};
-
-Roo.extend(Roo.bootstrap.Calendar, Roo.bootstrap.Component,  {
-    
-     /**
-     * @cfg {Number} startDay
-     * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
-     */
-    startDay : 0,
-    
-    loadMask : false,
+        this.showPanel(this.tabs[i+1]);
+    },
     
-    header : false,
-      
-    getAutoCreate : function(){
-        
+    showPanelPrev : function()
+    {
+        var i = this.indexOfPanel(this.getActivePanel());
         
-        var fc_button = function(name, corner, style, content ) {
-            return Roo.apply({},{
-                tag : 'span',
-                cls : 'fc-button fc-button-'+name+' fc-state-default ' + 
-                         (corner.length ?
-                            'fc-corner-' + corner.split(' ').join(' fc-corner-') :
-                            ''
-                        ),
-                html : '<SPAN class="fc-text-'+style+ '">'+content +'</SPAN>',
-                unselectable: 'on'
-            });
-        };
+        if (i  < 1 && !this.autoslide) {
+            return;
+        }
         
-        var header = {};
+        if (i < 1 && this.autoslide) {
+            i = this.tabs.length;
+        }
         
-        if(!this.header){
-            header = {
-                tag : 'table',
-                cls : 'fc-header',
-                style : 'width:100%',
-                cn : [
-                    {
-                        tag: 'tr',
-                        cn : [
-                            {
-                                tag : 'td',
-                                cls : 'fc-header-left',
-                                cn : [
-                                    fc_button('prev', 'left', 'arrow', '&#8249;' ),
-                                    fc_button('next', 'right', 'arrow', '&#8250;' ),
-                                    { tag: 'span', cls: 'fc-header-space' },
-                                    fc_button('today', 'left right', '', 'today' )  // neds state disabled..
+        this.showPanel(this.tabs[i-1]);
+    },
+    
+    initBullet : function()
+    {
+        if(Roo.isTouch){
+            return;
+        }
+        
+        var _this = this;
+        
+        for (var i = 0; i < this.bullets; i++){
+            var bullet = this.el.select('.bullet-' + i, true).first();
 
+            if(!bullet){
+                continue;
+            }
 
-                                ]
-                            },
+            bullet.on('click', (function(e, el, o, ii, t){
 
-                            {
-                                tag : 'td',
-                                cls : 'fc-header-center',
-                                cn : [
-                                    {
-                                        tag: 'span',
-                                        cls: 'fc-header-title',
-                                        cn : {
-                                            tag: 'H2',
-                                            html : 'month / year'
-                                        }
-                                    }
+                e.preventDefault();
 
-                                ]
-                            },
-                            {
-                                tag : 'td',
-                                cls : 'fc-header-right',
-                                cn : [
-                              /*      fc_button('month', 'left', '', 'month' ),
-                                    fc_button('week', '', '', 'week' ),
-                                    fc_button('day', 'right', '', 'day' )
-                                */    
+                _this.showPanel(ii);
 
-                                ]
-                            }
+                if(_this.autoslide && _this.slideFn){
+                    clearInterval(_this.slideFn);
+                    _this.slideFn = window.setInterval(function() {
+                        _this.showPanelNext();
+                    }, _this.timer);
+                }
 
-                        ]
-                    }
-                ]
-            };
+            }).createDelegate(this, [i, bullet], true));
+        }
+    },
+    
+    setActiveBullet : function(i)
+    {
+        if(Roo.isTouch){
+            return;
         }
         
-        header = this.header;
-        
-       
-        var cal_heads = function() {
-            var ret = [];
-            // fixme - handle this.
-            
-            for (var i =0; i < Date.dayNames.length; i++) {
-                var d = Date.dayNames[i];
-                ret.push({
-                    tag: 'th',
-                    cls : 'fc-day-header fc-' + d.substring(0,3).toLowerCase() + ' fc-widget-header',
-                    html : d.substring(0,3)
-                });
-                
-            }
-            ret[0].cls += ' fc-first';
-            ret[6].cls += ' fc-last';
-            return ret;
-        };
-        var cal_cell = function(n) {
-            return  {
-                tag: 'td',
-                cls : 'fc-day fc-'+n + ' fc-widget-content', ///fc-other-month fc-past
-                cn : [
-                    {
-                        cn : [
-                            {
-                                cls: 'fc-day-number',
-                                html: 'D'
-                            },
-                            {
-                                cls: 'fc-day-content',
-                             
-                                cn : [
-                                     {
-                                        style: 'position: relative;' // height: 17px;
-                                    }
-                                ]
-                            }
-                            
-                            
-                        ]
-                    }
-                ]
-                
-            }
-        };
-        var cal_rows = function() {
-            
-            var ret = [];
-            for (var r = 0; r < 6; r++) {
-                var row= {
-                    tag : 'tr',
-                    cls : 'fc-week',
-                    cn : []
-                };
-                
-                for (var i =0; i < Date.dayNames.length; i++) {
-                    var d = Date.dayNames[i];
-                    row.cn.push(cal_cell(d.substring(0,3).toLowerCase()));
+        Roo.each(this.el.select('.bullet', true).elements, function(el){
+            el.removeClass('selected');
+        });
 
-                }
-                row.cn[0].cls+=' fc-first';
-                row.cn[0].cn[0].style = 'min-height:90px';
-                row.cn[6].cls+=' fc-last';
-                ret.push(row);
-                
-            }
-            ret[0].cls += ' fc-first';
-            ret[4].cls += ' fc-prev-last';
-            ret[5].cls += ' fc-last';
-            return ret;
-            
-        };
+        var bullet = this.el.select('.bullet-' + i, true).first();
         
-        var cal_table = {
-            tag: 'table',
-            cls: 'fc-border-separate',
-            style : 'width:100%',
-            cellspacing  : 0,
-            cn : [
-                { 
-                    tag: 'thead',
-                    cn : [
-                        { 
-                            tag: 'tr',
-                            cls : 'fc-first fc-last',
-                            cn : cal_heads()
-                        }
-                    ]
-                },
-                { 
-                    tag: 'tbody',
-                    cn : cal_rows()
-                }
-                  
-            ]
-        };
-         
-         var cfg = {
-            cls : 'fc fc-ltr',
-            cn : [
-                header,
-                {
-                    cls : 'fc-content',
-                    style : "position: relative;",
-                    cn : [
-                        {
-                            cls : 'fc-view fc-view-month fc-grid',
-                            style : 'position: relative',
-                            unselectable : 'on',
-                            cn : [
-                                {
-                                    cls : 'fc-event-container',
-                                    style : 'position:absolute;z-index:8;top:0;left:0;'
-                                },
-                                cal_table
-                            ]
-                        }
-                    ]
+        if(!bullet){
+            return;
+        }
+        
+        bullet.addClass('selected');
+    }
+    
+    
+  
+});
+
+
+Roo.apply(Roo.bootstrap.TabGroup, {
+    
+    groups: {},
+     /**
+    * register a Navigation Group
+    * @param {Roo.bootstrap.NavGroup} the navgroup to add
+    */
+    register : function(navgrp)
+    {
+        this.groups[navgrp.navId] = navgrp;
+       
+    },
+    /**
+    * 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 
+    */
+    get: function(navId) {
+        if (typeof(this.groups[navId]) == 'undefined') {
+            this.register(new Roo.bootstrap.TabGroup({ navId : navId }));
+        }
+        return this.groups[navId] ;
+    }
+    
+    
+    
+});
+
+ /*
+ * - LGPL
+ *
+ * TabPanel
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.TabPanel
+ * @extends 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 ()
+ * 
+ * 
+ * @constructor
+ * Create a new TabPanel
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.TabPanel = function(config){
+    Roo.bootstrap.TabPanel.superclass.constructor.call(this, config);
+    this.addEvents({
+        /**
+            * @event changed
+            * Fires when the active status changes
+            * @param {Roo.bootstrap.TabPanel} this
+            * @param {Boolean} state the new state
+           
+         */
+        'changed': true,
+        /**
+            * @event beforedeactivate
+            * Fires before a tab is de-activated - can be used to do validation on a form.
+            * @param {Roo.bootstrap.TabPanel} this
+            * @return {Boolean} false if there is an error
+           
+         */
+        'beforedeactivate': true
+     });
     
-                }
-           ] 
-            
+    this.tabId = this.tabId || Roo.id();
+  
+};
+
+Roo.extend(Roo.bootstrap.TabPanel, Roo.bootstrap.Component,  {
+    
+    active: false,
+    html: false,
+    tabId: false,
+    navId : false,
+    
+    getAutoCreate : function(){
+        var cfg = {
+            tag: 'div',
+            // item is needed for carousel - not sure if it has any effect otherwise
+            cls: 'tab-pane item',
+            html: this.html || ''
         };
         
-         
+        if(this.active){
+            cfg.cls += ' active';
+        }
+        
+        if(this.tabId){
+            cfg.tabId = this.tabId;
+        }
+        
         
         return cfg;
     },
     
-    
-    initEvents : function()
+    initEvents:  function()
     {
-        if(!this.store){
-            throw "can not find store for calendar";
-        }
+        Roo.log('-------- init events on tab panel ---------');
         
-        var mark = {
-            tag: "div",
-            cls:"x-dlg-mask",
-            style: "text-align:center",
-            cn: [
-                {
-                    tag: "div",
-                    style: "background-color:white;width:50%;margin:250 auto",
-                    cn: [
-                        {
-                            tag: "img",
-                            src: Roo.rootURL + '/images/ux/lightbox/loading.gif' 
-                        },
-                        {
-                            tag: "span",
-                            html: "Loading"
-                        }
-                        
-                    ]
-                }
-            ]
-        }
-        this.maskEl = Roo.DomHelper.append(this.el.select('.fc-content', true).first(), mark, true);
+        var p = this.parent();
+        this.navId = this.navId || p.navId;
         
-        var size = this.el.select('.fc-content', true).first().getSize();
-        this.maskEl.setSize(size.width, size.height);
-        this.maskEl.enableDisplayMode("block");
-        if(!this.loadMask){
-            this.maskEl.hide();
+        if (typeof(this.navId) != 'undefined') {
+            // not really needed.. but just in case.. parent should be a NavGroup.
+            var tg = Roo.bootstrap.TabGroup.get(this.navId);
+            Roo.log(['register', tg, this]);
+            tg.register(this);
+            
+            var i = tg.tabs.length - 1;
+            
+            if(this.active && tg.bullets > 0 && i < tg.bullets){
+                tg.setActiveBullet(i);
+            }
         }
         
-        this.store = Roo.factory(this.store, Roo.data);
-        this.store.on('load', this.onLoad, this);
-        this.store.on('beforeload', this.onBeforeLoad, this);
+    },
+    
+    
+    onRender : function(ct, position)
+    {
+       // Roo.log("Call onRender: " + this.xtype);
+        
+        Roo.bootstrap.TabPanel.superclass.onRender.call(this, ct, position);
         
-        this.resize();
         
-        this.cells = this.el.select('.fc-day',true);
-        //Roo.log(this.cells);
-        this.textNodes = this.el.query('.fc-day-number');
-        this.cells.addClassOnOver('fc-state-hover');
         
-        this.el.select('.fc-button-prev',true).on('click', this.showPrevMonth, this);
-        this.el.select('.fc-button-next',true).on('click', this.showNextMonth, this);
-        this.el.select('.fc-button-today',true).on('click', this.showToday, this);
-        this.el.select('.fc-button',true).addClassOnOver('fc-state-hover');
         
-        this.on('monthchange', this.onMonthChange, this);
         
-        this.update(new Date().clearTime());
     },
     
-    resize : function() {
-        var sz  = this.el.getSize();
+    setActive: function(state)
+    {
+        Roo.log("panel - set active " + this.tabId + "=" + state);
         
-        this.el.select('.fc-day-header',true).setWidth(sz.width / 7);
-        this.el.select('.fc-day-content div',true).setHeight(34);
-    },
+        this.active = state;
+        if (!state) {
+            this.el.removeClass('active');
+            
+        } else  if (!this.el.hasClass('active')) {
+            this.el.addClass('active');
+        }
+        
+        this.fireEvent('changed', this, state);
+    }
     
     
-    // private
-    showPrevMonth : function(e){
-        this.update(this.activeDate.add("mo", -1));
+});
+
+
+ /*
+ * - LGPL
+ *
+ * DateField
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.DateField
+ * @extends Roo.bootstrap.Input
+ * Bootstrap DateField class
+ * @cfg {Number} weekStart default 0
+ * @cfg {String} viewMode default empty, (months|years)
+ * @cfg {String} minViewMode default empty, (months|years)
+ * @cfg {Number} startDate default -Infinity
+ * @cfg {Number} endDate default Infinity
+ * @cfg {Boolean} todayHighlight default false
+ * @cfg {Boolean} todayBtn default false
+ * @cfg {Boolean} calendarWeeks default false
+ * @cfg {Object} daysOfWeekDisabled default empty
+ * @cfg {Boolean} singleMode default false (true | false)
+ * 
+ * @cfg {Boolean} keyboardNavigation default true
+ * @cfg {String} language default en
+ * 
+ * @constructor
+ * Create a new DateField
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.DateField = function(config){
+    Roo.bootstrap.DateField.superclass.constructor.call(this, config);
+     this.addEvents({
+            /**
+             * @event show
+             * Fires when this field show.
+             * @param {Roo.bootstrap.DateField} this
+             * @param {Mixed} date The date value
+             */
+            show : true,
+            /**
+             * @event show
+             * Fires when this field hide.
+             * @param {Roo.bootstrap.DateField} this
+             * @param {Mixed} date The date value
+             */
+            hide : true,
+            /**
+             * @event select
+             * Fires when select a date.
+             * @param {Roo.bootstrap.DateField} this
+             * @param {Mixed} date The date value
+             */
+            select : true
+        });
+};
+
+Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
+    
+    /**
+     * @cfg {String} format
+     * The default date format string which can be overriden for localization support.  The format must be
+     * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
+     */
+    format : "m/d/y",
+    /**
+     * @cfg {String} altFormats
+     * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
+     * format (defaults to 'm/d/Y|m-d-y|m-d-Y|m/d|m-d|d').
+     */
+    altFormats : "m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d",
+    
+    weekStart : 0,
+    
+    viewMode : '',
+    
+    minViewMode : '',
+    
+    todayHighlight : false,
+    
+    todayBtn: false,
+    
+    language: 'en',
+    
+    keyboardNavigation: true,
+    
+    calendarWeeks: false,
+    
+    startDate: -Infinity,
+    
+    endDate: Infinity,
+    
+    daysOfWeekDisabled: [],
+    
+    _events: [],
+    
+    singleMode : false,
+    
+    UTCDate: function()
+    {
+        return new Date(Date.UTC.apply(Date, arguments));
     },
-    showToday : function(e){
-        this.update(new Date().clearTime());
+    
+    UTCToday: function()
+    {
+        var today = new Date();
+        return this.UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
     },
-    // private
-    showNextMonth : function(e){
-        this.update(this.activeDate.add("mo", 1));
+    
+    getDate: function() {
+            var d = this.getUTCDate();
+            return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
     },
-
-    // private
-    showPrevYear : function(){
-        this.update(this.activeDate.add("y", -1));
+    
+    getUTCDate: function() {
+            return this.date;
     },
-
-    // private
-    showNextYear : function(){
-        this.update(this.activeDate.add("y", 1));
+    
+    setDate: function(d) {
+            this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
     },
-
     
-   // private
-    update : function(date)
+    setUTCDate: function(d) {
+            this.date = d;
+            this.setValue(this.formatDate(this.date));
+    },
+        
+    onRender: function(ct, position)
     {
-        var vd = this.activeDate;
-        this.activeDate = date;
-//        if(vd && this.el){
-//            var t = date.getTime();
-//            if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
-//                Roo.log('using add remove');
-//                
-//                this.fireEvent('monthchange', this, date);
-//                
-//                this.cells.removeClass("fc-state-highlight");
-//                this.cells.each(function(c){
-//                   if(c.dateValue == t){
-//                       c.addClass("fc-state-highlight");
-//                       setTimeout(function(){
-//                            try{c.dom.firstChild.focus();}catch(e){}
-//                       }, 50);
-//                       return false;
-//                   }
-//                   return true;
-//                });
-//                return;
-//            }
-//        }
         
-        var days = date.getDaysInMonth();
+        Roo.bootstrap.DateField.superclass.onRender.call(this, ct, position);
         
-        var firstOfMonth = date.getFirstDateOfMonth();
-        var startingPos = firstOfMonth.getDay()-this.startDay;
+        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";
         
-        if(startingPos < this.startDay){
-            startingPos += 7;
+        this.isRTL = Roo.bootstrap.DateField.dates[this.language].rtl || false;
+        this.format = this.format || 'm/d/y';
+        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;
+        
+        if (typeof(this.minViewMode === 'string')) {
+            switch (this.minViewMode) {
+                case 'months':
+                    this.minViewMode = 1;
+                    break;
+                case 'years':
+                    this.minViewMode = 2;
+                    break;
+                default:
+                    this.minViewMode = 0;
+                    break;
+            }
         }
         
-        var pm = date.add(Date.MONTH, -1);
-        var prevStart = pm.getDaysInMonth()-startingPos;
-//        
-        this.cells = this.el.select('.fc-day',true);
-        this.textNodes = this.el.query('.fc-day-number');
-        this.cells.addClassOnOver('fc-state-hover');
+        if (typeof(this.viewMode === 'string')) {
+            switch (this.viewMode) {
+                case 'months':
+                    this.viewMode = 1;
+                    break;
+                case 'years':
+                    this.viewMode = 2;
+                    break;
+                default:
+                    this.viewMode = 0;
+                    break;
+            }
+        }
+                
+        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.DateField.template);
         
-        var cells = this.cells.elements;
-        var textEls = this.textNodes;
+//        this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.DateField.template);
         
-        Roo.each(cells, function(cell){
-            cell.removeClass([ 'fc-past', 'fc-other-month', 'fc-future', 'fc-state-highlight', 'fc-state-disabled']);
-        });
+        this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        days += startingPos;
-
-        // convert everything to numbers so it's fast
-        var day = 86400000;
-        var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
-        //Roo.log(d);
-        //Roo.log(pm);
-        //Roo.log(prevStart);
+        this.picker().on('mousedown', this.onMousedown, this);
+        this.picker().on('click', this.onClick, this);
         
-        var today = new Date().clearTime().getTime();
-        var sel = date.clearTime().getTime();
-        var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
-        var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
-        var ddMatch = this.disabledDatesRE;
-        var ddText = this.disabledDatesText;
-        var ddays = this.disabledDays ? this.disabledDays.join("") : false;
-        var ddaysText = this.disabledDaysText;
-        var format = this.format;
+        this.picker().addClass('datepicker-dropdown');
         
-        var setCellClass = function(cal, cell){
-            cell.row = 0;
-            cell.events = [];
-            cell.more = [];
-            //Roo.log('set Cell Class');
-            cell.title = "";
-            var t = d.getTime();
-            
-            //Roo.log(d);
+        this.startViewMode = this.viewMode;
+        
+        if(this.singleMode){
+            Roo.each(this.picker().select('thead > tr > th', true).elements, function(v){
+                v.setVisibilityMode(Roo.Element.DISPLAY)
+                v.hide();
+            });
             
-            cell.dateValue = t;
-            if(t == today){
-                cell.className += " fc-today";
-                cell.className += " fc-state-highlight";
-                cell.title = cal.todayText;
-            }
-            if(t == sel){
-                // disable highlight in other month..
-                //cell.className += " fc-state-highlight";
-                
-            }
-            // disabling
-            if(t < min) {
-                cell.className = " fc-state-disabled";
-                cell.title = cal.minText;
-                return;
-            }
-            if(t > max) {
-                cell.className = " fc-state-disabled";
-                cell.title = cal.maxText;
+            Roo.each(this.picker().select('tbody > tr > td', true).elements, function(v){
+                v.setStyle('width', '189px');
+            });
+        }
+        
+        Roo.each(this.picker().select('tfoot th.today', true).elements, function(v){
+            if(!this.calendarWeeks){
+                v.remove();
                 return;
             }
-            if(ddays){
-                if(ddays.indexOf(d.getDay()) != -1){
-                    cell.title = ddaysText;
-                    cell.className = " fc-state-disabled";
-                }
-            }
-            if(ddMatch && format){
-                var fvalue = d.dateFormat(format);
-                if(ddMatch.test(fvalue)){
-                    cell.title = ddText.replace("%0", fvalue);
-                    cell.className = " fc-state-disabled";
-                }
-            }
             
-            if (!cell.initialClassName) {
-                cell.initialClassName = cell.dom.className;
-            }
-            
-            cell.dom.className = cell.initialClassName  + ' ' +  cell.className;
-        };
-
-        var i = 0;
+            v.dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
+            v.attr('colspan', function(i, val){
+                return parseInt(val) + 1;
+            });
+        })
+                       
         
-        for(; i < startingPos; i++) {
-            textEls[i].innerHTML = (++prevStart);
-            d.setDate(d.getDate()+1);
-            
-            cells[i].className = "fc-past fc-other-month";
-            setCellClass(this, cells[i]);
-        }
+        this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
         
-        var intDay = 0;
+        this.setStartDate(this.startDate);
+        this.setEndDate(this.endDate);
         
-        for(; i < days; i++){
-            intDay = i - startingPos + 1;
-            textEls[i].innerHTML = (intDay);
-            d.setDate(d.getDate()+1);
-            
-            cells[i].className = ''; // "x-date-active";
-            setCellClass(this, cells[i]);
-        }
-        var extraDays = 0;
+        this.setDaysOfWeekDisabled(this.daysOfWeekDisabled);
         
-        for(; i < 42; i++) {
-            textEls[i].innerHTML = (++extraDays);
-            d.setDate(d.getDate()+1);
-            
-            cells[i].className = "fc-future fc-other-month";
-            setCellClass(this, cells[i]);
-        }
+        this.fillDow();
+        this.fillMonths();
+        this.update();
+        this.showMode();
         
-        this.el.select('.fc-header-title h2',true).update(Date.monthNames[date.getMonth()] + " " + date.getFullYear());
+        if(this.isInline) {
+            this.show();
+        }
+    },
+    
+    picker : function()
+    {
+        return this.pickerEl;
+//        return this.el.select('.datepicker', true).first();
+    },
+    
+    fillDow: function()
+    {
+        var dowCnt = this.weekStart;
         
-        var totalRows = Math.ceil((date.getDaysInMonth() + date.getFirstDateOfMonth().getDay()) / 7);
+        var dow = {
+            tag: 'tr',
+            cn: [
+                
+            ]
+        };
         
-        this.el.select('tr.fc-week.fc-prev-last',true).removeClass('fc-last');
-        this.el.select('tr.fc-week.fc-next-last',true).addClass('fc-last').show();
+        if(this.calendarWeeks){
+            dow.cn.push({
+                tag: 'th',
+                cls: 'cw',
+                html: '&nbsp;'
+            })
+        }
         
-        if(totalRows != 6){
-            this.el.select('tr.fc-week.fc-last',true).removeClass('fc-last').addClass('fc-next-last').hide();
-            this.el.select('tr.fc-week.fc-prev-last',true).addClass('fc-last');
+        while (dowCnt < this.weekStart + 7) {
+            dow.cn.push({
+                tag: 'th',
+                cls: 'dow',
+                html: Roo.bootstrap.DateField.dates[this.language].daysMin[(dowCnt++)%7]
+            });
         }
         
-        this.fireEvent('monthchange', this, date);
+        this.picker().select('>.datepicker-days thead', true).first().createChild(dow);
+    },
+    
+    fillMonths: function()
+    {    
+        var i = 0;
+        var months = this.picker().select('>.datepicker-months td', true).first();
         
+        months.dom.innerHTML = '';
         
-        /*
-        if(!this.internalRender){
-            var main = this.el.dom.firstChild;
-            var w = main.offsetWidth;
-            this.el.setWidth(w + this.el.getBorderWidth("lr"));
-            Roo.fly(main).setWidth(w);
-            this.internalRender = true;
-            // opera does not respect the auto grow header center column
-            // then, after it gets a width opera refuses to recalculate
-            // without a second pass
-            if(Roo.isOpera && !this.secondPass){
-                main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
-                this.secondPass = true;
-                this.update.defer(10, this, [date]);
+        while (i < 12) {
+            var month = {
+                tag: 'span',
+                cls: 'month',
+                html: Roo.bootstrap.DateField.dates[this.language].monthsShort[i++]
             }
+            
+            months.createChild(month);
         }
-        */
         
     },
     
-    findCell : function(dt) {
-        dt = dt.clearTime().getTime();
-        var ret = false;
-        this.cells.each(function(c){
-            //Roo.log("check " +c.dateValue + '?=' + dt);
-            if(c.dateValue == dt){
-                ret = c;
-                return false;
-            }
-            return true;
-        });
+    update: function()
+    {
+        this.date = (typeof(this.date) === 'undefined' || ((typeof(this.date) === 'string') && !this.date.length)) ? this.UTCToday() : (typeof(this.date) === 'string') ? this.parseDate(this.date) : this.date;
         
-        return ret;
-    },
-    
-    findCells : function(ev) {
-        var s = ev.start.clone().clearTime().getTime();
-       // Roo.log(s);
-        var e= ev.end.clone().clearTime().getTime();
-       // Roo.log(e);
-        var ret = [];
-        this.cells.each(function(c){
-             ////Roo.log("check " +c.dateValue + '<' + e + ' > ' + s);
-            
-            if(c.dateValue > e){
-                return ;
-            }
-            if(c.dateValue < s){
-                return ;
-            }
-            ret.push(c);
-        });
+        if (this.date < this.startDate) {
+            this.viewDate = new Date(this.startDate);
+        } else if (this.date > this.endDate) {
+            this.viewDate = new Date(this.endDate);
+        } else {
+            this.viewDate = new Date(this.date);
+        }
         
-        return ret;    
+        this.fill();
     },
     
-//    findBestRow: function(cells)
-//    {
-//        var ret = 0;
-//        
-//        for (var i =0 ; i < cells.length;i++) {
-//            ret  = Math.max(cells[i].rows || 0,ret);
-//        }
-//        return ret;
-//        
-//    },
-    
-    
-    addItem : function(ev)
+    fill: function() 
     {
-        // look for vertical location slot in
-        var cells = this.findCells(ev);
+        var d = new Date(this.viewDate),
+                year = d.getUTCFullYear(),
+                month = d.getUTCMonth(),
+                startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
+                startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
+                endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
+                endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
+                currentDate = this.date && this.date.valueOf(),
+                today = this.UTCToday();
         
-//        ev.row = this.findBestRow(cells);
+        this.picker().select('>.datepicker-days thead th.switch', true).first().dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].months[month]+' '+year;
         
-        // work out the location.
+//        this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
         
-        var crow = false;
-        var rows = [];
-        for(var i =0; i < cells.length; i++) {
+//        this.picker.select('>tfoot th.today').
+//                                             .text(dates[this.language].today)
+//                                             .toggle(this.todayBtn !== false);
+    
+        this.updateNavArrows();
+        this.fillMonths();
+                                                
+        var prevMonth = this.UTCDate(year, month-1, 28,0,0,0,0),
+        
+        day = prevMonth.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
+         
+        prevMonth.setUTCDate(day);
+        
+        prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
+        
+        var nextMonth = new Date(prevMonth);
+        
+        nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
+        
+        nextMonth = nextMonth.valueOf();
+        
+        var fillMonths = false;
+        
+        this.picker().select('>.datepicker-days tbody',true).first().dom.innerHTML = '';
+        
+        while(prevMonth.valueOf() < nextMonth) {
+            var clsName = '';
             
-            cells[i].row = cells[0].row;
+            if (prevMonth.getUTCDay() === this.weekStart) {
+                if(fillMonths){
+                    this.picker().select('>.datepicker-days tbody',true).first().createChild(fillMonths);
+                }
+                    
+                fillMonths = {
+                    tag: 'tr',
+                    cn: []
+                };
+                
+                if(this.calendarWeeks){
+                    // ISO 8601: First week contains first thursday.
+                    // ISO also states week starts on Monday, but we can be more abstract here.
+                    var
+                    // Start of current week: based on weekstart/current date
+                    ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
+                    // Thursday of this week
+                    th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
+                    // First Thursday of year, year from thursday
+                    yth = new Date(+(yth = this.UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
+                    // Calendar week: ms between thursdays, div ms per day, div 7 days
+                    calWeek =  (th - yth) / 864e5 / 7 + 1;
+                    
+                    fillMonths.cn.push({
+                        tag: 'td',
+                        cls: 'cw',
+                        html: calWeek
+                    });
+                }
+            }
             
-            if(i == 0){
-                cells[i].row = cells[i].row + 1;
+            if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
+                clsName += ' old';
+            } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
+                clsName += ' new';
+            }
+            if (this.todayHighlight &&
+                prevMonth.getUTCFullYear() == today.getFullYear() &&
+                prevMonth.getUTCMonth() == today.getMonth() &&
+                prevMonth.getUTCDate() == today.getDate()) {
+                clsName += ' today';
             }
             
-            if (!crow) {
-                crow = {
-                    start : cells[i],
-                    end :  cells[i]
-                };
-                continue;
+            if (currentDate && prevMonth.valueOf() === currentDate) {
+                clsName += ' active';
             }
-            if (crow.start.getY() == cells[i].getY()) {
-                // on same row.
-                crow.end = cells[i];
-                continue;
+            
+            if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate ||
+                    this.daysOfWeekDisabled.indexOf(prevMonth.getUTCDay()) !== -1) {
+                    clsName += ' disabled';
             }
-            // different row.
-            rows.push(crow);
-            crow = {
-                start: cells[i],
-                end : cells[i]
-            };
             
+            fillMonths.cn.push({
+                tag: 'td',
+                cls: 'day ' + clsName,
+                html: prevMonth.getDate()
+            })
+            
+            prevMonth.setDate(prevMonth.getDate()+1);
         }
+          
+        var currentYear = this.date && this.date.getUTCFullYear();
+        var currentMonth = this.date && this.date.getUTCMonth();
         
-        rows.push(crow);
-        ev.els = [];
-        ev.rows = rows;
-        ev.cells = cells;
+        this.picker().select('>.datepicker-months th.switch',true).first().dom.innerHTML = year;
         
-        cells[0].events.push(ev);
+        Roo.each(this.picker().select('>.datepicker-months tbody span',true).elements, function(v,k){
+            v.removeClass('active');
+            
+            if(currentYear === year && k === currentMonth){
+                v.addClass('active');
+            }
+            
+            if (year < startYear || year > endYear || (year == startYear && k < startMonth) || (year == endYear && k > endMonth)) {
+                v.addClass('disabled');
+            }
+            
+        });
+        
+        
+        year = parseInt(year/10, 10) * 10;
+        
+        this.picker().select('>.datepicker-years th.switch', true).first().dom.innerHTML = year + '-' + (year + 9);
+        
+        this.picker().select('>.datepicker-years tbody td',true).first().dom.innerHTML = '';
+        
+        year -= 1;
+        for (var i = -1; i < 11; i++) {
+            this.picker().select('>.datepicker-years tbody td',true).first().createChild({
+                tag: 'span',
+                cls: 'year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + (year < startYear || year > endYear ? ' disabled' : ''),
+                html: year
+            })
+            
+            year += 1;
+        }
+    },
+    
+    showMode: function(dir) 
+    {
+        if (dir) {
+            this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
+        }
         
-        this.calevents.push(ev);
+        Roo.each(this.picker().select('>div',true).elements, function(v){
+            v.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+            v.hide();
+        });
+        this.picker().select('>.datepicker-'+Roo.bootstrap.DateField.modes[this.viewMode].clsName, true).first().show();
     },
     
-    clearEvents: function() {
+    place: function()
+    {
+        if(this.isInline) return;
         
-        if(!this.calevents){
+        this.picker().removeClass(['bottom', 'top']);
+        
+        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){
+            /*
+             * place to the top of element!
+             *
+             */
+            
+            this.picker().addClass('top');
+            this.picker().setTop(this.inputEl().getTop() - this.picker().getHeight()).setLeft(this.inputEl().getLeft());
+            
             return;
         }
         
-        Roo.each(this.cells.elements, function(c){
-            c.row = 0;
-            c.events = [];
-            c.more = [];
-        });
-        
-        Roo.each(this.calevents, function(e) {
-            Roo.each(e.els, function(el) {
-                el.un('mouseenter' ,this.onEventEnter, this);
-                el.un('mouseleave' ,this.onEventLeave, this);
-                el.remove();
-            },this);
-        },this);
-        
-        Roo.each(Roo.select('.fc-more-event', true).elements, function(e){
-            e.remove();
-        });
+        this.picker().addClass('bottom');
         
+        this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());
     },
     
-    renderEvents: function()
-    {   
-        var _this = this;
-        
-        this.cells.each(function(c) {
-            
-            if(c.row < 5){
-                return;
-            }
-            
-            var ev = c.events;
-            
-            var r = 4;
-            if(c.row != c.events.length){
-                r = 4 - (4 - (c.row - c.events.length));
-            }
-            
-            c.events = ev.slice(0, r);
-            c.more = ev.slice(r);
-            
-            if(c.more.length && c.more.length == 1){
-                c.events.push(c.more.pop());
-            }
-            
-            c.row = (c.row - ev.length) + c.events.length + ((c.more.length) ? 1 : 0);
-            
-        });
-            
-        this.cells.each(function(c) {
-            
-            c.select('.fc-day-content div',true).first().setHeight(Math.max(34, c.row * 20));
-            
-            
-            for (var e = 0; e < c.events.length; e++){
-                var ev = c.events[e];
-                var rows = ev.rows;
-                
-                for(var i = 0; i < rows.length; i++) {
-                
-                    // how many rows should it span..
-
-                    var  cfg = {
-                        cls : 'roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable',
-                        style : 'position: absolute', // left: 387px; width: 121px; top: 359px;
-
-                        unselectable : "on",
-                        cn : [
-                            {
-                                cls: 'fc-event-inner',
-                                cn : [
-    //                                {
-    //                                  tag:'span',
-    //                                  cls: 'fc-event-time',
-    //                                  html : cells.length > 1 ? '' : ev.time
-    //                                },
-                                    {
-                                      tag:'span',
-                                      cls: 'fc-event-title',
-                                      html : String.format('{0}', ev.title)
-                                    }
-
-
-                                ]
-                            },
-                            {
-                                cls: 'ui-resizable-handle ui-resizable-e',
-                                html : '&nbsp;&nbsp;&nbsp'
-                            }
-
-                        ]
-                    };
-
-                    if (i == 0) {
-                        cfg.cls += ' fc-event-start';
-                    }
-                    if ((i+1) == rows.length) {
-                        cfg.cls += ' fc-event-end';
-                    }
-
-                    var ctr = _this.el.select('.fc-event-container',true).first();
-                    var cg = ctr.createChild(cfg);
-
-                    var sbox = rows[i].start.select('.fc-day-content',true).first().getBox();
-                    var ebox = rows[i].end.select('.fc-day-content',true).first().getBox();
-
-                    var r = (c.more.length) ? 1 : 0;
-                    cg.setXY([sbox.x +2, sbox.y + ((c.row - c.events.length - r + e) * 20)]);    
-                    cg.setWidth(ebox.right - sbox.x -2);
-
-                    cg.on('mouseenter' ,_this.onEventEnter, _this, ev);
-                    cg.on('mouseleave' ,_this.onEventLeave, _this, ev);
-                    cg.on('click', _this.onEventClick, _this, ev);
-
-                    ev.els.push(cg);
-                    
-                }
-                
+    parseDate : function(value)
+    {
+        if(!value || value instanceof Date){
+            return value;
+        }
+        var v = Date.parseDate(value, this.format);
+        if (!v && (this.useIso || value.match(/^(\d{4})-0?(\d+)-0?(\d+)/))) {
+            v = Date.parseDate(value, 'Y-m-d');
+        }
+        if(!v && this.altFormats){
+            if(!this.altFormatsArray){
+                this.altFormatsArray = this.altFormats.split("|");
             }
-            
-            
-            if(c.more.length){
-                var  cfg = {
-                    cls : 'fc-more-event roo-dynamic fc-event fc-event-hori fc-event-draggable ui-draggable fc-event-start fc-event-end',
-                    style : 'position: absolute',
-                    unselectable : "on",
-                    cn : [
-                        {
-                            cls: 'fc-event-inner',
-                            cn : [
-                                {
-                                  tag:'span',
-                                  cls: 'fc-event-title',
-                                  html : 'More'
-                                }
-
-
-                            ]
-                        },
-                        {
-                            cls: 'ui-resizable-handle ui-resizable-e',
-                            html : '&nbsp;&nbsp;&nbsp'
-                        }
-
-                    ]
-                };
-
-                var ctr = _this.el.select('.fc-event-container',true).first();
-                var cg = ctr.createChild(cfg);
-
-                var sbox = c.select('.fc-day-content',true).first().getBox();
-                var ebox = c.select('.fc-day-content',true).first().getBox();
-                //Roo.log(cg);
-                cg.setXY([sbox.x +2, sbox.y +((c.row - 1) * 20)]);    
-                cg.setWidth(ebox.right - sbox.x -2);
-
-                cg.on('click', _this.onMoreEventClick, _this, c.more);
-                
+            for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
+                v = Date.parseDate(value, this.altFormatsArray[i]);
             }
-            
-        });
-        
+        }
+        return v;
+    },
+    
+    formatDate : function(date, fmt)
+    {   
+        return (!date || !(date instanceof Date)) ?
+        date : date.dateFormat(fmt || this.format);
+    },
+    
+    onFocus : function()
+    {
+        Roo.bootstrap.DateField.superclass.onFocus.call(this);
+        this.show();
+    },
+    
+    onBlur : function()
+    {
+        Roo.bootstrap.DateField.superclass.onBlur.call(this);
         
+        var d = this.inputEl().getValue();
         
+        this.setValue(d);
+                
+        this.hide();
     },
     
-    onEventEnter: function (e, el,event,d) {
-        this.fireEvent('evententer', this, el, event);
+    show : function()
+    {
+        this.picker().show();
+        this.update();
+        this.place();
+        
+        this.fireEvent('show', this, this.date);
     },
     
-    onEventLeave: function (e, el,event,d) {
-        this.fireEvent('eventleave', this, el, event);
+    hide : function()
+    {
+        if(this.isInline) return;
+        this.picker().hide();
+        this.viewMode = this.startViewMode;
+        this.showMode();
+        
+        this.fireEvent('hide', this, this.date);
+        
     },
     
-    onEventClick: function (e, el,event,d) {
-        this.fireEvent('eventclick', this, el, event);
+    onMousedown: function(e)
+    {
+        e.stopPropagation();
+        e.preventDefault();
     },
     
-    onMonthChange: function () {
-        this.store.load();
+    keyup: function(e)
+    {
+        Roo.bootstrap.DateField.superclass.keyup.call(this);
+        this.update();
     },
-    
-    onMoreEventClick: function(e, el, more)
+
+    setValue: function(v)
     {
-        var _this = this;
         
-        this.calpopover.placement = 'right';
-        this.calpopover.setTitle('More');
+        // v can be a string or a date..
+        
         
-        this.calpopover.setContent('');
+        var d = new Date(this.parseDate(v) ).clearTime();
         
-        var ctr = this.calpopover.el.select('.popover-content', true).first();
+        if(isNaN(d.getTime())){
+            this.date = this.viewDate = '';
+            Roo.bootstrap.DateField.superclass.setValue.call(this, '');
+            return;
+        }
         
-        Roo.each(more, function(m){
-            var cfg = {
-                cls : 'fc-event-hori fc-event-draggable',
-                html : m.title
-            }
-            var cg = ctr.createChild(cfg);
-            
-            cg.on('click', _this.onEventClick, _this, m);
-        });
+        v = this.formatDate(d);
         
-        this.calpopover.show(el);
+        Roo.bootstrap.DateField.superclass.setValue.call(this, v);
         
+        this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
+     
+        this.update();
+
+        this.fireEvent('select', this, this.date);
         
     },
     
-    onLoad: function () 
-    {   
-        this.calevents = [];
-        var cal = this;
-        
-        if(this.store.getCount() > 0){
-            this.store.data.each(function(d){
-               cal.addItem({
-                    id : d.data.id,
-                    start: (typeof(d.data.start_dt) === 'string') ? new Date.parseDate(d.data.start_dt, 'Y-m-d H:i:s') : d.data.start_dt,
-                    end : (typeof(d.data.end_dt) === 'string') ? new Date.parseDate(d.data.end_dt, 'Y-m-d H:i:s') : d.data.end_dt,
-                    time : d.data.start_time,
-                    title : d.data.title,
-                    description : d.data.description,
-                    venue : d.data.venue
-                });
-            });
+    getValue: function()
+    {
+        return this.formatDate(this.date);
+    },
+    
+    fireKey: function(e)
+    {
+        if (!this.picker().isVisible()){
+            if (e.keyCode == 27) // allow escape to hide and re-show picker
+                this.show();
+            return;
         }
         
-        this.renderEvents();
+        var dateChanged = false,
+        dir, day, month,
+        newDate, newViewDate;
         
-        if(this.calevents.length && this.loadMask){
-            this.maskEl.hide();
+        switch(e.keyCode){
+            case 27: // escape
+                this.hide();
+                e.preventDefault();
+                break;
+            case 37: // left
+            case 39: // right
+                if (!this.keyboardNavigation) break;
+                dir = e.keyCode == 37 ? -1 : 1;
+                
+                if (e.ctrlKey){
+                    newDate = this.moveYear(this.date, dir);
+                    newViewDate = this.moveYear(this.viewDate, dir);
+                } else if (e.shiftKey){
+                    newDate = this.moveMonth(this.date, dir);
+                    newViewDate = this.moveMonth(this.viewDate, dir);
+                } else {
+                    newDate = new Date(this.date);
+                    newDate.setUTCDate(this.date.getUTCDate() + dir);
+                    newViewDate = new Date(this.viewDate);
+                    newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
+                }
+                if (this.dateWithinRange(newDate)){
+                    this.date = newDate;
+                    this.viewDate = newViewDate;
+                    this.setValue(this.formatDate(this.date));
+//                    this.update();
+                    e.preventDefault();
+                    dateChanged = true;
+                }
+                break;
+            case 38: // up
+            case 40: // down
+                if (!this.keyboardNavigation) break;
+                dir = e.keyCode == 38 ? -1 : 1;
+                if (e.ctrlKey){
+                    newDate = this.moveYear(this.date, dir);
+                    newViewDate = this.moveYear(this.viewDate, dir);
+                } else if (e.shiftKey){
+                    newDate = this.moveMonth(this.date, dir);
+                    newViewDate = this.moveMonth(this.viewDate, dir);
+                } else {
+                    newDate = new Date(this.date);
+                    newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
+                    newViewDate = new Date(this.viewDate);
+                    newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
+                }
+                if (this.dateWithinRange(newDate)){
+                    this.date = newDate;
+                    this.viewDate = newViewDate;
+                    this.setValue(this.formatDate(this.date));
+//                    this.update();
+                    e.preventDefault();
+                    dateChanged = true;
+                }
+                break;
+            case 13: // enter
+                this.setValue(this.formatDate(this.date));
+                this.hide();
+                e.preventDefault();
+                break;
+            case 9: // tab
+                this.setValue(this.formatDate(this.date));
+                this.hide();
+                break;
+            case 16: // shift
+            case 17: // ctrl
+            case 18: // alt
+                break;
+            default :
+                this.hide();
+                
         }
     },
     
-    onBeforeLoad: function()
-    {
-        this.clearEvents();
-        if(this.loadMask){
-            this.maskEl.show();
-        }
-    }
-});
-
- /*
- * - LGPL
- *
- * element
- * 
- */
-
-/**
- * @class Roo.bootstrap.Popover
- * @extends 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)
- * @cfg {String} placement how it is placed
- * @cfg {String} trigger click || hover (or false to trigger manually)
- * @cfg {String} over what (parent or false to trigger manually.)
- * @cfg {Number} delay - delay before showing
- * @constructor
- * Create a new Popover
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.Popover = function(config){
-    Roo.bootstrap.Popover.superclass.constructor.call(this, config);
-};
-
-Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
-    
-    title: 'Fill in a title',
-    html: false,
-    
-    placement : 'right',
-    trigger : 'hover', // hover
-    
-    delay : 0,
-    
-    over: 'parent',
-    
-    can_build_overlaid : false,
     
-    getChildContainer : function()
+    onClick: function(e) 
     {
-        return this.el.select('.popover-content',true).first();
-    },
-    
-    getAutoCreate : function(){
-         Roo.log('make popover?');
-        var cfg = {
-           cls : 'popover roo-dynamic',
-           style: 'display:block',
-           cn : [
-                {
-                    cls : 'arrow'
-                },
-                {
-                    cls : 'popover-inner',
-                    cn : [
-                        {
-                            tag: 'h3',
-                            cls: 'popover-title',
-                            html : this.title
-                        },
-                        {
-                            cls : 'popover-content',
-                            html : this.html
+        e.stopPropagation();
+        e.preventDefault();
+        
+        var target = e.getTarget();
+        
+        if(target.nodeName.toLowerCase() === 'i'){
+            target = Roo.get(target).dom.parentNode;
+        }
+        
+        var nodeName = target.nodeName;
+        var className = target.className;
+        var html = target.innerHTML;
+        //Roo.log(nodeName);
+        
+        switch(nodeName.toLowerCase()) {
+            case 'th':
+                switch(className) {
+                    case 'switch':
+                        this.showMode(1);
+                        break;
+                    case 'prev':
+                    case 'next':
+                        var dir = Roo.bootstrap.DateField.modes[this.viewMode].navStep * (className == 'prev' ? -1 : 1);
+                        switch(this.viewMode){
+                                case 0:
+                                        this.viewDate = this.moveMonth(this.viewDate, dir);
+                                        break;
+                                case 1:
+                                case 2:
+                                        this.viewDate = this.moveYear(this.viewDate, dir);
+                                        break;
                         }
-                    ]
+                        this.fill();
+                        break;
+                    case 'today':
+                        var date = new Date();
+                        this.date = this.UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
+//                        this.fill()
+                        this.setValue(this.formatDate(this.date));
+                        
+                        this.hide();
+                        break;
+                }
+                break;
+            case 'span':
+                if (className.indexOf('disabled') < 0) {
+                    this.viewDate.setUTCDate(1);
+                    if (className.indexOf('month') > -1) {
+                        this.viewDate.setUTCMonth(Roo.bootstrap.DateField.dates[this.language].monthsShort.indexOf(html));
+                    } else {
+                        var year = parseInt(html, 10) || 0;
+                        this.viewDate.setUTCFullYear(year);
+                        
+                    }
+                    
+                    if(this.singleMode){
+                        this.setValue(this.formatDate(this.viewDate));
+                        this.hide();
+                        return;
+                    }
                     
+                    this.showMode(-1);
+                    this.fill();
                 }
-           ]
-        };
-        
-        return cfg;
+                break;
+                
+            case 'td':
+                //Roo.log(className);
+                if (className.indexOf('day') > -1 && className.indexOf('disabled') < 0 ){
+                    var day = parseInt(html, 10) || 1;
+                    var year = this.viewDate.getUTCFullYear(),
+                        month = this.viewDate.getUTCMonth();
+
+                    if (className.indexOf('old') > -1) {
+                        if(month === 0 ){
+                            month = 11;
+                            year -= 1;
+                        }else{
+                            month -= 1;
+                        }
+                    } else if (className.indexOf('new') > -1) {
+                        if (month == 11) {
+                            month = 0;
+                            year += 1;
+                        } else {
+                            month += 1;
+                        }
+                    }
+                    //Roo.log([year,month,day]);
+                    this.date = this.UTCDate(year, month, day,0,0,0,0);
+                    this.viewDate = this.UTCDate(year, month, Math.min(28, day),0,0,0,0);
+//                    this.fill();
+                    //Roo.log(this.formatDate(this.date));
+                    this.setValue(this.formatDate(this.date));
+                    this.hide();
+                }
+                break;
+        }
     },
-    setTitle: function(str)
+    
+    setStartDate: function(startDate)
     {
-        this.el.select('.popover-title',true).first().dom.innerHTML = str;
+        this.startDate = startDate || -Infinity;
+        if (this.startDate !== -Infinity) {
+            this.startDate = this.parseDate(this.startDate);
+        }
+        this.update();
+        this.updateNavArrows();
     },
-    setContent: function(str)
+
+    setEndDate: function(endDate)
     {
-        this.el.select('.popover-content',true).first().dom.innerHTML = str;
+        this.endDate = endDate || Infinity;
+        if (this.endDate !== Infinity) {
+            this.endDate = this.parseDate(this.endDate);
+        }
+        this.update();
+        this.updateNavArrows();
     },
-    // as it get's added to the bottom of the page.
-    onRender : function(ct, position)
+    
+    setDaysOfWeekDisabled: function(daysOfWeekDisabled)
     {
-        Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
-        if(!this.el){
-            var cfg = Roo.apply({},  this.getAutoCreate());
-            cfg.id = Roo.id();
-            
-            if (this.cls) {
-                cfg.cls += ' ' + this.cls;
-            }
-            if (this.style) {
-                cfg.style = this.style;
-            }
-            Roo.log("adding to ")
-            this.el = Roo.get(document.body).createChild(cfg, position);
-            Roo.log(this.el);
+        this.daysOfWeekDisabled = daysOfWeekDisabled || [];
+        if (typeof(this.daysOfWeekDisabled) !== 'object') {
+            this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
         }
-        this.initEvents();
+        this.daysOfWeekDisabled = this.daysOfWeekDisabled.map(function (d) {
+            return parseInt(d, 10);
+        });
+        this.update();
+        this.updateNavArrows();
     },
     
-    initEvents : function()
+    updateNavArrows: function() 
     {
-        this.el.select('.popover-title',true).setVisibilityMode(Roo.Element.DISPLAY);
-        this.el.enableDisplayMode('block');
-        this.el.hide();
-        if (this.over === false) {
-            return; 
-        }
-        if (this.triggers === false) {
+        if(this.singleMode){
             return;
         }
-        var on_el = (this.over == 'parent') ? this.parent().el : Roo.get(this.over);
-        var triggers = this.trigger ? this.trigger.split(' ') : [];
-        Roo.each(triggers, function(trigger) {
         
-            if (trigger == 'click') {
-                on_el.on('click', this.toggle, this);
-            } else if (trigger != 'manual') {
-                var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin';
-                var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';
-      
-                on_el.on(eventIn  ,this.enter, this);
-                on_el.on(eventOut, this.leave, this);
-            }
-        }, this);
+        var d = new Date(this.viewDate),
+        year = d.getUTCFullYear(),
+        month = d.getUTCMonth();
         
-    },
-    
-    
-    // private
-    timeout : null,
-    hoverState : null,
-    
-    toggle : function () {
-        this.hoverState == 'in' ? this.leave() : this.enter();
-    },
-    
-    enter : function () {
-       
-    
-        clearTimeout(this.timeout);
-    
-        this.hoverState = 'in';
-    
-        if (!this.delay || !this.delay.show) {
-            this.show();
-            return;
-        }
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            if (_t.hoverState == 'in') {
-                _t.show();
+        Roo.each(this.picker().select('.prev', true).elements, function(v){
+            v.show();
+            switch (this.viewMode) {
+                case 0:
+
+                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
+                        v.hide();
+                    }
+                    break;
+                case 1:
+                case 2:
+                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
+                        v.hide();
+                    }
+                    break;
             }
-        }, this.delay.show)
-    },
-    leave : function() {
-        clearTimeout(this.timeout);
-    
-        this.hoverState = 'out';
-    
-        if (!this.delay || !this.delay.hide) {
-            this.hide();
-            return;
-        }
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            if (_t.hoverState == 'out') {
-                _t.hide();
+        });
+        
+        Roo.each(this.picker().select('.next', true).elements, function(v){
+            v.show();
+            switch (this.viewMode) {
+                case 0:
+
+                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
+                        v.hide();
+                    }
+                    break;
+                case 1:
+                case 2:
+                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
+                        v.hide();
+                    }
+                    break;
             }
-        }, this.delay.hide)
+        })
     },
     
-    show : function (on_el)
+    moveMonth: function(date, dir)
     {
-        if (!on_el) {
-            on_el= (this.over == 'parent') ? this.parent().el : Roo.get(this.over);
-        }
-        // set content.
-        this.el.select('.popover-title',true).first().dom.innerHtml = this.title;
-        if (this.html !== false) {
-            this.el.select('.popover-content',true).first().dom.innerHtml = this.title;
-        }
-        this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
-        if (!this.title.length) {
-            this.el.select('.popover-title',true).hide();
-        }
-        
-        var placement = typeof this.placement == 'function' ?
-            this.placement.call(this, this.el, on_el) :
-            this.placement;
-            
-        var autoToken = /\s?auto?\s?/i;
-        var autoPlace = autoToken.test(placement);
-        if (autoPlace) {
-            placement = placement.replace(autoToken, '') || 'top';
-        }
-        
-        //this.el.detach()
-        //this.el.setXY([0,0]);
-        this.el.show();
-        this.el.dom.style.display='block';
-        this.el.addClass(placement);
-        
-        //this.el.appendTo(on_el);
-        
-        var p = this.getPosition();
-        var box = this.el.getBox();
-        
-        if (autoPlace) {
-            // fixme..
+        if (!dir) return date;
+        var new_date = new Date(date.valueOf()),
+        day = new_date.getUTCDate(),
+        month = new_date.getUTCMonth(),
+        mag = Math.abs(dir),
+        new_month, test;
+        dir = dir > 0 ? 1 : -1;
+        if (mag == 1){
+            test = dir == -1
+            // If going back one month, make sure month is not current month
+            // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
+            ? function(){
+                return new_date.getUTCMonth() == month;
+            }
+            // If going forward one month, make sure month is as expected
+            // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
+            : function(){
+                return new_date.getUTCMonth() != new_month;
+            };
+            new_month = month + dir;
+            new_date.setUTCMonth(new_month);
+            // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
+            if (new_month < 0 || new_month > 11)
+                new_month = (new_month + 12) % 12;
+        } else {
+            // For magnitudes >1, move one month at a time...
+            for (var i=0; i<mag; i++)
+                // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
+                new_date = this.moveMonth(new_date, dir);
+            // ...then reset the day, keeping it in the new month
+            new_month = new_date.getUTCMonth();
+            new_date.setUTCDate(day);
+            test = function(){
+                return new_month != new_date.getUTCMonth();
+            };
         }
-        var align = Roo.bootstrap.Popover.alignment[placement];
-        this.el.alignTo(on_el, align[0],align[1]);
-        //var arrow = this.el.select('.arrow',true).first();
-        //arrow.set(align[2], 
-        
-        this.el.addClass('in');
-        this.hoverState = null;
-        
-        if (this.el.hasClass('fade')) {
-            // fade it?
+        // Common date-resetting loop -- if date is beyond end of month, make it
+        // end of month
+        while (test()){
+            new_date.setUTCDate(--day);
+            new_date.setUTCMonth(new_month);
         }
-        
+        return new_date;
     },
-    hide : function()
-    {
-        this.el.setXY([0,0]);
-        this.el.removeClass('in');
-        this.el.hide();
-        
-    }
-    
-});
-
-Roo.bootstrap.Popover.alignment = {
-    'left' : ['r-l', [-10,0], 'right'],
-    'right' : ['l-r', [10,0], 'left'],
-    'bottom' : ['t-b', [0,10], 'top'],
-    'top' : [ 'b-t', [0,-10], 'bottom']
-};
-
- /*
- * - LGPL
- *
- * Progress
- * 
- */
 
-/**
- * @class Roo.bootstrap.Progress
- * @extends Roo.bootstrap.Component
- * Bootstrap Progress class
- * @cfg {Boolean} striped striped of the progress bar
- * @cfg {Boolean} active animated of the progress bar
- * 
- * 
- * @constructor
- * Create a new Progress
- * @param {Object} config The config object
- */
+    moveYear: function(date, dir)
+    {
+        return this.moveMonth(date, dir*12);
+    },
 
-Roo.bootstrap.Progress = function(config){
-    Roo.bootstrap.Progress.superclass.constructor.call(this, config);
-};
+    dateWithinRange: function(date)
+    {
+        return date >= this.startDate && date <= this.endDate;
+    },
 
-Roo.extend(Roo.bootstrap.Progress, Roo.bootstrap.Component,  {
-    
-    striped : false,
-    active: false,
     
-    getAutoCreate : function(){
-        var cfg = {
-            tag: 'div',
-            cls: 'progress'
-        };
-        
-        
-        if(this.striped){
-            cfg.cls += ' progress-striped';
-        }
-      
-        if(this.active){
-            cfg.cls += ' active';
-        }
-        
-        
-        return cfg;
+    remove: function() 
+    {
+        this.picker().remove();
     }
    
 });
 
-
- /*
- * - LGPL
- *
- * ProgressBar
- * 
- */
-
-/**
- * @class Roo.bootstrap.ProgressBar
- * @extends Roo.bootstrap.Component
- * Bootstrap ProgressBar class
- * @cfg {Number} aria_valuenow aria-value now
- * @cfg {Number} aria_valuemin aria-value min
- * @cfg {Number} aria_valuemax aria-value max
- * @cfg {String} label label for the progress bar
- * @cfg {String} panel (success | info | warning | danger )
- * @cfg {String} role role of the progress bar
- * @cfg {String} sr_only text
- * 
- * 
- * @constructor
- * Create a new ProgressBar
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.ProgressBar = function(config){
-    Roo.bootstrap.ProgressBar.superclass.constructor.call(this, config);
-};
+Roo.apply(Roo.bootstrap.DateField,  {
+    
+    head : {
+        tag: 'thead',
+        cn: [
+        {
+            tag: 'tr',
+            cn: [
+            {
+                tag: 'th',
+                cls: 'prev',
+                html: '<i class="fa fa-arrow-left"/>'
+            },
+            {
+                tag: 'th',
+                cls: 'switch',
+                colspan: '5'
+            },
+            {
+                tag: 'th',
+                cls: 'next',
+                html: '<i class="fa fa-arrow-right"/>'
+            }
 
-Roo.extend(Roo.bootstrap.ProgressBar, Roo.bootstrap.Component,  {
+            ]
+        }
+        ]
+    },
     
-    aria_valuenow : 0,
-    aria_valuemin : 0,
-    aria_valuemax : 100,
-    label : false,
-    panel : false,
-    role : false,
-    sr_only: false,
+    content : {
+        tag: 'tbody',
+        cn: [
+        {
+            tag: 'tr',
+            cn: [
+            {
+                tag: 'td',
+                colspan: '7'
+            }
+            ]
+        }
+        ]
+    },
     
-    getAutoCreate : function()
+    footer : {
+        tag: 'tfoot',
+        cn: [
+        {
+            tag: 'tr',
+            cn: [
+            {
+                tag: 'th',
+                colspan: '7',
+                cls: 'today'
+            }
+                    
+            ]
+        }
+        ]
+    },
+    
+    dates:{
+        en: {
+            days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
+            daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+            daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
+            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+            today: "Today"
+        }
+    },
+    
+    modes: [
     {
-        
-        var cfg = {
+        clsName: 'days',
+        navFnc: 'Month',
+        navStep: 1
+    },
+    {
+        clsName: 'months',
+        navFnc: 'FullYear',
+        navStep: 1
+    },
+    {
+        clsName: 'years',
+        navFnc: 'FullYear',
+        navStep: 10
+    }]
+});
+
+Roo.apply(Roo.bootstrap.DateField,  {
+  
+    template : {
+        tag: 'div',
+        cls: 'datepicker dropdown-menu roo-dynamic',
+        cn: [
+        {
+            tag: 'div',
+            cls: 'datepicker-days',
+            cn: [
+            {
+                tag: 'table',
+                cls: 'table-condensed',
+                cn:[
+                Roo.bootstrap.DateField.head,
+                {
+                    tag: 'tbody'
+                },
+                Roo.bootstrap.DateField.footer
+                ]
+            }
+            ]
+        },
+        {
+            tag: 'div',
+            cls: 'datepicker-months',
+            cn: [
+            {
+                tag: 'table',
+                cls: 'table-condensed',
+                cn:[
+                Roo.bootstrap.DateField.head,
+                Roo.bootstrap.DateField.content,
+                Roo.bootstrap.DateField.footer
+                ]
+            }
+            ]
+        },
+        {
             tag: 'div',
-            cls: 'progress-bar',
-            style: 'width:' + Math.ceil((this.aria_valuenow / this.aria_valuemax) * 100) + '%'
-        };
-        
-        if(this.sr_only){
-            cfg.cn = {
-                tag: 'span',
-                cls: 'sr-only',
-                html: this.sr_only
+            cls: 'datepicker-years',
+            cn: [
+            {
+                tag: 'table',
+                cls: 'table-condensed',
+                cn:[
+                Roo.bootstrap.DateField.head,
+                Roo.bootstrap.DateField.content,
+                Roo.bootstrap.DateField.footer
+                ]
             }
+            ]
         }
-        
-        if(this.role){
-            cfg.role = this.role;
-        }
-        
-        if(this.aria_valuenow){
-            cfg['aria-valuenow'] = this.aria_valuenow;
-        }
-        
-        if(this.aria_valuemin){
-            cfg['aria-valuemin'] = this.aria_valuemin;
-        }
-        
-        if(this.aria_valuemax){
-            cfg['aria-valuemax'] = this.aria_valuemax;
-        }
-        
-        if(this.label && !this.sr_only){
-            cfg.html = this.label;
-        }
-        
-        if(this.panel){
-            cfg.cls += ' progress-bar-' + this.panel;
-        }
-        
-        return cfg;
-    },
-    
-    update : function(aria_valuenow)
-    {
-        this.aria_valuenow = aria_valuenow;
-        
-        this.el.setStyle('width', Math.ceil((this.aria_valuenow / this.aria_valuemax) * 100) + '%');
+        ]
     }
-   
 });
 
  
@@ -14925,8395 +17152,9807 @@ Roo.extend(Roo.bootstrap.ProgressBar, Roo.bootstrap.Component,  {
  /*
  * - LGPL
  *
- * column
+ * TimeField
  * 
  */
 
 /**
- * @class Roo.bootstrap.TabGroup
- * @extends Roo.bootstrap.Column
- * 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
- * @cfg {Number} bullets show the panel pointer.. default 0
- * @cfg {Boolean} autoslide (true|false) auto slide .. default false
- * @cfg {Boolean} slideOnTouch (true|false) slide on touch .. default false
- * @cfg {Number} timer auto slide timer .. default 0 millisecond
+ * @class Roo.bootstrap.TimeField
+ * @extends Roo.bootstrap.Input
+ * Bootstrap DateField class
+ * 
  * 
  * @constructor
- * Create a new TabGroup
+ * Create a new TimeField
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.TabGroup = function(config){
-    Roo.bootstrap.TabGroup.superclass.constructor.call(this, config);
-    if (!this.navId) {
-        this.navId = Roo.id();
-    }
-    this.tabs = [];
-    Roo.bootstrap.TabGroup.register(this);
-    
+Roo.bootstrap.TimeField = function(config){
+    Roo.bootstrap.TimeField.superclass.constructor.call(this, config);
+    this.addEvents({
+            /**
+             * @event show
+             * Fires when this field show.
+             * @param {Roo.bootstrap.DateField} thisthis
+             * @param {Mixed} date The date value
+             */
+            show : true,
+            /**
+             * @event show
+             * Fires when this field hide.
+             * @param {Roo.bootstrap.DateField} this
+             * @param {Mixed} date The date value
+             */
+            hide : true,
+            /**
+             * @event select
+             * Fires when select a date.
+             * @param {Roo.bootstrap.DateField} this
+             * @param {Mixed} date The date value
+             */
+            select : true
+        });
 };
 
-Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
-    
-    carousel : false,
-    transition : false,
-    bullets : 0,
-    timer : 0,
-    autoslide : false,
-    slideFn : false,
-    slideOnTouch : false,
+Roo.extend(Roo.bootstrap.TimeField, Roo.bootstrap.Input,  {
     
-    getAutoCreate : function()
+    /**
+     * @cfg {String} format
+     * The default time format string which can be overriden for localization support.  The format must be
+     * valid according to {@link Date#parseDate} (defaults to 'H:i').
+     */
+    format : "H:i",
+       
+    onRender: function(ct, position)
     {
-        var cfg = Roo.apply({}, Roo.bootstrap.TabGroup.superclass.getAutoCreate.call(this));
-        
-        cfg.cls += ' tab-content';
-        
-        Roo.log('get auto create...............');
-        
-        if (this.carousel) {
-            cfg.cls += ' carousel slide';
-            
-            cfg.cn = [{
-               cls : 'carousel-inner'
-            }];
         
-            if(this.bullets > 0 && !Roo.isTouch){
-                
-                var bullets = {
-                    cls : 'carousel-bullets',
-                    cn : []
-                };
-                
-                if(this.bullets_cls){
-                    bullets.cls = bullets.cls + ' ' + this.bullets_cls;
-                }
-                
-                for (var i = 0; i < this.bullets; i++){
-                    bullets.cn.push({
-                        cls : 'bullet bullet-' + i
-                    });
-                }
-                
-                bullets.cn.push({
-                    cls : 'clear'
-                });
+        Roo.bootstrap.TimeField.superclass.onRender.call(this, ct, position);
                 
-                cfg.cn[0].cn = bullets;
-            }
-        }
-        
-        return cfg;
-    },
-    
-    initEvents:  function()
-    {
-        Roo.log('-------- init events on tab group ---------');
+        this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.TimeField.template);
         
-        if(this.bullets > 0 && !Roo.isTouch){
-            this.initBullet();
-        }
+        this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        Roo.log(this);
+        this.pop = this.picker().select('>.datepicker-time',true).first();
+        this.pop.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        if(Roo.isTouch && this.slideOnTouch){
-            this.el.on("touchstart", this.onTouchStart, this);
-        }
+        this.picker().on('mousedown', this.onMousedown, this);
+        this.picker().on('click', this.onClick, this);
         
-        if(this.autoslide){
-            var _this = this;
+        this.picker().addClass('datepicker-dropdown');
+    
+        this.fillTime();
+        this.update();
             
-            this.slideFn = window.setInterval(function() {
-                _this.showPanelNext();
-            }, this.timer);
-        }
-        
+        this.pop.select('span.hours-up', true).first().on('click', this.onIncrementHours, this);
+        this.pop.select('span.hours-down', true).first().on('click', this.onDecrementHours, this);
+        this.pop.select('span.minutes-up', true).first().on('click', this.onIncrementMinutes, this);
+        this.pop.select('span.minutes-down', true).first().on('click', this.onDecrementMinutes, this);
+        this.pop.select('button.period', true).first().on('click', this.onTogglePeriod, this);
+        this.pop.select('button.ok', true).first().on('click', this.setTime, this);
+
     },
     
-    onTouchStart : function(e, el, o)
-    {
-        if(!this.slideOnTouch || !Roo.isTouch || Roo.get(e.getTarget()).hasClass('roo-button-text')){
+    fireKey: function(e){
+        if (!this.picker().isVisible()){
+            if (e.keyCode == 27) { // allow escape to hide and re-show picker
+                this.show();
+            }
             return;
         }
+
+        e.preventDefault();
         
-        this.showPanelNext();
-    },
-    
-    getChildContainer : function()
-    {
-        return this.carousel ? this.el.select('.carousel-inner', true).first() : this.el;
-    },
-    
-    /**
-    * register a Navigation item
-    * @param {Roo.bootstrap.NavItem} the navitem to add
-    */
-    register : function(item)
-    {
-        this.tabs.push( item);
-        item.navId = this.navId; // not really needed..
+        switch(e.keyCode){
+            case 27: // escape
+                this.hide();
+                break;
+            case 37: // left
+            case 39: // right
+                this.onTogglePeriod();
+                break;
+            case 38: // up
+                this.onIncrementMinutes();
+                break;
+            case 40: // down
+                this.onDecrementMinutes();
+                break;
+            case 13: // enter
+            case 9: // tab
+                this.setTime();
+                break;
+        }
+    },
     
+    onClick: function(e) {
+        e.stopPropagation();
+        e.preventDefault();
     },
     
-    getActivePanel : function()
+    picker : function()
     {
-        var r = false;
-        Roo.each(this.tabs, function(t) {
-            if (t.active) {
-                r = t;
-                return false;
-            }
-            return null;
+        return this.el.select('.datepicker', true).first();
+    },
+    
+    fillTime: function()
+    {    
+        var time = this.pop.select('tbody', true).first();
+        
+        time.dom.innerHTML = '';
+        
+        time.createChild({
+            tag: 'tr',
+            cn: [
+                {
+                    tag: 'td',
+                    cn: [
+                        {
+                            tag: 'a',
+                            href: '#',
+                            cls: 'btn',
+                            cn: [
+                                {
+                                    tag: 'span',
+                                    cls: 'hours-up glyphicon glyphicon-chevron-up'
+                                }
+                            ]
+                        } 
+                    ]
+                },
+                {
+                    tag: 'td',
+                    cls: 'separator'
+                },
+                {
+                    tag: 'td',
+                    cn: [
+                        {
+                            tag: 'a',
+                            href: '#',
+                            cls: 'btn',
+                            cn: [
+                                {
+                                    tag: 'span',
+                                    cls: 'minutes-up glyphicon glyphicon-chevron-up'
+                                }
+                            ]
+                        }
+                    ]
+                },
+                {
+                    tag: 'td',
+                    cls: 'separator'
+                }
+            ]
         });
-        return r;
         
-    },
-    getPanelByName : function(n)
-    {
-        var r = false;
-        Roo.each(this.tabs, function(t) {
-            if (t.tabId == n) {
-                r = t;
-                return false;
-            }
-            return null;
+        time.createChild({
+            tag: 'tr',
+            cn: [
+                {
+                    tag: 'td',
+                    cn: [
+                        {
+                            tag: 'span',
+                            cls: 'timepicker-hour',
+                            html: '00'
+                        }  
+                    ]
+                },
+                {
+                    tag: 'td',
+                    cls: 'separator',
+                    html: ':'
+                },
+                {
+                    tag: 'td',
+                    cn: [
+                        {
+                            tag: 'span',
+                            cls: 'timepicker-minute',
+                            html: '00'
+                        }  
+                    ]
+                },
+                {
+                    tag: 'td',
+                    cls: 'separator'
+                },
+                {
+                    tag: 'td',
+                    cn: [
+                        {
+                            tag: 'button',
+                            type: 'button',
+                            cls: 'btn btn-primary period',
+                            html: 'AM'
+                            
+                        }
+                    ]
+                }
+            ]
         });
-        return r;
-    },
-    indexOfPanel : function(p)
-    {
-        var r = false;
-        Roo.each(this.tabs, function(t,i) {
-            if (t.tabId == p.tabId) {
-                r = i;
-                return false;
-            }
-            return null;
+        
+        time.createChild({
+            tag: 'tr',
+            cn: [
+                {
+                    tag: 'td',
+                    cn: [
+                        {
+                            tag: 'a',
+                            href: '#',
+                            cls: 'btn',
+                            cn: [
+                                {
+                                    tag: 'span',
+                                    cls: 'hours-down glyphicon glyphicon-chevron-down'
+                                }
+                            ]
+                        }
+                    ]
+                },
+                {
+                    tag: 'td',
+                    cls: 'separator'
+                },
+                {
+                    tag: 'td',
+                    cn: [
+                        {
+                            tag: 'a',
+                            href: '#',
+                            cls: 'btn',
+                            cn: [
+                                {
+                                    tag: 'span',
+                                    cls: 'minutes-down glyphicon glyphicon-chevron-down'
+                                }
+                            ]
+                        }
+                    ]
+                },
+                {
+                    tag: 'td',
+                    cls: 'separator'
+                }
+            ]
         });
-        return r;
+        
     },
-    /**
-     * show a specific panel
-     * @param {Roo.bootstrap.TabPanel|number|string} panel to change to (use the tabId to specify a specific one)
-     * @return {boolean} false if panel was not shown (invalid entry or beforedeactivate fails.)
-     */
-    showPanel : function (pan)
+    
+    update: function()
     {
-        if(this.transition){
-            Roo.log("waiting for the transitionend");
-            return;
-        }
         
-        if (typeof(pan) == 'number') {
-            pan = this.tabs[pan];
-        }
-        if (typeof(pan) == 'string') {
-            pan = this.getPanelByName(pan);
-        }
-        if (pan.tabId == this.getActivePanel().tabId) {
-            return true;
-        }
-        var cur = this.getActivePanel();
+        this.time = (typeof(this.time) === 'undefined') ? new Date() : this.time;
         
-        if (false === cur.fireEvent('beforedeactivate')) {
-            return false;
-        }
+        this.fill();
+    },
+    
+    fill: function() 
+    {
+        var hours = this.time.getHours();
+        var minutes = this.time.getMinutes();
+        var period = 'AM';
         
-        if(this.bullets > 0 && !Roo.isTouch){
-            this.setActiveBullet(this.indexOfPanel(pan));
+        if(hours > 11){
+            period = 'PM';
         }
         
-        if (this.carousel && typeof(Roo.get(document.body).dom.style.transition) != 'undefined') {
-            
-            this.transition = true;
-            var dir = this.indexOfPanel(pan) > this.indexOfPanel(cur)  ? 'next' : 'prev';
-            var lr = dir == 'next' ? 'left' : 'right';
-            pan.el.addClass(dir); // or prev
-            pan.el.dom.offsetWidth; // find the offset with - causing a reflow?
-            cur.el.addClass(lr); // or right
-            pan.el.addClass(lr);
-            
-            var _this = this;
-            cur.el.on('transitionend', function() {
-                Roo.log("trans end?");
-                
-                pan.el.removeClass([lr,dir]);
-                pan.setActive(true);
-                
-                cur.el.removeClass([lr]);
-                cur.setActive(false);
-                
-                _this.transition = false;
-                
-            }, this, { single:  true } );
-            
-            return true;
+        if(hours == 0){
+            hours = 12;
         }
         
-        cur.setActive(false);
-        pan.setActive(true);
-        
-        return true;
-        
-    },
-    showPanelNext : function()
-    {
-        var i = this.indexOfPanel(this.getActivePanel());
-        
-        if (i >= this.tabs.length - 1 && !this.autoslide) {
-            return;
+        
+        if(hours > 12){
+            hours = hours - 12;
         }
         
-        if (i >= this.tabs.length - 1 && this.autoslide) {
-            i = -1;
+        if(hours < 10){
+            hours = '0' + hours;
         }
         
-        this.showPanel(this.tabs[i+1]);
+        if(minutes < 10){
+            minutes = '0' + minutes;
+        }
+        
+        this.pop.select('.timepicker-hour', true).first().dom.innerHTML = hours;
+        this.pop.select('.timepicker-minute', true).first().dom.innerHTML = minutes;
+        this.pop.select('button', true).first().dom.innerHTML = period;
+        
     },
     
-    showPanelPrev : function()
-    {
-        var i = this.indexOfPanel(this.getActivePanel());
+    place: function()
+    {   
+        this.picker().removeClass(['bottom-left', 'bottom-right', 'top-left', 'top-right']);
         
-        if (i  < 1 && !this.autoslide) {
-            return;
+        var cls = ['bottom'];
+        
+        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){ // top
+            cls.pop();
+            cls.push('top');
         }
         
-        if (i < 1 && this.autoslide) {
-            i = this.tabs.length;
+        cls.push('right');
+        
+        if((Roo.lib.Dom.getViewWidth() + Roo.get(document.body).getScroll().left) - (this.inputEl().getLeft() + this.picker().getWidth()) < 0){ // left
+            cls.pop();
+            cls.push('left');
         }
         
-        this.showPanel(this.tabs[i-1]);
+        this.picker().addClass(cls.join('-'));
+        
+        var _this = this;
+        
+        Roo.each(cls, function(c){
+            if(c == 'bottom'){
+                _this.picker().setTop(_this.inputEl().getHeight());
+                return;
+            }
+            if(c == 'top'){
+                _this.picker().setTop(0 - _this.picker().getHeight());
+                return;
+            }
+            
+            if(c == 'left'){
+                _this.picker().setLeft(_this.inputEl().getLeft() + _this.inputEl().getWidth() - _this.el.getLeft() - _this.picker().getWidth());
+                return;
+            }
+            if(c == 'right'){
+                _this.picker().setLeft(_this.inputEl().getLeft() - _this.el.getLeft());
+                return;
+            }
+        });
+        
+    },
+  
+    onFocus : function()
+    {
+        Roo.bootstrap.TimeField.superclass.onFocus.call(this);
+        this.show();
     },
     
-    initBullet : function()
+    onBlur : function()
     {
-        if(Roo.isTouch){
-            return;
-        }
+        Roo.bootstrap.TimeField.superclass.onBlur.call(this);
+        this.hide();
+    },
+    
+    show : function()
+    {
+        this.picker().show();
+        this.pop.show();
+        this.update();
+        this.place();
         
-        var _this = this;
+        this.fireEvent('show', this, this.date);
+    },
+    
+    hide : function()
+    {
+        this.picker().hide();
+        this.pop.hide();
         
-        for (var i = 0; i < this.bullets; i++){
-            var bullet = this.el.select('.bullet-' + i, true).first();
-
-            if(!bullet){
-                continue;
-            }
-
-            bullet.on('click', (function(e, el, o, ii, t){
-
-                e.preventDefault();
-
-                _this.showPanel(ii);
-
-                if(_this.autoslide && _this.slideFn){
-                    clearInterval(_this.slideFn);
-                    _this.slideFn = window.setInterval(function() {
-                        _this.showPanelNext();
-                    }, _this.timer);
-                }
-
-            }).createDelegate(this, [i, bullet], true));
-        }
+        this.fireEvent('hide', this, this.date);
     },
     
-    setActiveBullet : function(i)
+    setTime : function()
     {
-        if(Roo.isTouch){
-            return;
-        }
+        this.hide();
+        this.setValue(this.time.format(this.format));
         
-        Roo.each(this.el.select('.bullet', true).elements, function(el){
-            el.removeClass('selected');
-        });
-
-        var bullet = this.el.select('.bullet-' + i, true).first();
+        this.fireEvent('select', this, this.date);
         
-        if(!bullet){
-            return;
-        }
         
-        bullet.addClass('selected');
-    }
+    },
     
+    onMousedown: function(e){
+        e.stopPropagation();
+        e.preventDefault();
+    },
     
-  
+    onIncrementHours: function()
+    {
+        Roo.log('onIncrementHours');
+        this.time = this.time.add(Date.HOUR, 1);
+        this.update();
+        
+    },
+    
+    onDecrementHours: function()
+    {
+        Roo.log('onDecrementHours');
+        this.time = this.time.add(Date.HOUR, -1);
+        this.update();
+    },
+    
+    onIncrementMinutes: function()
+    {
+        Roo.log('onIncrementMinutes');
+        this.time = this.time.add(Date.MINUTE, 1);
+        this.update();
+    },
+    
+    onDecrementMinutes: function()
+    {
+        Roo.log('onDecrementMinutes');
+        this.time = this.time.add(Date.MINUTE, -1);
+        this.update();
+    },
+    
+    onTogglePeriod: function()
+    {
+        Roo.log('onTogglePeriod');
+        this.time = this.time.add(Date.HOUR, 12);
+        this.update();
+    }
+    
+   
 });
 
-
-Roo.apply(Roo.bootstrap.TabGroup, {
+Roo.apply(Roo.bootstrap.TimeField,  {
     
-    groups: {},
-     /**
-    * register a Navigation Group
-    * @param {Roo.bootstrap.NavGroup} the navgroup to add
-    */
-    register : function(navgrp)
-    {
-        this.groups[navgrp.navId] = navgrp;
-       
+    content : {
+        tag: 'tbody',
+        cn: [
+            {
+                tag: 'tr',
+                cn: [
+                {
+                    tag: 'td',
+                    colspan: '7'
+                }
+                ]
+            }
+        ]
     },
-    /**
-    * 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 
-    */
-    get: function(navId) {
-        if (typeof(this.groups[navId]) == 'undefined') {
-            this.register(new Roo.bootstrap.TabGroup({ navId : navId }));
-        }
-        return this.groups[navId] ;
+    
+    footer : {
+        tag: 'tfoot',
+        cn: [
+            {
+                tag: 'tr',
+                cn: [
+                {
+                    tag: 'th',
+                    colspan: '7',
+                    cls: '',
+                    cn: [
+                        {
+                            tag: 'button',
+                            cls: 'btn btn-info ok',
+                            html: 'OK'
+                        }
+                    ]
+                }
+
+                ]
+            }
+        ]
+    }
+});
+
+Roo.apply(Roo.bootstrap.TimeField,  {
+  
+    template : {
+        tag: 'div',
+        cls: 'datepicker dropdown-menu',
+        cn: [
+            {
+                tag: 'div',
+                cls: 'datepicker-time',
+                cn: [
+                {
+                    tag: 'table',
+                    cls: 'table-condensed',
+                    cn:[
+                    Roo.bootstrap.TimeField.content,
+                    Roo.bootstrap.TimeField.footer
+                    ]
+                }
+                ]
+            }
+        ]
     }
-    
-    
-    
 });
 
+
  /*
  * - LGPL
  *
- * TabPanel
+ * MonthField
  * 
  */
 
 /**
- * @class Roo.bootstrap.TabPanel
- * @extends 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 ()
+ * @class Roo.bootstrap.MonthField
+ * @extends Roo.bootstrap.Input
+ * Bootstrap MonthField class
  * 
+ * @cfg {String} language default en
  * 
  * @constructor
- * Create a new TabPanel
+ * Create a new MonthField
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.TabPanel = function(config){
-    Roo.bootstrap.TabPanel.superclass.constructor.call(this, config);
+Roo.bootstrap.MonthField = function(config){
+    Roo.bootstrap.MonthField.superclass.constructor.call(this, config);
+    
     this.addEvents({
         /**
-            * @event changed
-            * Fires when the active status changes
-            * @param {Roo.bootstrap.TabPanel} this
-            * @param {Boolean} state the new state
-           
+         * @event show
+         * Fires when this field show.
+         * @param {Roo.bootstrap.MonthField} this
+         * @param {Mixed} date The date value
          */
-        'changed': true,
+        show : true,
         /**
-            * @event beforedeactivate
-            * Fires before a tab is de-activated - can be used to do validation on a form.
-            * @param {Roo.bootstrap.TabPanel} this
-            * @return {Boolean} false if there is an error
-           
+         * @event show
+         * Fires when this field hide.
+         * @param {Roo.bootstrap.MonthField} this
+         * @param {Mixed} date The date value
          */
-        'beforedeactivate': true
-     });
-    
-    this.tabId = this.tabId || Roo.id();
-  
+        hide : true,
+        /**
+         * @event select
+         * Fires when select a date.
+         * @param {Roo.bootstrap.MonthField} this
+         * @param {String} oldvalue The old value
+         * @param {String} newvalue The new value
+         */
+        select : true
+    });
 };
 
-Roo.extend(Roo.bootstrap.TabPanel, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
     
-    active: false,
-    html: false,
-    tabId: false,
-    navId : false,
+    onRender: function(ct, position)
+    {
+        
+        Roo.bootstrap.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.isRTL = Roo.bootstrap.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.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.picker().on('mousedown', this.onMousedown, this);
+        this.picker().on('click', this.onClick, this);
+        
+        this.picker().addClass('datepicker-dropdown');
+        
+        Roo.each(this.picker().select('tbody > tr > td', true).elements, function(v){
+            v.setStyle('width', '189px');
+        });
+        
+        this.fillMonths();
+        
+        this.update();
+        
+        if(this.isInline) {
+            this.show();
+        }
+        
+    },
     
-    getAutoCreate : function(){
-        var cfg = {
-            tag: 'div',
-            // item is needed for carousel - not sure if it has any effect otherwise
-            cls: 'tab-pane item',
-            html: this.html || ''
-        };
+    setValue: function(v, suppressEvent)
+    {   
+        var o = this.getValue();
         
-        if(this.active){
-            cfg.cls += ' active';
+        Roo.bootstrap.MonthField.superclass.setValue.call(this, v);
+        
+        this.update();
+
+        if(suppressEvent !== true){
+            this.fireEvent('select', this, o, v);
         }
         
-        if(this.tabId){
-            cfg.tabId = this.tabId;
+    },
+    
+    getValue: function()
+    {
+        return this.value;
+    },
+    
+    onClick: function(e) 
+    {
+        e.stopPropagation();
+        e.preventDefault();
+        
+        var target = e.getTarget();
+        
+        if(target.nodeName.toLowerCase() === 'i'){
+            target = Roo.get(target).dom.parentNode;
         }
         
+        var nodeName = target.nodeName;
+        var className = target.className;
+        var html = target.innerHTML;
         
-        return cfg;
+        if(nodeName.toLowerCase() != 'span' || className.indexOf('disabled') > -1 || className.indexOf('month') == -1){
+            return;
+        }
+        
+        this.vIndex = Roo.bootstrap.MonthField.dates[this.language].monthsShort.indexOf(html);
+        
+        this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+        
+        this.hide();
+                        
     },
     
-    initEvents:  function()
+    picker : function()
     {
-        Roo.log('-------- init events on tab panel ---------');
+        return this.pickerEl;
+    },
+    
+    fillMonths: function()
+    {    
+        var i = 0;
+        var months = this.picker().select('>.datepicker-months td', true).first();
         
-        var p = this.parent();
-        this.navId = this.navId || p.navId;
+        months.dom.innerHTML = '';
         
-        if (typeof(this.navId) != 'undefined') {
-            // not really needed.. but just in case.. parent should be a NavGroup.
-            var tg = Roo.bootstrap.TabGroup.get(this.navId);
-            Roo.log(['register', tg, this]);
-            tg.register(this);
+        while (i < 12) {
+            var month = {
+                tag: 'span',
+                cls: 'month',
+                html: Roo.bootstrap.MonthField.dates[this.language].monthsShort[i++]
+            }
             
-            var i = tg.tabs.length - 1;
+            months.createChild(month);
+        }
+        
+    },
+    
+    update: function()
+    {
+        var _this = this;
+        
+        if(typeof(this.vIndex) == 'undefined' && this.value.length){
+            this.vIndex = Roo.bootstrap.MonthField.dates[this.language].months.indexOf(this.value);
+        }
+        
+        Roo.each(this.pickerEl.select('> .datepicker-months tbody > tr > td > span', true).elements, function(e, k){
+            e.removeClass('active');
             
-            if(this.active && tg.bullets > 0 && i < tg.bullets){
-                tg.setActiveBullet(i);
+            if(typeof(_this.vIndex) != 'undefined' && k == _this.vIndex){
+                e.addClass('active');
             }
+        })
+    },
+    
+    place: function()
+    {
+        if(this.isInline) return;
+        
+        this.picker().removeClass(['bottom', 'top']);
+        
+        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){
+            /*
+             * place to the top of element!
+             *
+             */
+            
+            this.picker().addClass('top');
+            this.picker().setTop(this.inputEl().getTop() - this.picker().getHeight()).setLeft(this.inputEl().getLeft());
+            
+            return;
         }
         
+        this.picker().addClass('bottom');
+        
+        this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());
+    },
+    
+    onFocus : function()
+    {
+        Roo.bootstrap.MonthField.superclass.onFocus.call(this);
+        this.show();
+    },
+    
+    onBlur : function()
+    {
+        Roo.bootstrap.MonthField.superclass.onBlur.call(this);
+        
+        var d = this.inputEl().getValue();
+        
+        this.setValue(d);
+                
+        this.hide();
+    },
+    
+    show : function()
+    {
+        this.picker().show();
+        this.picker().select('>.datepicker-months', true).first().show();
+        this.update();
+        this.place();
+        
+        this.fireEvent('show', this, this.date);
+    },
+    
+    hide : function()
+    {
+        if(this.isInline) return;
+        this.picker().hide();
+        this.fireEvent('hide', this, this.date);
+        
     },
     
+    onMousedown: function(e)
+    {
+        e.stopPropagation();
+        e.preventDefault();
+    },
     
-    onRender : function(ct, position)
+    keyup: function(e)
     {
-       // Roo.log("Call onRender: " + this.xtype);
-        
-        Roo.bootstrap.TabPanel.superclass.onRender.call(this, ct, position);
-        
-        
-        
+        Roo.bootstrap.MonthField.superclass.keyup.call(this);
+        this.update();
+    },
+
+    fireKey: function(e)
+    {
+        if (!this.picker().isVisible()){
+            if (e.keyCode == 27) // allow escape to hide and re-show picker
+                this.show();
+            return;
+        }
         
+        var dir;
         
+        switch(e.keyCode){
+            case 27: // escape
+                this.hide();
+                e.preventDefault();
+                break;
+            case 37: // left
+            case 39: // right
+                dir = e.keyCode == 37 ? -1 : 1;
+                
+                this.vIndex = this.vIndex + dir;
+                
+                if(this.vIndex < 0){
+                    this.vIndex = 0;
+                }
+                
+                if(this.vIndex > 11){
+                    this.vIndex = 11;
+                }
+                
+                if(isNaN(this.vIndex)){
+                    this.vIndex = 0;
+                }
+                
+                this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+                
+                break;
+            case 38: // up
+            case 40: // down
+                
+                dir = e.keyCode == 38 ? -1 : 1;
+                
+                this.vIndex = this.vIndex + dir * 4;
+                
+                if(this.vIndex < 0){
+                    this.vIndex = 0;
+                }
+                
+                if(this.vIndex > 11){
+                    this.vIndex = 11;
+                }
+                
+                if(isNaN(this.vIndex)){
+                    this.vIndex = 0;
+                }
+                
+                this.setValue(Roo.bootstrap.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.hide();
+                e.preventDefault();
+                break;
+            case 9: // tab
+                if(typeof(this.vIndex) != 'undefined' && !isNaN(this.vIndex)){
+                    this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+                }
+                this.hide();
+                break;
+            case 16: // shift
+            case 17: // ctrl
+            case 18: // alt
+                break;
+            default :
+                this.hide();
+                
+        }
     },
     
-    setActive: function(state)
+    remove: function() 
     {
-        Roo.log("panel - set active " + this.tabId + "=" + state);
-        
-        this.active = state;
-        if (!state) {
-            this.el.removeClass('active');
-            
-        } else  if (!this.el.hasClass('active')) {
-            this.el.addClass('active');
-        }
-        
-        this.fireEvent('changed', this, state);
+        this.picker().remove();
     }
+   
+});
+
+Roo.apply(Roo.bootstrap.MonthField,  {
     
+    content : {
+        tag: 'tbody',
+        cn: [
+        {
+            tag: 'tr',
+            cn: [
+            {
+                tag: 'td',
+                colspan: '7'
+            }
+            ]
+        }
+        ]
+    },
     
+    dates:{
+        en: {
+            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+        }
+    }
+});
+
+Roo.apply(Roo.bootstrap.MonthField,  {
+  
+    template : {
+        tag: 'div',
+        cls: 'datepicker dropdown-menu roo-dynamic',
+        cn: [
+            {
+                tag: 'div',
+                cls: 'datepicker-months',
+                cn: [
+                {
+                    tag: 'table',
+                    cls: 'table-condensed',
+                    cn:[
+                        Roo.bootstrap.DateField.content
+                    ]
+                }
+                ]
+            }
+        ]
+    }
 });
 
  
 
  /*
  * - LGPL
  *
- * DateField
+ * CheckBox
  * 
  */
 
 /**
- * @class Roo.bootstrap.DateField
+ * @class Roo.bootstrap.CheckBox
  * @extends Roo.bootstrap.Input
- * Bootstrap DateField class
- * @cfg {Number} weekStart default 0
- * @cfg {String} viewMode default empty, (months|years)
- * @cfg {String} minViewMode default empty, (months|years)
- * @cfg {Number} startDate default -Infinity
- * @cfg {Number} endDate default Infinity
- * @cfg {Boolean} todayHighlight default false
- * @cfg {Boolean} todayBtn default false
- * @cfg {Boolean} calendarWeeks default false
- * @cfg {Object} daysOfWeekDisabled default empty
- * @cfg {Boolean} singleMode default false (true | false)
- * 
- * @cfg {Boolean} keyboardNavigation default true
- * @cfg {String} language default en
+ * Bootstrap CheckBox class
  * 
- * @constructor
- * Create a new DateField
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.DateField = function(config){
-    Roo.bootstrap.DateField.superclass.constructor.call(this, config);
-     this.addEvents({
-            /**
-             * @event show
-             * Fires when this field show.
-             * @param {Roo.bootstrap.DateField} this
-             * @param {Mixed} date The date value
-             */
-            show : true,
-            /**
-             * @event show
-             * Fires when this field hide.
-             * @param {Roo.bootstrap.DateField} this
-             * @param {Mixed} date The date value
-             */
-            hide : true,
-            /**
-             * @event select
-             * Fires when select a date.
-             * @param {Roo.bootstrap.DateField} this
-             * @param {Mixed} date The date value
-             */
-            select : true
-        });
-};
-
-Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
-    
-    /**
-     * @cfg {String} format
-     * The default date format string which can be overriden for localization support.  The format must be
-     * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
-     */
-    format : "m/d/y",
-    /**
-     * @cfg {String} altFormats
-     * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
-     * format (defaults to 'm/d/Y|m-d-y|m-d-Y|m/d|m-d|d').
-     */
-    altFormats : "m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d",
-    
-    weekStart : 0,
-    
-    viewMode : '',
-    
-    minViewMode : '',
-    
-    todayHighlight : false,
-    
-    todayBtn: false,
-    
-    language: 'en',
-    
-    keyboardNavigation: true,
-    
-    calendarWeeks: false,
-    
-    startDate: -Infinity,
-    
-    endDate: Infinity,
-    
-    daysOfWeekDisabled: [],
-    
-    _events: [],
-    
-    singleMode : false,
+ * @cfg {String} valueOff The value that should go into the generated input element's value when unchecked.
+ * @cfg {String} inputValue The value that should go into the generated input element's value when checked.
+ * @cfg {String} boxLabel The text that appears beside the checkbox
+ * @cfg {String} weight (primary|warning|info|danger|success) The text that appears beside the checkbox
+ * @cfg {Boolean} checked initnal the element
+ * @cfg {Boolean} inline inline the element (default false)
+ * @cfg {String} groupId the checkbox group id // normal just use for checkbox
+ * 
+ * @constructor
+ * Create a new CheckBox
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.CheckBox = function(config){
+    Roo.bootstrap.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 {Boolean} checked The new checked value
+        */
+       check : true
+    });
     
-    UTCDate: function()
-    {
-        return new Date(Date.UTC.apply(Date, arguments));
-    },
+};
+
+Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
+  
+    inputType: 'checkbox',
+    inputValue: 1,
+    valueOff: 0,
+    boxLabel: false,
+    checked: false,
+    weight : false,
+    inline: false,
     
-    UTCToday: function()
+    getAutoCreate : function()
     {
-        var today = new Date();
-        return this.UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
-    },
-    
-    getDate: function() {
-            var d = this.getUTCDate();
-            return new Date(d.getTime() + (d.getTimezoneOffset()*60000));
-    },
-    
-    getUTCDate: function() {
-            return this.date;
-    },
-    
-    setDate: function(d) {
-            this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
-    },
-    
-    setUTCDate: function(d) {
-            this.date = d;
-            this.setValue(this.formatDate(this.date));
-    },
+        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
         
-    onRender: function(ct, position)
-    {
+        var id = Roo.id();
         
-        Roo.bootstrap.DateField.superclass.onRender.call(this, ct, position);
+        var cfg = {};
         
-        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";
+        cfg.cls = 'form-group ' + this.inputType; //input-group
         
-        this.isRTL = Roo.bootstrap.DateField.dates[this.language].rtl || false;
-        this.format = this.format || 'm/d/y';
-        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;
+        if(this.inline){
+            cfg.cls += ' ' + this.inputType + '-inline';
+        }
         
-        if (typeof(this.minViewMode === 'string')) {
-            switch (this.minViewMode) {
-                case 'months':
-                    this.minViewMode = 1;
-                    break;
-                case 'years':
-                    this.minViewMode = 2;
-                    break;
-                default:
-                    this.minViewMode = 0;
-                    break;
-            }
+        var input =  {
+            tag: 'input',
+            id : id,
+            type : this.inputType,
+            value : this.inputType == 'radio' ? this.inputValue : ((!this.checked) ? this.valueOff : this.inputValue),
+            cls : 'roo-' + this.inputType, //'form-box',
+            placeholder : this.placeholder || ''
+            
+        };
+        
+        if (this.weight) { // Validity check?
+            cfg.cls += " " + this.inputType + "-" + this.weight;
         }
         
-        if (typeof(this.viewMode === 'string')) {
-            switch (this.viewMode) {
-                case 'months':
-                    this.viewMode = 1;
-                    break;
-                case 'years':
-                    this.viewMode = 2;
-                    break;
-                default:
-                    this.viewMode = 0;
-                    break;
-            }
+        if (this.disabled) {
+            input.disabled=true;
         }
-                
-        this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.DateField.template);
         
-//        this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.DateField.template);
+        if(this.checked){
+            input.checked = this.checked;
+        }
         
-        this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        if (this.name) {
+            input.name = this.name;
+        }
         
-        this.picker().on('mousedown', this.onMousedown, this);
-        this.picker().on('click', this.onClick, this);
+        if (this.size) {
+            input.cls += ' input-' + this.size;
+        }
         
-        this.picker().addClass('datepicker-dropdown');
+        var settings=this;
         
-        this.startViewMode = this.viewMode;
+        ['xs','sm','md','lg'].map(function(size){
+            if (settings[size]) {
+                cfg.cls += ' col-' + size + '-' + settings[size];
+            }
+        });
         
-        if(this.singleMode){
-            Roo.each(this.picker().select('thead > tr > th', true).elements, function(v){
-                v.setVisibilityMode(Roo.Element.DISPLAY)
-                v.hide();
-            });
+        var inputblock = input;
+         
+        if (this.before || this.after) {
+            
+            inputblock = {
+                cls : 'input-group',
+                cn :  [] 
+            };
+            
+            if (this.before) {
+                inputblock.cn.push({
+                    tag :'span',
+                    cls : 'input-group-addon',
+                    html : this.before
+                });
+            }
+            
+            inputblock.cn.push(input);
+            
+            if (this.after) {
+                inputblock.cn.push({
+                    tag :'span',
+                    cls : 'input-group-addon',
+                    html : this.after
+                });
+            }
             
-            Roo.each(this.picker().select('tbody > tr > td', true).elements, function(v){
-                v.setStyle('width', '189px');
-            });
         }
         
-        Roo.each(this.picker().select('tfoot th.today', true).elements, function(v){
-            if(!this.calendarWeeks){
-                v.remove();
-                return;
+        if (align ==='left' && this.fieldLabel.length) {
+                Roo.log("left and has label");
+                cfg.cn = [
+                    
+                    {
+                        tag: 'label',
+                        'for' :  id,
+                        cls : 'control-label col-md-' + this.labelWidth,
+                        html : this.fieldLabel
+                        
+                    },
+                    {
+                        cls : "col-md-" + (12 - this.labelWidth), 
+                        cn: [
+                            inputblock
+                        ]
+                    }
+                    
+                ];
+        } else if ( this.fieldLabel.length) {
+                Roo.log(" label");
+                cfg.cn = [
+                   
+                    {
+                        tag: this.boxLabel ? 'span' : 'label',
+                        'for': id,
+                        cls: 'control-label box-input-label',
+                        //cls : 'input-group-addon',
+                        html : this.fieldLabel
+                        
+                    },
+                    
+                    inputblock
+                    
+                ];
+
+        } else {
+            
+                Roo.log(" no label && no align");
+                cfg.cn = [  inputblock ] ;
+                
+                
+        }
+        if(this.boxLabel){
+             var boxLabelCfg = {
+                tag: 'label',
+                //'for': id, // box label is handled by onclick - so no for...
+                cls: 'box-label',
+                html: this.boxLabel
             }
             
-            v.dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
-            v.attr('colspan', function(i, val){
-                return parseInt(val) + 1;
-            });
-        })
-                       
-        
-        this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
-        
-        this.setStartDate(this.startDate);
-        this.setEndDate(this.endDate);
-        
-        this.setDaysOfWeekDisabled(this.daysOfWeekDisabled);
-        
-        this.fillDow();
-        this.fillMonths();
-        this.update();
-        this.showMode();
-        
-        if(this.isInline) {
-            this.show();
+            if(this.tooltip){
+                boxLabelCfg.tooltip = this.tooltip;
+            }
+             
+            cfg.cn.push(boxLabelCfg);
         }
+        
+        
+       
+        return cfg;
+        
     },
     
-    picker : function()
+    /**
+     * return the real input element.
+     */
+    inputEl: function ()
     {
-        return this.pickerEl;
-//        return this.el.select('.datepicker', true).first();
+        return this.el.select('input.roo-' + this.inputType,true).first();
     },
     
-    fillDow: function()
+    labelEl: function()
     {
-        var dowCnt = this.weekStart;
+        return this.el.select('label.control-label',true).first();
+    },
+    /* depricated... */
+    
+    label: function()
+    {
+        return this.labelEl();
+    },
+    
+    initEvents : function()
+    {
+//        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
         
-        var dow = {
-            tag: 'tr',
-            cn: [
-                
-            ]
-        };
+        this.inputEl().on('click', this.onClick,  this);
         
-        if(this.calendarWeeks){
-            dow.cn.push({
-                tag: 'th',
-                cls: 'cw',
-                html: '&nbsp;'
-            })
+        if (this.boxLabel) { 
+            this.el.select('label.box-label',true).first().on('click', this.onClick,  this);
         }
         
-        while (dowCnt < this.weekStart + 7) {
-            dow.cn.push({
-                tag: 'th',
-                cls: 'dow',
-                html: Roo.bootstrap.DateField.dates[this.language].daysMin[(dowCnt++)%7]
-            });
-        }
+        this.startValue = this.getValue();
         
-        this.picker().select('>.datepicker-days thead', true).first().createChild(dow);
+        if(this.groupId){
+            Roo.bootstrap.CheckBox.register(this);
+        }
     },
     
-    fillMonths: function()
-    {    
-        var i = 0;
-        var months = this.picker().select('>.datepicker-months td', true).first();
-        
-        months.dom.innerHTML = '';
+    onClick : function()
+    {   
+        this.setChecked(!this.checked);
+    },
+    
+    setChecked : function(state,suppressEvent)
+    {
+        this.startValue = this.getValue();
         
-        while (i < 12) {
-            var month = {
-                tag: 'span',
-                cls: 'month',
-                html: Roo.bootstrap.DateField.dates[this.language].monthsShort[i++]
+        if(this.inputType == 'radio'){
+            
+            Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
+                e.dom.checked = false;
+            });
+            
+            this.inputEl().dom.checked = true;
+            
+            this.inputEl().dom.value = this.inputValue;
+            
+            if(suppressEvent !== true){
+                this.fireEvent('check', this, true);
             }
             
-            months.createChild(month);
+            this.validate();
+            
+            return;
         }
         
-    },
-    
-    update: function()
-    {
-        this.date = (typeof(this.date) === 'undefined' || ((typeof(this.date) === 'string') && !this.date.length)) ? this.UTCToday() : (typeof(this.date) === 'string') ? this.parseDate(this.date) : this.date;
+        this.checked = state;
         
-        if (this.date < this.startDate) {
-            this.viewDate = new Date(this.startDate);
-        } else if (this.date > this.endDate) {
-            this.viewDate = new Date(this.endDate);
-        } else {
-            this.viewDate = new Date(this.date);
+        this.inputEl().dom.checked = state;
+        
+        this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
+        
+        if(suppressEvent !== true){
+            this.fireEvent('check', this, state);
         }
         
-        this.fill();
+        this.validate();
     },
     
-    fill: function() 
+    getValue : function()
     {
-        var d = new Date(this.viewDate),
-                year = d.getUTCFullYear(),
-                month = d.getUTCMonth(),
-                startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
-                startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
-                endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
-                endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
-                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;
+        if(this.inputType == 'radio'){
+            return this.getGroupValue();
+        }
         
-//        this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.DateField.dates[this.language].today;
+        return this.inputEl().getValue();
         
-//        this.picker.select('>tfoot th.today').
-//                                             .text(dates[this.language].today)
-//                                             .toggle(this.todayBtn !== false);
+    },
     
-        this.updateNavArrows();
-        this.fillMonths();
-                                                
-        var prevMonth = this.UTCDate(year, month-1, 28,0,0,0,0),
-        
-        day = prevMonth.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
-         
-        prevMonth.setUTCDate(day);
-        
-        prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
-        
-        var nextMonth = new Date(prevMonth);
-        
-        nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
+    getGroupValue : function()
+    {
+        if(typeof(this.el.up('form').child('input[name='+this.name+']:checked', true)) == 'undefined'){
+            return '';
+        }
         
-        nextMonth = nextMonth.valueOf();
+        return this.el.up('form').child('input[name='+this.name+']:checked', true).value;
+    },
+    
+    setValue : function(v,suppressEvent)
+    {
+        if(this.inputType == 'radio'){
+            this.setGroupValue(v, suppressEvent);
+            return;
+        }
         
-        var fillMonths = false;
+        this.setChecked(((typeof(v) == 'undefined') ? this.checked : (String(v) === String(this.inputValue))), suppressEvent);
         
-        this.picker().select('>.datepicker-days tbody',true).first().dom.innerHTML = '';
+        this.validate();
+    },
+    
+    setGroupValue : function(v, suppressEvent)
+    {
+        this.startValue = this.getValue();
         
-        while(prevMonth.valueOf() < nextMonth) {
-            var clsName = '';
-            
-            if (prevMonth.getUTCDay() === this.weekStart) {
-                if(fillMonths){
-                    this.picker().select('>.datepicker-days tbody',true).first().createChild(fillMonths);
-                }
-                    
-                fillMonths = {
-                    tag: 'tr',
-                    cn: []
-                };
-                
-                if(this.calendarWeeks){
-                    // ISO 8601: First week contains first thursday.
-                    // ISO also states week starts on Monday, but we can be more abstract here.
-                    var
-                    // Start of current week: based on weekstart/current date
-                    ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
-                    // Thursday of this week
-                    th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
-                    // First Thursday of year, year from thursday
-                    yth = new Date(+(yth = this.UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
-                    // Calendar week: ms between thursdays, div ms per day, div 7 days
-                    calWeek =  (th - yth) / 864e5 / 7 + 1;
-                    
-                    fillMonths.cn.push({
-                        tag: 'td',
-                        cls: 'cw',
-                        html: calWeek
-                    });
-                }
-            }
-            
-            if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
-                clsName += ' old';
-            } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
-                clsName += ' new';
-            }
-            if (this.todayHighlight &&
-                prevMonth.getUTCFullYear() == today.getFullYear() &&
-                prevMonth.getUTCMonth() == today.getMonth() &&
-                prevMonth.getUTCDate() == today.getDate()) {
-                clsName += ' today';
-            }
-            
-            if (currentDate && prevMonth.valueOf() === currentDate) {
-                clsName += ' active';
-            }
+        Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
+            e.dom.checked = false;
             
-            if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate ||
-                    this.daysOfWeekDisabled.indexOf(prevMonth.getUTCDay()) !== -1) {
-                    clsName += ' disabled';
+            if(e.dom.value == v){
+                e.dom.checked = true;
             }
-            
-            fillMonths.cn.push({
-                tag: 'td',
-                cls: 'day ' + clsName,
-                html: prevMonth.getDate()
-            })
-            
-            prevMonth.setDate(prevMonth.getDate()+1);
+        });
+        
+        if(suppressEvent !== true){
+            this.fireEvent('check', this, true);
+        }
+
+        this.validate();
+        
+        return;
+    },
+    
+    validate : function()
+    {
+        if(
+                this.disabled || 
+                (this.inputType == 'radio' && this.validateRadio()) ||
+                (this.inputType == 'checkbox' && this.validateCheckbox())
+        ){
+            this.markValid();
+            return true;
         }
-          
-        var currentYear = this.date && this.date.getUTCFullYear();
-        var currentMonth = this.date && this.date.getUTCMonth();
         
-        this.picker().select('>.datepicker-months th.switch',true).first().dom.innerHTML = year;
+        this.markInvalid();
+        return false;
+    },
+    
+    validateRadio : function()
+    {
+        var valid = false;
         
-        Roo.each(this.picker().select('>.datepicker-months tbody span',true).elements, function(v,k){
-            v.removeClass('active');
-            
-            if(currentYear === year && k === currentMonth){
-                v.addClass('active');
+        Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
+            if(!e.dom.checked){
+                return;
             }
             
-            if (year < startYear || year > endYear || (year == startYear && k < startMonth) || (year == endYear && k > endMonth)) {
-                v.addClass('disabled');
-            }
+            valid = true;
             
+            return false;
         });
         
+        return valid;
+    },
+    
+    validateCheckbox : function()
+    {
+        if(!this.groupId){
+            return (this.getValue() == this.inputValue || this.allowBlank) ? true : false;
+        }
         
-        year = parseInt(year/10, 10) * 10;
+        var group = Roo.bootstrap.CheckBox.get(this.groupId);
         
-        this.picker().select('>.datepicker-years th.switch', true).first().dom.innerHTML = year + '-' + (year + 9);
+        if(!group){
+            return false;
+        }
         
-        this.picker().select('>.datepicker-years tbody td',true).first().dom.innerHTML = '';
+        var r = false;
         
-        year -= 1;
-        for (var i = -1; i < 11; i++) {
-            this.picker().select('>.datepicker-years tbody td',true).first().createChild({
-                tag: 'span',
-                cls: 'year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + (year < startYear || year > endYear ? ' disabled' : ''),
-                html: year
-            })
+        for(var i in group){
+            if(r){
+                break;
+            }
             
-            year += 1;
+            r = (group[i].getValue() == group[i].inputValue) ? true : false;
         }
+        
+        return r;
     },
     
-    showMode: function(dir) 
+    /**
+     * Mark this field as valid
+     */
+    markValid : function()
     {
-        if (dir) {
-            this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
+        if(this.allowBlank){
+            return;
         }
         
-        Roo.each(this.picker().select('>div',true).elements, function(v){
-            v.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-            v.hide();
-        });
-        this.picker().select('>.datepicker-'+Roo.bootstrap.DateField.modes[this.viewMode].clsName, true).first().show();
-    },
-    
-    place: function()
-    {
-        if(this.isInline) return;
+        var _this = this;
         
-        this.picker().removeClass(['bottom', 'top']);
+        this.fireEvent('valid', this);
         
-        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){
-            /*
-             * place to the top of element!
-             *
-             */
-            
-            this.picker().addClass('top');
-            this.picker().setTop(this.inputEl().getTop() - this.picker().getHeight()).setLeft(this.inputEl().getLeft());
+        if(this.inputType == 'radio'){
+            Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
+                e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
+                e.findParent('.form-group', false, true).addClass(_this.validClass);
+            });
             
             return;
         }
         
-        this.picker().addClass('bottom');
+        if(!this.groupId){
+            this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
+            this.el.findParent('.form-group', false, true).addClass(this.validClass);
+            return;
+        }
         
-        this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());
+        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+            
+        if(!group){
+            return;
+        }
+        
+        for(var i in group){
+            group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
+            group[i].el.findParent('.form-group', false, true).addClass(this.validClass);
+        }
     },
     
-    parseDate : function(value)
+     /**
+     * Mark this field as invalid
+     * @param {String} msg The validation message
+     */
+    markInvalid : function(msg)
     {
-        if(!value || value instanceof Date){
-            return value;
+        if(this.allowBlank){
+            return;
         }
-        var v = Date.parseDate(value, this.format);
-        if (!v && (this.useIso || value.match(/^(\d{4})-0?(\d+)-0?(\d+)/))) {
-            v = Date.parseDate(value, 'Y-m-d');
+        
+        var _this = this;
+        
+        this.fireEvent('invalid', this, msg);
+        
+        if(this.inputType == 'radio'){
+            Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
+                e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
+                e.findParent('.form-group', false, true).addClass(_this.invalidClass);
+            });
+            
+            return;
         }
-        if(!v && this.altFormats){
-            if(!this.altFormatsArray){
-                this.altFormatsArray = this.altFormats.split("|");
-            }
-            for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
-                v = Date.parseDate(value, this.altFormatsArray[i]);
-            }
+        
+        if(!this.groupId){
+            this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
+            this.el.findParent('.form-group', false, true).addClass(this.invalidClass);
+            return;
         }
-        return v;
-    },
+        
+        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+            
+        if(!group){
+            return;
+        }
+        
+        for(var i in group){
+            group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
+            group[i].el.findParent('.form-group', false, true).addClass(this.invalidClass);
+        }
+        
+    }
     
-    formatDate : function(date, fmt)
-    {   
-        return (!date || !(date instanceof Date)) ?
-        date : date.dateFormat(fmt || this.format);
-    },
+});
+
+Roo.apply(Roo.bootstrap.CheckBox, {
     
-    onFocus : function()
-    {
-        Roo.bootstrap.DateField.superclass.onFocus.call(this);
-        this.show();
-    },
+    groups: {},
     
-    onBlur : function()
+     /**
+    * register a CheckBox Group
+    * @param {Roo.bootstrap.CheckBox} the CheckBox to add
+    */
+    register : function(checkbox)
     {
-        Roo.bootstrap.DateField.superclass.onBlur.call(this);
+        if(typeof(this.groups[checkbox.groupId]) == 'undefined'){
+            this.groups[checkbox.groupId] = {};
+        }
         
-        var d = this.inputEl().getValue();
+        if(this.groups[checkbox.groupId].hasOwnProperty(checkbox.name)){
+            return;
+        }
         
-        this.setValue(d);
-                
-        this.hide();
+        this.groups[checkbox.groupId][checkbox.name] = checkbox;
+       
     },
-    
-    show : function()
-    {
-        this.picker().show();
-        this.update();
-        this.place();
+    /**
+    * fetch a CheckBox Group based on the group ID
+    * @param {string} the group ID
+    * @returns {Roo.bootstrap.CheckBox} the CheckBox group
+    */
+    get: function(groupId) {
+        if (typeof(this.groups[groupId]) == 'undefined') {
+            return false;
+        }
         
-        this.fireEvent('show', this, this.date);
-    },
+        return this.groups[groupId] ;
+    }
     
-    hide : function()
-    {
-        if(this.isInline) return;
-        this.picker().hide();
-        this.viewMode = this.startViewMode;
-        this.showMode();
-        
-        this.fireEvent('hide', this, this.date);
-        
-    },
     
-    onMousedown: function(e)
-    {
-        e.stopPropagation();
-        e.preventDefault();
-    },
+});
+/*
+ * - LGPL
+ *
+ * Radio
+ *
+ *
+ * not inline
+ *<div class="radio">
+  <label>
+    <input type="radio" name="optionsRadios" id="optionsRadios1" value="option1" checked>
+    Option one is this and that&mdash;be sure to include why it's great
+  </label>
+</div>
+ *
+ *
+ *inline
+ *<span>
+ *<label class="radio-inline">fieldLabel</label>
+ *<label class="radio-inline">
+  <input type="radio" name="inlineRadioOptions" id="inlineRadio1" value="option1"> 1
+</label>
+<span>
+ * 
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.Radio
+ * @extends Roo.bootstrap.CheckBox
+ * Bootstrap Radio class
+
+ * @constructor
+ * Create a new Radio
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Radio = function(config){
+    Roo.bootstrap.Radio.superclass.constructor.call(this, config);
+   
+};
+
+Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
+    
+    inputType: 'radio',
+    inputValue: '',
+    valueOff: '',
     
-    keyup: function(e)
-    {
-        Roo.bootstrap.DateField.superclass.keyup.call(this);
-        this.update();
-    },
-
-    setValue: function(v)
+    getAutoCreate : function()
     {
+        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
+        align = align || 'left'; // default...
         
-        // v can be a string or a date..
-        
-        
-        var d = new Date(this.parseDate(v) ).clearTime();
-        
-        if(isNaN(d.getTime())){
-            this.date = this.viewDate = '';
-            Roo.bootstrap.DateField.superclass.setValue.call(this, '');
-            return;
-        }
-        
-        v = this.formatDate(d);
         
-        Roo.bootstrap.DateField.superclass.setValue.call(this, v);
         
-        this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
-     
-        this.update();
-
-        this.fireEvent('select', this, this.date);
+        var id = Roo.id();
         
-    },
-    
-    getValue: function()
-    {
-        return this.formatDate(this.date);
-    },
-    
-    fireKey: function(e)
-    {
-        if (!this.picker().isVisible()){
-            if (e.keyCode == 27) // allow escape to hide and re-show picker
-                this.show();
-            return;
-        }
+        var cfg = {
+                tag : this.inline ? 'span' : 'div',
+                cls : '',
+                cn : []
+        };
         
-        var dateChanged = false,
-        dir, day, month,
-        newDate, newViewDate;
+        var inline = this.inline ? ' radio-inline' : '';
         
-        switch(e.keyCode){
-            case 27: // escape
-                this.hide();
-                e.preventDefault();
-                break;
-            case 37: // left
-            case 39: // right
-                if (!this.keyboardNavigation) break;
-                dir = e.keyCode == 37 ? -1 : 1;
-                
-                if (e.ctrlKey){
-                    newDate = this.moveYear(this.date, dir);
-                    newViewDate = this.moveYear(this.viewDate, dir);
-                } else if (e.shiftKey){
-                    newDate = this.moveMonth(this.date, dir);
-                    newViewDate = this.moveMonth(this.viewDate, dir);
-                } else {
-                    newDate = new Date(this.date);
-                    newDate.setUTCDate(this.date.getUTCDate() + dir);
-                    newViewDate = new Date(this.viewDate);
-                    newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
-                }
-                if (this.dateWithinRange(newDate)){
-                    this.date = newDate;
-                    this.viewDate = newViewDate;
-                    this.setValue(this.formatDate(this.date));
-//                    this.update();
-                    e.preventDefault();
-                    dateChanged = true;
-                }
-                break;
-            case 38: // up
-            case 40: // down
-                if (!this.keyboardNavigation) break;
-                dir = e.keyCode == 38 ? -1 : 1;
-                if (e.ctrlKey){
-                    newDate = this.moveYear(this.date, dir);
-                    newViewDate = this.moveYear(this.viewDate, dir);
-                } else if (e.shiftKey){
-                    newDate = this.moveMonth(this.date, dir);
-                    newViewDate = this.moveMonth(this.viewDate, dir);
-                } else {
-                    newDate = new Date(this.date);
-                    newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
-                    newViewDate = new Date(this.viewDate);
-                    newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
-                }
-                if (this.dateWithinRange(newDate)){
-                    this.date = newDate;
-                    this.viewDate = newViewDate;
-                    this.setValue(this.formatDate(this.date));
-//                    this.update();
-                    e.preventDefault();
-                    dateChanged = true;
-                }
-                break;
-            case 13: // enter
-                this.setValue(this.formatDate(this.date));
-                this.hide();
-                e.preventDefault();
-                break;
-            case 9: // tab
-                this.setValue(this.formatDate(this.date));
-                this.hide();
-                break;
-            case 16: // shift
-            case 17: // ctrl
-            case 18: // alt
-                break;
-            default :
-                this.hide();
-                
-        }
-    },
-    
-    
-    onClick: function(e) 
-    {
-        e.stopPropagation();
-        e.preventDefault();
+        var lbl = {
+                tag: 'label' ,
+                // does not need for, as we wrap the input with it..
+                'for' : id,
+                cls : 'control-label box-label' + inline,
+                cn : []
+        };
+        var labelWidth = this.labelWidth ? this.labelWidth *1 : 100;
         
-        var target = e.getTarget();
+        var fieldLabel = {
+            tag: 'label' ,
+            //cls : 'control-label' + inline,
+            html : this.fieldLabel,
+            style : 'width:' +  labelWidth  + 'px;line-height:1;vertical-align:bottom;cursor:default;' // should be css really.
+        };
         
-        if(target.nodeName.toLowerCase() === 'i'){
-            target = Roo.get(target).dom.parentNode;
-        }
         
-        var nodeName = target.nodeName;
-        var className = target.className;
-        var html = target.innerHTML;
-        //Roo.log(nodeName);
         
-        switch(nodeName.toLowerCase()) {
-            case 'th':
-                switch(className) {
-                    case 'switch':
-                        this.showMode(1);
-                        break;
-                    case 'prev':
-                    case 'next':
-                        var dir = Roo.bootstrap.DateField.modes[this.viewMode].navStep * (className == 'prev' ? -1 : 1);
-                        switch(this.viewMode){
-                                case 0:
-                                        this.viewDate = this.moveMonth(this.viewDate, dir);
-                                        break;
-                                case 1:
-                                case 2:
-                                        this.viewDate = this.moveYear(this.viewDate, dir);
-                                        break;
-                        }
-                        this.fill();
-                        break;
-                    case 'today':
-                        var date = new Date();
-                        this.date = this.UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
-//                        this.fill()
-                        this.setValue(this.formatDate(this.date));
-                        
-                        this.hide();
-                        break;
-                }
-                break;
-            case 'span':
-                if (className.indexOf('disabled') < 0) {
-                    this.viewDate.setUTCDate(1);
-                    if (className.indexOf('month') > -1) {
-                        this.viewDate.setUTCMonth(Roo.bootstrap.DateField.dates[this.language].monthsShort.indexOf(html));
-                    } else {
-                        var year = parseInt(html, 10) || 0;
-                        this.viewDate.setUTCFullYear(year);
-                        
-                    }
-                    
-                    if(this.singleMode){
-                        this.setValue(this.formatDate(this.viewDate));
-                        this.hide();
-                        return;
-                    }
-                    
-                    this.showMode(-1);
-                    this.fill();
-                }
-                break;
-                
-            case 'td':
-                //Roo.log(className);
-                if (className.indexOf('day') > -1 && className.indexOf('disabled') < 0 ){
-                    var day = parseInt(html, 10) || 1;
-                    var year = this.viewDate.getUTCFullYear(),
-                        month = this.viewDate.getUTCMonth();
-
-                    if (className.indexOf('old') > -1) {
-                        if(month === 0 ){
-                            month = 11;
-                            year -= 1;
-                        }else{
-                            month -= 1;
-                        }
-                    } else if (className.indexOf('new') > -1) {
-                        if (month == 11) {
-                            month = 0;
-                            year += 1;
-                        } else {
-                            month += 1;
-                        }
-                    }
-                    //Roo.log([year,month,day]);
-                    this.date = this.UTCDate(year, month, day,0,0,0,0);
-                    this.viewDate = this.UTCDate(year, month, Math.min(28, day),0,0,0,0);
-//                    this.fill();
-                    //Roo.log(this.formatDate(this.date));
-                    this.setValue(this.formatDate(this.date));
-                    this.hide();
-                }
-                break;
+        var input =  {
+            tag: 'input',
+            id : id,
+            type : this.inputType,
+            //value : (!this.checked) ? this.valueOff : this.inputValue,
+            value : this.inputValue,
+            cls : 'roo-radio',
+            placeholder : this.placeholder || '' // ?? needed????
+            
+        };
+        if (this.weight) { // Validity check?
+            input.cls += " radio-" + this.weight;
         }
-    },
-    
-    setStartDate: function(startDate)
-    {
-        this.startDate = startDate || -Infinity;
-        if (this.startDate !== -Infinity) {
-            this.startDate = this.parseDate(this.startDate);
+        if (this.disabled) {
+            input.disabled=true;
         }
-        this.update();
-        this.updateNavArrows();
-    },
-
-    setEndDate: function(endDate)
-    {
-        this.endDate = endDate || Infinity;
-        if (this.endDate !== Infinity) {
-            this.endDate = this.parseDate(this.endDate);
+        
+        if(this.checked){
+            input.checked = this.checked;
         }
-        this.update();
-        this.updateNavArrows();
-    },
-    
-    setDaysOfWeekDisabled: function(daysOfWeekDisabled)
-    {
-        this.daysOfWeekDisabled = daysOfWeekDisabled || [];
-        if (typeof(this.daysOfWeekDisabled) !== 'object') {
-            this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
+        
+        if (this.name) {
+            input.name = this.name;
         }
-        this.daysOfWeekDisabled = this.daysOfWeekDisabled.map(function (d) {
-            return parseInt(d, 10);
-        });
-        this.update();
-        this.updateNavArrows();
-    },
-    
-    updateNavArrows: function() 
-    {
-        if(this.singleMode){
-            return;
+        
+        if (this.size) {
+            input.cls += ' input-' + this.size;
         }
         
-        var d = new Date(this.viewDate),
-        year = d.getUTCFullYear(),
-        month = d.getUTCMonth();
+        //?? can span's inline have a width??
         
-        Roo.each(this.picker().select('.prev', true).elements, function(v){
-            v.show();
-            switch (this.viewMode) {
-                case 0:
-
-                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
-                        v.hide();
-                    }
-                    break;
-                case 1:
-                case 2:
-                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
-                        v.hide();
-                    }
-                    break;
+        var settings=this;
+        ['xs','sm','md','lg'].map(function(size){
+            if (settings[size]) {
+                cfg.cls += ' col-' + size + '-' + settings[size];
             }
         });
         
-        Roo.each(this.picker().select('.next', true).elements, function(v){
-            v.show();
-            switch (this.viewMode) {
-                case 0:
-
-                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
-                        v.hide();
-                    }
-                    break;
-                case 1:
-                case 2:
-                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
-                        v.hide();
-                    }
-                    break;
-            }
-        })
-    },
-    
-    moveMonth: function(date, dir)
-    {
-        if (!dir) return date;
-        var new_date = new Date(date.valueOf()),
-        day = new_date.getUTCDate(),
-        month = new_date.getUTCMonth(),
-        mag = Math.abs(dir),
-        new_month, test;
-        dir = dir > 0 ? 1 : -1;
-        if (mag == 1){
-            test = dir == -1
-            // If going back one month, make sure month is not current month
-            // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
-            ? function(){
-                return new_date.getUTCMonth() == month;
-            }
-            // If going forward one month, make sure month is as expected
-            // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
-            : function(){
-                return new_date.getUTCMonth() != new_month;
-            };
-            new_month = month + dir;
-            new_date.setUTCMonth(new_month);
-            // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
-            if (new_month < 0 || new_month > 11)
-                new_month = (new_month + 12) % 12;
-        } else {
-            // For magnitudes >1, move one month at a time...
-            for (var i=0; i<mag; i++)
-                // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
-                new_date = this.moveMonth(new_date, dir);
-            // ...then reset the day, keeping it in the new month
-            new_month = new_date.getUTCMonth();
-            new_date.setUTCDate(day);
-            test = function(){
-                return new_month != new_date.getUTCMonth();
+        var inputblock = input;
+        
+        if (this.before || this.after) {
+            
+            inputblock = {
+                cls : 'input-group',
+                tag : 'span',
+                cn :  [] 
             };
-        }
-        // Common date-resetting loop -- if date is beyond end of month, make it
-        // end of month
-        while (test()){
-            new_date.setUTCDate(--day);
-            new_date.setUTCMonth(new_month);
-        }
-        return new_date;
-    },
-
-    moveYear: function(date, dir)
-    {
-        return this.moveMonth(date, dir*12);
-    },
-
-    dateWithinRange: function(date)
-    {
-        return date >= this.startDate && date <= this.endDate;
-    },
-
-    
-    remove: function() 
-    {
-        this.picker().remove();
-    }
-   
-});
-
-Roo.apply(Roo.bootstrap.DateField,  {
-    
-    head : {
-        tag: 'thead',
-        cn: [
-        {
-            tag: 'tr',
-            cn: [
-            {
-                tag: 'th',
-                cls: 'prev',
-                html: '<i class="fa fa-arrow-left"/>'
-            },
-            {
-                tag: 'th',
-                cls: 'switch',
-                colspan: '5'
-            },
-            {
-                tag: 'th',
-                cls: 'next',
-                html: '<i class="fa fa-arrow-right"/>'
+            if (this.before) {
+                inputblock.cn.push({
+                    tag :'span',
+                    cls : 'input-group-addon',
+                    html : this.before
+                });
             }
-
-            ]
-        }
-        ]
-    },
-    
-    content : {
-        tag: 'tbody',
-        cn: [
-        {
-            tag: 'tr',
-            cn: [
-            {
-                tag: 'td',
-                colspan: '7'
+            inputblock.cn.push(input);
+            if (this.after) {
+                inputblock.cn.push({
+                    tag :'span',
+                    cls : 'input-group-addon',
+                    html : this.after
+                });
             }
-            ]
+            
+        };
+        
+        
+        if (this.fieldLabel && this.fieldLabel.length) {
+            cfg.cn.push(fieldLabel);
         }
-        ]
-    },
-    
-    footer : {
-        tag: 'tfoot',
-        cn: [
-        {
-            tag: 'tr',
+       
+        // normal bootstrap puts the input inside the label.
+        // however with our styled version - it has to go after the input.
+       
+        //lbl.cn.push(inputblock);
+        
+        var lblwrap =  {
+            tag: 'span',
+            cls: 'radio' + inline,
             cn: [
-            {
-                tag: 'th',
-                colspan: '7',
-                cls: 'today'
-            }
-                    
+                inputblock,
+                lbl
             ]
+        };
+        
+        cfg.cn.push( lblwrap);
+        
+        if(this.boxLabel){
+            lbl.cn.push({
+                tag: 'span',
+                html: this.boxLabel
+            })
         }
-        ]
+         
+        
+        return cfg;
+        
     },
     
-    dates:{
-        en: {
-            days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
-            daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
-            daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
-            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
-            today: "Today"
+    initEvents : function()
+    {
+//        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
+        
+        this.inputEl().on('click', this.onClick,  this);
+        if (this.boxLabel) {
+            Roo.log('find label')
+            this.el.select('span.radio label span',true).first().on('click', this.onClick,  this);
         }
+        
     },
     
-    modes: [
+    inputEl: function ()
     {
-        clsName: 'days',
-        navFnc: 'Month',
-        navStep: 1
+        return this.el.select('input.roo-radio',true).first();
+    },
+    onClick : function()
+    {   
+        Roo.log("click");
+        this.setChecked(true);
     },
+    
+    setChecked : function(state,suppressEvent)
     {
-        clsName: 'months',
-        navFnc: 'FullYear',
-        navStep: 1
+        if(state){
+            Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
+                v.dom.checked = false;
+            });
+        }
+        Roo.log(this.inputEl().dom);
+        this.checked = state;
+        this.inputEl().dom.checked = state;
+        
+        if(suppressEvent !== true){
+            this.fireEvent('check', this, state);
+        }
+        
+        //this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
+        
     },
+    
+    getGroupValue : function()
     {
-        clsName: 'years',
-        navFnc: 'FullYear',
-        navStep: 10
-    }]
-});
-
-Roo.apply(Roo.bootstrap.DateField,  {
-  
-    template : {
-        tag: 'div',
-        cls: 'datepicker dropdown-menu roo-dynamic',
-        cn: [
-        {
-            tag: 'div',
-            cls: 'datepicker-days',
-            cn: [
-            {
-                tag: 'table',
-                cls: 'table-condensed',
-                cn:[
-                Roo.bootstrap.DateField.head,
-                {
-                    tag: 'tbody'
-                },
-                Roo.bootstrap.DateField.footer
-                ]
-            }
-            ]
-        },
-        {
-            tag: 'div',
-            cls: 'datepicker-months',
-            cn: [
-            {
-                tag: 'table',
-                cls: 'table-condensed',
-                cn:[
-                Roo.bootstrap.DateField.head,
-                Roo.bootstrap.DateField.content,
-                Roo.bootstrap.DateField.footer
-                ]
-            }
-            ]
-        },
-        {
-            tag: 'div',
-            cls: 'datepicker-years',
-            cn: [
-            {
-                tag: 'table',
-                cls: 'table-condensed',
-                cn:[
-                Roo.bootstrap.DateField.head,
-                Roo.bootstrap.DateField.content,
-                Roo.bootstrap.DateField.footer
-                ]
+        var value = '';
+        Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
+            if(v.dom.checked == true){
+                value = v.dom.value;
             }
-            ]
-        }
-        ]
+        });
+        
+        return value;
+    },
+    
+    /**
+     * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
+     * @return {Mixed} value The field value
+     */
+    getValue : function(){
+        return this.getGroupValue();
     }
+    
 });
 
  
+//<script type="text/javascript">
 
- /*
- * - LGPL
+/*
+ * Based  Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ * LGPL
  *
- * TimeField
- * 
  */
-
 /**
- * @class Roo.bootstrap.TimeField
- * @extends Roo.bootstrap.Input
- * Bootstrap DateField class
- * 
- * 
- * @constructor
- * Create a new TimeField
- * @param {Object} config The config object
+ * @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.bootstrap.TimeField = function(config){
-    Roo.bootstrap.TimeField.superclass.constructor.call(this, config);
+Roo.HtmlEditorCore = function(config){
+    
+    
+    Roo.HtmlEditorCore.superclass.constructor.call(this, config);
+    
+    
     this.addEvents({
-            /**
-             * @event show
-             * Fires when this field show.
-             * @param {Roo.bootstrap.DateField} thisthis
-             * @param {Mixed} date The date value
-             */
-            show : true,
-            /**
-             * @event show
-             * Fires when this field hide.
-             * @param {Roo.bootstrap.DateField} this
-             * @param {Mixed} date The date value
-             */
-            hide : true,
-            /**
-             * @event select
-             * Fires when select a date.
-             * @param {Roo.bootstrap.DateField} this
-             * @param {Mixed} date The date value
-             */
-            select : true
-        });
+        /**
+         * @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.bootstrap.TimeField, Roo.bootstrap.Input,  {
+
+Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
+
+
+     /**
+     * @cfg {Roo.form.HtmlEditor|Roo.bootstrap.HtmlEditor} the owner field 
+     */
+    
+    owner : false,
+    
+     /**
+     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
+     *                        Roo.resizable.
+     */
+    resizable : false,
+     /**
+     * @cfg {Number} height (in pixels)
+     */   
+    height: 300,
+   /**
+     * @cfg {Number} width (in pixels)
+     */   
+    width: 500,
     
     /**
-     * @cfg {String} format
-     * The default time format string which can be overriden for localization support.  The format must be
-     * valid according to {@link Date#parseDate} (defaults to 'H:i').
+     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
+     * 
      */
-    format : "H:i",
-       
-    onRender: function(ct, position)
-    {
-        
-        Roo.bootstrap.TimeField.superclass.onRender.call(this, ct, position);
-                
-        this.el.select('>.input-group', true).first().createChild(Roo.bootstrap.TimeField.template);
-        
-        this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-        
-        this.pop = this.picker().select('>.datepicker-time',true).first();
-        this.pop.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-        
-        this.picker().on('mousedown', this.onMousedown, this);
-        this.picker().on('click', this.onClick, this);
-        
-        this.picker().addClass('datepicker-dropdown');
+    stylesheets: false,
     
-        this.fillTime();
-        this.update();
-            
-        this.pop.select('span.hours-up', true).first().on('click', this.onIncrementHours, this);
-        this.pop.select('span.hours-down', true).first().on('click', this.onDecrementHours, this);
-        this.pop.select('span.minutes-up', true).first().on('click', this.onIncrementMinutes, this);
-        this.pop.select('span.minutes-down', true).first().on('click', this.onDecrementMinutes, this);
-        this.pop.select('button.period', true).first().on('click', this.onTogglePeriod, this);
-        this.pop.select('button.ok', true).first().on('click', this.setTime, this);
-
-    },
+    // id of frame..
+    frameId: false,
     
-    fireKey: function(e){
-        if (!this.picker().isVisible()){
-            if (e.keyCode == 27) { // allow escape to hide and re-show picker
-                this.show();
-            }
-            return;
-        }
-
-        e.preventDefault();
-        
-        switch(e.keyCode){
-            case 27: // escape
-                this.hide();
-                break;
-            case 37: // left
-            case 39: // right
-                this.onTogglePeriod();
-                break;
-            case 38: // up
-                this.onIncrementMinutes();
-                break;
-            case 40: // down
-                this.onDecrementMinutes();
-                break;
-            case 13: // enter
-            case 9: // tab
-                this.setTime();
-                break;
-        }
-    },
+    // private properties
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
+    sourceEditMode : false,
+    onFocus : Roo.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
     
-    onClick: function(e) {
-        e.stopPropagation();
-        e.preventDefault();
-    },
+    clearUp: true,
     
-    picker : function()
-    {
-        return this.el.select('.datepicker', true).first();
-    },
+    // blacklist + whitelisted elements..
+    black: false,
+    white: false,
+     
     
-    fillTime: function()
-    {    
-        var time = this.pop.select('tbody', true).first();
-        
-        time.dom.innerHTML = '';
-        
-        time.createChild({
-            tag: 'tr',
-            cn: [
-                {
-                    tag: 'td',
-                    cn: [
-                        {
-                            tag: 'a',
-                            href: '#',
-                            cls: 'btn',
-                            cn: [
-                                {
-                                    tag: 'span',
-                                    cls: 'hours-up glyphicon glyphicon-chevron-up'
-                                }
-                            ]
-                        } 
-                    ]
-                },
-                {
-                    tag: 'td',
-                    cls: 'separator'
-                },
-                {
-                    tag: 'td',
-                    cn: [
-                        {
-                            tag: 'a',
-                            href: '#',
-                            cls: 'btn',
-                            cn: [
-                                {
-                                    tag: 'span',
-                                    cls: 'minutes-up glyphicon glyphicon-chevron-up'
-                                }
-                            ]
-                        }
-                    ]
-                },
-                {
-                    tag: 'td',
-                    cls: 'separator'
-                }
-            ]
-        });
-        
-        time.createChild({
-            tag: 'tr',
-            cn: [
-                {
-                    tag: 'td',
-                    cn: [
-                        {
-                            tag: 'span',
-                            cls: 'timepicker-hour',
-                            html: '00'
-                        }  
-                    ]
-                },
-                {
-                    tag: 'td',
-                    cls: 'separator',
-                    html: ':'
-                },
-                {
-                    tag: 'td',
-                    cn: [
-                        {
-                            tag: 'span',
-                            cls: 'timepicker-minute',
-                            html: '00'
-                        }  
-                    ]
-                },
-                {
-                    tag: 'td',
-                    cls: 'separator'
-                },
-                {
-                    tag: 'td',
-                    cn: [
-                        {
-                            tag: 'button',
-                            type: 'button',
-                            cls: 'btn btn-primary period',
-                            html: 'AM'
-                            
-                        }
-                    ]
-                }
-            ]
-        });
-        
-        time.createChild({
-            tag: 'tr',
-            cn: [
-                {
-                    tag: 'td',
-                    cn: [
-                        {
-                            tag: 'a',
-                            href: '#',
-                            cls: 'btn',
-                            cn: [
-                                {
-                                    tag: 'span',
-                                    cls: 'hours-down glyphicon glyphicon-chevron-down'
-                                }
-                            ]
-                        }
-                    ]
-                },
-                {
-                    tag: 'td',
-                    cls: 'separator'
-                },
-                {
-                    tag: 'td',
-                    cn: [
-                        {
-                            tag: 'a',
-                            href: '#',
-                            cls: 'btn',
-                            cn: [
-                                {
-                                    tag: 'span',
-                                    cls: 'minutes-down glyphicon glyphicon-chevron-down'
-                                }
-                            ]
-                        }
-                    ]
-                },
-                {
-                    tag: 'td',
-                    cls: 'separator'
-                }
-            ]
-        });
+
+    /**
+     * 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 = '';
         
-    },
-    
-    update: function()
-    {
+        // 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 { 
+            
+        }
         
-        this.time = (typeof(this.time) === 'undefined') ? new Date() : this.time;
+        st +=  '<style type="text/css">' +
+            'IMG { cursor: pointer } ' +
+        '</style>';
+
         
-        this.fill();
+        return '<html><head>' + st  +
+            //<style type="text/css">' +
+            //'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
+            //'</style>' +
+            ' </head><body class="roo-htmleditor-body"></body></html>';
     },
-    
-    fill: function() 
+
+    // private
+    onRender : function(ct, position)
     {
-        var hours = this.time.getHours();
-        var minutes = this.time.getMinutes();
-        var period = 'AM';
+        var _t = this;
+        //Roo.HtmlEditorCore.superclass.onRender.call(this, ct, position);
+        this.el = this.owner.inputEl ? this.owner.inputEl() : this.owner.el;
         
-        if(hours > 11){
-            period = 'PM';
-        }
         
-        if(hours == 0){
-            hours = 12;
-        }
+        this.el.dom.style.border = '0 none';
+        this.el.dom.setAttribute('tabIndex', -1);
+        this.el.addClass('x-hidden hide');
         
         
-        if(hours > 12){
-            hours = hours - 12;
-        }
         
-        if(hours < 10){
-            hours = '0' + hours;
+        if(Roo.isIE){ // fix IE 1px bogus margin
+            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
         }
+       
         
-        if(minutes < 10){
-            minutes = '0' + minutes;
-        }
+        this.frameId = Roo.id();
         
-        this.pop.select('.timepicker-hour', true).first().dom.innerHTML = hours;
-        this.pop.select('.timepicker-minute', true).first().dom.innerHTML = minutes;
-        this.pop.select('button', true).first().dom.innerHTML = period;
+         
         
-    },
-    
-    place: function()
-    {   
-        this.picker().removeClass(['bottom-left', 'bottom-right', 'top-left', 'top-right']);
+        var iframe = this.owner.wrap.createChild({
+            tag: 'iframe',
+            cls: 'form-control', // bootstrap..
+            id: this.frameId,
+            name: this.frameId,
+            frameBorder : 'no',
+            'src' : Roo.SSL_SECURE_URL ? Roo.SSL_SECURE_URL  :  "javascript:false"
+        }, this.el
+        );
         
-        var cls = ['bottom'];
         
-        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){ // top
-            cls.pop();
-            cls.push('top');
-        }
+        this.iframe = iframe.dom;
+
+         this.assignDocWin();
         
-        cls.push('right');
+        this.doc.designMode = 'on';
+       
+        this.doc.open();
+        this.doc.write(this.getDocMarkup());
+        this.doc.close();
+
         
-        if((Roo.lib.Dom.getViewWidth() + Roo.get(document.body).getScroll().left) - (this.inputEl().getLeft() + this.picker().getWidth()) < 0){ // left
-            cls.pop();
-            cls.push('left');
+        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';
+            }
         }
         
-        this.picker().addClass(cls.join('-'));
+    },
+
+    /**
+     * Toggles the editor between standard and source edit mode.
+     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     */
+    toggleSourceEdit : function(sourceEditMode){
         
-        var _this = this;
+        this.sourceEditMode = sourceEditMode === true;
         
-        Roo.each(cls, function(c){
-            if(c == 'bottom'){
-                _this.picker().setTop(_this.inputEl().getHeight());
-                return;
+        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();
+        }
+        //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(c == 'top'){
-                _this.picker().setTop(0 - _this.picker().getHeight());
-                return;
+        }
+        if(html == '&nbsp;'){
+            html = '';
+        }
+        return html;
+    },
+
+    /**
+     * HTML Editor -> Textarea
+     * Protected method that will not generally be called directly. Syncs the contents
+     * of the editor iframe with the textarea.
+     */
+    syncValue : function(){
+        if(this.initialized){
+            var bd = (this.doc.body || this.doc.documentElement);
+            //this.cleanUpPaste(); -- this is done else where and causes havoc..
+            var html = bd.innerHTML;
+            if(Roo.isSafari){
+                var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
+                var m = bs ? bs.match(/text-align:(.*?);/i) : false;
+                if(m && m[1]){
+                    html = '<div style="'+m[0]+'">' + html + '</div>';
+                }
             }
-            
-            if(c == 'left'){
-                _this.picker().setLeft(_this.inputEl().getLeft() + _this.inputEl().getWidth() - _this.el.getLeft() - _this.picker().getWidth());
-                return;
+            html = this.cleanHtml(html);
+            // fix up the special chars.. normaly like back quotes in word...
+            // however we do not want to do this with chinese..
+            html = html.replace(/([\x80-\uffff])/g, function (a, b) {
+                var cc = b.charCodeAt();
+                if (
+                    (cc >= 0x4E00 && cc < 0xA000 ) ||
+                    (cc >= 0x3400 && cc < 0x4E00 ) ||
+                    (cc >= 0xf900 && cc < 0xfb00 )
+                ) {
+                        return b;
+                }
+                return "&#"+cc+";" 
+            });
+            if(this.owner.fireEvent('beforesync', this, html) !== false){
+                this.el.dom.value = html;
+                this.owner.fireEvent('sync', this, html);
             }
-            if(c == 'right'){
-                _this.picker().setLeft(_this.inputEl().getLeft() - _this.el.getLeft());
-                return;
+        }
+    },
+
+    /**
+     * Protected method that will not generally be called directly. Pushes the value of the textarea
+     * into the iframe editor.
+     */
+    pushValue : function(){
+        if(this.initialized){
+            var v = this.el.dom.value.trim();
+            
+//            if(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);
             }
-        });
-        
+        }
     },
-  
-    onFocus : function()
-    {
-        Roo.bootstrap.TimeField.superclass.onFocus.call(this);
-        this.show();
+
+    // private
+    deferFocus : function(){
+        this.focus.defer(10, this);
     },
-    
-    onBlur : function()
-    {
-        Roo.bootstrap.TimeField.superclass.onBlur.call(this);
-        this.hide();
+
+    // doc'ed in Field
+    focus : function(){
+        if(this.win && !this.sourceEditMode){
+            this.win.focus();
+        }else{
+            this.el.focus();
+        }
     },
     
-    show : function()
+    assignDocWin: function()
     {
-        this.picker().show();
-        this.pop.show();
-        this.update();
-        this.place();
+        var iframe = this.iframe;
         
-        this.fireEvent('show', this, this.date);
+         if(Roo.isIE){
+            this.doc = iframe.contentWindow.document;
+            this.win = iframe.contentWindow;
+        } else {
+//            if (!Roo.get(this.frameId)) {
+//                return;
+//            }
+//            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
+//            this.win = Roo.get(this.frameId).dom.contentWindow;
+            
+            if (!Roo.get(this.frameId) && !iframe.contentDocument) {
+                return;
+            }
+            
+            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
+            this.win = (iframe.contentWindow || Roo.get(this.frameId).dom.contentWindow);
+        }
     },
     
-    hide : function()
-    {
-        this.picker().hide();
-        this.pop.hide();
+    // private
+    initEditor : function(){
+        //console.log("INIT EDITOR");
+        this.assignDocWin();
         
-        this.fireEvent('hide', this, this.date);
-    },
-    
-    setTime : function()
-    {
-        this.hide();
-        this.setValue(this.time.format(this.format));
         
-        this.fireEvent('select', this, this.date);
         
+        this.doc.designMode="on";
+        this.doc.open();
+        this.doc.write(this.getDocMarkup());
+        this.doc.close();
         
-    },
-    
-    onMousedown: function(e){
-        e.stopPropagation();
-        e.preventDefault();
-    },
-    
-    onIncrementHours: function()
-    {
-        Roo.log('onIncrementHours');
-        this.time = this.time.add(Date.HOUR, 1);
-        this.update();
+        var dbody = (this.doc.body || this.doc.documentElement);
+        //var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
+        // this copies styles from the containing element into thsi one..
+        // not sure why we need all of this..
+        //var ss = this.el.getStyles('font-size', 'background-image', 'background-repeat');
         
-    },
-    
-    onDecrementHours: function()
-    {
-        Roo.log('onDecrementHours');
-        this.time = this.time.add(Date.HOUR, -1);
-        this.update();
-    },
-    
-    onIncrementMinutes: function()
-    {
-        Roo.log('onIncrementMinutes');
-        this.time = this.time.add(Date.MINUTE, 1);
-        this.update();
-    },
-    
-    onDecrementMinutes: function()
-    {
-        Roo.log('onDecrementMinutes');
-        this.time = this.time.add(Date.MINUTE, -1);
-        this.update();
-    },
-    
-    onTogglePeriod: function()
-    {
-        Roo.log('onTogglePeriod');
-        this.time = this.time.add(Date.HOUR, 12);
-        this.update();
-    }
-    
-   
-});
+        //var ss = this.el.getStyles( 'background-image', 'background-repeat');
+        //ss['background-attachment'] = 'fixed'; // w3c
+        dbody.bgProperties = 'fixed'; // ie
+        //Roo.DomHelper.applyStyles(dbody, ss);
+        Roo.EventManager.on(this.doc, {
+            //'mousedown': this.onEditorEvent,
+            'mouseup': this.onEditorEvent,
+            'dblclick': this.onEditorEvent,
+            'click': this.onEditorEvent,
+            'keyup': this.onEditorEvent,
+            buffer:100,
+            scope: this
+        });
+        if(Roo.isGecko){
+            Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
+        }
+        if(Roo.isIE || Roo.isSafari || Roo.isOpera){
+            Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
+        }
+        this.initialized = true;
 
-Roo.apply(Roo.bootstrap.TimeField,  {
-    
-    content : {
-        tag: 'tbody',
-        cn: [
-            {
-                tag: 'tr',
-                cn: [
-                {
-                    tag: 'td',
-                    colspan: '7'
-                }
-                ]
-            }
-        ]
+        this.owner.fireEvent('initialize', this);
+        this.pushValue();
     },
-    
-    footer : {
-        tag: 'tfoot',
-        cn: [
-            {
-                tag: 'tr',
-                cn: [
-                {
-                    tag: 'th',
-                    colspan: '7',
-                    cls: '',
-                    cn: [
-                        {
-                            tag: 'button',
-                            cls: 'btn btn-info ok',
-                            html: 'OK'
-                        }
-                    ]
-                }
-
-                ]
-            }
-        ]
-    }
-});
-
-Roo.apply(Roo.bootstrap.TimeField,  {
-  
-    template : {
-        tag: 'div',
-        cls: 'datepicker dropdown-menu',
-        cn: [
-            {
-                tag: 'div',
-                cls: 'datepicker-time',
-                cn: [
-                {
-                    tag: 'table',
-                    cls: 'table-condensed',
-                    cn:[
-                    Roo.bootstrap.TimeField.content,
-                    Roo.bootstrap.TimeField.footer
-                    ]
-                }
-                ]
-            }
-        ]
-    }
-});
-
-
- /*
- * - LGPL
- *
- * MonthField
- * 
- */
-
-/**
- * @class Roo.bootstrap.MonthField
- * @extends Roo.bootstrap.Input
- * Bootstrap MonthField class
- * 
- * @cfg {String} language default en
- * 
- * @constructor
- * Create a new MonthField
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.MonthField = function(config){
-    Roo.bootstrap.MonthField.superclass.constructor.call(this, config);
-    
-    this.addEvents({
-        /**
-         * @event show
-         * Fires when this field show.
-         * @param {Roo.bootstrap.MonthField} this
-         * @param {Mixed} date The date value
-         */
-        show : true,
-        /**
-         * @event show
-         * Fires when this field hide.
-         * @param {Roo.bootstrap.MonthField} this
-         * @param {Mixed} date The date value
-         */
-        hide : true,
-        /**
-         * @event select
-         * Fires when select a date.
-         * @param {Roo.bootstrap.MonthField} this
-         * @param {String} oldvalue The old value
-         * @param {String} newvalue The new value
-         */
-        select : true
-    });
-};
 
-Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
-    
-    onRender: function(ct, position)
-    {
-        
-        Roo.bootstrap.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";
+    // private
+    onDestroy : function(){
         
-        this.isRTL = Roo.bootstrap.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.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        if(this.rendered){
+            
+            //for (var i =0; i < this.toolbars.length;i++) {
+            //    // fixme - ask toolbars for heights?
+            //    this.toolbars[i].onDestroy();
+           // }
+            
+            //this.wrap.dom.innerHTML = '';
+            //this.wrap.remove();
+        }
+    },
+
+    // private
+    onFirstFocus : function(){
         
-        this.picker().on('mousedown', this.onMousedown, this);
-        this.picker().on('click', this.onClick, this);
+        this.assignDocWin();
         
-        this.picker().addClass('datepicker-dropdown');
         
-        Roo.each(this.picker().select('tbody > tr > td', true).elements, function(v){
-            v.setStyle('width', '189px');
-        });
+        this.activated = true;
+         
+    
+        if(Roo.isGecko){ // prevent silly gecko errors
+            this.win.focus();
+            var s = this.win.getSelection();
+            if(!s.focusNode || s.focusNode.nodeType != 3){
+                var r = s.getRangeAt(0);
+                r.selectNodeContents((this.doc.body || this.doc.documentElement));
+                r.collapse(true);
+                this.deferFocus();
+            }
+            try{
+                this.execCmd('useCSS', true);
+                this.execCmd('styleWithCSS', false);
+            }catch(e){}
+        }
+        this.owner.fireEvent('activate', this);
+    },
+
+    // private
+    adjustFont: function(btn){
+        var adjust = btn.cmd == 'increasefontsize' ? 1 : -1;
+        //if(Roo.isSafari){ // safari
+        //    adjust *= 2;
+       // }
+        var v = parseInt(this.doc.queryCommandValue('FontSize')|| 3, 10);
+        if(Roo.isSafari){ // safari
+            var sm = { 10 : 1, 13: 2, 16:3, 18:4, 24: 5, 32:6, 48: 7 };
+            v =  (v < 10) ? 10 : v;
+            v =  (v > 48) ? 48 : v;
+            v = typeof(sm[v]) == 'undefined' ? 1 : sm[v];
+            
+        }
         
-        this.fillMonths();
         
-        this.update();
+        v = Math.max(1, v+adjust);
         
-        if(this.isInline) {
-            this.show();
+        this.execCmd('FontSize', v  );
+    },
+
+    onEditorEvent : function(e)
+    {
+        this.owner.fireEvent('editorevent', this, e);
+      //  this.updateToolbar();
+        this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
+    },
+
+    insertTag : function(tg)
+    {
+        // could be a bit smarter... -> wrap the current selected tRoo..
+        if (tg.toLowerCase() == 'span' || tg.toLowerCase() == 'code') {
+            
+            range = this.createRange(this.getSelection());
+            var wrappingNode = this.doc.createElement(tg.toLowerCase());
+            wrappingNode.appendChild(range.extractContents());
+            range.insertNode(wrappingNode);
+
+            return;
+            
+            
+            
         }
+        this.execCmd("formatblock",   tg);
         
     },
     
-    setValue: function(v, suppressEvent)
-    {   
-        var o = this.getValue();
+    insertText : function(txt)
+    {
         
-        Roo.bootstrap.MonthField.superclass.setValue.call(this, v);
         
-        this.update();
+        var range = this.createRange();
+        range.deleteContents();
+               //alert(Sender.getAttribute('label'));
+               
+        range.insertNode(this.doc.createTextNode(txt));
+    } ,
+    
+     
 
-        if(suppressEvent !== true){
-            this.fireEvent('select', this, o, v);
-        }
-        
+    /**
+     * Executes a Midas editor command on the editor document and performs necessary focus and
+     * toolbar updates. <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    relayCmd : function(cmd, value){
+        this.win.focus();
+        this.execCmd(cmd, value);
+        this.owner.fireEvent('editorevent', this);
+        //this.updateToolbar();
+        this.owner.deferFocus();
     },
-    
-    getValue: function()
-    {
-        return this.value;
+
+    /**
+     * Executes a Midas editor command directly on the editor document.
+     * For visual commands, you should use {@link #relayCmd} instead.
+     * <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    execCmd : function(cmd, value){
+        this.doc.execCommand(cmd, false, value === undefined ? null : value);
+        this.syncValue();
     },
-    
-    onClick: function(e) 
+   
+    /**
+     * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
+     * to insert tRoo.
+     * @param {String} text | dom node.. 
+     */
+    insertAtCursor : function(text)
     {
-        e.stopPropagation();
-        e.preventDefault();
         
-        var target = e.getTarget();
-        
-        if(target.nodeName.toLowerCase() === 'i'){
-            target = Roo.get(target).dom.parentNode;
-        }
         
-        var nodeName = target.nodeName;
-        var className = target.className;
-        var html = target.innerHTML;
         
-        if(nodeName.toLowerCase() != 'span' || className.indexOf('disabled') > -1 || className.indexOf('month') == -1){
+        if(!this.activated){
             return;
         }
-        
-        this.vIndex = Roo.bootstrap.MonthField.dates[this.language].monthsShort.indexOf(html);
-        
-        this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
-        
-        this.hide();
-                        
-    },
-    
-    picker : function()
-    {
-        return this.pickerEl;
+        /*
+        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();
+            
+            
+            // from jquery ui (MIT licenced)
+            var range, node;
+            var win = this.win;
+            
+            if (win.getSelection && win.getSelection().getRangeAt) {
+                range = win.getSelection().getRangeAt(0);
+                node = typeof(text) == 'string' ? range.createContextualFragment(text) : text;
+                range.insertNode(node);
+            } else if (win.document.selection && win.document.selection.createRange) {
+                // no firefox support
+                var txt = typeof(text) == 'string' ? text : text.outerHTML;
+                win.document.selection.createRange().pasteHTML(txt);
+            } else {
+                // no firefox support
+                var txt = typeof(text) == 'string' ? text : text.outerHTML;
+                this.execCmd('InsertHTML', txt);
+            } 
+            
+            this.syncValue();
+            
+            this.deferFocus();
+        }
     },
-    
-    fillMonths: function()
-    {    
-        var i = 0;
-        var months = this.picker().select('>.datepicker-months td', true).first();
-        
-        months.dom.innerHTML = '';
-        
-        while (i < 12) {
-            var month = {
-                tag: 'span',
-                cls: 'month',
-                html: Roo.bootstrap.MonthField.dates[this.language].monthsShort[i++]
+ // private
+    mozKeyPress : function(e){
+        if(e.ctrlKey){
+            var c = e.getCharCode(), cmd;
+          
+            if(c > 0){
+                c = String.fromCharCode(c).toLowerCase();
+                switch(c){
+                    case 'b':
+                        cmd = 'bold';
+                        break;
+                    case 'i':
+                        cmd = 'italic';
+                        break;
+                    
+                    case 'u':
+                        cmd = 'underline';
+                        break;
+                    
+                    case 'v':
+                        this.cleanUpPaste.defer(100, this);
+                        return;
+                        
+                }
+                if(cmd){
+                    this.win.focus();
+                    this.execCmd(cmd);
+                    this.deferFocus();
+                    e.preventDefault();
+                }
+                
             }
-            
-            months.createChild(month);
         }
-        
     },
-    
-    update: function()
-    {
-        var _this = this;
-        
-        if(typeof(this.vIndex) == 'undefined' && this.value.length){
-            this.vIndex = Roo.bootstrap.MonthField.dates[this.language].months.indexOf(this.value);
+
+    // private
+    fixKeys : function(){ // load time branching for fastest keydown performance
+        if(Roo.isIE){
+            return function(e){
+                var k = e.getKey(), r;
+                if(k == e.TAB){
+                    e.stopEvent();
+                    r = this.doc.selection.createRange();
+                    if(r){
+                        r.collapse(true);
+                        r.pasteHTML('&#160;&#160;&#160;&#160;');
+                        this.deferFocus();
+                    }
+                    return;
+                }
+                
+                if(k == e.ENTER){
+                    r = this.doc.selection.createRange();
+                    if(r){
+                        var target = r.parentElement();
+                        if(!target || target.tagName.toLowerCase() != 'li'){
+                            e.stopEvent();
+                            r.pasteHTML('<br />');
+                            r.collapse(false);
+                            r.select();
+                        }
+                    }
+                }
+                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+                
+            };
+        }else if(Roo.isOpera){
+            return function(e){
+                var k = e.getKey();
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.win.focus();
+                    this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
+                    this.deferFocus();
+                }
+                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+            };
+        }else if(Roo.isSafari){
+            return function(e){
+                var k = e.getKey();
+                
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.execCmd('InsertText','\t');
+                    this.deferFocus();
+                    return;
+                }
+               if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
+                    this.cleanUpPaste.defer(100, this);
+                    return;
+                }
+                
+             };
         }
-        
-        Roo.each(this.pickerEl.select('> .datepicker-months tbody > tr > td > span', true).elements, function(e, k){
-            e.removeClass('active');
-            
-            if(typeof(_this.vIndex) != 'undefined' && k == _this.vIndex){
-                e.addClass('active');
-            }
-        })
-    },
+    }(),
     
-    place: function()
+    getAllAncestors: function()
     {
-        if(this.isInline) return;
-        
-        this.picker().removeClass(['bottom', 'top']);
-        
-        if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){
-            /*
-             * place to the top of element!
-             *
-             */
-            
-            this.picker().addClass('top');
-            this.picker().setTop(this.inputEl().getTop() - this.picker().getHeight()).setLeft(this.inputEl().getLeft());
-            
-            return;
+        var p = this.getSelectedNode();
+        var a = [];
+        if (!p) {
+            a.push(p); // push blank onto stack..
+            p = this.getParentElement();
         }
         
-        this.picker().addClass('bottom');
         
-        this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());
+        while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
+            a.push(p);
+            p = p.parentNode;
+        }
+        a.push(this.doc.body);
+        return a;
     },
+    lastSel : false,
+    lastSelNode : false,
     
-    onFocus : function()
-    {
-        Roo.bootstrap.MonthField.superclass.onFocus.call(this);
-        this.show();
-    },
     
-    onBlur : function()
+    getSelection : function() 
     {
-        Roo.bootstrap.MonthField.superclass.onBlur.call(this);
-        
-        var d = this.inputEl().getValue();
-        
-        this.setValue(d);
-                
-        this.hide();
+        this.assignDocWin();
+        return Roo.isIE ? this.doc.selection : this.win.getSelection();
     },
     
-    show : function()
+    getSelectedNode: function() 
     {
-        this.picker().show();
-        this.picker().select('>.datepicker-months', true).first().show();
-        this.update();
-        this.place();
+        // this may only work on Gecko!!!
         
-        this.fireEvent('show', this, this.date);
-    },
-    
-    hide : function()
-    {
-        if(this.isInline) return;
-        this.picker().hide();
-        this.fireEvent('hide', this, this.date);
+        // should we cache this!!!!
         
-    },
-    
-    onMousedown: function(e)
-    {
-        e.stopPropagation();
-        e.preventDefault();
-    },
-    
-    keyup: function(e)
-    {
-        Roo.bootstrap.MonthField.superclass.keyup.call(this);
-        this.update();
-    },
-
-    fireKey: function(e)
-    {
-        if (!this.picker().isVisible()){
-            if (e.keyCode == 27) // allow escape to hide and re-show picker
-                this.show();
-            return;
-        }
         
-        var dir;
         
-        switch(e.keyCode){
-            case 27: // escape
-                this.hide();
-                e.preventDefault();
-                break;
-            case 37: // left
-            case 39: // right
-                dir = e.keyCode == 37 ? -1 : 1;
-                
-                this.vIndex = this.vIndex + dir;
-                
-                if(this.vIndex < 0){
-                    this.vIndex = 0;
-                }
-                
-                if(this.vIndex > 11){
-                    this.vIndex = 11;
-                }
-                
-                if(isNaN(this.vIndex)){
-                    this.vIndex = 0;
-                }
-                
-                this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
-                
-                break;
-            case 38: // up
-            case 40: // down
-                
-                dir = e.keyCode == 38 ? -1 : 1;
-                
-                this.vIndex = this.vIndex + dir * 4;
-                
-                if(this.vIndex < 0){
-                    this.vIndex = 0;
-                }
-                
-                if(this.vIndex > 11){
-                    this.vIndex = 11;
-                }
-                
-                if(isNaN(this.vIndex)){
-                    this.vIndex = 0;
-                }
-                
-                this.setValue(Roo.bootstrap.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.hide();
-                e.preventDefault();
-                break;
-            case 9: // tab
-                if(typeof(this.vIndex) != 'undefined' && !isNaN(this.vIndex)){
-                    this.setValue(Roo.bootstrap.MonthField.dates[this.language].months[this.vIndex]);
+         
+        var range = this.createRange(this.getSelection()).cloneRange();
+        
+        if (Roo.isIE) {
+            var parent = range.parentElement();
+            while (true) {
+                var testRange = range.duplicate();
+                testRange.moveToElementText(parent);
+                if (testRange.inRange(range)) {
+                    break;
                 }
-                this.hide();
-                break;
-            case 16: // shift
-            case 17: // ctrl
-            case 18: // alt
-                break;
-            default :
-                this.hide();
-                
+                if ((parent.nodeType != 1) || (parent.tagName.toLowerCase() == 'body')) {
+                    break;
+                }
+                parent = parent.parentElement;
+            }
+            return parent;
+        }
+        
+        // is ancestor a text element.
+        var ac =  range.commonAncestorContainer;
+        if (ac.nodeType == 3) {
+            ac = ac.parentNode;
+        }
+        
+        var ar = ac.childNodes;
+         
+        var nodes = [];
+        var other_nodes = [];
+        var has_other_nodes = false;
+        for (var i=0;i<ar.length;i++) {
+            if ((ar[i].nodeType == 3) && (!ar[i].data.length)) { // empty text ? 
+                continue;
+            }
+            // fullly contained node.
+            
+            if (this.rangeIntersectsNode(range,ar[i]) && this.rangeCompareNode(range,ar[i]) == 3) {
+                nodes.push(ar[i]);
+                continue;
+            }
+            
+            // probably selected..
+            if ((ar[i].nodeType == 1) && this.rangeIntersectsNode(range,ar[i]) && (this.rangeCompareNode(range,ar[i]) > 0)) {
+                other_nodes.push(ar[i]);
+                continue;
+            }
+            // outer..
+            if (!this.rangeIntersectsNode(range,ar[i])|| (this.rangeCompareNode(range,ar[i]) == 0))  {
+                continue;
+            }
+            
+            
+            has_other_nodes = true;
+        }
+        if (!nodes.length && other_nodes.length) {
+            nodes= other_nodes;
+        }
+        if (has_other_nodes || !nodes.length || (nodes.length > 1)) {
+            return false;
         }
+        
+        return nodes[0];
     },
-    
-    remove: function() 
+    createRange: function(sel)
     {
-        this.picker().remove();
-    }
-   
-});
-
-Roo.apply(Roo.bootstrap.MonthField,  {
-    
-    content : {
-        tag: 'tbody',
-        cn: [
-        {
-            tag: 'tr',
-            cn: [
-            {
-                tag: 'td',
-                colspan: '7'
+        // this has strange effects when using with 
+        // top toolbar - not sure if it's a great idea.
+        //this.editor.contentWindow.focus();
+        if (typeof sel != "undefined") {
+            try {
+                return sel.getRangeAt ? sel.getRangeAt(0) : sel.createRange();
+            } catch(e) {
+                return this.doc.createRange();
             }
-            ]
+        } else {
+            return this.doc.createRange();
         }
-        ]
     },
+    getParentElement: function()
+    {
+        
+        this.assignDocWin();
+        var sel = Roo.isIE ? this.doc.selection : this.win.getSelection();
+        
+        var range = this.createRange(sel);
+         
+        try {
+            var p = range.commonAncestorContainer;
+            while (p.nodeType == 3) { // text node
+                p = p.parentNode;
+            }
+            return p;
+        } catch (e) {
+            return null;
+        }
     
-    dates:{
-        en: {
-            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+    },
+    /***
+     *
+     * Range intersection.. the hard stuff...
+     *  '-1' = before
+     *  '0' = hits..
+     *  '1' = after.
+     *         [ -- selected range --- ]
+     *   [fail]                        [fail]
+     *
+     *    basically..
+     *      if end is before start or  hits it. fail.
+     *      if start is after end or hits it fail.
+     *
+     *   if either hits (but other is outside. - then it's not 
+     *   
+     *    
+     **/
+    
+    
+    // @see http://www.thismuchiknow.co.uk/?p=64.
+    rangeIntersectsNode : function(range, node)
+    {
+        var nodeRange = node.ownerDocument.createRange();
+        try {
+            nodeRange.selectNode(node);
+        } catch (e) {
+            nodeRange.selectNodeContents(node);
         }
-    }
-});
-
-Roo.apply(Roo.bootstrap.MonthField,  {
-  
-    template : {
-        tag: 'div',
-        cls: 'datepicker dropdown-menu roo-dynamic',
-        cn: [
-            {
-                tag: 'div',
-                cls: 'datepicker-months',
-                cn: [
-                {
-                    tag: 'table',
-                    cls: 'table-condensed',
-                    cn:[
-                        Roo.bootstrap.DateField.content
-                    ]
-                }
-                ]
-            }
-        ]
-    }
-});
-
-
- /*
- * - LGPL
- *
- * CheckBox
- * 
- */
-
-/**
- * @class Roo.bootstrap.CheckBox
- * @extends Roo.bootstrap.Input
- * Bootstrap CheckBox class
- * 
- * @cfg {String} valueOff The value that should go into the generated input element's value when unchecked.
- * @cfg {String} inputValue The value that should go into the generated input element's value when checked.
- * @cfg {String} boxLabel The text that appears beside the checkbox
- * @cfg {String} weight (primary|warning|info|danger|success) The text that appears beside the checkbox
- * @cfg {Boolean} checked initnal the element
- * @cfg {Boolean} inline inline the element (default false)
- * @cfg {String} groupId the checkbox group id // normal just use for checkbox
- * 
- * @constructor
- * Create a new CheckBox
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.CheckBox = function(config){
-    Roo.bootstrap.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 {Boolean} checked The new checked value
-        */
-       check : true
-    });
     
-};
-
-Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
-  
-    inputType: 'checkbox',
-    inputValue: 1,
-    valueOff: 0,
-    boxLabel: false,
-    checked: false,
-    weight : false,
-    inline: false,
+        var rangeStartRange = range.cloneRange();
+        rangeStartRange.collapse(true);
     
-    getAutoCreate : function()
+        var rangeEndRange = range.cloneRange();
+        rangeEndRange.collapse(false);
+    
+        var nodeStartRange = nodeRange.cloneRange();
+        nodeStartRange.collapse(true);
+    
+        var nodeEndRange = nodeRange.cloneRange();
+        nodeEndRange.collapse(false);
+    
+        return rangeStartRange.compareBoundaryPoints(
+                 Range.START_TO_START, nodeEndRange) == -1 &&
+               rangeEndRange.compareBoundaryPoints(
+                 Range.START_TO_START, nodeStartRange) == 1;
+        
+         
+    },
+    rangeCompareNode : function(range, node)
     {
-        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
+        var nodeRange = node.ownerDocument.createRange();
+        try {
+            nodeRange.selectNode(node);
+        } catch (e) {
+            nodeRange.selectNodeContents(node);
+        }
         
-        var id = Roo.id();
         
-        var cfg = {};
+        range.collapse(true);
+    
+        nodeRange.collapse(true);
+     
+        var ss = range.compareBoundaryPoints( Range.START_TO_START, nodeRange);
+        var ee = range.compareBoundaryPoints(  Range.END_TO_END, nodeRange);
+         
+        //Roo.log(node.tagName + ': ss='+ss +', ee='+ee)
+        
+        var nodeIsBefore   =  ss == 1;
+        var nodeIsAfter    = ee == -1;
+        
+        if (nodeIsBefore && nodeIsAfter)
+            return 0; // outer
+        if (!nodeIsBefore && nodeIsAfter)
+            return 1; //right trailed.
         
-        cfg.cls = 'form-group ' + this.inputType; //input-group
+        if (nodeIsBefore && !nodeIsAfter)
+            return 2;  // left trailed.
+        // fully contined.
+        return 3;
+    },
+
+    // private? - in a new class?
+    cleanUpPaste :  function()
+    {
+        // cleans up the whole document..
+        Roo.log('cleanuppaste');
         
-        if(this.inline){
-            cfg.cls += ' ' + this.inputType + '-inline';
+        this.cleanUpChildren(this.doc.body);
+        var clean = this.cleanWordChars(this.doc.body.innerHTML);
+        if (clean != this.doc.body.innerHTML) {
+            this.doc.body.innerHTML = clean;
         }
         
-        var input =  {
-            tag: 'input',
-            id : id,
-            type : this.inputType,
-            value : this.inputType == 'radio' ? this.inputValue : ((!this.checked) ? this.valueOff : this.inputValue),
-            cls : 'roo-' + this.inputType, //'form-box',
-            placeholder : this.placeholder || ''
+    },
+    
+    cleanWordChars : function(input) {// change the chars to hex code
+        var he = Roo.HtmlEditorCore;
+        
+        var output = input;
+        Roo.each(he.swapCodes, function(sw) { 
+            var swapper = new RegExp("\\u" + sw[0].toString(16), "g"); // hex codes
             
-        };
+            output = output.replace(swapper, sw[1]);
+        });
         
-        if (this.weight) { // Validity check?
-            cfg.cls += " " + this.inputType + "-" + this.weight;
+        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]);
         }
+    },
+    
+    
         
-        if (this.disabled) {
-            input.disabled=true;
+    
+    cleanUpChild : function (node)
+    {
+        var ed = this;
+        //console.log(node);
+        if (node.nodeName == "#text") {
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        if (node.nodeName == "#comment") {
+            node.parentNode.removeChild(node);
+            // clean up silly Windows -- stuff?
+            return; 
         }
+        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.checked){
-            input.checked = this.checked;
+        if (this.black.indexOf(lcname) > -1 && this.clearUp ) {
+            // remove node.
+            node.parentNode.removeChild(node);
+            return;
+            
         }
         
-        if (this.name) {
-            input.name = this.name;
+        var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
+        
+        // remove <a name=....> as rendering on yahoo mailer is borked with this.
+        // this will have to be flaged elsewhere - perhaps ablack=name... on the mailer..
+        
+        //if (node.tagName.toLowerCase() == 'a' && !node.hasAttribute('href')) {
+        //    remove_keep_children = true;
+        //}
+        
+        if (remove_keep_children) {
+            this.cleanUpChildren(node);
+            // inserts everything just before this node...
+            while (node.childNodes.length) {
+                var cn = node.childNodes[0];
+                node.removeChild(cn);
+                node.parentNode.insertBefore(cn, node);
+            }
+            node.parentNode.removeChild(node);
+            return;
         }
         
-        if (this.size) {
-            input.cls += ' input-' + this.size;
+        if (!node.attributes || !node.attributes.length) {
+            this.cleanUpChildren(node);
+            return;
         }
         
-        var settings=this;
+        function cleanAttr(n,v)
+        {
+            
+            if (v.match(/^\./) || v.match(/^\//)) {
+                return;
+            }
+            if (v.match(/^(http|https):\/\//) || v.match(/^mailto:/)) {
+                return;
+            }
+            if (v.match(/^#/)) {
+                return;
+            }
+//            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
+            node.removeAttribute(n);
+            
+        }
         
-        ['xs','sm','md','lg'].map(function(size){
-            if (settings[size]) {
-                cfg.cls += ' col-' + size + '-' + settings[size];
+        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);
+            }
+            
+        }
         
-        var inputblock = input;
-         
-        if (this.before || this.after) {
+        
+        for (var i = node.attributes.length-1; i > -1 ; i--) {
+            var a = node.attributes[i];
+            //console.log(a);
             
-            inputblock = {
-                cls : 'input-group',
-                cn :  [] 
-            };
+            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 (this.before) {
-                inputblock.cn.push({
-                    tag :'span',
-                    cls : 'input-group-addon',
-                    html : this.before
-                });
+            
+            if (a.name == 'class') {
+                if (a.value.match(/^Mso/)) {
+                    node.className = '';
+                }
+                
+                if (a.value.match(/body/)) {
+                    node.className = '';
+                }
+                continue;
+            }
+            
+            // style cleanup!?
+            // class cleanup?
+            
+        }
+        
+        
+        this.cleanUpChildren(node);
+        
+        
+    },
+    
+    /**
+     * Clean up MS wordisms...
+     */
+    cleanWord : function(node)
+    {
+        
+        
+        if (!node) {
+            this.cleanWord(this.doc.body);
+            return;
+        }
+        if (node.nodeName == "#text") {
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        if (node.nodeName == "#comment") {
+            node.parentNode.removeChild(node);
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        
+        if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
+            node.parentNode.removeChild(node);
+            return;
+        }
+        
+        // remove - but keep children..
+        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|font)/)) {
+            while (node.childNodes.length) {
+                var cn = node.childNodes[0];
+                node.removeChild(cn);
+                node.parentNode.insertBefore(cn, node);
             }
+            node.parentNode.removeChild(node);
+            this.iterateChildren(node, this.cleanWord);
+            return;
+        }
+        // clean styles
+        if (node.className.length) {
             
-            inputblock.cn.push(input);
-            
-            if (this.after) {
-                inputblock.cn.push({
-                    tag :'span',
-                    cls : 'input-group-addon',
-                    html : this.after
-                });
+            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 (align ==='left' && this.fieldLabel.length) {
-                Roo.log("left and has label");
-                cfg.cn = [
-                    
-                    {
-                        tag: 'label',
-                        'for' :  id,
-                        cls : 'control-label col-md-' + this.labelWidth,
-                        html : this.fieldLabel
-                        
-                    },
-                    {
-                        cls : "col-md-" + (12 - this.labelWidth), 
-                        cn: [
-                            inputblock
-                        ]
-                    }
-                    
-                ];
-        } else if ( this.fieldLabel.length) {
-                Roo.log(" label");
-                cfg.cn = [
-                   
-                    {
-                        tag: this.boxLabel ? 'span' : 'label',
-                        'for': id,
-                        cls: 'control-label box-input-label',
-                        //cls : 'input-group-addon',
-                        html : this.fieldLabel
-                        
-                    },
-                    
-                    inputblock
-                    
-                ];
-
-        } else {
-            
-                Roo.log(" no label && no align");
-                cfg.cn = [  inputblock ] ;
-                
-                
+        if (node.hasAttribute("lang")) {
+            node.removeAttribute("lang");
         }
-        if(this.boxLabel){
-             var boxLabelCfg = {
-                tag: 'label',
-                //'for': id, // box label is handled by onclick - so no for...
-                cls: 'box-label',
-                html: this.boxLabel
-            }
+        
+        if (node.hasAttribute("style")) {
             
-            if(this.tooltip){
-                boxLabelCfg.tooltip = this.tooltip;
+            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');
             }
-             
-            cfg.cn.push(boxLabelCfg);
         }
+        this.iterateChildren(node, this.cleanWord);
         
         
-       
-        return cfg;
         
     },
-    
     /**
-     * return the real input element.
+     * 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.
      */
-    inputEl: function ()
-    {
-        return this.el.select('input.roo-' + this.inputType,true).first();
-    },
-    
-    labelEl: function()
+    iterateChildren : function(node, fn)
     {
-        return this.el.select('label.control-label',true).first();
+        if (!node.childNodes.length) {
+                return;
+        }
+        for (var i = node.childNodes.length-1; i > -1 ; i--) {
+           fn.call(this, node.childNodes[i])
+        }
     },
-    /* depricated... */
     
-    label: function()
-    {
-        return this.labelEl();
-    },
     
-    initEvents : function()
+    /**
+     * 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..
+     *
+     */
+    cleanTableWidths : function(node)
     {
-//        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
+         
+         
+        if (!node) {
+            this.cleanTableWidths(this.doc.body);
+            return;
+        }
         
-        this.inputEl().on('click', this.onClick,  this);
+        // 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 (this.boxLabel) { 
-            this.el.select('label.box-label',true).first().on('click', this.onClick,  this);
+         
+        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.startValue = this.getValue();
+        this.iterateChildren(node, this.cleanTableWidths);
+        
         
-        if(this.groupId){
-            Roo.bootstrap.CheckBox.register(this);
-        }
     },
     
-    onClick : function()
-    {   
-        this.setChecked(!this.checked);
-    },
     
-    setChecked : function(state,suppressEvent)
-    {
-        this.startValue = this.getValue();
+    
+    
+    domToHTML : function(currentElement, depth, nopadtext) {
         
-        if(this.inputType == 'radio'){
-            
-            Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
-                e.dom.checked = false;
-            });
-            
-            this.inputEl().dom.checked = true;
-            
-            this.inputEl().dom.value = this.inputValue;
-            
-            if(suppressEvent !== true){
-                this.fireEvent('check', this, true);
-            }
-            
-            this.validate();
+        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;
+            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;
         }
-        
-        this.checked = state;
-        
-        this.inputEl().dom.checked = state;
-        
-        this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
-        
-        if(suppressEvent !== true){
-            this.fireEvent('check', this, state);
+        if (['IMG', 'BR', 'HR', 'INPUT'].indexOf(tagName) > -1) {
+            return ret;
         }
-        
-        this.validate();
-    },
-    
-    getValue : function()
-    {
-        if(this.inputType == 'radio'){
-            return this.getGroupValue();
+        if (['PRE', 'TEXTAREA', 'TD', 'A', 'SPAN'].indexOf(tagName) > -1) { // or code?
+            nopadtext = true;
         }
         
-        return this.inputEl().getValue();
-        
-    },
-    
-    getGroupValue : function()
-    {
-        if(typeof(this.el.up('form').child('input[name='+this.name+']:checked', true)) == 'undefined'){
-            return '';
-        }
         
-        return this.el.up('form').child('input[name='+this.name+']:checked', true).value;
-    },
-    
-    setValue : function(v,suppressEvent)
-    {
-        if(this.inputType == 'radio'){
-            this.setGroupValue(v, suppressEvent);
-            return;
+        // 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);
         }
         
-        this.setChecked(((typeof(v) == 'undefined') ? this.checked : (String(v) === String(this.inputValue))), suppressEvent);
+        ret += innerHTML;
         
-        this.validate();
-    },
-    
-    setGroupValue : function(v, suppressEvent)
-    {
-        this.startValue = this.getValue();
+        if (!allText) {
+                // The remaining code is mostly for formatting the tree
+            ret+= nopadtext ? '' : "\n" + (new Array( depth  )).join( "  "  );
+        }
         
-        Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
-            e.dom.checked = false;
-            
-            if(e.dom.value == v){
-                e.dom.checked = true;
-            }
-        });
         
-        if(suppressEvent !== true){
-            this.fireEvent('check', this, true);
+        if (tagName) {
+            ret+= "</"+tagName+">";
         }
-
-        this.validate();
+        return ret;
         
-        return;
     },
-    
-    validate : function()
-    {
-        if(
-                this.disabled || 
-                (this.inputType == 'radio' && this.validateRadio()) ||
-                (this.inputType == 'checkbox' && this.validateCheckbox())
-        ){
-            this.markValid();
-            return true;
-        }
         
-        this.markInvalid();
-        return false;
-    },
-    
-    validateRadio : function()
+    applyBlacklists : function()
     {
-        var valid = false;
+        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 :  [];
         
-        Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
-            if(!e.dom.checked){
+        this.white = [];
+        this.black = [];
+        Roo.each(Roo.HtmlEditorCore.white, function(tag) {
+            if (b.indexOf(tag) > -1) {
                 return;
             }
+            this.white.push(tag);
             
-            valid = true;
-            
-            return false;
-        });
-        
-        return valid;
-    },
-    
-    validateCheckbox : function()
-    {
-        if(!this.groupId){
-            return (this.getValue() == this.inputValue || this.allowBlank) ? true : false;
-        }
+        }, this);
         
-        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+        Roo.each(w, function(tag) {
+            if (b.indexOf(tag) > -1) {
+                return;
+            }
+            if (this.white.indexOf(tag) > -1) {
+                return;
+            }
+            this.white.push(tag);
+            
+        }, this);
         
-        if(!group){
-            return false;
-        }
         
-        var r = false;
+        Roo.each(Roo.HtmlEditorCore.black, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
+            }
+            this.black.push(tag);
+            
+        }, this);
         
-        for(var i in group){
-            if(r){
-                break;
+        Roo.each(b, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
+            }
+            if (this.black.indexOf(tag) > -1) {
+                return;
             }
+            this.black.push(tag);
             
-            r = (group[i].getValue() == group[i].inputValue) ? true : false;
-        }
+        }, this);
         
-        return r;
-    },
-    
-    /**
-     * Mark this field as valid
-     */
-    markValid : function()
-    {
-        if(this.allowBlank){
-            return;
-        }
         
-        var _this = this;
+        w = typeof(this.owner.cwhite) != 'undefined' && this.owner.cwhite ? this.owner.cwhite  : [];
+        b = typeof(this.owner.cblack) != 'undefined' && this.owner.cblack ? this.owner.cblack :  [];
         
-        this.fireEvent('valid', this);
+        this.cwhite = [];
+        this.cblack = [];
+        Roo.each(Roo.HtmlEditorCore.cwhite, function(tag) {
+            if (b.indexOf(tag) > -1) {
+                return;
+            }
+            this.cwhite.push(tag);
+            
+        }, this);
         
-        if(this.inputType == 'radio'){
-            Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
-                e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
-                e.findParent('.form-group', false, true).addClass(_this.validClass);
-            });
+        Roo.each(w, function(tag) {
+            if (b.indexOf(tag) > -1) {
+                return;
+            }
+            if (this.cwhite.indexOf(tag) > -1) {
+                return;
+            }
+            this.cwhite.push(tag);
             
-            return;
-        }
+        }, this);
         
-        if(!this.groupId){
-            this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
-            this.el.findParent('.form-group', false, true).addClass(this.validClass);
-            return;
-        }
         
-        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+        Roo.each(Roo.HtmlEditorCore.cblack, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
+            }
+            this.cblack.push(tag);
             
-        if(!group){
-            return;
-        }
+        }, this);
         
-        for(var i in group){
-            group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
-            group[i].el.findParent('.form-group', false, true).addClass(this.validClass);
-        }
+        Roo.each(b, function(tag) {
+            if (w.indexOf(tag) > -1) {
+                return;
+            }
+            if (this.cblack.indexOf(tag) > -1) {
+                return;
+            }
+            this.cblack.push(tag);
+            
+        }, this);
     },
-    
-     /**
-     * Mark this field as invalid
-     * @param {String} msg The validation message
-     */
-    markInvalid : function(msg)
+    
+    setStylesheets : function(stylesheets)
     {
-        if(this.allowBlank){
-            return;
-        }
-        
-        var _this = this;
-        
-        this.fireEvent('invalid', this, msg);
-        
-        if(this.inputType == 'radio'){
-            Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
-                e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
-                e.findParent('.form-group', false, true).addClass(_this.invalidClass);
+        if(typeof(stylesheets) == 'string'){
+            Roo.get(this.iframe.contentDocument.head).createChild({
+                tag : 'link',
+                rel : 'stylesheet',
+                type : 'text/css',
+                href : stylesheets
             });
             
             return;
         }
-        
-        if(!this.groupId){
-            this.el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
-            this.el.findParent('.form-group', false, true).addClass(this.invalidClass);
-            return;
-        }
-        
-        var group = Roo.bootstrap.CheckBox.get(this.groupId);
+        var _this = this;
+     
+        Roo.each(stylesheets, function(s) {
+            if(!s.length){
+                return;
+            }
             
-        if(!group){
-            return;
-        }
+            Roo.get(_this.iframe.contentDocument.head).createChild({
+                tag : 'link',
+                rel : 'stylesheet',
+                type : 'text/css',
+                href : s
+            });
+        });
+
         
-        for(var i in group){
-            group[i].el.findParent('.form-group', false, true).removeClass([this.invalidClass, this.validClass]);
-            group[i].el.findParent('.form-group', false, true).addClass(this.invalidClass);
-        }
+    },
+    
+    removeStylesheets : function()
+    {
+        var _this = this;
         
+        Roo.each(Roo.get(_this.iframe.contentDocument.head).select('link[rel=stylesheet]', true).elements, function(s){
+            s.remove();
+        });
     }
     
+    // hide stuff that is not compatible
+    /**
+     * @event blur
+     * @hide
+     */
+    /**
+     * @event change
+     * @hide
+     */
+    /**
+     * @event focus
+     * @hide
+     */
+    /**
+     * @event specialkey
+     * @hide
+     */
+    /**
+     * @cfg {String} fieldClass @hide
+     */
+    /**
+     * @cfg {String} focusClass @hide
+     */
+    /**
+     * @cfg {String} autoCreate @hide
+     */
+    /**
+     * @cfg {String} inputType @hide
+     */
+    /**
+     * @cfg {String} invalidClass @hide
+     */
+    /**
+     * @cfg {String} invalidText @hide
+     */
+    /**
+     * @cfg {String} msgFx @hide
+     */
+    /**
+     * @cfg {String} validateOnBlur @hide
+     */
 });
 
-Roo.apply(Roo.bootstrap.CheckBox, {
+Roo.HtmlEditorCore.white = [
+        'area', 'br', 'img', 'input', 'hr', 'wbr',
+        
+       'address', 'blockquote', 'center', 'dd',      'dir',       'div', 
+       'dl',      'dt',         'h1',     'h2',      'h3',        'h4', 
+       'h5',      'h6',         'hr',     'isindex', 'listing',   'marquee', 
+       'menu',    'multicol',   'ol',     'p',       'plaintext', 'pre', 
+       'table',   'ul',         'xmp', 
+       
+       'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', 
+      'thead',   'tr', 
+     
+      'dir', 'menu', 'ol', 'ul', 'dl',
+       
+      'embed',  'object'
+];
+
+
+Roo.HtmlEditorCore.black = [
+    //    'embed',  'object', // enable - backend responsiblity to clean thiese
+        'applet', // 
+        'base',   'basefont', 'bgsound', 'blink',  'body', 
+        'frame',  'frameset', 'head',    'html',   'ilayer', 
+        'iframe', 'layer',  'link',     'meta',    'object',   
+        'script', 'style' ,'title',  'xml' // clean later..
+];
+Roo.HtmlEditorCore.clean = [
+    'script', 'style', 'title', 'xml'
+];
+Roo.HtmlEditorCore.remove = [
+    'font'
+];
+// attributes..
+
+Roo.HtmlEditorCore.ablack = [
+    'on'
+];
+    
+Roo.HtmlEditorCore.aclean = [ 
+    'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc' 
+];
+
+// protocols..
+Roo.HtmlEditorCore.pwhite= [
+        'http',  'https',  'mailto'
+];
+
+// white listed style attributes.
+Roo.HtmlEditorCore.cwhite= [
+      //  'text-align', /// default is to allow most things..
+      
+         
+//        'font-size'//??
+];
+
+// black listed style attributes.
+Roo.HtmlEditorCore.cblack= [
+      //  'font-size' -- this can be set by the project 
+];
+
+
+Roo.HtmlEditorCore.swapCodes   =[ 
+    [    8211, "--" ], 
+    [    8212, "--" ], 
+    [    8216,  "'" ],  
+    [    8217, "'" ],  
+    [    8220, '"' ],  
+    [    8221, '"' ],  
+    [    8226, "*" ],  
+    [    8230, "..." ]
+]; 
+
+    /*
+ * - LGPL
+ *
+ * HtmlEditor
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.HtmlEditor
+ * @extends Roo.bootstrap.TextArea
+ * Bootstrap HtmlEditor class
+
+ * @constructor
+ * Create a new HtmlEditor
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.HtmlEditor = function(config){
+    Roo.bootstrap.HtmlEditor.superclass.constructor.call(this, config);
+    if (!this.toolbars) {
+        this.toolbars = [];
+    }
+    this.editorcore = new Roo.HtmlEditorCore(Roo.apply({ owner : this} , config));
+    this.addEvents({
+            /**
+             * @event initialize
+             * Fires when the editor is fully initialized (including the iframe)
+             * @param {HtmlEditor} this
+             */
+            initialize: true,
+            /**
+             * @event activate
+             * Fires when the editor is first receives the focus. Any insertion must wait
+             * until after this event.
+             * @param {HtmlEditor} this
+             */
+            activate: true,
+             /**
+             * @event beforesync
+             * Fires before the textarea is updated with content from the editor iframe. Return false
+             * to cancel the sync.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            beforesync: true,
+             /**
+             * @event beforepush
+             * Fires before the iframe editor is updated with content from the textarea. Return false
+             * to cancel the push.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            beforepush: true,
+             /**
+             * @event sync
+             * Fires when the textarea is updated with content from the editor iframe.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            sync: true,
+             /**
+             * @event push
+             * Fires when the iframe editor is updated with content from the textarea.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            push: true,
+             /**
+             * @event editmodechange
+             * Fires when the editor switches edit modes
+             * @param {HtmlEditor} this
+             * @param {Boolean} sourceEdit True if source edit, false if standard editing.
+             */
+            editmodechange: true,
+            /**
+             * @event editorevent
+             * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
+             * @param {HtmlEditor} this
+             */
+            editorevent: true,
+            /**
+             * @event firstfocus
+             * Fires when on first focus - needed by toolbars..
+             * @param {HtmlEditor} this
+             */
+            firstfocus: true,
+            /**
+             * @event autosave
+             * Auto save the htmlEditor value as a file into Events
+             * @param {HtmlEditor} this
+             */
+            autosave: true,
+            /**
+             * @event savedpreview
+             * preview the saved version of htmlEditor
+             * @param {HtmlEditor} this
+             */
+            savedpreview: true
+        });
+};
+
+
+Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
     
-    groups: {},
     
+      /**
+     * @cfg {Array} toolbars Array of toolbars. - defaults to just the Standard one
+     */
+    toolbars : false,
+   
      /**
-    * register a CheckBox Group
-    * @param {Roo.bootstrap.CheckBox} the CheckBox to add
-    */
-    register : function(checkbox)
-    {
-        if(typeof(this.groups[checkbox.groupId]) == 'undefined'){
-            this.groups[checkbox.groupId] = {};
-        }
-        
-        if(this.groups[checkbox.groupId].hasOwnProperty(checkbox.name)){
-            return;
-        }
-        
-        this.groups[checkbox.groupId][checkbox.name] = checkbox;
-       
-    },
+     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
+     *                        Roo.resizable.
+     */
+    resizable : false,
+     /**
+     * @cfg {Number} height (in pixels)
+     */   
+    height: 300,
+   /**
+     * @cfg {Number} width (in pixels)
+     */   
+    width: false,
+    
     /**
-    * fetch a CheckBox Group based on the group ID
-    * @param {string} the group ID
-    * @returns {Roo.bootstrap.CheckBox} the CheckBox group
-    */
-    get: function(groupId) {
-        if (typeof(this.groups[groupId]) == 'undefined') {
-            return false;
-        }
-        
-        return this.groups[groupId] ;
-    }
+     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
+     * 
+     */
+    stylesheets: false,
     
+    // id of frame..
+    frameId: false,
     
-});
-/*
- * - LGPL
- *
- * Radio
- *
- *
- * not inline
- *<div class="radio">
-  <label>
-    <input type="radio" name="optionsRadios" id="optionsRadios1" value="option1" checked>
-    Option one is this and that&mdash;be sure to include why it's great
-  </label>
-</div>
- *
- *
- *inline
- *<span>
- *<label class="radio-inline">fieldLabel</label>
- *<label class="radio-inline">
-  <input type="radio" name="inlineRadioOptions" id="inlineRadio1" value="option1"> 1
-</label>
-<span>
- * 
- * 
- */
-
-/**
- * @class Roo.bootstrap.Radio
- * @extends Roo.bootstrap.CheckBox
- * Bootstrap Radio class
-
- * @constructor
- * Create a new Radio
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.Radio = function(config){
-    Roo.bootstrap.Radio.superclass.constructor.call(this, config);
-   
-};
-
-Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
+    // private properties
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
     
-    inputType: 'radio',
-    inputValue: '',
-    valueOff: '',
+    onFocus : Roo.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
     
-    getAutoCreate : function()
-    {
-        var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
-        align = align || 'left'; // default...
-        
-        
-        
-        var id = Roo.id();
-        
-        var cfg = {
-                tag : this.inline ? 'span' : 'div',
-                cls : '',
-                cn : []
-        };
-        
-        var inline = this.inline ? ' radio-inline' : '';
-        
-        var lbl = {
-                tag: 'label' ,
-                // does not need for, as we wrap the input with it..
-                'for' : id,
-                cls : 'control-label box-label' + inline,
-                cn : []
-        };
-        var labelWidth = this.labelWidth ? this.labelWidth *1 : 100;
-        
-        var fieldLabel = {
-            tag: 'label' ,
-            //cls : 'control-label' + inline,
-            html : this.fieldLabel,
-            style : 'width:' +  labelWidth  + 'px;line-height:1;vertical-align:bottom;cursor:default;' // should be css really.
-        };
-        
-        
-        
-        var input =  {
-            tag: 'input',
-            id : id,
-            type : this.inputType,
-            //value : (!this.checked) ? this.valueOff : this.inputValue,
-            value : this.inputValue,
-            cls : 'roo-radio',
-            placeholder : this.placeholder || '' // ?? needed????
-            
-        };
-        if (this.weight) { // Validity check?
-            input.cls += " radio-" + this.weight;
-        }
-        if (this.disabled) {
-            input.disabled=true;
-        }
-        
-        if(this.checked){
-            input.checked = this.checked;
-        }
-        
-        if (this.name) {
-            input.name = this.name;
-        }
-        
-        if (this.size) {
-            input.cls += ' input-' + this.size;
-        }
-        
-        //?? can span's inline have a width??
+    
+    tbContainer : false,
+    
+    toolbarContainer :function() {
+        return this.wrap.select('.x-html-editor-tb',true).first();
+    },
+
+    /**
+     * Protected method that will not generally be called directly. It
+     * is called when the editor creates its toolbar. Override this method if you need to
+     * add custom toolbar buttons.
+     * @param {HtmlEditor} editor
+     */
+    createToolbar : function(){
         
-        var settings=this;
-        ['xs','sm','md','lg'].map(function(size){
-            if (settings[size]) {
-                cfg.cls += ' col-' + size + '-' + settings[size];
-            }
-        });
+        Roo.log("create toolbars");
         
-        var inputblock = input;
+        this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
+        this.toolbars[0].render(this.toolbarContainer());
         
-        if (this.before || this.after) {
-            
-            inputblock = {
-                cls : 'input-group',
-                tag : 'span',
-                cn :  [] 
-            };
-            if (this.before) {
-                inputblock.cn.push({
-                    tag :'span',
-                    cls : 'input-group-addon',
-                    html : this.before
-                });
-            }
-            inputblock.cn.push(input);
-            if (this.after) {
-                inputblock.cn.push({
-                    tag :'span',
-                    cls : 'input-group-addon',
-                    html : this.after
-                });
-            }
-            
-        };
+        return;
         
+//        if (!editor.toolbars || !editor.toolbars.length) {
+//            editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
+//        }
+//        
+//        for (var i =0 ; i < editor.toolbars.length;i++) {
+//            editor.toolbars[i] = Roo.factory(
+//                    typeof(editor.toolbars[i]) == 'string' ?
+//                        { xtype: editor.toolbars[i]} : editor.toolbars[i],
+//                Roo.bootstrap.HtmlEditor);
+//            editor.toolbars[i].init(editor);
+//        }
+    },
+
+     
+    // private
+    onRender : function(ct, position)
+    {
+       // Roo.log("Call onRender: " + this.xtype);
+        var _t = this;
+        Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
+      
+        this.wrap = this.inputEl().wrap({
+            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
+        });
         
-        if (this.fieldLabel && this.fieldLabel.length) {
-            cfg.cn.push(fieldLabel);
+        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);
        
-        // normal bootstrap puts the input inside the label.
-        // however with our styled version - it has to go after the input.
-       
-        //lbl.cn.push(inputblock);
         
-        var lblwrap =  {
-            tag: 'span',
-            cls: 'radio' + inline,
-            cn: [
-                inputblock,
-                lbl
-            ]
-        };
+        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..
+        }
         
-        cfg.cn.push( lblwrap);
+    },
+
+    // private
+    onResize : function(w, h)
+    {
+        Roo.log('resize: ' +w + ',' + h );
+        Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
+        var ew = false;
+        var eh = false;
         
-        if(this.boxLabel){
-            lbl.cn.push({
-                tag: 'span',
-                html: this.boxLabel
-            })
+        if(this.inputEl() ){
+            if(typeof w == 'number'){
+                var aw = w - this.wrap.getFrameWidth('lr');
+                this.inputEl().setWidth(this.adjustWidth('textarea', aw));
+                ew = aw;
+            }
+            if(typeof h == 'number'){
+                 var tbh = -11;  // fixme it needs to tool bar size!
+                for (var i =0; i < this.toolbars.length;i++) {
+                    // fixme - ask toolbars for heights?
+                    tbh += this.toolbars[i].el.getHeight();
+                    //if (this.toolbars[i].footer) {
+                    //    tbh += this.toolbars[i].footer.el.getHeight();
+                    //}
+                }
+              
+                
+                
+                
+                
+                var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
+                ah -= 5; // knock a few pixes off for look..
+                this.inputEl().setHeight(this.adjustWidth('textarea', ah));
+                var eh = ah;
+            }
         }
-         
-        
-        return cfg;
+        Roo.log('onResize:' + [w,h,ew,eh].join(',') );
+        this.editorcore.onResize(ew,eh);
         
     },
-    
-    initEvents : function()
+
+    /**
+     * Toggles the editor between standard and source edit mode.
+     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     */
+    toggleSourceEdit : function(sourceEditMode)
     {
-//        Roo.bootstrap.CheckBox.superclass.initEvents.call(this);
+        this.editorcore.toggleSourceEdit(sourceEditMode);
         
-        this.inputEl().on('click', this.onClick,  this);
-        if (this.boxLabel) {
-            Roo.log('find label')
-            this.el.select('span.radio label span',true).first().on('click', this.onClick,  this);
+        if(this.editorcore.sourceEditMode){
+            Roo.log('editor - showing textarea');
+            
+//            Roo.log('in');
+//            Roo.log(this.syncValue());
+            this.syncValue();
+            this.inputEl().removeClass(['hide', 'x-hidden']);
+            this.inputEl().dom.removeAttribute('tabIndex');
+            this.inputEl().focus();
+        }else{
+            Roo.log('editor - hiding textarea');
+//            Roo.log('out')
+//            Roo.log(this.pushValue()); 
+            this.pushValue();
+            
+            this.inputEl().addClass(['hide', 'x-hidden']);
+            this.inputEl().dom.setAttribute('tabIndex', -1);
+            //this.deferFocus();
+        }
+         
+        if(this.resizable){
+            this.setSize(this.wrap.getSize());
         }
         
+        this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
     },
-    
-    inputEl: function ()
-    {
-        return this.el.select('input.roo-radio',true).first();
+    // private (for BoxComponent)
+    adjustSize : Roo.BoxComponent.prototype.adjustSize,
+
+    // private (for BoxComponent)
+    getResizeEl : function(){
+        return this.wrap;
     },
-    onClick : function()
-    {   
-        Roo.log("click");
-        this.setChecked(true);
+
+    // private (for BoxComponent)
+    getPositionEl : function(){
+        return this.wrap;
     },
-    
-    setChecked : function(state,suppressEvent)
-    {
-        if(state){
-            Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
-                v.dom.checked = false;
-            });
-        }
-        Roo.log(this.inputEl().dom);
-        this.checked = state;
-        this.inputEl().dom.checked = state;
+
+    // private
+    initEvents : function(){
+        this.originalValue = this.getValue();
+    },
+
+//    /**
+//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+//     * @method
+//     */
+//    markInvalid : Roo.emptyFn,
+//    /**
+//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+//     * @method
+//     */
+//    clearInvalid : Roo.emptyFn,
+
+    setValue : function(v){
+        Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
+        this.editorcore.pushValue();
+    },
+
+     
+    // private
+    deferFocus : function(){
+        this.focus.defer(10, this);
+    },
+
+    // doc'ed in Field
+    focus : function(){
+        this.editorcore.focus();
         
-        if(suppressEvent !== true){
-            this.fireEvent('check', this, state);
-        }
+    },
+      
+
+    // private
+    onDestroy : function(){
         
-        //this.inputEl().dom.value = state ? this.inputValue : this.valueOff;
         
-    },
-    
-    getGroupValue : function()
-    {
-        var value = '';
-        Roo.each(this.inputEl().up('form').select('input[name='+this.inputEl().dom.name+']', true).elements, function(v){
-            if(v.dom.checked == true){
-                value = v.dom.value;
+        
+        if(this.rendered){
+            
+            for (var i =0; i < this.toolbars.length;i++) {
+                // fixme - ask toolbars for heights?
+                this.toolbars[i].onDestroy();
             }
-        });
+            
+            this.wrap.dom.innerHTML = '';
+            this.wrap.remove();
+        }
+    },
+
+    // private
+    onFirstFocus : function(){
+        //Roo.log("onFirstFocus");
+        this.editorcore.onFirstFocus();
+         for (var i =0; i < this.toolbars.length;i++) {
+            this.toolbars[i].onFirstFocus();
+        }
         
-        return value;
     },
     
+    // private
+    syncValue : function()
+    {   
+        this.editorcore.syncValue();
+    },
+    
+    pushValue : function()
+    {   
+        this.editorcore.pushValue();
+    }
+     
+    
+    // hide stuff that is not compatible
+    /**
+     * @event blur
+     * @hide
+     */
+    /**
+     * @event change
+     * @hide
+     */
+    /**
+     * @event focus
+     * @hide
+     */
+    /**
+     * @event specialkey
+     * @hide
+     */
     /**
-     * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
-     * @return {Mixed} value The field value
+     * @cfg {String} fieldClass @hide
+     */
+    /**
+     * @cfg {String} focusClass @hide
+     */
+    /**
+     * @cfg {String} autoCreate @hide
+     */
+    /**
+     * @cfg {String} inputType @hide
+     */
+    /**
+     * @cfg {String} invalidClass @hide
+     */
+    /**
+     * @cfg {String} invalidText @hide
+     */
+    /**
+     * @cfg {String} msgFx @hide
+     */
+    /**
+     * @cfg {String} validateOnBlur @hide
      */
-    getValue : function(){
-        return this.getGroupValue();
-    }
-    
 });
-
-//<script type="text/javascript">
-
-/*
- * Based  Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- * LGPL
- *
- */
  
+    
+   
+   
+   
+      
+Roo.namespace('Roo.bootstrap.htmleditor');
 /**
- * @class Roo.HtmlEditorCore
- * @extends Roo.Component
- * Provides a the editing component for the HTML editors in Roo. (bootstrap and Roo.form)
+ * @class Roo.bootstrap.HtmlEditorToolbar1
+ * Basic Toolbar
+ * 
+ * Usage:
  *
- * any element that has display set to 'none' can cause problems in Safari and Firefox.<br/><br/>
+ new Roo.bootstrap.HtmlEditor({
+    ....
+    toolbars : [
+        new Roo.bootstrap.HtmlEditorToolbar1({
+            disable : { fonts: 1 , format: 1, ..., ... , ...],
+            btns : [ .... ]
+        })
+    }
+     
+ * 
+ * @cfg {Object} disable List of elements to disable..
+ * @cfg {Array} btns List of additional buttons.
+ * 
+ * 
+ * NEEDS Extra CSS? 
+ * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
  */
-
-Roo.HtmlEditorCore = function(config){
-    
-    
-    Roo.HtmlEditorCore.superclass.constructor.call(this, config);
+Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
+{
     
+    Roo.apply(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
-        
+    // default disabled, based on 'good practice'..
+    this.disable = this.disable || {};
+    Roo.applyIf(this.disable, {
+        fontSize : true,
+        colors : true,
+        specialElements : true
     });
+    Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
     
-    // 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} 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.editor = config.editor;
+    this.editorcore = config.editor.editorcore;
     
-    /**
-     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
-     * 
-     */
-    stylesheets: false,
+    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
     
-    // id of frame..
-    frameId: false,
+    //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
+    // dont call parent... till later.
+}
+Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,  {
+     
+    bar : true,
     
-    // private properties
-    validationEvent : false,
-    deferHeight: true,
-    initialized : false,
-    activated : false,
-    sourceEditMode : false,
-    onFocus : Roo.emptyFn,
-    iframePad:3,
-    hideMode:'offsets',
+    editor : false,
+    editorcore : false,
     
-    clearUp: true,
     
-    // blacklist + whitelisted elements..
-    black: false,
-    white: false,
-     
+    formats : [
+        "p" ,  
+        "h1","h2","h3","h4","h5","h6", 
+        "pre", "code", 
+        "abbr", "acronym", "address", "cite", "samp", "var",
+        'div','span'
+    ],
     
-
-    /**
-     * 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 = '';
+    onRender : function(ct, position)
+    {
+       // Roo.log("Call onRender: " + this.xtype);
         
-        // 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.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
+       Roo.log(this.el);
+       this.el.dom.style.marginBottom = '0';
+       var _this = this;
+       var editorcore = this.editorcore;
+       var editor= this.editor;
+       
+       var children = [];
+       var btn = function(id,cmd , toggle, handler){
+       
+            var  event = toggle ? 'toggle' : 'click';
+       
+            var a = {
+                size : 'sm',
+                xtype: 'Button',
+                xns: Roo.bootstrap,
+                glyphicon : id,
+                cmd : id || cmd,
+                enableToggle:toggle !== false,
+                //html : 'submit'
+                pressed : toggle ? false : null,
+                listeners : {}
+            };
+            a.listeners[toggle ? 'toggle' : 'click'] = function() {
+                handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd ||  id);
+            };
+            children.push(a);
+            return a;
+       }
+        
+        var style = {
+                xtype: 'Button',
+                size : 'sm',
+                xns: Roo.bootstrap,
+                glyphicon : 'font',
+                //html : 'submit'
+                menu : {
+                    xtype: 'Menu',
+                    xns: Roo.bootstrap,
+                    items:  []
+                }
+        };
+        Roo.each(this.formats, function(f) {
+            style.menu.items.push({
+                xtype :'MenuItem',
+                xns: Roo.bootstrap,
+                html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
+                tagname : f,
+                listeners : {
+                    click : function()
+                    {
+                        editorcore.insertTag(this.tagname);
+                        editor.focus();
+                    }
+                }
+                
             });
+        });
+         children.push(style);   
             
-            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 { 
+        btn('bold',false,true);
+        btn('italic',false,true);
+        btn('align-left', 'justifyleft',true);
+        btn('align-center', 'justifycenter',true);
+        btn('align-right' , 'justifyright',true);
+        btn('link', false, false, function(btn) {
+            //Roo.log("create link?");
+            var url = prompt(this.createLinkText, this.defaultLinkValue);
+            if(url && url != 'http:/'+'/'){
+                this.editorcore.relayCmd('createlink', url);
+            }
+        }),
+        btn('list','insertunorderedlist',true);
+        btn('pencil', false,true, function(btn){
+                Roo.log(this);
+                
+                this.toggleSourceEdit(btn.pressed);
+        });
+        /*
+        var cog = {
+                xtype: 'Button',
+                size : 'sm',
+                xns: Roo.bootstrap,
+                glyphicon : 'cog',
+                //html : 'submit'
+                menu : {
+                    xtype: 'Menu',
+                    xns: Roo.bootstrap,
+                    items:  []
+                }
+        };
+        
+        cog.menu.items.push({
+            xtype :'MenuItem',
+            xns: Roo.bootstrap,
+            html : Clean styles,
+            tagname : f,
+            listeners : {
+                click : function()
+                {
+                    editorcore.insertTag(this.tagname);
+                    editor.focus();
+                }
+            }
             
-        }
+        });
+       */
         
-        st +=  '<style type="text/css">' +
-            'IMG { cursor: pointer } ' +
-        '</style>';
-
+         
+       this.xtype = 'NavSimplebar';
         
-        return '<html><head>' + st  +
-            //<style type="text/css">' +
-            //'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}' +
-            //'</style>' +
-            ' </head><body class="roo-htmleditor-body"></body></html>';
+        for(var i=0;i< children.length;i++) {
+            
+            this.buttons.add(this.addxtypeChild(children[i]));
+            
+        }
+        
+        editor.on('editorevent', this.updateToolbar, this);
     },
-
-    // private
-    onRender : function(ct, position)
+    onBtnClick : function(id)
     {
-        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.editorcore.relayCmd(id);
+       this.editorcore.focus();
+    },
+    
+    /**
+     * Protected method that will not generally be called directly. It triggers
+     * a toolbar update by reading the markup state of the current selection in the editor.
+     */
+    updateToolbar: function(){
+
+        if(!this.editorcore.activated){
+            this.editor.onFirstFocus(); // is this neeed?
+            return;
+        }
+
+        var btns = this.buttons; 
+        var doc = this.editorcore.doc;
+        btns.get('bold').setActive(doc.queryCommandState('bold'));
+        btns.get('italic').setActive(doc.queryCommandState('italic'));
+        //btns.get('underline').setActive(doc.queryCommandState('underline'));
         
+        btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
+        btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
+        btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
         
+        //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
+        btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
+         /*
         
-        if(Roo.isIE){ // fix IE 1px bogus margin
-            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
+        var ans = this.editorcore.getAllAncestors();
+        if (this.formatCombo) {
+            
+            
+            var store = this.formatCombo.store;
+            this.formatCombo.setValue("");
+            for (var i =0; i < ans.length;i++) {
+                if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
+                    // select it..
+                    this.formatCombo.setValue(ans[i].tagName.toLowerCase());
+                    break;
+                }
+            }
         }
-       
-        
-        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();
+        // hides menus... - so this cant be on a menu...
+        Roo.bootstrap.MenuMgr.hideAll();
+        */
+        Roo.bootstrap.MenuMgr.hideAll();
+        //this.editorsyncValue();
+    },
+    onFirstFocus: function() {
+        this.buttons.each(function(item){
+           item.enable();
+        });
+    },
+    toggleSourceEdit : function(sourceEditMode){
         
-        this.doc.designMode = 'on';
+          
+        if(sourceEditMode){
+            Roo.log("disabling buttons");
+           this.buttons.each( function(item){
+                if(item.cmd != 'pencil'){
+                    item.disable();
+                }
+            });
+          
+        }else{
+            Roo.log("enabling buttons");
+            if(this.editorcore.initialized){
+                this.buttons.each( function(item){
+                    item.enable();
+                });
+            }
+            
+        }
+        Roo.log("calling toggole on editor");
+        // tell the editor that it's been pressed..
+        this.editor.toggleSourceEdit(sourceEditMode);
        
-        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';
-            }
-        }
-        
+
+
+/**
+ * @class Roo.bootstrap.Table.AbstractSelectionModel
+ * @extends Roo.util.Observable
+ * Abstract base class for grid SelectionModels.  It provides the interface that should be
+ * implemented by descendant classes.  This class should not be directly instantiated.
+ * @constructor
+ */
+Roo.bootstrap.Table.AbstractSelectionModel = function(){
+    this.locked = false;
+    Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
+};
+
+
+Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable,  {
+    /** @ignore Called by the grid automatically. Do not call directly. */
+    init : function(grid){
+        this.grid = grid;
+        this.initEvents();
     },
 
     /**
-     * Toggles the editor between standard and source edit mode.
-     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     * Locks the selections.
      */
-    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();
-        }
-        //this.setSize(this.owner.wrap.getSize());
-        //this.fireEvent('editmodechange', this, this.sourceEditMode);
+    lock : function(){
+        this.locked = true;
     },
 
-    
-  
-
     /**
-     * Protected method that will not generally be called directly. If you need/want
-     * custom HTML cleanup, this is the method you should override.
-     * @param {String} html The HTML to be cleaned
-     * return {String} The cleaned HTML
+     * Unlocks the selections.
      */
-    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;
+    unlock : function(){
+        this.locked = false;
     },
 
     /**
-     * HTML Editor -> Textarea
-     * Protected method that will not generally be called directly. Syncs the contents
-     * of the editor iframe with the textarea.
+     * Returns true if the selections are locked.
+     * @return {Boolean}
      */
-    syncValue : function(){
-        if(this.initialized){
-            var bd = (this.doc.body || this.doc.documentElement);
-            //this.cleanUpPaste(); -- this is done else where and causes havoc..
-            var html = bd.innerHTML;
-            if(Roo.isSafari){
-                var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
-                var m = bs ? bs.match(/text-align:(.*?);/i) : false;
-                if(m && m[1]){
-                    html = '<div style="'+m[0]+'">' + html + '</div>';
-                }
-            }
-            html = this.cleanHtml(html);
-            // fix up the special chars.. normaly like back quotes in word...
-            // however we do not want to do this with chinese..
-            html = html.replace(/([\x80-\uffff])/g, function (a, b) {
-                var cc = b.charCodeAt();
-                if (
-                    (cc >= 0x4E00 && cc < 0xA000 ) ||
-                    (cc >= 0x3400 && cc < 0x4E00 ) ||
-                    (cc >= 0xf900 && cc < 0xfb00 )
-                ) {
-                        return b;
-                }
-                return "&#"+cc+";" 
-            });
-            if(this.owner.fireEvent('beforesync', this, html) !== false){
-                this.el.dom.value = html;
-                this.owner.fireEvent('sync', this, html);
-            }
-        }
-    },
+    isLocked : function(){
+        return this.locked;
+    }
+});
+/**
+ * @extends Roo.bootstrap.Table.AbstractSelectionModel
+ * @class Roo.bootstrap.Table.RowSelectionModel
+ * The default SelectionModel used by {@link Roo.bootstrap.Table}.
+ * It supports multiple selections and keyboard selection/navigation. 
+ * @constructor
+ * @param {Object} config
+ */
+
+Roo.bootstrap.Table.RowSelectionModel = function(config){
+    Roo.apply(this, config);
+    this.selections = new Roo.util.MixedCollection(false, function(o){
+        return o.id;
+    });
+
+    this.last = false;
+    this.lastActive = false;
+
+    this.addEvents({
+        /**
+            * @event selectionchange
+            * Fires when the selection changes
+            * @param {SelectionModel} this
+            */
+           "selectionchange" : true,
+        /**
+            * @event afterselectionchange
+            * Fires after the selection changes (eg. by key press or clicking)
+            * @param {SelectionModel} this
+            */
+           "afterselectionchange" : true,
+        /**
+            * @event beforerowselect
+            * Fires when a row is selected being selected, return false to cancel.
+            * @param {SelectionModel} this
+            * @param {Number} rowIndex The selected index
+            * @param {Boolean} keepExisting False if other selections will be cleared
+            */
+           "beforerowselect" : true,
+        /**
+            * @event rowselect
+            * Fires when a row is selected.
+            * @param {SelectionModel} this
+            * @param {Number} rowIndex The selected index
+            * @param {Roo.data.Record} r The record
+            */
+           "rowselect" : true,
+        /**
+            * @event rowdeselect
+            * Fires when a row is deselected.
+            * @param {SelectionModel} this
+            * @param {Number} rowIndex The selected index
+            */
+        "rowdeselect" : true
+    });
+    Roo.bootstrap.Table.RowSelectionModel.superclass.constructor.call(this);
+    this.locked = false;
+};
 
+Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSelectionModel,  {
     /**
-     * Protected method that will not generally be called directly. Pushes the value of the textarea
-     * into the iframe editor.
+     * @cfg {Boolean} singleSelect
+     * True to allow selection of only one row at a time (defaults to false)
      */
-    pushValue : function(){
-        if(this.initialized){
-            var v = this.el.dom.value.trim();
-            
-//            if(v.length < 1){
-//                v = '&#160;';
-//            }
-            
-            if(this.owner.fireEvent('beforepush', this, v) !== false){
-                var d = (this.doc.body || this.doc.documentElement);
-                d.innerHTML = v;
-                this.cleanUpPaste();
-                this.el.dom.value = d.innerHTML;
-                this.owner.fireEvent('push', this, v);
-            }
-        }
-    },
+    singleSelect : false,
 
     // private
-    deferFocus : function(){
-        this.focus.defer(10, this);
-    },
+    initEvents : function(){
 
-    // doc'ed in Field
-    focus : function(){
-        if(this.win && !this.sourceEditMode){
-            this.win.focus();
-        }else{
-            this.el.focus();
+        if(!this.grid.enableDragDrop && !this.grid.enableDrag){
+            this.grid.on("mousedown", this.handleMouseDown, this);
+        }else{ // allow click to work like normal
+            this.grid.on("rowclick", this.handleDragableRowClick, this);
         }
+
+        this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), {
+            "up" : function(e){
+                if(!e.shiftKey){
+                    this.selectPrevious(e.shiftKey);
+                }else if(this.last !== false && this.lastActive !== false){
+                    var last = this.last;
+                    this.selectRange(this.last,  this.lastActive-1);
+                    this.grid.getView().focusRow(this.lastActive);
+                    if(last !== false){
+                        this.last = last;
+                    }
+                }else{
+                    this.selectFirstRow();
+                }
+                this.fireEvent("afterselectionchange", this);
+            },
+            "down" : function(e){
+                if(!e.shiftKey){
+                    this.selectNext(e.shiftKey);
+                }else if(this.last !== false && this.lastActive !== false){
+                    var last = this.last;
+                    this.selectRange(this.last,  this.lastActive+1);
+                    this.grid.getView().focusRow(this.lastActive);
+                    if(last !== false){
+                        this.last = last;
+                    }
+                }else{
+                    this.selectFirstRow();
+                }
+                this.fireEvent("afterselectionchange", this);
+            },
+            scope: this
+        });
+
+        var view = this.grid.view;
+        view.on("refresh", this.onRefresh, this);
+        view.on("rowupdated", this.onRowUpdated, this);
+        view.on("rowremoved", this.onRemove, this);
     },
-    
-    assignDocWin: function()
-    {
-        var iframe = this.iframe;
-        
-         if(Roo.isIE){
-            this.doc = iframe.contentWindow.document;
-            this.win = iframe.contentWindow;
-        } else {
-//            if (!Roo.get(this.frameId)) {
-//                return;
-//            }
-//            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
-//            this.win = Roo.get(this.frameId).dom.contentWindow;
-            
-            if (!Roo.get(this.frameId) && !iframe.contentDocument) {
-                return;
+
+    // private
+    onRefresh : function(){
+        var ds = this.grid.dataSource, i, v = this.grid.view;
+        var s = this.selections;
+        s.each(function(r){
+            if((i = ds.indexOfId(r.id)) != -1){
+                v.onRowSelect(i);
+            }else{
+                s.remove(r);
             }
-            
-            this.doc = (iframe.contentDocument || Roo.get(this.frameId).dom.document);
-            this.win = (iframe.contentWindow || Roo.get(this.frameId).dom.contentWindow);
-        }
+        });
     },
-    
+
     // private
-    initEditor : function(){
-        //console.log("INIT EDITOR");
-        this.assignDocWin();
-        
-        
-        
-        this.doc.designMode="on";
-        this.doc.open();
-        this.doc.write(this.getDocMarkup());
-        this.doc.close();
-        
-        var dbody = (this.doc.body || this.doc.documentElement);
-        //var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
-        // this copies styles from the containing element into thsi one..
-        // not sure why we need all of this..
-        //var ss = this.el.getStyles('font-size', 'background-image', 'background-repeat');
-        
-        //var ss = this.el.getStyles( 'background-image', 'background-repeat');
-        //ss['background-attachment'] = 'fixed'; // w3c
-        dbody.bgProperties = 'fixed'; // ie
-        //Roo.DomHelper.applyStyles(dbody, ss);
-        Roo.EventManager.on(this.doc, {
-            //'mousedown': this.onEditorEvent,
-            'mouseup': this.onEditorEvent,
-            'dblclick': this.onEditorEvent,
-            'click': this.onEditorEvent,
-            'keyup': this.onEditorEvent,
-            buffer:100,
-            scope: this
-        });
-        if(Roo.isGecko){
-            Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
+    onRemove : function(v, index, r){
+        this.selections.remove(r);
+    },
+
+    // private
+    onRowUpdated : function(v, index, r){
+        if(this.isSelected(r)){
+            v.onRowSelect(index);
         }
-        if(Roo.isIE || Roo.isSafari || Roo.isOpera){
-            Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
+    },
+
+    /**
+     * Select records.
+     * @param {Array} records The records to select
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectRecords : function(records, keepExisting){
+        if(!keepExisting){
+            this.clearSelections();
         }
-        this.initialized = true;
+        var ds = this.grid.dataSource;
+        for(var i = 0, len = records.length; i < len; i++){
+            this.selectRow(ds.indexOf(records[i]), true);
+        }
+    },
 
-        this.owner.fireEvent('initialize', this);
-        this.pushValue();
+    /**
+     * Gets the number of selected rows.
+     * @return {Number}
+     */
+    getCount : function(){
+        return this.selections.length;
     },
 
-    // private
-    onDestroy : function(){
-        
-        
-        
-        if(this.rendered){
-            
-            //for (var i =0; i < this.toolbars.length;i++) {
-            //    // fixme - ask toolbars for heights?
-            //    this.toolbars[i].onDestroy();
-           // }
-            
-            //this.wrap.dom.innerHTML = '';
-            //this.wrap.remove();
-        }
+    /**
+     * Selects the first row in the grid.
+     */
+    selectFirstRow : function(){
+        this.selectRow(0);
     },
 
-    // private
-    onFirstFocus : function(){
-        
-        this.assignDocWin();
-        
-        
-        this.activated = true;
-         
-    
-        if(Roo.isGecko){ // prevent silly gecko errors
-            this.win.focus();
-            var s = this.win.getSelection();
-            if(!s.focusNode || s.focusNode.nodeType != 3){
-                var r = s.getRangeAt(0);
-                r.selectNodeContents((this.doc.body || this.doc.documentElement));
-                r.collapse(true);
-                this.deferFocus();
-            }
-            try{
-                this.execCmd('useCSS', true);
-                this.execCmd('styleWithCSS', false);
-            }catch(e){}
+    /**
+     * Select the last row.
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectLastRow : function(keepExisting){
+        this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting);
+    },
+
+    /**
+     * Selects the row immediately following the last selected row.
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectNext : function(keepExisting){
+        if(this.last !== false && (this.last+1) < this.grid.dataSource.getCount()){
+            this.selectRow(this.last+1, keepExisting);
+            this.grid.getView().focusRow(this.last);
         }
-        this.owner.fireEvent('activate', this);
     },
 
-    // private
-    adjustFont: function(btn){
-        var adjust = btn.cmd == 'increasefontsize' ? 1 : -1;
-        //if(Roo.isSafari){ // safari
-        //    adjust *= 2;
-       // }
-        var v = parseInt(this.doc.queryCommandValue('FontSize')|| 3, 10);
-        if(Roo.isSafari){ // safari
-            var sm = { 10 : 1, 13: 2, 16:3, 18:4, 24: 5, 32:6, 48: 7 };
-            v =  (v < 10) ? 10 : v;
-            v =  (v > 48) ? 48 : v;
-            v = typeof(sm[v]) == 'undefined' ? 1 : sm[v];
-            
+    /**
+     * Selects the row that precedes the last selected row.
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectPrevious : function(keepExisting){
+        if(this.last){
+            this.selectRow(this.last-1, keepExisting);
+            this.grid.getView().focusRow(this.last);
         }
-        
-        
-        v = Math.max(1, v+adjust);
-        
-        this.execCmd('FontSize', v  );
     },
 
-    onEditorEvent : function(e)
-    {
-        this.owner.fireEvent('editorevent', this, e);
-      //  this.updateToolbar();
-        this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
+    /**
+     * Returns the selected records
+     * @return {Array} Array of selected records
+     */
+    getSelections : function(){
+        return [].concat(this.selections.items);
     },
 
-    insertTag : function(tg)
-    {
-        // could be a bit smarter... -> wrap the current selected tRoo..
-        if (tg.toLowerCase() == 'span' || tg.toLowerCase() == 'code') {
-            
-            range = this.createRange(this.getSelection());
-            var wrappingNode = this.doc.createElement(tg.toLowerCase());
-            wrappingNode.appendChild(range.extractContents());
-            range.insertNode(wrappingNode);
+    /**
+     * Returns the first selected record.
+     * @return {Record}
+     */
+    getSelected : function(){
+        return this.selections.itemAt(0);
+    },
 
-            return;
-            
-            
-            
+
+    /**
+     * Clears all selections.
+     */
+    clearSelections : function(fast){
+        if(this.locked) return;
+        if(fast !== true){
+            var ds = this.grid.dataSource;
+            var s = this.selections;
+            s.each(function(r){
+                this.deselectRow(ds.indexOfId(r.id));
+            }, this);
+            s.clear();
+        }else{
+            this.selections.clear();
         }
-        this.execCmd("formatblock",   tg);
-        
+        this.last = false;
     },
-    
-    insertText : function(txt)
-    {
-        
-        
-        var range = this.createRange();
-        range.deleteContents();
-               //alert(Sender.getAttribute('label'));
-               
-        range.insertNode(this.doc.createTextNode(txt));
-    } ,
-    
-     
+
 
     /**
-     * Executes a Midas editor command on the editor document and performs necessary focus and
-     * toolbar updates. <b>This should only be called after the editor is initialized.</b>
-     * @param {String} cmd The Midas command
-     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     * Selects all rows.
      */
-    relayCmd : function(cmd, value){
-        this.win.focus();
-        this.execCmd(cmd, value);
-        this.owner.fireEvent('editorevent', this);
-        //this.updateToolbar();
-        this.owner.deferFocus();
+    selectAll : function(){
+        if(this.locked) return;
+        this.selections.clear();
+        for(var i = 0, len = this.grid.dataSource.getCount(); i < len; i++){
+            this.selectRow(i, true);
+        }
     },
 
     /**
-     * Executes a Midas editor command directly on the editor document.
-     * For visual commands, you should use {@link #relayCmd} instead.
-     * <b>This should only be called after the editor is initialized.</b>
-     * @param {String} cmd The Midas command
-     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     * Returns True if there is a selection.
+     * @return {Boolean}
+     */
+    hasSelection : function(){
+        return this.selections.length > 0;
+    },
+
+    /**
+     * Returns True if the specified row is selected.
+     * @param {Number/Record} record The record or index of the record to check
+     * @return {Boolean}
      */
-    execCmd : function(cmd, value){
-        this.doc.execCommand(cmd, false, value === undefined ? null : value);
-        this.syncValue();
+    isSelected : function(index){
+        var r = typeof index == "number" ? this.grid.dataSource.getAt(index) : index;
+        return (r && this.selections.key(r.id) ? true : false);
     },
-   
+
     /**
-     * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
-     * to insert tRoo.
-     * @param {String} text | dom node.. 
+     * Returns True if the specified record id is selected.
+     * @param {String} id The id of record to check
+     * @return {Boolean}
      */
-    insertAtCursor : function(text)
-    {
-        
-        
-        
-        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();
-            
-            
-            // from jquery ui (MIT licenced)
-            var range, node;
-            var win = this.win;
-            
-            if (win.getSelection && win.getSelection().getRangeAt) {
-                range = win.getSelection().getRangeAt(0);
-                node = typeof(text) == 'string' ? range.createContextualFragment(text) : text;
-                range.insertNode(node);
-            } else if (win.document.selection && win.document.selection.createRange) {
-                // no firefox support
-                var txt = typeof(text) == 'string' ? text : text.outerHTML;
-                win.document.selection.createRange().pasteHTML(txt);
-            } else {
-                // no firefox support
-                var txt = typeof(text) == 'string' ? text : text.outerHTML;
-                this.execCmd('InsertHTML', txt);
-            } 
-            
-            this.syncValue();
-            
-            this.deferFocus();
-        }
+    isIdSelected : function(id){
+        return (this.selections.key(id) ? true : false);
     },
- // private
-    mozKeyPress : function(e){
-        if(e.ctrlKey){
-            var c = e.getCharCode(), cmd;
-          
-            if(c > 0){
-                c = String.fromCharCode(c).toLowerCase();
-                switch(c){
-                    case 'b':
-                        cmd = 'bold';
-                        break;
-                    case 'i':
-                        cmd = 'italic';
-                        break;
-                    
-                    case 'u':
-                        cmd = 'underline';
-                        break;
-                    
-                    case 'v':
-                        this.cleanUpPaste.defer(100, this);
-                        return;
-                        
-                }
-                if(cmd){
-                    this.win.focus();
-                    this.execCmd(cmd);
-                    this.deferFocus();
-                    e.preventDefault();
-                }
-                
+
+    // private
+    handleMouseDown : function(e, t){
+        var view = this.grid.getView(), rowIndex;
+        if(this.isLocked() || (rowIndex = view.findRowIndex(t)) === false){
+            return;
+        };
+        if(e.shiftKey && this.last !== false){
+            var last = this.last;
+            this.selectRange(last, rowIndex, e.ctrlKey);
+            this.last = last; // reset the last
+            view.focusRow(rowIndex);
+        }else{
+            var isSelected = this.isSelected(rowIndex);
+            if(e.button !== 0 && isSelected){
+                view.focusRow(rowIndex);
+            }else if(e.ctrlKey && isSelected){
+                this.deselectRow(rowIndex);
+            }else if(!isSelected){
+                this.selectRow(rowIndex, e.button === 0 && (e.ctrlKey || e.shiftKey));
+                view.focusRow(rowIndex);
             }
         }
+        this.fireEvent("afterselectionchange", this);
     },
-
     // private
-    fixKeys : function(){ // load time branching for fastest keydown performance
-        if(Roo.isIE){
-            return function(e){
-                var k = e.getKey(), r;
-                if(k == e.TAB){
-                    e.stopEvent();
-                    r = this.doc.selection.createRange();
-                    if(r){
-                        r.collapse(true);
-                        r.pasteHTML('&#160;&#160;&#160;&#160;');
-                        this.deferFocus();
-                    }
-                    return;
-                }
-                
-                if(k == e.ENTER){
-                    r = this.doc.selection.createRange();
-                    if(r){
-                        var target = r.parentElement();
-                        if(!target || target.tagName.toLowerCase() != 'li'){
-                            e.stopEvent();
-                            r.pasteHTML('<br />');
-                            r.collapse(false);
-                            r.select();
-                        }
-                    }
-                }
-                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
-                
-                
-            };
-        }else if(Roo.isOpera){
-            return function(e){
-                var k = e.getKey();
-                if(k == e.TAB){
-                    e.stopEvent();
-                    this.win.focus();
-                    this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
-                    this.deferFocus();
-                }
-                if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
-                
-            };
-        }else if(Roo.isSafari){
-            return function(e){
-                var k = e.getKey();
-                
-                if(k == e.TAB){
-                    e.stopEvent();
-                    this.execCmd('InsertText','\t');
-                    this.deferFocus();
-                    return;
-                }
-               if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
-                    this.cleanUpPaste.defer(100, this);
-                    return;
-                }
-                
-             };
-        }
-    }(),
-    
-    getAllAncestors: function()
+    handleDragableRowClick :  function(grid, rowIndex, e) 
     {
-        var p = this.getSelectedNode();
-        var a = [];
-        if (!p) {
-            a.push(p); // push blank onto stack..
-            p = this.getParentElement();
-        }
-        
-        
-        while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
-            a.push(p);
-            p = p.parentNode;
+        if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
+            this.selectRow(rowIndex, false);
+            grid.view.focusRow(rowIndex);
+             this.fireEvent("afterselectionchange", this);
         }
-        a.push(this.doc.body);
-        return a;
     },
-    lastSel : false,
-    lastSelNode : false,
-    
     
-    getSelection : function() 
-    {
-        this.assignDocWin();
-        return Roo.isIE ? this.doc.selection : this.win.getSelection();
+    /**
+     * Selects multiple rows.
+     * @param {Array} rows Array of the indexes of the row to select
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectRows : function(rows, keepExisting){
+        if(!keepExisting){
+            this.clearSelections();
+        }
+        for(var i = 0, len = rows.length; i < len; i++){
+            this.selectRow(rows[i], true);
+        }
     },
-    
-    getSelectedNode: function() 
-    {
-        // this may only work on Gecko!!!
-        
-        // should we cache this!!!!
-        
-        
-        
-         
-        var range = this.createRange(this.getSelection()).cloneRange();
-        
-        if (Roo.isIE) {
-            var parent = range.parentElement();
-            while (true) {
-                var testRange = range.duplicate();
-                testRange.moveToElementText(parent);
-                if (testRange.inRange(range)) {
-                    break;
-                }
-                if ((parent.nodeType != 1) || (parent.tagName.toLowerCase() == 'body')) {
-                    break;
-                }
-                parent = parent.parentElement;
+
+    /**
+     * Selects a range of rows. All rows in between startRow and endRow are also selected.
+     * @param {Number} startRow The index of the first row in the range
+     * @param {Number} endRow The index of the last row in the range
+     * @param {Boolean} keepExisting (optional) True to retain existing selections
+     */
+    selectRange : function(startRow, endRow, keepExisting){
+        if(this.locked) return;
+        if(!keepExisting){
+            this.clearSelections();
+        }
+        if(startRow <= endRow){
+            for(var i = startRow; i <= endRow; i++){
+                this.selectRow(i, true);
+            }
+        }else{
+            for(var i = startRow; i >= endRow; i--){
+                this.selectRow(i, true);
             }
-            return parent;
         }
-        
-        // is ancestor a text element.
-        var ac =  range.commonAncestorContainer;
-        if (ac.nodeType == 3) {
-            ac = ac.parentNode;
+    },
+
+    /**
+     * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
+     * @param {Number} startRow The index of the first row in the range
+     * @param {Number} endRow The index of the last row in the range
+     */
+    deselectRange : function(startRow, endRow, preventViewNotify){
+        if(this.locked) return;
+        for(var i = startRow; i <= endRow; i++){
+            this.deselectRow(i, preventViewNotify);
         }
-        
-        var ar = ac.childNodes;
-         
-        var nodes = [];
-        var other_nodes = [];
-        var has_other_nodes = false;
-        for (var i=0;i<ar.length;i++) {
-            if ((ar[i].nodeType == 3) && (!ar[i].data.length)) { // empty text ? 
-                continue;
+    },
+
+    /**
+     * Selects a row.
+     * @param {Number} row The index of the row to select
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectRow : function(index, keepExisting, preventViewNotify){
+        if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) return;
+        if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
+            if(!keepExisting || this.singleSelect){
+                this.clearSelections();
             }
-            // fullly contained node.
-            
-            if (this.rangeIntersectsNode(range,ar[i]) && this.rangeCompareNode(range,ar[i]) == 3) {
-                nodes.push(ar[i]);
-                continue;
+            var r = this.grid.dataSource.getAt(index);
+            this.selections.add(r);
+            this.last = this.lastActive = index;
+            if(!preventViewNotify){
+                this.grid.getView().onRowSelect(index);
             }
-            
-            // probably selected..
-            if ((ar[i].nodeType == 1) && this.rangeIntersectsNode(range,ar[i]) && (this.rangeCompareNode(range,ar[i]) > 0)) {
-                other_nodes.push(ar[i]);
-                continue;
+            this.fireEvent("rowselect", this, index, r);
+            this.fireEvent("selectionchange", this);
+        }
+    },
+
+    /**
+     * Deselects a row.
+     * @param {Number} row The index of the row to deselect
+     */
+    deselectRow : function(index, preventViewNotify){
+        if(this.locked) return;
+        if(this.last == index){
+            this.last = false;
+        }
+        if(this.lastActive == index){
+            this.lastActive = false;
+        }
+        var r = this.grid.dataSource.getAt(index);
+        this.selections.remove(r);
+        if(!preventViewNotify){
+            this.grid.getView().onRowDeselect(index);
+        }
+        this.fireEvent("rowdeselect", this, index);
+        this.fireEvent("selectionchange", this);
+    },
+
+    // private
+    restoreLast : function(){
+        if(this._last){
+            this.last = this._last;
+        }
+    },
+
+    // private
+    acceptsNav : function(row, col, cm){
+        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    },
+
+    // private
+    onEditorKey : function(field, e){
+        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
+        if(k == e.TAB){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
             }
-            // outer..
-            if (!this.rangeIntersectsNode(range,ar[i])|| (this.rangeCompareNode(range,ar[i]) == 0))  {
-                continue;
+        }else if(k == e.ENTER && !e.ctrlKey){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
             }
-            
-            
-            has_other_nodes = true;
+        }else if(k == e.ESC){
+            ed.cancelEdit();
         }
-        if (!nodes.length && other_nodes.length) {
-            nodes= other_nodes;
+        if(newCell){
+            g.startEditing(newCell[0], newCell[1]);
         }
-        if (has_other_nodes || !nodes.length || (nodes.length > 1)) {
-            return false;
+    }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+/**
+ * @class Roo.bootstrap.PagingToolbar
+ * @extends Roo.bootstrap.NavSimplebar
+ * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
+ * @constructor
+ * Create a new PagingToolbar
+ * @param {Object} config The config object
+ * @param {Roo.data.Store} store
+ */
+Roo.bootstrap.PagingToolbar = function(config)
+{
+    // old args format still supported... - xtype is prefered..
+        // created from xtype...
+    
+    this.ds = config.dataSource;
+    
+    if (config.store && !this.ds) {
+        this.store= Roo.factory(config.store, Roo.data);
+        this.ds = this.store;
+        this.ds.xmodule = this.xmodule || false;
+    }
+    
+    this.toolbarItems = [];
+    if (config.items) {
+        this.toolbarItems = config.items;
+    }
+    
+    Roo.bootstrap.PagingToolbar.superclass.constructor.call(this, config);
+    
+    this.cursor = 0;
+    
+    if (this.ds) { 
+        this.bind(this.ds);
+    }
+    
+    this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
+    
+};
+
+Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
+    /**
+     * @cfg {Roo.data.Store} dataSource
+     * The underlying data store providing the paged data
+     */
+    /**
+     * @cfg {String/HTMLElement/Element} container
+     * container The id or element that will contain the toolbar
+     */
+    /**
+     * @cfg {Boolean} displayInfo
+     * True to display the displayMsg (defaults to false)
+     */
+    /**
+     * @cfg {Number} pageSize
+     * The number of records to display per page (defaults to 20)
+     */
+    pageSize: 20,
+    /**
+     * @cfg {String} displayMsg
+     * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
+     */
+    displayMsg : 'Displaying {0} - {1} of {2}',
+    /**
+     * @cfg {String} emptyMsg
+     * The message to display when no records are found (defaults to "No data to display")
+     */
+    emptyMsg : 'No data to display',
+    /**
+     * Customizable piece of the default paging text (defaults to "Page")
+     * @type String
+     */
+    beforePageText : "Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "of %0")
+     * @type String
+     */
+    afterPageText : "of {0}",
+    /**
+     * Customizable piece of the default paging text (defaults to "First Page")
+     * @type String
+     */
+    firstText : "First Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Previous Page")
+     * @type String
+     */
+    prevText : "Previous Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Next Page")
+     * @type String
+     */
+    nextText : "Next Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Last Page")
+     * @type String
+     */
+    lastText : "Last Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Refresh")
+     * @type String
+     */
+    refreshText : "Refresh",
+
+    buttons : false,
+    // private
+    onRender : function(ct, position) 
+    {
+        Roo.bootstrap.PagingToolbar.superclass.onRender.call(this, ct, position);
+        this.navgroup.parentId = this.id;
+        this.navgroup.onRender(this.el, null);
+        // add the buttons to the navgroup
+        
+        if(this.displayInfo){
+            Roo.log(this.el.select('ul.navbar-nav',true).first());
+            this.el.select('ul.navbar-nav',true).first().createChild({cls:'x-paging-info'});
+            this.displayEl = this.el.select('.x-paging-info', true).first();
+//            var navel = this.navgroup.addItem( { tagtype : 'span', html : '', cls : 'x-paging-info', preventDefault : true } );
+//            this.displayEl = navel.el.select('span',true).first();
         }
         
-        return nodes[0];
-    },
-    createRange: function(sel)
-    {
-        // this has strange effects when using with 
-        // top toolbar - not sure if it's a great idea.
-        //this.editor.contentWindow.focus();
-        if (typeof sel != "undefined") {
-            try {
-                return sel.getRangeAt ? sel.getRangeAt(0) : sel.createRange();
-            } catch(e) {
-                return this.doc.createRange();
-            }
-        } else {
-            return this.doc.createRange();
+        var _this = this;
+        
+        if(this.buttons){
+            Roo.each(_this.buttons, function(e){ // this might need to use render????
+               Roo.factory(e).onRender(_this.el, null);
+            });
         }
-    },
-    getParentElement: function()
-    {
+            
+        Roo.each(_this.toolbarItems, function(e) {
+            _this.navgroup.addItem(e);
+        });
         
-        this.assignDocWin();
-        var sel = Roo.isIE ? this.doc.selection : this.win.getSelection();
         
-        var range = this.createRange(sel);
-         
-        try {
-            var p = range.commonAncestorContainer;
-            while (p.nodeType == 3) { // text node
-                p = p.parentNode;
-            }
-            return p;
-        } catch (e) {
-            return null;
-        }
-    
-    },
-    /***
-     *
-     * Range intersection.. the hard stuff...
-     *  '-1' = before
-     *  '0' = hits..
-     *  '1' = after.
-     *         [ -- selected range --- ]
-     *   [fail]                        [fail]
-     *
-     *    basically..
-     *      if end is before start or  hits it. fail.
-     *      if start is after end or hits it fail.
-     *
-     *   if either hits (but other is outside. - then it's not 
-     *   
-     *    
-     **/
-    
-    
-    // @see http://www.thismuchiknow.co.uk/?p=64.
-    rangeIntersectsNode : function(range, node)
-    {
-        var nodeRange = node.ownerDocument.createRange();
-        try {
-            nodeRange.selectNode(node);
-        } catch (e) {
-            nodeRange.selectNodeContents(node);
-        }
-    
-        var rangeStartRange = range.cloneRange();
-        rangeStartRange.collapse(true);
-    
-        var rangeEndRange = range.cloneRange();
-        rangeEndRange.collapse(false);
-    
-        var nodeStartRange = nodeRange.cloneRange();
-        nodeStartRange.collapse(true);
-    
-        var nodeEndRange = nodeRange.cloneRange();
-        nodeEndRange.collapse(false);
-    
-        return rangeStartRange.compareBoundaryPoints(
-                 Range.START_TO_START, nodeEndRange) == -1 &&
-               rangeEndRange.compareBoundaryPoints(
-                 Range.START_TO_START, nodeStartRange) == 1;
+        this.first = this.navgroup.addItem({
+            tooltip: this.firstText,
+            cls: "prev",
+            icon : 'fa fa-backward',
+            disabled: true,
+            preventDefault: true,
+            listeners : { click : this.onClick.createDelegate(this, ["first"]) }
+        });
         
-         
-    },
-    rangeCompareNode : function(range, node)
-    {
-        var nodeRange = node.ownerDocument.createRange();
-        try {
-            nodeRange.selectNode(node);
-        } catch (e) {
-            nodeRange.selectNodeContents(node);
-        }
+        this.prev =  this.navgroup.addItem({
+            tooltip: this.prevText,
+            cls: "prev",
+            icon : 'fa fa-step-backward',
+            disabled: true,
+            preventDefault: true,
+            listeners : { click :  this.onClick.createDelegate(this, ["prev"]) }
+        });
+    //this.addSeparator();
         
         
-        range.collapse(true);
-    
-        nodeRange.collapse(true);
-     
-        var ss = range.compareBoundaryPoints( Range.START_TO_START, nodeRange);
-        var ee = range.compareBoundaryPoints(  Range.END_TO_END, nodeRange);
-         
-        //Roo.log(node.tagName + ': ss='+ss +', ee='+ee)
+        var field = this.navgroup.addItem( {
+            tagtype : 'span',
+            cls : 'x-paging-position',
+            
+            html : this.beforePageText  +
+                '<input type="text" size="3" value="1" class="x-grid-page-number">' +
+                '<span class="x-paging-after">' +  String.format(this.afterPageText, 1) + '</span>'
+         } ); //?? escaped?
         
-        var nodeIsBefore   =  ss == 1;
-        var nodeIsAfter    = ee == -1;
+        this.field = field.el.select('input', true).first();
+        this.field.on("keydown", this.onPagingKeydown, this);
+        this.field.on("focus", function(){this.dom.select();});
+    
+    
+        this.afterTextEl =  field.el.select('.x-paging-after',true).first();
+        //this.field.setHeight(18);
+        //this.addSeparator();
+        this.next = this.navgroup.addItem({
+            tooltip: this.nextText,
+            cls: "next",
+            html : ' <i class="fa fa-step-forward">',
+            disabled: true,
+            preventDefault: true,
+            listeners : { click :  this.onClick.createDelegate(this, ["next"]) }
+        });
+        this.last = this.navgroup.addItem({
+            tooltip: this.lastText,
+            icon : 'fa fa-forward',
+            cls: "next",
+            disabled: true,
+            preventDefault: true,
+            listeners : { click :  this.onClick.createDelegate(this, ["last"]) }
+        });
+    //this.addSeparator();
+        this.loading = this.navgroup.addItem({
+            tooltip: this.refreshText,
+            icon: 'fa fa-refresh',
+            preventDefault: true,
+            listeners : { click : this.onClick.createDelegate(this, ["refresh"]) }
+        });
         
-        if (nodeIsBefore && nodeIsAfter)
-            return 0; // outer
-        if (!nodeIsBefore && nodeIsAfter)
-            return 1; //right trailed.
+    },
+
+    // private
+    updateInfo : function(){
+        if(this.displayEl){
+            var count = (typeof(this.getCount) == 'undefined') ? this.ds.getCount() : this.getCount();
+            var msg = count == 0 ?
+                this.emptyMsg :
+                String.format(
+                    this.displayMsg,
+                    this.cursor+1, this.cursor+count, this.ds.getTotalCount()    
+                );
+            this.displayEl.update(msg);
+        }
+    },
+
+    // private
+    onLoad : function(ds, r, o){
+       this.cursor = o.params ? o.params.start : 0;
+       var d = this.getPageData(),
+            ap = d.activePage,
+            ps = d.pages;
         
-        if (nodeIsBefore && !nodeIsAfter)
-            return 2;  // left trailed.
-        // fully contined.
-        return 3;
+       this.afterTextEl.dom.innerHTML = String.format(this.afterPageText, d.pages);
+       this.field.dom.value = ap;
+       this.first.setDisabled(ap == 1);
+       this.prev.setDisabled(ap == 1);
+       this.next.setDisabled(ap == ps);
+       this.last.setDisabled(ap == ps);
+       this.loading.enable();
+       this.updateInfo();
+    },
+
+    // private
+    getPageData : function(){
+        var total = this.ds.getTotalCount();
+        return {
+            total : total,
+            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
+            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
+        };
+    },
+
+    // private
+    onLoadError : function(){
+        this.loading.enable();
+    },
+
+    // private
+    onPagingKeydown : function(e){
+        var k = e.getKey();
+        var d = this.getPageData();
+        if(k == e.RETURN){
+            var v = this.field.dom.value, pageNum;
+            if(!v || isNaN(pageNum = parseInt(v, 10))){
+                this.field.dom.value = d.activePage;
+                return;
+            }
+            pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
+            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
+            e.stopEvent();
+        }
+        else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
+        {
+          var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
+          this.field.dom.value = pageNum;
+          this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
+          e.stopEvent();
+        }
+        else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+        {
+          var v = this.field.dom.value, pageNum; 
+          var increment = (e.shiftKey) ? 10 : 1;
+          if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+            increment *= -1;
+          if(!v || isNaN(pageNum = parseInt(v, 10))) {
+            this.field.dom.value = d.activePage;
+            return;
+          }
+          else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
+          {
+            this.field.dom.value = parseInt(v, 10) + increment;
+            pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
+            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
+          }
+          e.stopEvent();
+        }
     },
 
-    // private? - 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;
+    // private
+    beforeLoad : function(){
+        if(this.loading){
+            this.loading.disable();
         }
-        
     },
-    
-    cleanWordChars : function(input) {// change the chars to hex code
-        var he = Roo.HtmlEditorCore;
-        
-        var output = input;
-        Roo.each(he.swapCodes, function(sw) { 
-            var swapper = new RegExp("\\u" + sw[0].toString(16), "g"); // hex codes
-            
-            output = output.replace(swapper, sw[1]);
-        });
+
+    // private
+    onClick : function(which){
         
-        return output;
-    },
-    
-    
-    cleanUpChildren : function (n)
-    {
-        if (!n.childNodes.length) {
+        var ds = this.ds;
+        if (!ds) {
             return;
         }
-        for (var i = n.childNodes.length-1; i > -1 ; i--) {
-           this.cleanUpChild(n.childNodes[i]);
+        
+        switch(which){
+            case "first":
+                ds.load({params:{start: 0, limit: this.pageSize}});
+            break;
+            case "prev":
+                ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
+            break;
+            case "next":
+                ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
+            break;
+            case "last":
+                var total = ds.getTotalCount();
+                var extra = total % this.pageSize;
+                var lastStart = extra ? (total - extra) : total-this.pageSize;
+                ds.load({params:{start: lastStart, limit: this.pageSize}});
+            break;
+            case "refresh":
+                ds.load({params:{start: this.cursor, limit: this.pageSize}});
+            break;
         }
     },
+
+    /**
+     * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
+     * @param {Roo.data.Store} store The data store to unbind
+     */
+    unbind : function(ds){
+        ds.un("beforeload", this.beforeLoad, this);
+        ds.un("load", this.onLoad, this);
+        ds.un("loadexception", this.onLoadError, this);
+        ds.un("remove", this.updateInfo, this);
+        ds.un("add", this.updateInfo, this);
+        this.ds = undefined;
+    },
+
+    /**
+     * Binds the paging toolbar to the specified {@link Roo.data.Store}
+     * @param {Roo.data.Store} store The data store to bind
+     */
+    bind : function(ds){
+        ds.on("beforeload", this.beforeLoad, this);
+        ds.on("load", this.onLoad, this);
+        ds.on("loadexception", this.onLoadError, this);
+        ds.on("remove", this.updateInfo, this);
+        ds.on("add", this.updateInfo, this);
+        this.ds = ds;
+    }
+});/*
+ * - LGPL
+ *
+ * element
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.MessageBar
+ * @extends Roo.bootstrap.Component
+ * Bootstrap MessageBar class
+ * @cfg {String} html contents of the MessageBar
+ * @cfg {String} weight (info | success | warning | danger) default info
+ * @cfg {String} beforeClass insert the bar before the given class
+ * @cfg {Boolean} closable (true | false) default false
+ * @cfg {Boolean} fixed (true | false) default false, fix the bar at the top
+ * 
+ * @constructor
+ * Create a new Element
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.MessageBar = function(config){
+    Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component,  {
     
+    html: '',
+    weight: 'info',
+    closable: false,
+    fixed: false,
+    beforeClass: 'bootstrap-sticky-wrap',
     
+    getAutoCreate : function(){
         
-    
-    cleanUpChild : function (node)
-    {
-        var ed = this;
-        //console.log(node);
-        if (node.nodeName == "#text") {
-            // clean up silly Windows -- stuff?
-            return; 
-        }
-        if (node.nodeName == "#comment") {
-            node.parentNode.removeChild(node);
-            // clean up silly Windows -- stuff?
-            return; 
-        }
-        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 cfg = {
+            tag: 'div',
+            cls: 'alert alert-dismissable alert-' + this.weight,
+            cn: [
+                {
+                    tag: 'span',
+                    cls: 'message',
+                    html: this.html || ''
+                }
+            ]
         }
         
-        var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
-        
-        // remove <a name=....> as rendering on yahoo mailer is borked with this.
-        // this will have to be flaged elsewhere - perhaps ablack=name... on the mailer..
-        
-        //if (node.tagName.toLowerCase() == 'a' && !node.hasAttribute('href')) {
-        //    remove_keep_children = true;
-        //}
-        
-        if (remove_keep_children) {
-            this.cleanUpChildren(node);
-            // inserts everything just before this node...
-            while (node.childNodes.length) {
-                var cn = node.childNodes[0];
-                node.removeChild(cn);
-                node.parentNode.insertBefore(cn, node);
-            }
-            node.parentNode.removeChild(node);
-            return;
+        if(this.fixed){
+            cfg.cls += ' alert-messages-fixed';
         }
         
-        if (!node.attributes || !node.attributes.length) {
-            this.cleanUpChildren(node);
-            return;
+        if(this.closable){
+            cfg.cn.push({
+                tag: 'button',
+                cls: 'close',
+                html: 'x'
+            });
         }
         
-        function cleanAttr(n,v)
-        {
-            
-            if (v.match(/^\./) || v.match(/^\//)) {
-                return;
-            }
-            if (v.match(/^(http|https):\/\//) || v.match(/^mailto:/)) {
-                return;
-            }
-            if (v.match(/^#/)) {
-                return;
-            }
-//            Roo.log("(REMOVE TAG)"+ node.tagName +'.' + n + '=' + v);
-            node.removeAttribute(n);
-            
-        }
+        return cfg;
+    },
+    
+    onRender : function(ct, position)
+    {
+        Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
         
-        var cwhite = this.cwhite;
-        var cblack = this.cblack;
+        if(!this.el){
+            var cfg = Roo.apply({},  this.getAutoCreate());
+            cfg.id = Roo.id();
             
-        function cleanStyle(n,v)
-        {
-            if (v.match(/expression/)) { //XSS?? should we even bother..
-                node.removeAttribute(n);
-                return;
+            if (this.cls) {
+                cfg.cls += ' ' + this.cls;
             }
-            
-            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);
+            if (this.style) {
+                cfg.style = this.style;
             }
+            this.el = Roo.get(document.body).createChild(cfg, Roo.select('.'+this.beforeClass, true).first());
             
+            this.el.setVisibilityMode(Roo.Element.DISPLAY);
         }
         
+        this.el.select('>button.close').on('click', this.hide, this);
         
-        for (var i = node.attributes.length-1; i > -1 ; i--) {
-            var a = node.attributes[i];
-            //console.log(a);
-            
-            if (a.name.toLowerCase().substr(0,2)=='on')  {
-                node.removeAttribute(a.name);
-                continue;
-            }
-            if (Roo.HtmlEditorCore.ablack.indexOf(a.name.toLowerCase()) > -1) {
-                node.removeAttribute(a.name);
-                continue;
-            }
-            if (Roo.HtmlEditorCore.aclean.indexOf(a.name.toLowerCase()) > -1) {
-                cleanAttr(a.name,a.value); // fixme..
-                continue;
-            }
-            if (a.name == 'style') {
-                cleanStyle(a.name,a.value);
-                continue;
-            }
-            /// clean up MS crap..
-            // tecnically this should be a list of valid class'es..
-            
-            
-            if (a.name == 'class') {
-                if (a.value.match(/^Mso/)) {
-                    node.className = '';
-                }
-                
-                if (a.value.match(/body/)) {
-                    node.className = '';
-                }
-                continue;
-            }
-            
-            // style cleanup!?
-            // class cleanup?
-            
+    },
+    
+    show : function()
+    {
+        if (!this.rendered) {
+            this.render();
         }
         
+        this.el.show();
+        
+        this.fireEvent('show', this);
         
-        this.cleanUpChildren(node);
+    },
+    
+    hide : function()
+    {
+        if (!this.rendered) {
+            this.render();
+        }
         
+        this.el.hide();
         
+        this.fireEvent('hide', this);
     },
     
-    /**
-     * Clean up MS wordisms...
-     */
-    cleanWord : function(node)
+    update : function()
     {
+//        var e = this.el.dom.firstChild;
+//        
+//        if(this.closable){
+//            e = e.nextSibling;
+//        }
+//        
+//        e.data = this.html || '';
+
+        this.el.select('>.message', true).first().dom.innerHTML = this.html || '';
+    }
+   
+});
+
+
+     /*
+ * - LGPL
+ *
+ * Graph
+ * 
+ */
+
+
+/**
+ * @class Roo.bootstrap.Graph
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Graph class
+> Prameters
+ -sm {number} sm 4
+ -md {number} md 5
+ @cfg {String} graphtype  bar | vbar | pie
+ @cfg {number} g_x coodinator | centre x (pie)
+ @cfg {number} g_y coodinator | centre y (pie)
+ @cfg {number} g_r radius (pie)
+ @cfg {number} g_height height of the chart (respected by all elements in the set)
+ @cfg {number} g_width width of the chart (respected by all elements in the set)
+ @cfg {Object} title The title of the chart
+    
+ -{Array}  values
+ -opts (object) options for the chart 
+     o {
+     o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
+     o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
+     o vgutter (number)
+     o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
+     o stacked (boolean) whether or not to tread values as in a stacked bar chart
+     o to
+     o stretch (boolean)
+     o }
+ -opts (object) options for the pie
+     o{
+     o cut
+     o startAngle (number)
+     o endAngle (number)
+     } 
+ *
+ * @constructor
+ * Create a new Input
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Graph = function(config){
+    Roo.bootstrap.Graph.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // img events
+        /**
+         * @event click
+         * The img click event for the img.
+         * @param {Roo.EventObject} e
+         */
+        "click" : true
+    });
+};
+
+Roo.extend(Roo.bootstrap.Graph, Roo.bootstrap.Component,  {
+    
+    sm: 4,
+    md: 5,
+    graphtype: 'bar',
+    g_height: 250,
+    g_width: 400,
+    g_x: 50,
+    g_y: 50,
+    g_r: 30,
+    opts:{
+        //g_colors: this.colors,
+        g_type: 'soft',
+        g_gutter: '20%'
+
+    },
+    title : false,
+
+    getAutoCreate : function(){
+        
+        var cfg = {
+            tag: 'div',
+            html : null
+        }
         
         
-        if (!node) {
-            this.cleanWord(this.doc.body);
-            return;
+        return  cfg;
+    },
+
+    onRender : function(ct,position){
+        Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
+        this.raphael = Raphael(this.el.dom);
+        
+                    // data1 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    // data2 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    // data3 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    // txtattr = { font: "12px 'Fontin Sans', Fontin-Sans, sans-serif" };
+                /*
+                r.text(160, 10, "Single Series Chart").attr(txtattr);
+                r.text(480, 10, "Multiline Series Chart").attr(txtattr);
+                r.text(160, 250, "Multiple Series Stacked Chart").attr(txtattr);
+                r.text(480, 250, 'Multiline Series Stacked Vertical Chart. Type "round"').attr(txtattr);
+                
+                r.barchart(10, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10]], 0, {type: "sharp"});
+                r.barchart(330, 10, 300, 220, data1);
+                r.barchart(10, 250, 300, 220, data2, {stacked: true});
+                r.barchart(330, 250, 300, 220, data3, {stacked: true, type: "round"});
+                */
+                
+                // var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
+                // r.barchart(30, 30, 560, 250,  xdata, {
+                //    labels : [55, 20, 13, 32, 5, 1, 2, 10,5 , 10],
+                //     axis : "0 0 1 1",
+                //     axisxlabels :  xdata
+                //     //yvalues : cols,
+                   
+                // });
+//        var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
+//        
+//        this.load(null,xdata,{
+//                axis : "0 0 1 1",
+//                axisxlabels :  xdata
+//                });
+
+    },
+
+    load : function(graphtype,xdata,opts){
+        this.raphael.clear();
+        if(!graphtype) {
+            graphtype = this.graphtype;
         }
-        if (node.nodeName == "#text") {
-            // clean up silly Windows -- stuff?
-            return; 
+        if(!opts){
+            opts = this.opts;
         }
-        if (node.nodeName == "#comment") {
-            node.parentNode.removeChild(node);
-            // clean up silly Windows -- stuff?
-            return; 
+        var r = this.raphael,
+            fin = function () {
+                this.flag = r.popup(this.bar.x, this.bar.y, this.bar.value || "0").insertBefore(this);
+            },
+            fout = function () {
+                this.flag.animate({opacity: 0}, 300, function () {this.remove();});
+            },
+            pfin = function() {
+                this.sector.stop();
+                this.sector.scale(1.1, 1.1, this.cx, this.cy);
+
+                if (this.label) {
+                    this.label[0].stop();
+                    this.label[0].attr({ r: 7.5 });
+                    this.label[1].attr({ "font-weight": 800 });
+                }
+            },
+            pfout = function() {
+                this.sector.animate({ transform: 's1 1 ' + this.cx + ' ' + this.cy }, 500, "bounce");
+
+                if (this.label) {
+                    this.label[0].animate({ r: 5 }, 500, "bounce");
+                    this.label[1].attr({ "font-weight": 400 });
+                }
+            };
+
+        switch(graphtype){
+            case 'bar':
+                this.raphael.barchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
+                break;
+            case 'hbar':
+                this.raphael.hbarchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
+                break;
+            case 'pie':
+//                opts = { legend: ["%% - Enterprise Users", "% - ddd","Chrome Users"], legendpos: "west", 
+//                href: ["http://raphaeljs.com", "http://g.raphaeljs.com"]};
+//            
+                this.raphael.piechart(this.g_x,this.g_y,this.g_r,xdata,opts).hover(pfin, pfout);
+                
+                break;
+
         }
         
-        if (node.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)) {
-            node.parentNode.removeChild(node);
-            return;
+        if(this.title){
+            this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
         }
         
-        // remove - but keep children..
-        if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|font)/)) {
-            while (node.childNodes.length) {
-                var cn = node.childNodes[0];
-                node.removeChild(cn);
-                node.parentNode.insertBefore(cn, node);
-            }
-            node.parentNode.removeChild(node);
-            this.iterateChildren(node, this.cleanWord);
-            return;
+    },
+    
+    setTitle: function(o)
+    {
+        this.title = o;
+    },
+    
+    initEvents: function() {
+        
+        if(!this.href){
+            this.el.on('click', this.onClick, this);
         }
-        // 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;
+    },
+    
+    onClick : function(e)
+    {
+        Roo.log('img onclick');
+        this.fireEvent('click', this, e);
+    }
+   
+});
+
+/*
+ * - LGPL
+ *
+ * numberBox
+ * 
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+
+/**
+ * @class Roo.bootstrap.dash.NumberBox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap NumberBox class
+ * @cfg {String} headline Box headline
+ * @cfg {String} content Box content
+ * @cfg {String} icon Box icon
+ * @cfg {String} footer Footer text
+ * @cfg {String} fhref Footer href
+ * 
+ * @constructor
+ * Create a new NumberBox
+ * @param {Object} config The config object
+ */
+
+
+Roo.bootstrap.dash.NumberBox = function(config){
+    Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+    
+};
+
+Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component,  {
+    
+    headline : '',
+    content : '',
+    icon : '',
+    footer : '',
+    fhref : '',
+    ficon : '',
+    
+    getAutoCreate : function(){
+        
+        var cfg = {
+            tag : 'div',
+            cls : 'small-box ',
+            cn : [
+                {
+                    tag : 'div',
+                    cls : 'inner',
+                    cn :[
+                        {
+                            tag : 'h3',
+                            cls : 'roo-headline',
+                            html : this.headline
+                        },
+                        {
+                            tag : 'p',
+                            cls : 'roo-content',
+                            html : this.content
+                        }
+                    ]
                 }
-                cna.push(cls);
-            });
-            node.className = cna.length ? cna.join(' ') : '';
-            if (!cna.length) {
-                node.removeAttribute("class");
-            }
+            ]
         }
         
-        if (node.hasAttribute("lang")) {
-            node.removeAttribute("lang");
+        if(this.icon){
+            cfg.cn.push({
+                tag : 'div',
+                cls : 'icon',
+                cn :[
+                    {
+                        tag : 'i',
+                        cls : 'ion ' + this.icon
+                    }
+                ]
+            });
         }
         
-        if (node.hasAttribute("style")) {
+        if(this.footer){
+            var footer = {
+                tag : 'a',
+                cls : 'small-box-footer',
+                href : this.fhref || '#',
+                html : this.footer
+            };
+            
+            cfg.cn.push(footer);
             
-            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);
-        
-        
         
+        return  cfg;
     },
-    /**
-     * 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)
+
+    onRender : function(ct,position){
+        Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
+
+
+       
+                
+    },
+
+    setHeadline: function (value)
     {
-        if (!node.childNodes.length) {
-                return;
-        }
-        for (var i = node.childNodes.length-1; i > -1 ; i--) {
-           fn.call(this, node.childNodes[i])
-        }
+        this.el.select('.roo-headline',true).first().dom.innerHTML = value;
     },
     
-    
-    /**
-     * 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..
-     *
-     */
-    cleanTableWidths : function(node)
+    setFooter: function (value, href)
     {
-         
-         
-        if (!node) {
-            this.cleanTableWidths(this.doc.body);
-            return;
-        }
+        this.el.select('a.small-box-footer',true).first().dom.innerHTML = value;
         
-        // 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(href){
+            this.el.select('a.small-box-footer',true).first().attr('href', href);
         }
         
+    },
+
+    setContent: function (value)
+    {
+        this.el.select('.roo-content',true).first().dom.innerHTML = value;
+    },
+
+    initEvents: function() 
+    {   
+        
+    }
+    
+});
+
+/*
+ * - LGPL
+ *
+ * TabBox
+ * 
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+
+/**
+ * @class Roo.bootstrap.dash.TabBox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TabBox class
+ * @cfg {String} title Title of the TabBox
+ * @cfg {String} icon Icon of the TabBox
+ * @cfg {Boolean} showtabs (true|false) show the tabs default true
+ * @cfg {Boolean} tabScrollable (true|false) tab scrollable when mobile view default false
+ * 
+ * @constructor
+ * Create a new TabBox
+ * @param {Object} config The config object
+ */
+
+
+Roo.bootstrap.dash.TabBox = function(config){
+    Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
+    this.addEvents({
+        // raw events
+        /**
+         * @event addpane
+         * When a pane is added
+         * @param {Roo.bootstrap.dash.TabPane} pane
+         */
+        "addpane" : true,
+        /**
+         * @event activatepane
+         * When a pane is activated
+         * @param {Roo.bootstrap.dash.TabPane} pane
+         */
+        "activatepane" : true
+        
          
-        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);
-        
-        
-    },
-    
-    
+    });
     
+    this.panes = [];
+};
+
+Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component,  {
+
+    title : '',
+    icon : false,
+    showtabs : true,
+    tabScrollable : false,
     
-    domToHTML : function(currentElement, depth, nopadtext) {
-        
-        depth = depth || 0;
-        nopadtext = nopadtext || false;
+    getChildContainer : function()
+    {
+        return this.el.select('.tab-content', true).first();
+    },
     
-        if (!currentElement) {
-            return this.domToHTML(this.doc.body);
-        }
+    getAutoCreate : function(){
         
-        //Roo.log(currentElement);
-        var j;
-        var allText = false;
-        var nodeName = currentElement.nodeName;
-        var tagName = Roo.util.Format.htmlEncode(currentElement.tagName);
+        var header = {
+            tag: 'li',
+            cls: 'pull-left header',
+            html: this.title,
+            cn : []
+        };
         
-        if  (nodeName == '#text') {
-            
-            return nopadtext ? currentElement.nodeValue : currentElement.nodeValue.trim();
+        if(this.icon){
+            header.cn.push({
+                tag: 'i',
+                cls: 'fa ' + this.icon
+            });
         }
         
+        var h = {
+            tag: 'ul',
+            cls: 'nav nav-tabs pull-right',
+            cn: [
+                header
+            ]
+        };
         
-        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;
+        if(this.tabScrollable){
+            h = {
+                tag: 'div',
+                cls: 'tab-header',
+                cn: [
+                    {
+                        tag: 'ul',
+                        cls: 'nav nav-tabs pull-right',
+                        cn: [
+                            header
+                        ]
                     }
-                    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( "  "  );
+        var cfg = {
+            tag: 'div',
+            cls: 'nav-tabs-custom',
+            cn: [
+                h,
+                {
+                    tag: 'div',
+                    cls: 'tab-content no-padding',
+                    cn: []
                 }
-                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;
-        
+
+        return  cfg;
     },
-        
-    applyBlacklists : function()
+    initEvents : function()
     {
-        var w = typeof(this.owner.white) != 'undefined' && this.owner.white ? this.owner.white  : [];
-        var b = typeof(this.owner.black) != 'undefined' && this.owner.black ? this.owner.black :  [];
-        
-        this.white = [];
-        this.black = [];
-        Roo.each(Roo.HtmlEditorCore.white, function(tag) {
-            if (b.indexOf(tag) > -1) {
-                return;
-            }
-            this.white.push(tag);
-            
-        }, this);
-        
-        Roo.each(w, function(tag) {
-            if (b.indexOf(tag) > -1) {
-                return;
-            }
-            if (this.white.indexOf(tag) > -1) {
-                return;
-            }
-            this.white.push(tag);
-            
-        }, this);
-        
-        
-        Roo.each(Roo.HtmlEditorCore.black, function(tag) {
-            if (w.indexOf(tag) > -1) {
-                return;
-            }
-            this.black.push(tag);
-            
-        }, this);
+        //Roo.log('add add pane handler');
+        this.on('addpane', this.onAddPane, this);
+    },
+     /**
+     * Updates the box title
+     * @param {String} html to set the title to.
+     */
+    setTitle : function(value)
+    {
+        this.el.select('.nav-tabs .header', true).first().dom.innerHTML = value;
+    },
+    onAddPane : function(pane)
+    {
+        this.panes.push(pane);
+        //Roo.log('addpane');
+        //Roo.log(pane);
+        // tabs are rendere left to right..
+        if(!this.showtabs){
+            return;
+        }
         
-        Roo.each(b, function(tag) {
-            if (w.indexOf(tag) > -1) {
-                return;
-            }
-            if (this.black.indexOf(tag) > -1) {
-                return;
-            }
-            this.black.push(tag);
-            
-        }, this);
+        var ctr = this.el.select('.nav-tabs', true).first();
+         
+         
+        var existing = ctr.select('.nav-tab',true);
+        var qty = existing.getCount();;
         
         
-        w = typeof(this.owner.cwhite) != 'undefined' && this.owner.cwhite ? this.owner.cwhite  : [];
-        b = typeof(this.owner.cblack) != 'undefined' && this.owner.cblack ? this.owner.cblack :  [];
+        var tab = ctr.createChild({
+            tag : 'li',
+            cls : 'nav-tab' + (qty ? '' : ' active'),
+            cn : [
+                {
+                    tag : 'a',
+                    href:'#',
+                    html : pane.title
+                }
+            ]
+        }, qty ? existing.first().dom : ctr.select('.header', true).first().dom );
+        pane.tab = tab;
         
-        this.cwhite = [];
-        this.cblack = [];
-        Roo.each(Roo.HtmlEditorCore.cwhite, function(tag) {
-            if (b.indexOf(tag) > -1) {
-                return;
-            }
-            this.cwhite.push(tag);
-            
-        }, this);
+        tab.on('click', this.onTabClick.createDelegate(this, [pane], true));
+        if (!qty) {
+            pane.el.addClass('active');
+        }
         
-        Roo.each(w, function(tag) {
-            if (b.indexOf(tag) > -1) {
-                return;
-            }
-            if (this.cwhite.indexOf(tag) > -1) {
-                return;
-            }
-            this.cwhite.push(tag);
-            
-        }, this);
+                
+    },
+    onTabClick : function(ev,un,ob,pane)
+    {
+        //Roo.log('tab - prev default');
+        ev.preventDefault();
         
         
-        Roo.each(Roo.HtmlEditorCore.cblack, function(tag) {
-            if (w.indexOf(tag) > -1) {
-                return;
-            }
-            this.cblack.push(tag);
-            
-        }, this);
+        this.el.select('.nav-tabs li.nav-tab', true).removeClass('active');
+        pane.tab.addClass('active');
+        //Roo.log(pane.title);
+        this.getChildContainer().select('.tab-pane',true).removeClass('active');
+        // technically we should have a deactivate event.. but maybe add later.
+        // and it should not de-activate the selected tab...
+        this.fireEvent('activatepane', pane);
+        pane.el.addClass('active');
+        pane.fireEvent('activate');
+        
         
-        Roo.each(b, function(tag) {
-            if (w.indexOf(tag) > -1) {
-                return;
-            }
-            if (this.cblack.indexOf(tag) > -1) {
-                return;
-            }
-            this.cblack.push(tag);
-            
-        }, this);
     },
     
-    setStylesheets : function(stylesheets)
+    getActivePane : function()
     {
-        if(typeof(stylesheets) == 'string'){
-            Roo.get(this.iframe.contentDocument.head).createChild({
-                tag : 'link',
-                rel : 'stylesheet',
-                type : 'text/css',
-                href : stylesheets
-            });
-            
-            return;
-        }
-        var _this = this;
-     
-        Roo.each(stylesheets, function(s) {
-            if(!s.length){
-                return;
+        var r = false;
+        Roo.each(this.panes, function(p) {
+            if(p.el.hasClass('active')){
+                r = p;
+                return false;
             }
             
-            Roo.get(_this.iframe.contentDocument.head).createChild({
-                tag : 'link',
-                rel : 'stylesheet',
-                type : 'text/css',
-                href : s
-            });
+            return;
         });
-
-        
-    },
-    
-    removeStylesheets : function()
-    {
-        var _this = this;
         
-        Roo.each(Roo.get(_this.iframe.contentDocument.head).select('link[rel=stylesheet]', true).elements, function(s){
-            s.remove();
-        });
+        return r;
     }
     
-    // hide stuff that is not compatible
-    /**
-     * @event blur
-     * @hide
-     */
-    /**
-     * @event change
-     * @hide
-     */
-    /**
-     * @event focus
-     * @hide
-     */
-    /**
-     * @event specialkey
-     * @hide
-     */
-    /**
-     * @cfg {String} fieldClass @hide
-     */
-    /**
-     * @cfg {String} focusClass @hide
-     */
-    /**
-     * @cfg {String} autoCreate @hide
-     */
-    /**
-     * @cfg {String} inputType @hide
-     */
-    /**
-     * @cfg {String} invalidClass @hide
-     */
-    /**
-     * @cfg {String} invalidText @hide
-     */
-    /**
-     * @cfg {String} msgFx @hide
-     */
-    /**
-     * @cfg {String} validateOnBlur @hide
-     */
+    
 });
 
-Roo.HtmlEditorCore.white = [
-        'area', 'br', 'img', 'input', 'hr', 'wbr',
-        
-       'address', 'blockquote', 'center', 'dd',      'dir',       'div', 
-       'dl',      'dt',         'h1',     'h2',      'h3',        'h4', 
-       'h5',      'h6',         'hr',     'isindex', 'listing',   'marquee', 
-       'menu',    'multicol',   'ol',     'p',       'plaintext', 'pre', 
-       'table',   'ul',         'xmp', 
-       
-       'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', 
-      'thead',   'tr', 
-     
-      'dir', 'menu', 'ol', 'ul', 'dl',
-       
-      'embed',  'object'
-];
+/*
+ * - LGPL
+ *
+ * Tab pane
+ * 
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+/**
+ * @class Roo.bootstrap.TabPane
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TabPane class
+ * @cfg {Boolean} active (false | true) Default false
+ * @cfg {String} title title of panel
 
+ * 
+ * @constructor
+ * Create a new TabPane
+ * @param {Object} config The config object
+ */
 
-Roo.HtmlEditorCore.black = [
-    //    'embed',  'object', // enable - backend responsiblity to clean thiese
-        'applet', // 
-        'base',   'basefont', 'bgsound', 'blink',  'body', 
-        'frame',  'frameset', 'head',    'html',   'ilayer', 
-        'iframe', 'layer',  'link',     'meta',    'object',   
-        'script', 'style' ,'title',  'xml' // clean later..
-];
-Roo.HtmlEditorCore.clean = [
-    'script', 'style', 'title', 'xml'
-];
-Roo.HtmlEditorCore.remove = [
-    'font'
-];
-// attributes..
+Roo.bootstrap.dash.TabPane = function(config){
+    Roo.bootstrap.dash.TabPane.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // raw events
+        /**
+         * @event activate
+         * When a pane is activated
+         * @param {Roo.bootstrap.dash.TabPane} pane
+         */
+        "activate" : true
+         
+    });
+};
 
-Roo.HtmlEditorCore.ablack = [
-    'on'
-];
+Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component,  {
+    
+    active : false,
+    title : '',
+    
+    // the tabBox that this is attached to.
+    tab : false,
+     
+    getAutoCreate : function() 
+    {
+        var cfg = {
+            tag: 'div',
+            cls: 'tab-pane'
+        }
+        
+        if(this.active){
+            cfg.cls += ' active';
+        }
+        
+        return cfg;
+    },
+    initEvents  : function()
+    {
+        //Roo.log('trigger add pane handler');
+        this.parent().fireEvent('addpane', this)
+    },
+    
+     /**
+     * Updates the tab title 
+     * @param {String} html to set the title to.
+     */
+    setTitle: function(str)
+    {
+        if (!this.tab) {
+            return;
+        }
+        this.title = str;
+        this.tab.select('a', true).first().dom.innerHTML = str;
+        
+    }
     
-Roo.HtmlEditorCore.aclean = [ 
-    'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc' 
-];
-
-// protocols..
-Roo.HtmlEditorCore.pwhite= [
-        'http',  'https',  'mailto'
-];
-
-// white listed style attributes.
-Roo.HtmlEditorCore.cwhite= [
-      //  'text-align', /// default is to allow most things..
-      
-         
-//        'font-size'//??
-];
-
-// black listed style attributes.
-Roo.HtmlEditorCore.cblack= [
-      //  'font-size' -- this can be set by the project 
-];
+    
+    
+});
 
 
-Roo.HtmlEditorCore.swapCodes   =[ 
-    [    8211, "--" ], 
-    [    8212, "--" ], 
-    [    8216,  "'" ],  
-    [    8217, "'" ],  
-    [    8220, '"' ],  
-    [    8221, '"' ],  
-    [    8226, "*" ],  
-    [    8230, "..." ]
-]; 
 
   /*
+ /*
  * - LGPL
  *
- * HtmlEditor
+ * menu
  * 
  */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
 
 /**
- * @class Roo.bootstrap.HtmlEditor
- * @extends Roo.bootstrap.TextArea
- * Bootstrap HtmlEditor class
-
+ * @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 HtmlEditor
+ * Create a new Menu
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.HtmlEditor = function(config){
-    Roo.bootstrap.HtmlEditor.superclass.constructor.call(this, config);
-    if (!this.toolbars) {
-        this.toolbars = [];
-    }
-    this.editorcore = new Roo.HtmlEditorCore(Roo.apply({ owner : this} , config));
-    this.addEvents({
-            /**
-             * @event initialize
-             * Fires when the editor is fully initialized (including the iframe)
-             * @param {HtmlEditor} this
-             */
-            initialize: true,
-            /**
-             * @event activate
-             * Fires when the editor is first receives the focus. Any insertion must wait
-             * until after this event.
-             * @param {HtmlEditor} this
-             */
-            activate: true,
-             /**
-             * @event beforesync
-             * Fires before the textarea is updated with content from the editor iframe. Return false
-             * to cancel the sync.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            beforesync: true,
-             /**
-             * @event beforepush
-             * Fires before the iframe editor is updated with content from the textarea. Return false
-             * to cancel the push.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            beforepush: true,
-             /**
-             * @event sync
-             * Fires when the textarea is updated with content from the editor iframe.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            sync: true,
-             /**
-             * @event push
-             * Fires when the iframe editor is updated with content from the textarea.
-             * @param {HtmlEditor} this
-             * @param {String} html
-             */
-            push: true,
-             /**
-             * @event editmodechange
-             * Fires when the editor switches edit modes
-             * @param {HtmlEditor} this
-             * @param {Boolean} sourceEdit True if source edit, false if standard editing.
-             */
-            editmodechange: true,
-            /**
-             * @event editorevent
-             * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
-             * @param {HtmlEditor} this
-             */
-            editorevent: true,
-            /**
-             * @event firstfocus
-             * Fires when on first focus - needed by toolbars..
-             * @param {HtmlEditor} this
-             */
-            firstfocus: true,
-            /**
-             * @event autosave
-             * Auto save the htmlEditor value as a file into Events
-             * @param {HtmlEditor} this
-             */
-            autosave: true,
-            /**
-             * @event savedpreview
-             * preview the saved version of htmlEditor
-             * @param {HtmlEditor} this
-             */
-            savedpreview: true
-        });
-};
-
 
-Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
-    
-    
-      /**
-     * @cfg {Array} toolbars Array of toolbars. - defaults to just the Standard one
-     */
-    toolbars : false,
-   
-     /**
-     * @cfg {String} resizable  's' or 'se' or 'e' - wrapps the element in a
-     *                        Roo.resizable.
-     */
-    resizable : false,
-     /**
-     * @cfg {Number} height (in pixels)
-     */   
-    height: 300,
-   /**
-     * @cfg {Number} width (in pixels)
-     */   
-    width: false,
-    
-    /**
-     * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
-     * 
-     */
-    stylesheets: false,
-    
-    // id of frame..
-    frameId: false,
+Roo.bootstrap.menu.Menu = function(config){
+    Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
     
-    // private properties
-    validationEvent : false,
-    deferHeight: true,
-    initialized : false,
-    activated : false,
+    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
+    });
     
-    onFocus : Roo.emptyFn,
-    iframePad:3,
-    hideMode:'offsets',
+};
+
+Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component,  {
     
+    submenu : false,
+    html : '',
+    weight : 'default',
+    icon : false,
+    pos : 'bottom',
     
-    tbContainer : false,
     
-    toolbarContainer :function() {
-        return this.wrap.select('.x-html-editor-tb',true).first();
+    getChildContainer : function() {
+        if(this.isSubMenu){
+            return this.el;
+        }
+        
+        return this.el.select('ul.dropdown-menu', true).first();  
     },
-
-    /**
-     * Protected method that will not generally be called directly. It
-     * is called when the editor creates its toolbar. Override this method if you need to
-     * add custom toolbar buttons.
-     * @param {HtmlEditor} editor
-     */
-    createToolbar : function(){
+    
+    getAutoCreate : function()
+    {
+        var text = [
+            {
+                tag : 'span',
+                cls : 'roo-menu-text',
+                html : this.html
+            }
+        ];
+        
+        if(this.icon){
+            text.unshift({
+                tag : 'i',
+                cls : 'fa ' + this.icon
+            })
+        }
         
-        Roo.log("create toolbars");
         
-        this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
-        this.toolbars[0].render(this.toolbarContainer());
+        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'
+                }
+            ]
+            
+        };
         
-        return;
+        if(this.pos == 'top'){
+            cfg.cls += ' dropup';
+        }
         
-//        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);
-//        }
+        if(this.isSubMenu){
+            cfg = {
+                tag : 'ul',
+                cls : 'dropdown-menu'
+            }
+        }
+       
+        return cfg;
     },
-
-     
-    // private
+    
     onRender : function(ct, position)
     {
-       // Roo.log("Call onRender: " + this.xtype);
-        var _t = this;
-        Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
-      
-        this.wrap = this.inputEl().wrap({
-            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
-        });
+        this.isSubMenu = ct.hasClass('dropdown-submenu');
         
-        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
-                    }
-                }
-            });
-            
+        Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
+    },
+    
+    initEvents : function() 
+    {
+        if(this.isSubMenu){
+            return;
         }
-        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..
-        }
+        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);
         
     },
-
-    // private
-    onResize : function(w, h)
+    
+    list : function()
     {
-        Roo.log('resize: ' +w + ',' + h );
-        Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
-        var ew = false;
-        var eh = false;
-        
-        if(this.inputEl() ){
-            if(typeof w == 'number'){
-                var aw = w - this.wrap.getFrameWidth('lr');
-                this.inputEl().setWidth(this.adjustWidth('textarea', aw));
-                ew = aw;
-            }
-            if(typeof h == 'number'){
-                 var tbh = -11;  // fixme it needs to tool bar size!
-                for (var i =0; i < this.toolbars.length;i++) {
-                    // fixme - ask toolbars for heights?
-                    tbh += this.toolbars[i].el.getHeight();
-                    //if (this.toolbars[i].footer) {
-                    //    tbh += this.toolbars[i].footer.el.getHeight();
-                    //}
-                }
-              
-                
-                
-                
-                
-                var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
-                ah -= 5; // knock a few pixes off for look..
-                this.inputEl().setHeight(this.adjustWidth('textarea', ah));
-                var eh = ah;
-            }
+        if(this.isSubMenu){
+            return this.el;
         }
-        Roo.log('onResize:' + [w,h,ew,eh].join(',') );
-        this.editorcore.onResize(ew,eh);
         
+        return this.el.select('ul.dropdown-menu', true).first();
     },
-
-    /**
-     * Toggles the editor between standard and source edit mode.
-     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
-     */
-    toggleSourceEdit : function(sourceEditMode)
+    
+    onClick : function(e)
     {
-        this.editorcore.toggleSourceEdit(sourceEditMode);
-        
-        if(this.editorcore.sourceEditMode){
-            Roo.log('editor - showing textarea');
-            
-//            Roo.log('in');
-//            Roo.log(this.syncValue());
-            this.syncValue();
-            this.inputEl().removeClass(['hide', 'x-hidden']);
-            this.inputEl().dom.removeAttribute('tabIndex');
-            this.inputEl().focus();
-        }else{
-            Roo.log('editor - hiding textarea');
-//            Roo.log('out')
-//            Roo.log(this.pushValue()); 
-            this.pushValue();
-            
-            this.inputEl().addClass(['hide', 'x-hidden']);
-            this.inputEl().dom.setAttribute('tabIndex', -1);
-            //this.deferFocus();
-        }
-         
-        if(this.resizable){
-            this.setSize(this.wrap.getSize());
+        this.fireEvent("click", this, e);
+    },
+    
+    onTriggerPress  : function(e)
+    {   
+        if (this.isVisible()) {
+            this.hide();
+        } else {
+            this.show();
         }
-        
-        this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
     },
-    // private (for BoxComponent)
-    adjustSize : Roo.BoxComponent.prototype.adjustSize,
-
-    // private (for BoxComponent)
-    getResizeEl : function(){
-        return this.wrap;
+    
+    isVisible : function(){
+        return !this.hidden;
     },
-
-    // private (for BoxComponent)
-    getPositionEl : function(){
-        return this.wrap;
+    
+    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);
+        
+        
     },
-
-    // private
-    initEvents : function(){
-        this.originalValue = this.getValue();
+    
+    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();
+    }
+    
+});
 
-//    /**
-//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-//     * @method
-//     */
-//    markInvalid : Roo.emptyFn,
-//    /**
-//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-//     * @method
-//     */
-//    clearInvalid : Roo.emptyFn,
+ /*
+ * - LGPL
+ *
+ * menu item
+ * 
+ */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
 
-    setValue : function(v){
-        Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
-        this.editorcore.pushValue();
-    },
+/**
+ * @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
+ */
 
-     
-    // private
-    deferFocus : function(){
-        this.focus.defer(10, this);
-    },
 
-    // doc'ed in Field
-    focus : function(){
-        this.editorcore.focus();
-        
-    },
-      
+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
+    });
+};
 
-    // private
-    onDestroy : function(){
+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.rendered){
+        if(this.submenu){
+            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
             
-            for (var i =0; i < this.toolbars.length;i++) {
-                // fixme - ask toolbars for heights?
-                this.toolbars[i].onDestroy();
+            if(this.pos == 'left'){
+                cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
             }
-            
-            this.wrap.dom.innerHTML = '';
-            this.wrap.remove();
         }
+        
+        return cfg;
     },
-
-    // private
-    onFirstFocus : function(){
-        //Roo.log("onFirstFocus");
-        this.editorcore.onFirstFocus();
-         for (var i =0; i < this.toolbars.length;i++) {
-            this.toolbars[i].onFirstFocus();
+    
+    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);
     },
     
-    // private
-    syncValue : function()
-    {   
-        this.editorcore.syncValue();
+    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);
     },
     
-    pushValue : function()
-    {   
-        this.editorcore.pushValue();
+    onMouseOut : function(e)
+    {
+        this.fireEvent("mouseout", this, e);
     }
-     
-    
-    // hide stuff that is not compatible
-    /**
-     * @event blur
-     * @hide
-     */
-    /**
-     * @event change
-     * @hide
-     */
-    /**
-     * @event focus
-     * @hide
-     */
-    /**
-     * @event specialkey
-     * @hide
-     */
-    /**
-     * @cfg {String} fieldClass @hide
-     */
-    /**
-     * @cfg {String} focusClass @hide
-     */
-    /**
-     * @cfg {String} autoCreate @hide
-     */
-    /**
-     * @cfg {String} inputType @hide
-     */
-    /**
-     * @cfg {String} invalidClass @hide
-     */
-    /**
-     * @cfg {String} invalidText @hide
-     */
-    /**
-     * @cfg {String} msgFx @hide
-     */
-    /**
-     * @cfg {String} validateOnBlur @hide
-     */
 });
+
  
-    
-   
-   
-   
-      
-Roo.namespace('Roo.bootstrap.htmleditor');
+
+ /*
+ * - LGPL
+ *
+ * menu separator
+ * 
+ */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+
 /**
- * @class Roo.bootstrap.HtmlEditorToolbar1
- * Basic Toolbar
+ * @class Roo.bootstrap.menu.Separator
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Separator class
  * 
- * Usage:
- *
- new Roo.bootstrap.HtmlEditor({
-    ....
-    toolbars : [
-        new Roo.bootstrap.HtmlEditorToolbar1({
-            disable : { fonts: 1 , format: 1, ..., ... , ...],
-            btns : [ .... ]
-        })
+ * @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: 'divider'
+        };
+        
+        return cfg;
     }
-     
+   
+});
+
+
+ /*
+ * - LGPL
+ *
+ * Tooltip
  * 
- * @cfg {Object} disable List of elements to disable..
- * @cfg {Array} btns List of additional buttons.
+ */
+
+/**
+ * @class Roo.bootstrap.Tooltip
+ * Bootstrap Tooltip class
+ * This is basic at present - all componets support it by default, however they should add tooltipEl() method
+ * to determine which dom element triggers the tooltip.
  * 
+ * It needs to add support for additional attributes like tooltip-position
  * 
- * NEEDS Extra CSS? 
- * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
+ * @constructor
+ * Create a new Toolti
+ * @param {Object} config The config object
  */
-Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
-{
-    
-    Roo.apply(this, config);
-    
-    // default disabled, based on 'good practice'..
-    this.disable = this.disable || {};
-    Roo.applyIf(this.disable, {
-        fontSize : true,
-        colors : true,
-        specialElements : true
-    });
-    Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
-    
-    this.editor = config.editor;
-    this.editorcore = config.editor.editorcore;
-    
-    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
-    
-    //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
-    // dont call parent... till later.
-}
-Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,  {
-     
-    bar : true,
-    
-    editor : false,
-    editorcore : false,
+
+Roo.bootstrap.Tooltip = function(config){
+    Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
+};
+
+Roo.apply(Roo.bootstrap.Tooltip, {
+    /**
+     * @function init initialize tooltip monitoring.
+     * @static
+     */
+    currentEl : false,
+    currentTip : false,
+    currentRegion : false,
     
+    //  init : delay?
     
-    formats : [
-        "p" ,  
-        "h1","h2","h3","h4","h5","h6", 
-        "pre", "code", 
-        "abbr", "acronym", "address", "cite", "samp", "var",
-        'div','span'
-    ],
+    init : function()
+    {
+        Roo.get(document).on('mouseover', this.enter ,this);
+        Roo.get(document).on('mouseout', this.leave, this);
+         
+        
+        this.currentTip = new Roo.bootstrap.Tooltip();
+    },
     
-    onRender : function(ct, position)
+    enter : function(ev)
     {
-       // Roo.log("Call onRender: " + this.xtype);
+        var dom = ev.getTarget();
         
-       Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
-       Roo.log(this.el);
-       this.el.dom.style.marginBottom = '0';
-       var _this = this;
-       var editorcore = this.editorcore;
-       var editor= this.editor;
-       
-       var children = [];
-       var btn = function(id,cmd , toggle, handler){
-       
-            var  event = toggle ? 'toggle' : 'click';
-       
-            var a = {
-                size : 'sm',
-                xtype: 'Button',
-                xns: Roo.bootstrap,
-                glyphicon : id,
-                cmd : id || cmd,
-                enableToggle:toggle !== false,
-                //html : 'submit'
-                pressed : toggle ? false : null,
-                listeners : {}
+        //Roo.log(['enter',dom]);
+        var el = Roo.fly(dom);
+        if (this.currentEl) {
+            //Roo.log(dom);
+            //Roo.log(this.currentEl);
+            //Roo.log(this.currentEl.contains(dom));
+            if (this.currentEl == el) {
+                return;
             }
-            a.listeners[toggle ? 'toggle' : 'click'] = function() {
-                handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd ||  id);
+            if (dom != this.currentEl.dom && this.currentEl.contains(dom)) {
+                return;
             }
-            children.push(a);
-            return a;
-       }
+
+        }
         
-        var style = {
-                xtype: 'Button',
-                size : 'sm',
-                xns: Roo.bootstrap,
-                glyphicon : 'font',
-                //html : 'submit'
-                menu : {
-                    xtype: 'Menu',
-                    xns: Roo.bootstrap,
-                    items:  []
-                }
-        };
-        Roo.each(this.formats, function(f) {
-            style.menu.items.push({
-                xtype :'MenuItem',
-                xns: Roo.bootstrap,
-                html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
-                tagname : f,
-                listeners : {
-                    click : function()
-                    {
-                        editorcore.insertTag(this.tagname);
-                        editor.focus();
-                    }
-                }
-                
-            });
-        });
-         children.push(style);   
-            
-            
-        btn('bold',false,true);
-        btn('italic',false,true);
-        btn('align-left', 'justifyleft',true);
-        btn('align-center', 'justifycenter',true);
-        btn('align-right' , 'justifyright',true);
-        btn('link', false, false, function(btn) {
-            //Roo.log("create link?");
-            var url = prompt(this.createLinkText, this.defaultLinkValue);
-            if(url && url != 'http:/'+'/'){
-                this.editorcore.relayCmd('createlink', url);
+        if (this.currentTip.el) {
+            this.currentTip.el.setVisibilityMode(Roo.Element.DISPLAY).hide(); // force hiding...
+        }    
+        //Roo.log(ev);
+        var bindEl = el;
+        
+        // you can not look for children, as if el is the body.. then everythign is the child..
+        if (!el.attr('tooltip')) { //
+            if (!el.select("[tooltip]").elements.length) {
+                return;
             }
-        }),
-        btn('list','insertunorderedlist',true);
-        btn('pencil', false,true, function(btn){
-                Roo.log(this);
-                
-                this.toggleSourceEdit(btn.pressed);
-        });
-        /*
-        var cog = {
-                xtype: 'Button',
-                size : 'sm',
-                xns: Roo.bootstrap,
-                glyphicon : 'cog',
-                //html : 'submit'
-                menu : {
-                    xtype: 'Menu',
-                    xns: Roo.bootstrap,
-                    items:  []
-                }
-        };
+            // is the mouse over this child...?
+            bindEl = el.select("[tooltip]").first();
+            var xy = ev.getXY();
+            if (!bindEl.getRegion().contains( { top : xy[1] ,right : xy[0] , bottom : xy[1], left : xy[0]})) {
+                //Roo.log("not in region.");
+                return;
+            }
+            //Roo.log("child element over..");
+            
+        }
+        this.currentEl = bindEl;
+        this.currentTip.bind(bindEl);
+        this.currentRegion = Roo.lib.Region.getRegion(dom);
+        this.currentTip.enter();
         
-        cog.menu.items.push({
-            xtype :'MenuItem',
-            xns: Roo.bootstrap,
-            html : Clean styles,
-            tagname : f,
-            listeners : {
-                click : function()
+    },
+    leave : function(ev)
+    {
+        var dom = ev.getTarget();
+        //Roo.log(['leave',dom]);
+        if (!this.currentEl) {
+            return;
+        }
+        
+        
+        if (dom != this.currentEl.dom) {
+            return;
+        }
+        var xy = ev.getXY();
+        if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0]  ))) {
+            return;
+        }
+        // only activate leave if mouse cursor is outside... bounding box..
+        
+        
+        
+        
+        if (this.currentTip) {
+            this.currentTip.leave();
+        }
+        //Roo.log('clear currentEl');
+        this.currentEl = false;
+        
+        
+    },
+    alignment : {
+        'left' : ['r-l', [-2,0], 'right'],
+        'right' : ['l-r', [2,0], 'left'],
+        'bottom' : ['t-b', [0,2], 'top'],
+        'top' : [ 'b-t', [0,-2], 'bottom']
+    }
+    
+});
+
+
+Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
+    
+    
+    bindEl : false,
+    
+    delay : null, // can be { show : 300 , hide: 500}
+    
+    timeout : null,
+    
+    hoverState : null, //???
+    
+    placement : 'bottom', 
+    
+    getAutoCreate : function(){
+    
+        var cfg = {
+           cls : 'tooltip',
+           role : 'tooltip',
+           cn : [
                 {
-                    editorcore.insertTag(this.tagname);
-                    editor.focus();
+                    cls : 'tooltip-arrow'
+                },
+                {
+                    cls : 'tooltip-inner'
                 }
-            }
-            
-        });
-       */
-        
-         
-       this.xtype = 'NavSimplebar';
+           ]
+        };
         
-        for(var i=0;i< children.length;i++) {
-            
-            this.buttons.add(this.addxtypeChild(children[i]));
-            
+        return cfg;
+    },
+    bind : function(el)
+    {
+        this.bindEl = el;
+    },
+      
+    
+    enter : function () {
+       
+        if (this.timeout != null) {
+            clearTimeout(this.timeout);
         }
         
-        editor.on('editorevent', this.updateToolbar, this);
+        this.hoverState = 'in';
+         //Roo.log("enter - show");
+        if (!this.delay || !this.delay.show) {
+            this.show();
+            return;
+        }
+        var _t = this;
+        this.timeout = setTimeout(function () {
+            if (_t.hoverState == 'in') {
+                _t.show();
+            }
+        }, this.delay.show);
     },
-    onBtnClick : function(id)
+    leave : function()
     {
-       this.editorcore.relayCmd(id);
-       this.editorcore.focus();
-    },
+        clearTimeout(this.timeout);
     
-    /**
-     * Protected method that will not generally be called directly. It triggers
-     * a toolbar update by reading the markup state of the current selection in the editor.
-     */
-    updateToolbar: function(){
-
-        if(!this.editorcore.activated){
-            this.editor.onFirstFocus(); // is this neeed?
+        this.hoverState = 'out';
+         if (!this.delay || !this.delay.hide) {
+            this.hide();
             return;
         }
-
-        var btns = this.buttons; 
-        var doc = this.editorcore.doc;
-        btns.get('bold').setActive(doc.queryCommandState('bold'));
-        btns.get('italic').setActive(doc.queryCommandState('italic'));
-        //btns.get('underline').setActive(doc.queryCommandState('underline'));
+       
+        var _t = this;
+        this.timeout = setTimeout(function () {
+            //Roo.log("leave - timeout");
+            
+            if (_t.hoverState == 'out') {
+                _t.hide();
+                Roo.bootstrap.Tooltip.currentEl = false;
+            }
+        }, delay);
+    },
+    
+    show : function ()
+    {
+        if (!this.el) {
+            this.render(document.body);
+        }
+        // set content.
+        //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
         
-        btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
-        btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
-        btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
+        var tip = this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
         
-        //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
-        btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
-         /*
+        this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
         
-        var ans = this.editorcore.getAllAncestors();
-        if (this.formatCombo) {
-            
+        this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
+        
+        var placement = typeof this.placement == 'function' ?
+            this.placement.call(this, this.el, on_el) :
+            this.placement;
             
-            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;
-                }
-            }
+        var autoToken = /\s?auto?\s?/i;
+        var autoPlace = autoToken.test(placement);
+        if (autoPlace) {
+            placement = placement.replace(autoToken, '') || 'top';
         }
         
+        //this.el.detach()
+        //this.el.setXY([0,0]);
+        this.el.show();
+        //this.el.dom.style.display='block';
+        
+        //this.el.appendTo(on_el);
         
+        var p = this.getPosition();
+        var box = this.el.getBox();
         
-        // hides menus... - so this cant be on a menu...
-        Roo.bootstrap.MenuMgr.hideAll();
-        */
-        Roo.bootstrap.MenuMgr.hideAll();
-        //this.editorsyncValue();
-    },
-    onFirstFocus: function() {
-        this.buttons.each(function(item){
-           item.enable();
-        });
-    },
-    toggleSourceEdit : function(sourceEditMode){
+        if (autoPlace) {
+            // fixme..
+        }
         
-          
-        if(sourceEditMode){
-            Roo.log("disabling buttons");
-           this.buttons.each( function(item){
-                if(item.cmd != 'pencil'){
-                    item.disable();
-                }
-            });
-          
-        }else{
-            Roo.log("enabling buttons");
-            if(this.editorcore.initialized){
-                this.buttons.each( function(item){
-                    item.enable();
-                });
+        var align = Roo.bootstrap.Tooltip.alignment[placement];
+        
+        var xy = this.el.getAlignToXY(this.bindEl, align[0], align[1]);
+        
+        if(placement == 'top' || placement == 'bottom'){
+            if(xy[0] < 0){
+                placement = 'right';
             }
             
+            if(xy[0] + this.el.getWidth() > Roo.lib.Dom.getViewWidth()){
+                placement = 'left';
+            }
         }
-        Roo.log("calling toggole on editor");
-        // tell the editor that it's been pressed..
-        this.editor.toggleSourceEdit(sourceEditMode);
-       
+        
+        align = Roo.bootstrap.Tooltip.alignment[placement];
+        
+        this.el.alignTo(this.bindEl, align[0],align[1]);
+        //var arrow = this.el.select('.arrow',true).first();
+        //arrow.set(align[2], 
+        
+        this.el.addClass(placement);
+        
+        this.el.addClass('in fade');
+        
+        this.hoverState = null;
+        
+        if (this.el.hasClass('fade')) {
+            // fade it?
+        }
+        
+    },
+    hide : function()
+    {
+         
+        if (!this.el) {
+            return;
+        }
+        //this.el.setXY([0,0]);
+        this.el.removeClass('in');
+        //this.el.hide();
+        
     }
+    
 });
 
-
-
-
-
-/**
- * @class Roo.bootstrap.Table.AbstractSelectionModel
- * @extends Roo.util.Observable
- * Abstract base class for grid SelectionModels.  It provides the interface that should be
- * implemented by descendant classes.  This class should not be directly instantiated.
- * @constructor
+ /*
+ * - LGPL
+ *
+ * Location Picker
+ * 
  */
-Roo.bootstrap.Table.AbstractSelectionModel = function(){
-    this.locked = false;
-    Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
-};
-
-
-Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable,  {
-    /** @ignore Called by the grid automatically. Do not call directly. */
-    init : function(grid){
-        this.grid = grid;
-        this.initEvents();
-    },
-
-    /**
-     * Locks the selections.
-     */
-    lock : function(){
-        this.locked = true;
-    },
-
-    /**
-     * Unlocks the selections.
-     */
-    unlock : function(){
-        this.locked = false;
-    },
 
-    /**
-     * Returns true if the selections are locked.
-     * @return {Boolean}
-     */
-    isLocked : function(){
-        return this.locked;
-    }
-});
 /**
- * @extends Roo.bootstrap.Table.AbstractSelectionModel
- * @class Roo.bootstrap.Table.RowSelectionModel
- * The default SelectionModel used by {@link Roo.bootstrap.Table}.
- * It supports multiple selections and keyboard selection/navigation. 
+ * @class Roo.bootstrap.LocationPicker
+ * @extends Roo.bootstrap.Component
+ * Bootstrap LocationPicker class
+ * @cfg {Number} latitude Position when init default 0
+ * @cfg {Number} longitude Position when init default 0
+ * @cfg {Number} zoom default 15
+ * @cfg {String} mapTypeId default google.maps.MapTypeId.ROADMAP
+ * @cfg {Boolean} mapTypeControl default false
+ * @cfg {Boolean} disableDoubleClickZoom default false
+ * @cfg {Boolean} scrollwheel default true
+ * @cfg {Boolean} streetViewControl default false
+ * @cfg {Number} radius default 0
+ * @cfg {String} locationName
+ * @cfg {Boolean} draggable default true
+ * @cfg {Boolean} enableAutocomplete default false
+ * @cfg {Boolean} enableReverseGeocode default true
+ * @cfg {String} markerTitle
+ * 
  * @constructor
- * @param {Object} config
+ * Create a new LocationPicker
+ * @param {Object} config The config object
  */
 
-Roo.bootstrap.Table.RowSelectionModel = function(config){
-    Roo.apply(this, config);
-    this.selections = new Roo.util.MixedCollection(false, function(o){
-        return o.id;
-    });
-
-    this.last = false;
-    this.lastActive = false;
 
+Roo.bootstrap.LocationPicker = function(config){
+    
+    Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
+    
     this.addEvents({
         /**
-            * @event selectionchange
-            * Fires when the selection changes
-            * @param {SelectionModel} this
-            */
-           "selectionchange" : true,
+         * @event initial
+         * Fires when the picker initialized.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Google Location} location
+         */
+        initial : true,
         /**
-            * @event afterselectionchange
-            * Fires after the selection changes (eg. by key press or clicking)
-            * @param {SelectionModel} this
-            */
-           "afterselectionchange" : true,
+         * @event positionchanged
+         * Fires when the picker position changed.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Google Location} location
+         */
+        positionchanged : true,
         /**
-            * @event beforerowselect
-            * Fires when a row is selected being selected, return false to cancel.
-            * @param {SelectionModel} this
-            * @param {Number} rowIndex The selected index
-            * @param {Boolean} keepExisting False if other selections will be cleared
-            */
-           "beforerowselect" : true,
+         * @event resize
+         * Fires when the map resize.
+         * @param {Roo.bootstrap.LocationPicker} this
+         */
+        resize : true,
         /**
-            * @event rowselect
-            * Fires when a row is selected.
-            * @param {SelectionModel} this
-            * @param {Number} rowIndex The selected index
-            * @param {Roo.data.Record} r The record
-            */
-           "rowselect" : true,
+         * @event show
+         * Fires when the map show.
+         * @param {Roo.bootstrap.LocationPicker} this
+         */
+        show : true,
         /**
-            * @event rowdeselect
-            * Fires when a row is deselected.
-            * @param {SelectionModel} this
-            * @param {Number} rowIndex The selected index
-            */
-        "rowdeselect" : true
+         * @event hide
+         * Fires when the map hide.
+         * @param {Roo.bootstrap.LocationPicker} this
+         */
+        hide : true,
+        /**
+         * @event mapClick
+         * Fires when click the map.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Map event} e
+         */
+        mapClick : true,
+        /**
+         * @event mapRightClick
+         * Fires when right click the map.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Map event} e
+         */
+        mapRightClick : true,
+        /**
+         * @event markerClick
+         * Fires when click the marker.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Map event} e
+         */
+        markerClick : true,
+        /**
+         * @event markerRightClick
+         * Fires when right click the marker.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Map event} e
+         */
+        markerRightClick : true,
+        /**
+         * @event OverlayViewDraw
+         * Fires when OverlayView Draw
+         * @param {Roo.bootstrap.LocationPicker} this
+         */
+        OverlayViewDraw : true,
+        /**
+         * @event OverlayViewOnAdd
+         * Fires when OverlayView Draw
+         * @param {Roo.bootstrap.LocationPicker} this
+         */
+        OverlayViewOnAdd : true,
+        /**
+         * @event OverlayViewOnRemove
+         * Fires when OverlayView Draw
+         * @param {Roo.bootstrap.LocationPicker} this
+         */
+        OverlayViewOnRemove : true,
+        /**
+         * @event OverlayViewShow
+         * Fires when OverlayView Draw
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Pixel} cpx
+         */
+        OverlayViewShow : true,
+        /**
+         * @event OverlayViewHide
+         * Fires when OverlayView Draw
+         * @param {Roo.bootstrap.LocationPicker} this
+         */
+        OverlayViewHide : true
     });
-    Roo.bootstrap.Table.RowSelectionModel.superclass.constructor.call(this);
-    this.locked = false;
+        
 };
 
-Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSelectionModel,  {
-    /**
-     * @cfg {Boolean} singleSelect
-     * True to allow selection of only one row at a time (defaults to false)
-     */
-    singleSelect : false,
-
-    // private
-    initEvents : function(){
+Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component,  {
+    
+    gMapContext: false,
+    
+    latitude: 0,
+    longitude: 0,
+    zoom: 15,
+    mapTypeId: false,
+    mapTypeControl: false,
+    disableDoubleClickZoom: false,
+    scrollwheel: true,
+    streetViewControl: false,
+    radius: 0,
+    locationName: '',
+    draggable: true,
+    enableAutocomplete: false,
+    enableReverseGeocode: true,
+    markerTitle: '',
+    
+    getAutoCreate: function()
+    {
 
-        if(!this.grid.enableDragDrop && !this.grid.enableDrag){
-            this.grid.on("mousedown", this.handleMouseDown, this);
-        }else{ // allow click to work like normal
-            this.grid.on("rowclick", this.handleDragableRowClick, this);
+        var cfg = {
+            tag: 'div',
+            cls: 'roo-location-picker'
+        };
+        
+        return cfg
+    },
+    
+    initEvents: function(ct, position)
+    {       
+        if(!this.el.getWidth() || this.isApplied()){
+            return;
         }
-
-        this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), {
-            "up" : function(e){
-                if(!e.shiftKey){
-                    this.selectPrevious(e.shiftKey);
-                }else if(this.last !== false && this.lastActive !== false){
-                    var last = this.last;
-                    this.selectRange(this.last,  this.lastActive-1);
-                    this.grid.getView().focusRow(this.lastActive);
-                    if(last !== false){
-                        this.last = last;
-                    }
-                }else{
-                    this.selectFirstRow();
-                }
-                this.fireEvent("afterselectionchange", this);
-            },
-            "down" : function(e){
-                if(!e.shiftKey){
-                    this.selectNext(e.shiftKey);
-                }else if(this.last !== false && this.lastActive !== false){
-                    var last = this.last;
-                    this.selectRange(this.last,  this.lastActive+1);
-                    this.grid.getView().focusRow(this.lastActive);
-                    if(last !== false){
-                        this.last = last;
-                    }
-                }else{
-                    this.selectFirstRow();
-                }
-                this.fireEvent("afterselectionchange", this);
-            },
-            scope: this
+        
+        this.el.setVisibilityMode(Roo.Element.DISPLAY);
+        
+        this.initial();
+    },
+    
+    initial: function()
+    {
+        if(!this.mapTypeId){
+            this.mapTypeId = google.maps.MapTypeId.ROADMAP;
+        }
+        
+        this.gMapContext = this.GMapContext();
+        
+        this.initOverlayView();
+        
+        this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
+        
+        var _this = this;
+                
+        google.maps.event.addListener(this.gMapContext.marker, "dragend", function(event) {
+            _this.setPosition(_this.gMapContext.marker.position);
+        });
+        
+        google.maps.event.addListener(this.gMapContext.map, 'click', function(event){
+            _this.fireEvent('mapClick', this, event);
+            
+        });
+
+        google.maps.event.addListener(this.gMapContext.map, 'rightclick', function(event){
+            _this.fireEvent('mapRightClick', this, event);
+            
+        });
+        
+        google.maps.event.addListener(this.gMapContext.marker, 'click', function(event){
+            _this.fireEvent('markerClick', this, event);
+            
         });
 
-        var view = this.grid.view;
-        view.on("refresh", this.onRefresh, this);
-        view.on("rowupdated", this.onRowUpdated, this);
-        view.on("rowremoved", this.onRemove, this);
+        google.maps.event.addListener(this.gMapContext.marker, 'rightclick', function(event){
+            _this.fireEvent('markerRightClick', this, event);
+            
+        });
+        
+        this.setPosition(this.gMapContext.location);
+        
+        this.fireEvent('initial', this, this.gMapContext.location);
     },
-
-    // private
-    onRefresh : function(){
-        var ds = this.grid.dataSource, i, v = this.grid.view;
-        var s = this.selections;
-        s.each(function(r){
-            if((i = ds.indexOfId(r.id)) != -1){
-                v.onRowSelect(i);
-            }else{
-                s.remove(r);
+    
+    initOverlayView: function()
+    {
+        var _this = this;
+        
+        Roo.bootstrap.LocationPicker.OverlayView.prototype = Roo.apply(new google.maps.OverlayView(), {
+            
+            draw: function()
+            {
+                _this.fireEvent('OverlayViewDraw', _this);
+            },
+            
+            onAdd: function()
+            {
+                _this.fireEvent('OverlayViewOnAdd', _this);
+            },
+            
+            onRemove: function()
+            {
+                _this.fireEvent('OverlayViewOnRemove', _this);
+            },
+            
+            show: function(cpx)
+            {
+                _this.fireEvent('OverlayViewShow', _this, cpx);
+            },
+            
+            hide: function()
+            {
+                _this.fireEvent('OverlayViewHide', _this);
             }
+            
         });
     },
-
-    // private
-    onRemove : function(v, index, r){
-        this.selections.remove(r);
-    },
-
-    // private
-    onRowUpdated : function(v, index, r){
-        if(this.isSelected(r)){
-            v.onRowSelect(index);
-        }
-    },
-
-    /**
-     * Select records.
-     * @param {Array} records The records to select
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectRecords : function(records, keepExisting){
-        if(!keepExisting){
-            this.clearSelections();
-        }
-        var ds = this.grid.dataSource;
-        for(var i = 0, len = records.length; i < len; i++){
-            this.selectRow(ds.indexOf(records[i]), true);
-        }
+    
+    fromLatLngToContainerPixel: function(event)
+    {
+        return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
     },
-
-    /**
-     * Gets the number of selected rows.
-     * @return {Number}
-     */
-    getCount : function(){
-        return this.selections.length;
+    
+    isApplied: function() 
+    {
+        return this.getGmapContext() == false ? false : true;
     },
-
-    /**
-     * Selects the first row in the grid.
-     */
-    selectFirstRow : function(){
-        this.selectRow(0);
+    
+    getGmapContext: function() 
+    {
+        return this.gMapContext
     },
-
-    /**
-     * Select the last row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectLastRow : function(keepExisting){
-        this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting);
+    
+    GMapContext: function() 
+    {
+        var position = new google.maps.LatLng(this.latitude, this.longitude);
+        
+        var _map = new google.maps.Map(this.el.dom, {
+            center: position,
+            zoom: this.zoom,
+            mapTypeId: this.mapTypeId,
+            mapTypeControl: this.mapTypeControl,
+            disableDoubleClickZoom: this.disableDoubleClickZoom,
+            scrollwheel: this.scrollwheel,
+            streetViewControl: this.streetViewControl,
+            locationName: this.locationName,
+            draggable: this.draggable,
+            enableAutocomplete: this.enableAutocomplete,
+            enableReverseGeocode: this.enableReverseGeocode
+        });
+        
+        var _marker = new google.maps.Marker({
+            position: position,
+            map: _map,
+            title: this.markerTitle,
+            draggable: this.draggable
+        });
+        
+        return {
+            map: _map,
+            marker: _marker,
+            circle: null,
+            location: position,
+            radius: this.radius,
+            locationName: this.locationName,
+            addressComponents: {
+                formatted_address: null,
+                addressLine1: null,
+                addressLine2: null,
+                streetName: null,
+                streetNumber: null,
+                city: null,
+                district: null,
+                state: null,
+                stateOrProvince: null
+            },
+            settings: this,
+            domContainer: this.el.dom,
+            geodecoder: new google.maps.Geocoder()
+        };
     },
-
-    /**
-     * Selects the row immediately following the last selected row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectNext : function(keepExisting){
-        if(this.last !== false && (this.last+1) < this.grid.dataSource.getCount()){
-            this.selectRow(this.last+1, keepExisting);
-            this.grid.getView().focusRow(this.last);
+    
+    drawCircle: function(center, radius, options) 
+    {
+        if (this.gMapContext.circle != null) {
+            this.gMapContext.circle.setMap(null);
         }
-    },
-
-    /**
-     * Selects the row that precedes the last selected row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectPrevious : function(keepExisting){
-        if(this.last){
-            this.selectRow(this.last-1, keepExisting);
-            this.grid.getView().focusRow(this.last);
+        if (radius > 0) {
+            radius *= 1;
+            options = Roo.apply({}, options, {
+                strokeColor: "#0000FF",
+                strokeOpacity: .35,
+                strokeWeight: 2,
+                fillColor: "#0000FF",
+                fillOpacity: .2
+            });
+            
+            options.map = this.gMapContext.map;
+            options.radius = radius;
+            options.center = center;
+            this.gMapContext.circle = new google.maps.Circle(options);
+            return this.gMapContext.circle;
         }
+        
+        return null;
     },
-
-    /**
-     * Returns the selected records
-     * @return {Array} Array of selected records
-     */
-    getSelections : function(){
-        return [].concat(this.selections.items);
-    },
-
-    /**
-     * Returns the first selected record.
-     * @return {Record}
-     */
-    getSelected : function(){
-        return this.selections.itemAt(0);
-    },
-
-
-    /**
-     * Clears all selections.
-     */
-    clearSelections : function(fast){
-        if(this.locked) return;
-        if(fast !== true){
-            var ds = this.grid.dataSource;
-            var s = this.selections;
-            s.each(function(r){
-                this.deselectRow(ds.indexOfId(r.id));
-            }, this);
-            s.clear();
-        }else{
-            this.selections.clear();
+    
+    setPosition: function(location) 
+    {
+        this.gMapContext.location = location;
+        this.gMapContext.marker.setPosition(location);
+        this.gMapContext.map.panTo(location);
+        this.drawCircle(location, this.gMapContext.radius, {});
+        
+        var _this = this;
+        
+        if (this.gMapContext.settings.enableReverseGeocode) {
+            this.gMapContext.geodecoder.geocode({
+                latLng: this.gMapContext.location
+            }, function(results, status) {
+                
+                if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
+                    _this.gMapContext.locationName = results[0].formatted_address;
+                    _this.gMapContext.addressComponents = _this.address_component_from_google_geocode(results[0].address_components);
+                    
+                    _this.fireEvent('positionchanged', this, location);
+                }
+            });
+            
+            return;
         }
-        this.last = false;
+        
+        this.fireEvent('positionchanged', this, location);
     },
-
-
-    /**
-     * Selects all rows.
-     */
-    selectAll : function(){
-        if(this.locked) return;
-        this.selections.clear();
-        for(var i = 0, len = this.grid.dataSource.getCount(); i < len; i++){
-            this.selectRow(i, true);
-        }
+    
+    resize: function()
+    {
+        google.maps.event.trigger(this.gMapContext.map, "resize");
+        
+        this.gMapContext.map.setCenter(this.gMapContext.marker.position);
+        
+        this.fireEvent('resize', this);
     },
-
-    /**
-     * Returns True if there is a selection.
-     * @return {Boolean}
-     */
-    hasSelection : function(){
-        return this.selections.length > 0;
+    
+    setPositionByLatLng: function(latitude, longitude)
+    {
+        this.setPosition(new google.maps.LatLng(latitude, longitude));
     },
-
-    /**
-     * Returns True if the specified row is selected.
-     * @param {Number/Record} record The record or index of the record to check
-     * @return {Boolean}
-     */
-    isSelected : function(index){
-        var r = typeof index == "number" ? this.grid.dataSource.getAt(index) : index;
-        return (r && this.selections.key(r.id) ? true : false);
+    
+    getCurrentPosition: function() 
+    {
+        return {
+            latitude: this.gMapContext.location.lat(),
+            longitude: this.gMapContext.location.lng()
+        };
     },
-
-    /**
-     * Returns True if the specified record id is selected.
-     * @param {String} id The id of record to check
-     * @return {Boolean}
-     */
-    isIdSelected : function(id){
-        return (this.selections.key(id) ? true : false);
+    
+    getAddressName: function() 
+    {
+        return this.gMapContext.locationName;
     },
-
-    // private
-    handleMouseDown : function(e, t){
-        var view = this.grid.getView(), rowIndex;
-        if(this.isLocked() || (rowIndex = view.findRowIndex(t)) === false){
-            return;
-        };
-        if(e.shiftKey && this.last !== false){
-            var last = this.last;
-            this.selectRange(last, rowIndex, e.ctrlKey);
-            this.last = last; // reset the last
-            view.focusRow(rowIndex);
-        }else{
-            var isSelected = this.isSelected(rowIndex);
-            if(e.button !== 0 && isSelected){
-                view.focusRow(rowIndex);
-            }else if(e.ctrlKey && isSelected){
-                this.deselectRow(rowIndex);
-            }else if(!isSelected){
-                this.selectRow(rowIndex, e.button === 0 && (e.ctrlKey || e.shiftKey));
-                view.focusRow(rowIndex);
+    
+    getAddressComponents: function() 
+    {
+        return this.gMapContext.addressComponents;
+    },
+    
+    address_component_from_google_geocode: function(address_components) 
+    {
+        var result = {};
+        
+        for (var i = 0; i < address_components.length; i++) {
+            var component = address_components[i];
+            if (component.types.indexOf("postal_code") >= 0) {
+                result.postalCode = component.short_name;
+            } else if (component.types.indexOf("street_number") >= 0) {
+                result.streetNumber = component.short_name;
+            } else if (component.types.indexOf("route") >= 0) {
+                result.streetName = component.short_name;
+            } else if (component.types.indexOf("neighborhood") >= 0) {
+                result.city = component.short_name;
+            } else if (component.types.indexOf("locality") >= 0) {
+                result.city = component.short_name;
+            } else if (component.types.indexOf("sublocality") >= 0) {
+                result.district = component.short_name;
+            } else if (component.types.indexOf("administrative_area_level_1") >= 0) {
+                result.stateOrProvince = component.short_name;
+            } else if (component.types.indexOf("country") >= 0) {
+                result.country = component.short_name;
             }
         }
-        this.fireEvent("afterselectionchange", this);
+        
+        result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
+        result.addressLine2 = "";
+        return result;
     },
-    // private
-    handleDragableRowClick :  function(grid, rowIndex, e) 
+    
+    setZoomLevel: function(zoom)
     {
-        if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
-            this.selectRow(rowIndex, false);
-            grid.view.focusRow(rowIndex);
-             this.fireEvent("afterselectionchange", this);
-        }
+        this.gMapContext.map.setZoom(zoom);
     },
     
-    /**
-     * Selects multiple rows.
-     * @param {Array} rows Array of the indexes of the row to select
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectRows : function(rows, keepExisting){
-        if(!keepExisting){
-            this.clearSelections();
-        }
-        for(var i = 0, len = rows.length; i < len; i++){
-            this.selectRow(rows[i], true);
+    show: function()
+    {
+        if(!this.el){
+            return;
         }
+        
+        this.el.show();
+        
+        this.resize();
+        
+        this.fireEvent('show', this);
     },
-
-    /**
-     * Selects a range of rows. All rows in between startRow and endRow are also selected.
-     * @param {Number} startRow The index of the first row in the range
-     * @param {Number} endRow The index of the last row in the range
-     * @param {Boolean} keepExisting (optional) True to retain existing selections
-     */
-    selectRange : function(startRow, endRow, keepExisting){
-        if(this.locked) return;
-        if(!keepExisting){
-            this.clearSelections();
+    
+    hide: function()
+    {
+        if(!this.el){
+            return;
         }
-        if(startRow <= endRow){
-            for(var i = startRow; i <= endRow; i++){
-                this.selectRow(i, true);
-            }
-        }else{
-            for(var i = startRow; i >= endRow; i--){
-                this.selectRow(i, true);
-            }
+        
+        this.el.hide();
+        
+        this.fireEvent('hide', this);
+    }
+    
+});
+
+Roo.apply(Roo.bootstrap.LocationPicker, {
+    
+    OverlayView : function(map, options)
+    {
+        options = options || {};
+        
+        this.setMap(map);
+    }
+    
+    
+});/*
+ * - LGPL
+ *
+ * Alert
+ * 
+ */
+
+/**
+ * @class Roo.bootstrap.Alert
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Alert class
+ * @cfg {String} title The title of alert
+ * @cfg {String} html The content of alert
+ * @cfg {String} weight (  success | info | warning | danger )
+ * @cfg {String} faicon font-awesomeicon
+ * 
+ * @constructor
+ * Create a new alert
+ * @param {Object} config The config object
+ */
+
+
+Roo.bootstrap.Alert = function(config){
+    Roo.bootstrap.Alert.superclass.constructor.call(this, config);
+    
+};
+
+Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component,  {
+    
+    title: '',
+    html: '',
+    weight: false,
+    faicon: false,
+    
+    getAutoCreate : function()
+    {
+        
+        var cfg = {
+            tag : 'div',
+            cls : 'alert',
+            cn : [
+                {
+                    tag : 'i',
+                    cls : 'roo-alert-icon'
+                    
+                },
+                {
+                    tag : 'b',
+                    cls : 'roo-alert-title',
+                    html : this.title
+                },
+                {
+                    tag : 'span',
+                    cls : 'roo-alert-text',
+                    html : this.html
+                }
+            ]
+        };
+        
+        if(this.faicon){
+            cfg.cn[0].cls += ' fa ' + this.faicon;
         }
-    },
-
-    /**
-     * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
-     * @param {Number} startRow The index of the first row in the range
-     * @param {Number} endRow The index of the last row in the range
-     */
-    deselectRange : function(startRow, endRow, preventViewNotify){
-        if(this.locked) return;
-        for(var i = startRow; i <= endRow; i++){
-            this.deselectRow(i, preventViewNotify);
+        
+        if(this.weight){
+            cfg.cls += ' alert-' + this.weight;
         }
+        
+        return cfg;
     },
-
-    /**
-     * Selects a row.
-     * @param {Number} row The index of the row to select
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectRow : function(index, keepExisting, preventViewNotify){
-        if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) return;
-        if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
-            if(!keepExisting || this.singleSelect){
-                this.clearSelections();
-            }
-            var r = this.grid.dataSource.getAt(index);
-            this.selections.add(r);
-            this.last = this.lastActive = index;
-            if(!preventViewNotify){
-                this.grid.getView().onRowSelect(index);
-            }
-            this.fireEvent("rowselect", this, index, r);
-            this.fireEvent("selectionchange", this);
-        }
+    
+    initEvents: function() 
+    {
+        this.el.setVisibilityMode(Roo.Element.DISPLAY);
     },
-
-    /**
-     * Deselects a row.
-     * @param {Number} row The index of the row to deselect
-     */
-    deselectRow : function(index, preventViewNotify){
-        if(this.locked) return;
-        if(this.last == index){
-            this.last = false;
-        }
-        if(this.lastActive == index){
-            this.lastActive = false;
-        }
-        var r = this.grid.dataSource.getAt(index);
-        this.selections.remove(r);
-        if(!preventViewNotify){
-            this.grid.getView().onRowDeselect(index);
+    
+    setTitle : function(str)
+    {
+        this.el.select('.roo-alert-title',true).first().dom.innerHTML = str;
+    },
+    
+    setText : function(str)
+    {
+        this.el.select('.roo-alert-text',true).first().dom.innerHTML = str;
+    },
+    
+    setWeight : function(weight)
+    {
+        if(this.weight){
+            this.el.select('.alert',true).first().removeClass('alert-' + this.weight);
         }
-        this.fireEvent("rowdeselect", this, index);
-        this.fireEvent("selectionchange", this);
+        
+        this.weight = weight;
+        
+        this.el.select('.alert',true).first().addClass('alert-' + this.weight);
     },
-
-    // private
-    restoreLast : function(){
-        if(this._last){
-            this.last = this._last;
+    
+    setIcon : function(icon)
+    {
+        if(this.faicon){
+            this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
         }
+        
+        this.faicon = icon
+        
+        this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
     },
-
-    // private
-    acceptsNav : function(row, col, cm){
-        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    
+    hide: function() 
+    {
+        this.el.hide();   
     },
-
-    // private
-    onEditorKey : function(field, e){
-        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
-        if(k == e.TAB){
-            e.stopEvent();
-            ed.completeEdit();
-            if(e.shiftKey){
-                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
-            }else{
-                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
-            }
-        }else if(k == e.ENTER && !e.ctrlKey){
-            e.stopEvent();
-            ed.completeEdit();
-            if(e.shiftKey){
-                newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
-            }else{
-                newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
-            }
-        }else if(k == e.ESC){
-            ed.cancelEdit();
-        }
-        if(newCell){
-            g.startEditing(newCell[0], newCell[1]);
-        }
+    
+    show: function() 
+    {  
+        this.el.show();   
     }
-});/*
- * 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">
- */
+    
+});
+
  
+/*
+* Licence: LGPL
+*/
+
 /**
- * @class Roo.bootstrap.PagingToolbar
- * @extends Roo.Row
- * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
+ * @class Roo.bootstrap.UploadCropbox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap UploadCropbox class
+ * @cfg {String} emptyText show when image has been loaded
+ * @cfg {String} rotateNotify show when image too small to rotate
+ * @cfg {Number} errorTimeout default 3000
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
+ * @cfg {Array} buttons default ['rotateLeft', 'pictureBtn', 'rotateRight']
+ * @cfg {Boolean} isDocument (true|false) default false
+ * @cfg {String} url action url
+ * @cfg {String} paramName default 'imageUpload'
+ * @cfg {String} method default POST
+ * 
  * @constructor
- * Create a new PagingToolbar
+ * Create a new UploadCropbox
  * @param {Object} config The config object
  */
-Roo.bootstrap.PagingToolbar = function(config)
-{
-    // old args format still supported... - xtype is prefered..
-        // created from xtype...
-    var ds = config.dataSource;
-    this.toolbarItems = [];
-    if (config.items) {
-        this.toolbarItems = config.items;
-//        config.items = [];
-    }
-    
-    Roo.bootstrap.PagingToolbar.superclass.constructor.call(this, config);
-    this.ds = ds;
-    this.cursor = 0;
-    if (ds) { 
-        this.bind(ds);
-    }
-    
-    this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
-    
-};
 
-Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
-    /**
-     * @cfg {Roo.data.Store} dataSource
-     * The underlying data store providing the paged data
-     */
-    /**
-     * @cfg {String/HTMLElement/Element} container
-     * container The id or element that will contain the toolbar
-     */
-    /**
-     * @cfg {Boolean} displayInfo
-     * True to display the displayMsg (defaults to false)
-     */
-    /**
-     * @cfg {Number} pageSize
-     * The number of records to display per page (defaults to 20)
-     */
-    pageSize: 20,
-    /**
-     * @cfg {String} displayMsg
-     * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
-     */
-    displayMsg : 'Displaying {0} - {1} of {2}',
-    /**
-     * @cfg {String} emptyMsg
-     * The message to display when no records are found (defaults to "No data to display")
-     */
-    emptyMsg : 'No data to display',
-    /**
-     * Customizable piece of the default paging text (defaults to "Page")
-     * @type String
-     */
-    beforePageText : "Page",
-    /**
-     * Customizable piece of the default paging text (defaults to "of %0")
-     * @type String
-     */
-    afterPageText : "of {0}",
-    /**
-     * Customizable piece of the default paging text (defaults to "First Page")
-     * @type String
-     */
-    firstText : "First Page",
-    /**
-     * Customizable piece of the default paging text (defaults to "Previous Page")
-     * @type String
-     */
-    prevText : "Previous Page",
-    /**
-     * Customizable piece of the default paging text (defaults to "Next Page")
-     * @type String
-     */
-    nextText : "Next Page",
-    /**
-     * Customizable piece of the default paging text (defaults to "Last Page")
-     * @type String
-     */
-    lastText : "Last Page",
-    /**
-     * Customizable piece of the default paging text (defaults to "Refresh")
-     * @type String
-     */
-    refreshText : "Refresh",
+Roo.bootstrap.UploadCropbox = function(config){
+    Roo.bootstrap.UploadCropbox.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        /**
+         * @event beforeselectfile
+         * Fire before select file
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "beforeselectfile" : true,
+        /**
+         * @event initial
+         * Fire after initEvent
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "initial" : true,
+        /**
+         * @event crop
+         * Fire after initEvent
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} data
+         */
+        "crop" : true,
+        /**
+         * @event prepare
+         * Fire when preparing the file data
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {Object} file
+         */
+        "prepare" : true,
+        /**
+         * @event exception
+         * Fire when get exception
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {XMLHttpRequest} xhr
+         */
+        "exception" : true,
+        /**
+         * @event beforeloadcanvas
+         * Fire before load the canvas
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} src
+         */
+        "beforeloadcanvas" : true,
+        /**
+         * @event trash
+         * Fire when trash image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "trash" : true,
+        /**
+         * @event download
+         * Fire when download the image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "download" : true,
+        /**
+         * @event footerbuttonclick
+         * Fire when footerbuttonclick
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} type
+         */
+        "footerbuttonclick" : true,
+        /**
+         * @event resize
+         * Fire when resize
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "resize" : true,
+        /**
+         * @event rotate
+         * Fire when rotate the image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} pos
+         */
+        "rotate" : true,
+        /**
+         * @event inspect
+         * Fire when inspect the file
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {Object} file
+         */
+        "inspect" : true,
+        /**
+         * @event upload
+         * Fire when xhr upload the file
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {Object} data
+         */
+        "upload" : true,
+        /**
+         * @event arrange
+         * Fire when arrange the file data
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {Object} formData
+         */
+        "arrange" : true
+    });
+    
+    this.buttons = this.buttons || Roo.bootstrap.UploadCropbox.footer.STANDARD;
+};
 
+Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
+    
+    emptyText : 'Click to upload image',
+    rotateNotify : 'Image is too small to rotate',
+    errorTimeout : 3000,
+    scale : 0,
+    baseScale : 1,
+    rotate : 0,
+    dragable : false,
+    pinching : false,
+    mouseX : 0,
+    mouseY : 0,
+    cropData : false,
+    minWidth : 300,
+    minHeight : 300,
+    file : false,
+    exif : {},
+    baseRotate : 1,
+    cropType : 'image/jpeg',
     buttons : false,
-    // private
-    onRender : function(ct, position) 
+    canvasLoaded : false,
+    isDocument : false,
+    method : 'POST',
+    paramName : 'imageUpload',
+    
+    getAutoCreate : function()
     {
-        Roo.bootstrap.PagingToolbar.superclass.onRender.call(this, ct, position);
-        this.navgroup.parentId = this.id;
-        this.navgroup.onRender(this.el, null);
-        // add the buttons to the navgroup
+        var cfg = {
+            tag : 'div',
+            cls : 'roo-upload-cropbox',
+            cn : [
+                {
+                    tag : 'input',
+                    cls : 'roo-upload-cropbox-selector',
+                    type : 'file'
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-body',
+                    style : 'cursor:pointer',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-preview'
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-thumb'
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-empty-notify',
+                            html : this.emptyText
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-error-notify alert alert-danger',
+                            html : this.rotateNotify
+                        }
+                    ]
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-footer',
+                    cn : {
+                        tag : 'div',
+                        cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group',
+                        cn : []
+                    }
+                }
+            ]
+        };
         
-        if(this.displayInfo){
-            Roo.log(this.el.select('ul.navbar-nav',true).first());
-            this.el.select('ul.navbar-nav',true).first().createChild({cls:'x-paging-info'});
-            this.displayEl = this.el.select('.x-paging-info', true).first();
-//            var navel = this.navgroup.addItem( { tagtype : 'span', html : '', cls : 'x-paging-info', preventDefault : true } );
-//            this.displayEl = navel.el.select('span',true).first();
+        return cfg;
+    },
+    
+    onRender : function(ct, position)
+    {
+        Roo.bootstrap.UploadCropbox.superclass.onRender.call(this, ct, position);
+        
+        if (this.buttons.length) {
+            
+            Roo.each(this.buttons, function(bb) {
+                
+                var btn = this.el.select('.roo-upload-cropbox-footer div.roo-upload-cropbox-btn-group').first().createChild(bb);
+                
+                btn.on('click', this.onFooterButtonClick.createDelegate(this, [bb.action], true));
+                
+            }, this);
         }
+    },
+    
+    initEvents : function()
+    {
+        this.urlAPI = (window.createObjectURL && window) || 
+                                (window.URL && URL.revokeObjectURL && URL) || 
+                                (window.webkitURL && webkitURL);
+                        
+        this.bodyEl = this.el.select('.roo-upload-cropbox-body', true).first();
+        this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.selectorEl = this.el.select('.roo-upload-cropbox-selector', true).first();
+        this.selectorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.selectorEl.hide();
+        
+        this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first();
+        this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first();
+        this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.thumbEl.hide();
+        
+        this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first();
+        this.notifyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.errorEl = this.el.select('.roo-upload-cropbox-error-notify', true).first();
+        this.errorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.errorEl.hide();
+        
+        this.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first();
+        this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.footerEl.hide();
+        
+        this.setThumbBoxSize();
+        
+        this.bind();
+        
+        this.resize();
         
+        this.fireEvent('initial', this);
+    },
+
+    bind : function()
+    {
         var _this = this;
         
-        if(this.buttons){
-            Roo.each(_this.buttons, function(e){
-               Roo.factory(e).onRender(_this.el, null);
-            });
-        }
-            
-        Roo.each(_this.toolbarItems, function(e) {
-            _this.navgroup.addItem(e);
-        });
+        window.addEventListener("resize", function() { _this.resize(); } );
         
+        this.bodyEl.on('click', this.beforeSelectFile, this);
         
-        this.first = this.navgroup.addItem({
-            tooltip: this.firstText,
-            cls: "prev",
-            icon : 'fa fa-backward',
-            disabled: true,
-            preventDefault: true,
-            listeners : { click : this.onClick.createDelegate(this, ["first"]) }
-        });
+        if(Roo.isTouch){
+            this.bodyEl.on('touchstart', this.onTouchStart, this);
+            this.bodyEl.on('touchmove', this.onTouchMove, this);
+            this.bodyEl.on('touchend', this.onTouchEnd, this);
+        }
         
-        this.prev =  this.navgroup.addItem({
-            tooltip: this.prevText,
-            cls: "prev",
-            icon : 'fa fa-step-backward',
-            disabled: true,
-            preventDefault: true,
-            listeners : { click :  this.onClick.createDelegate(this, ["prev"]) }
-        });
-    //this.addSeparator();
+        if(!Roo.isTouch){
+            this.bodyEl.on('mousedown', this.onMouseDown, this);
+            this.bodyEl.on('mousemove', this.onMouseMove, this);
+            var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
+            this.bodyEl.on(mousewheel, this.onMouseWheel, this);
+            Roo.get(document).on('mouseup', this.onMouseUp, this);
+        }
         
+        this.selectorEl.on('change', this.onFileSelected, this);
+    },
+    
+    reset : function()
+    {    
+        this.scale = 0;
+        this.baseScale = 1;
+        this.rotate = 0;
+        this.baseRotate = 1;
+        this.dragable = false;
+        this.pinching = false;
+        this.mouseX = 0;
+        this.mouseY = 0;
+        this.cropData = false;
+        this.notifyEl.dom.innerHTML = this.emptyText;
         
-        var field = this.navgroup.addItem( {
-            tagtype : 'span',
-            cls : 'x-paging-position',
-            
-            html : this.beforePageText  +
-                '<input type="text" size="3" value="1" class="x-grid-page-number">' +
-                '<span class="x-paging-after">' +  String.format(this.afterPageText, 1) + '</span>'
-         } ); //?? escaped?
+        this.selectorEl.dom.value = '';
         
-        this.field = field.el.select('input', true).first();
-        this.field.on("keydown", this.onPagingKeydown, this);
-        this.field.on("focus", function(){this.dom.select();});
+    },
     
+    resize : function()
+    {
+        if(this.fireEvent('resize', this) != false){
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
+        }
+    },
     
-        this.afterTextEl =  field.el.select('.x-paging-after',true).first();
-        //this.field.setHeight(18);
-        //this.addSeparator();
-        this.next = this.navgroup.addItem({
-            tooltip: this.nextText,
-            cls: "next",
-            html : ' <i class="fa fa-step-forward">',
-            disabled: true,
-            preventDefault: true,
-            listeners : { click :  this.onClick.createDelegate(this, ["next"]) }
-        });
-        this.last = this.navgroup.addItem({
-            tooltip: this.lastText,
-            icon : 'fa fa-forward',
-            cls: "next",
-            disabled: true,
-            preventDefault: true,
-            listeners : { click :  this.onClick.createDelegate(this, ["last"]) }
-        });
-    //this.addSeparator();
-        this.loading = this.navgroup.addItem({
-            tooltip: this.refreshText,
-            icon: 'fa fa-refresh',
-            preventDefault: true,
-            listeners : { click : this.onClick.createDelegate(this, ["refresh"]) }
-        });
-
+    onFooterButtonClick : function(e, el, o, type)
+    {
+        switch (type) {
+            case 'rotate-left' :
+                this.onRotateLeft(e);
+                break;
+            case 'rotate-right' :
+                this.onRotateRight(e);
+                break;
+            case 'picture' :
+                this.beforeSelectFile(e);
+                break;
+            case 'trash' :
+                this.trash(e);
+                break;
+            case 'crop' :
+                this.crop(e);
+                break;
+            case 'download' :
+                this.download(e);
+                break;
+            default :
+                break;
+        }
+        
+        this.fireEvent('footerbuttonclick', this, type);
     },
-
-    // private
-    updateInfo : function(){
-        if(this.displayEl){
-            var count = (typeof(this.getCount) == 'undefined') ? this.ds.getCount() : this.getCount();
-            var msg = count == 0 ?
-                this.emptyMsg :
-                String.format(
-                    this.displayMsg,
-                    this.cursor+1, this.cursor+count, this.ds.getTotalCount()    
-                );
-            this.displayEl.update(msg);
+    
+    beforeSelectFile : function(e)
+    {
+        e.preventDefault();
+        
+        if(this.fireEvent('beforeselectfile', this) != false){
+            this.selectorEl.dom.click();
         }
     },
-
-    // private
-    onLoad : function(ds, r, o){
-       this.cursor = o.params ? o.params.start : 0;
-       var d = this.getPageData(),
-            ap = d.activePage,
-            ps = d.pages;
+    
+    onFileSelected : function(e)
+    {
+        e.preventDefault();
+        
+        if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
+            return;
+        }
+        
+        var file = this.selectorEl.dom.files[0];
+        
+        if(this.fireEvent('inspect', this, file) != false){
+            this.prepare(file);
+        }
         
-       this.afterTextEl.dom.innerHTML = String.format(this.afterPageText, d.pages);
-       this.field.dom.value = ap;
-       this.first.setDisabled(ap == 1);
-       this.prev.setDisabled(ap == 1);
-       this.next.setDisabled(ap == ps);
-       this.last.setDisabled(ap == ps);
-       this.loading.enable();
-       this.updateInfo();
     },
-
-    // private
-    getPageData : function(){
-        var total = this.ds.getTotalCount();
-        return {
-            total : total,
-            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
-            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
-        };
+    
+    trash : function(e)
+    {
+        this.fireEvent('trash', this);
     },
-
-    // private
-    onLoadError : function(){
-        this.loading.enable();
+    
+    download : function(e)
+    {
+        this.fireEvent('download', this);
     },
-
-    // private
-    onPagingKeydown : function(e){
-        var k = e.getKey();
-        var d = this.getPageData();
-        if(k == e.RETURN){
-            var v = this.field.dom.value, pageNum;
-            if(!v || isNaN(pageNum = parseInt(v, 10))){
-                this.field.dom.value = d.activePage;
-                return;
-            }
-            pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
-            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
-            e.stopEvent();
+    
+    loadCanvas : function(src)
+    {   
+        if(this.fireEvent('beforeloadcanvas', this, src) != false){
+            
+            this.reset();
+            
+            this.imageEl = document.createElement('img');
+            
+            var _this = this;
+            
+            this.imageEl.addEventListener("load", function(){ _this.onLoadCanvas(); });
+            
+            this.imageEl.src = src;
         }
-        else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
-        {
-          var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
-          this.field.dom.value = pageNum;
-          this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
-          e.stopEvent();
+    },
+    
+    onLoadCanvas : function()
+    {   
+        this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width;
+        this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height;
+        
+        this.bodyEl.un('click', this.beforeSelectFile, this);
+        
+        this.notifyEl.hide();
+        this.thumbEl.show();
+        this.footerEl.show();
+        
+        this.baseRotateLevel();
+        
+        if(this.isDocument){
+            this.setThumbBoxSize();
         }
-        else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
-        {
-          var v = this.field.dom.value, pageNum; 
-          var increment = (e.shiftKey) ? 10 : 1;
-          if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
-            increment *= -1;
-          if(!v || isNaN(pageNum = parseInt(v, 10))) {
-            this.field.dom.value = d.activePage;
+        
+        this.setThumbBoxPosition();
+        
+        this.baseScaleLevel();
+        
+        this.draw();
+        
+        this.resize();
+        
+        this.canvasLoaded = true;
+        
+    },
+    
+    setCanvasPosition : function()
+    {   
+        if(!this.canvasEl){
             return;
-          }
-          else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
-          {
-            this.field.dom.value = parseInt(v, 10) + increment;
-            pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
-            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
-          }
-          e.stopEvent();
         }
+        
+        var pw = Math.ceil((this.bodyEl.getWidth() - this.canvasEl.width) / 2);
+        var ph = Math.ceil((this.bodyEl.getHeight() - this.canvasEl.height) / 2);
+        
+        this.previewEl.setLeft(pw);
+        this.previewEl.setTop(ph);
+        
     },
-
-    // private
-    beforeLoad : function(){
-        if(this.loading){
-            this.loading.disable();
+    
+    onMouseDown : function(e)
+    {   
+        e.stopEvent();
+        
+        this.dragable = true;
+        this.pinching = false;
+        
+        if(this.isDocument && (this.canvasEl.width < this.thumbEl.getWidth() || this.canvasEl.height < this.thumbEl.getHeight())){
+            this.dragable = false;
+            return;
         }
+        
+        this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+        
     },
-
-    // private
-    onClick : function(which){
+    
+    onMouseMove : function(e)
+    {   
+        e.stopEvent();
         
-        var ds = this.ds;
-        if (!ds) {
+        if(!this.canvasLoaded){
             return;
         }
         
-        switch(which){
-            case "first":
-                ds.load({params:{start: 0, limit: this.pageSize}});
-            break;
-            case "prev":
-                ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
-            break;
-            case "next":
-                ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
-            break;
-            case "last":
-                var total = ds.getTotalCount();
-                var extra = total % this.pageSize;
-                var lastStart = extra ? (total - extra) : total-this.pageSize;
-                ds.load({params:{start: lastStart, limit: this.pageSize}});
-            break;
-            case "refresh":
-                ds.load({params:{start: this.cursor, limit: this.pageSize}});
-            break;
+        if (!this.dragable){
+            return;
         }
+        
+        var minX = Math.ceil(this.thumbEl.getLeft(true));
+        var minY = Math.ceil(this.thumbEl.getTop(true));
+        
+        var maxX = Math.ceil(minX + this.thumbEl.getWidth() - this.canvasEl.width);
+        var maxY = Math.ceil(minY + this.thumbEl.getHeight() - this.canvasEl.height);
+        
+        var x = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        var y = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+        
+        x = x - this.mouseX;
+        y = y - this.mouseY;
+        
+        var bgX = Math.ceil(x + this.previewEl.getLeft(true));
+        var bgY = Math.ceil(y + this.previewEl.getTop(true));
+        
+        bgX = (minX < bgX) ? minX : ((maxX > bgX) ? maxX : bgX);
+        bgY = (minY < bgY) ? minY : ((maxY > bgY) ? maxY : bgY);
+        
+        this.previewEl.setLeft(bgX);
+        this.previewEl.setTop(bgY);
+        
+        this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
     },
-
-    /**
-     * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
-     * @param {Roo.data.Store} store The data store to unbind
-     */
-    unbind : function(ds){
-        ds.un("beforeload", this.beforeLoad, this);
-        ds.un("load", this.onLoad, this);
-        ds.un("loadexception", this.onLoadError, this);
-        ds.un("remove", this.updateInfo, this);
-        ds.un("add", this.updateInfo, this);
-        this.ds = undefined;
+    
+    onMouseUp : function(e)
+    {   
+        e.stopEvent();
+        
+        this.dragable = false;
     },
-
-    /**
-     * Binds the paging toolbar to the specified {@link Roo.data.Store}
-     * @param {Roo.data.Store} store The data store to bind
-     */
-    bind : function(ds){
-        ds.on("beforeload", this.beforeLoad, this);
-        ds.on("load", this.onLoad, this);
-        ds.on("loadexception", this.onLoadError, this);
-        ds.on("remove", this.updateInfo, this);
-        ds.on("add", this.updateInfo, this);
-        this.ds = ds;
-    }
-});/*
- * - LGPL
- *
- * element
- * 
- */
-
-/**
- * @class Roo.bootstrap.MessageBar
- * @extends Roo.bootstrap.Component
- * Bootstrap MessageBar class
- * @cfg {String} html contents of the MessageBar
- * @cfg {String} weight (info | success | warning | danger) default info
- * @cfg {String} beforeClass insert the bar before the given class
- * @cfg {Boolean} closable (true | false) default false
- * @cfg {Boolean} fixed (true | false) default false, fix the bar at the top
- * 
- * @constructor
- * Create a new Element
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.MessageBar = function(config){
-    Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
-};
-
-Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component,  {
     
-    html: '',
-    weight: 'info',
-    closable: false,
-    fixed: false,
-    beforeClass: 'bootstrap-sticky-wrap',
+    onMouseWheel : function(e)
+    {   
+        e.stopEvent();
+        
+        this.startScale = this.scale;
+        
+        this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1);
+        
+        if(!this.zoomable()){
+            this.scale = this.startScale;
+            return;
+        }
+        
+        this.draw();
+        
+        return;
+    },
     
-    getAutoCreate : function(){
+    zoomable : function()
+    {
+        var minScale = this.thumbEl.getWidth() / this.minWidth;
         
-        var cfg = {
-            tag: 'div',
-            cls: 'alert alert-dismissable alert-' + this.weight,
-            cn: [
-                {
-                    tag: 'span',
-                    cls: 'message',
-                    html: this.html || ''
-                }
-            ]
+        if(this.minWidth < this.minHeight){
+            minScale = this.thumbEl.getHeight() / this.minHeight;
         }
         
-        if(this.fixed){
-            cfg.cls += ' alert-messages-fixed';
+        var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale);
+        var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale);
+        
+        if(
+                this.isDocument &&
+                (this.rotate == 0 || this.rotate == 180) && 
+                (
+                    width > this.imageEl.OriginWidth || 
+                    height > this.imageEl.OriginHeight ||
+                    (width < this.minWidth && height < this.minHeight)
+                )
+        ){
+            return false;
         }
         
-        if(this.closable){
-            cfg.cn.push({
-                tag: 'button',
-                cls: 'close',
-                html: 'x'
-            });
+        if(
+                this.isDocument &&
+                (this.rotate == 90 || this.rotate == 270) && 
+                (
+                    width > this.imageEl.OriginWidth || 
+                    height > this.imageEl.OriginHeight ||
+                    (width < this.minHeight && height < this.minWidth)
+                )
+        ){
+            return false;
         }
         
-        return cfg;
+        if(
+                !this.isDocument &&
+                (this.rotate == 0 || this.rotate == 180) && 
+                (
+                    width < this.minWidth || 
+                    width > this.imageEl.OriginWidth || 
+                    height < this.minHeight || 
+                    height > this.imageEl.OriginHeight
+                )
+        ){
+            return false;
+        }
+        
+        if(
+                !this.isDocument &&
+                (this.rotate == 90 || this.rotate == 270) && 
+                (
+                    width < this.minHeight || 
+                    width > this.imageEl.OriginWidth || 
+                    height < this.minWidth || 
+                    height > this.imageEl.OriginHeight
+                )
+        ){
+            return false;
+        }
+        
+        return true;
+        
     },
     
-    onRender : function(ct, position)
+    onRotateLeft : function(e)
+    {   
+        if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+            
+            var minScale = this.thumbEl.getWidth() / this.minWidth;
+            
+            var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+            var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
+            
+            this.startScale = this.scale;
+            
+            while (this.getScaleLevel() < minScale){
+            
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
+                }
+                
+                if(
+                        Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+                        Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
+
+                this.draw();
+                
+                return;
+            }
+            
+            this.scale = this.startScale;
+            
+            this.onRotateFail();
+            
+            return false;
+        }
+        
+        this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
+
+        if(this.isDocument){
+            this.setThumbBoxSize();
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
+        }
+        
+        this.draw();
+        
+        this.fireEvent('rotate', this, 'left');
+        
+    },
+    
+    onRotateRight : function(e)
     {
-        Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
+        if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+            
+            var minScale = this.thumbEl.getWidth() / this.minWidth;
         
-        if(!this.el){
-            var cfg = Roo.apply({},  this.getAutoCreate());
-            cfg.id = Roo.id();
+            var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+            var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
             
-            if (this.cls) {
-                cfg.cls += ' ' + this.cls;
-            }
-            if (this.style) {
-                cfg.style = this.style;
+            this.startScale = this.scale;
+            
+            while (this.getScaleLevel() < minScale){
+            
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
+                }
+                
+                if(
+                        Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+                        Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+                this.draw();
+                
+                return;
             }
-            this.el = Roo.get(document.body).createChild(cfg, Roo.select('.'+this.beforeClass, true).first());
             
-            this.el.setVisibilityMode(Roo.Element.DISPLAY);
+            this.scale = this.startScale;
+            
+            this.onRotateFail();
+            
+            return false;
+        }
+        
+        this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+        if(this.isDocument){
+            this.setThumbBoxSize();
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
         }
         
-        this.el.select('>button.close').on('click', this.hide, this);
+        this.draw();
         
+        this.fireEvent('rotate', this, 'right');
     },
     
-    show : function()
+    onRotateFail : function()
     {
-        if (!this.rendered) {
-            this.render();
-        }
-        
-        this.el.show();
+        this.errorEl.show(true);
         
-        this.fireEvent('show', this);
+        var _this = this;
         
+        (function() { _this.errorEl.hide(true); }).defer(this.errorTimeout);
     },
     
-    hide : function()
+    draw : function()
     {
-        if (!this.rendered) {
-            this.render();
+        this.previewEl.dom.innerHTML = '';
+        
+        var canvasEl = document.createElement("canvas");
+        
+        var contextEl = canvasEl.getContext("2d");
+        
+        canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+        canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        var center = this.imageEl.OriginWidth / 2;
+        
+        if(this.imageEl.OriginWidth < this.imageEl.OriginHeight){
+            canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+            canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+            center = this.imageEl.OriginHeight / 2;
         }
         
-        this.el.hide();
+        contextEl.scale(this.getScaleLevel(), this.getScaleLevel());
         
-        this.fireEvent('hide', this);
-    },
-    
-    update : function()
-    {
-//        var e = this.el.dom.firstChild;
-//        
-//        if(this.closable){
-//            e = e.nextSibling;
-//        }
-//        
-//        e.data = this.html || '';
-
-        this.el.select('>.message', true).first().dom.innerHTML = this.html || '';
-    }
-   
-});
-
-
-     /*
- * - LGPL
- *
- * Graph
- * 
- */
-
-
-/**
- * @class Roo.bootstrap.Graph
- * @extends Roo.bootstrap.Component
- * Bootstrap Graph class
-> Prameters
- -sm {number} sm 4
- -md {number} md 5
- @cfg {String} graphtype  bar | vbar | pie
- @cfg {number} g_x coodinator | centre x (pie)
- @cfg {number} g_y coodinator | centre y (pie)
- @cfg {number} g_r radius (pie)
- @cfg {number} g_height height of the chart (respected by all elements in the set)
- @cfg {number} g_width width of the chart (respected by all elements in the set)
- @cfg {Object} title The title of the chart
-    
- -{Array}  values
- -opts (object) options for the chart 
-     o {
-     o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
-     o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
-     o vgutter (number)
-     o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
-     o stacked (boolean) whether or not to tread values as in a stacked bar chart
-     o to
-     o stretch (boolean)
-     o }
- -opts (object) options for the pie
-     o{
-     o cut
-     o startAngle (number)
-     o endAngle (number)
-     } 
- *
- * @constructor
- * Create a new Input
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.Graph = function(config){
-    Roo.bootstrap.Graph.superclass.constructor.call(this, config);
-    
-    this.addEvents({
-        // img events
-        /**
-         * @event click
-         * The img click event for the img.
-         * @param {Roo.EventObject} e
-         */
-        "click" : true
-    });
-};
+        contextEl.translate(center, center);
+        contextEl.rotate(this.rotate * Math.PI / 180);
 
-Roo.extend(Roo.bootstrap.Graph, Roo.bootstrap.Component,  {
-    
-    sm: 4,
-    md: 5,
-    graphtype: 'bar',
-    g_height: 250,
-    g_width: 400,
-    g_x: 50,
-    g_y: 50,
-    g_r: 30,
-    opts:{
-        //g_colors: this.colors,
-        g_type: 'soft',
-        g_gutter: '20%'
-
-    },
-    title : false,
-
-    getAutoCreate : function(){
+        contextEl.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
         
-        var cfg = {
-            tag: 'div',
-            html : null
+        this.canvasEl = document.createElement("canvas");
+        
+        this.contextEl = this.canvasEl.getContext("2d");
+        
+        switch (this.rotate) {
+            case 0 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 90 : 
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 180 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 270 :
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            default : 
+                break;
         }
         
+        this.previewEl.appendChild(this.canvasEl);
         
-        return  cfg;
+        this.setCanvasPosition();
     },
-
-    onRender : function(ct,position){
-        Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
-        this.raphael = Raphael(this.el.dom);
+    
+    crop : function()
+    {
+        if(!this.canvasLoaded){
+            return;
+        }
         
-                    // data1 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
-                    // data2 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
-                    // data3 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
-                    // txtattr = { font: "12px 'Fontin Sans', Fontin-Sans, sans-serif" };
-                /*
-                r.text(160, 10, "Single Series Chart").attr(txtattr);
-                r.text(480, 10, "Multiline Series Chart").attr(txtattr);
-                r.text(160, 250, "Multiple Series Stacked Chart").attr(txtattr);
-                r.text(480, 250, 'Multiline Series Stacked Vertical Chart. Type "round"').attr(txtattr);
+        var imageCanvas = document.createElement("canvas");
+        
+        var imageContext = imageCanvas.getContext("2d");
+        
+        imageCanvas.width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
+        imageCanvas.height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
+        
+        var center = imageCanvas.width / 2;
+        
+        imageContext.translate(center, center);
+        
+        imageContext.rotate(this.rotate * Math.PI / 180);
+        
+        imageContext.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
+        
+        var canvas = document.createElement("canvas");
+        
+        var context = canvas.getContext("2d");
                 
-                r.barchart(10, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10]], 0, {type: "sharp"});
-                r.barchart(330, 10, 300, 220, data1);
-                r.barchart(10, 250, 300, 220, data2, {stacked: true});
-                r.barchart(330, 250, 300, 220, data3, {stacked: true, type: "round"});
-                */
+        canvas.width = this.minWidth;
+        canvas.height = this.minHeight;
+
+        switch (this.rotate) {
+            case 0 :
                 
-                // var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
-                // r.barchart(30, 30, 560, 250,  xdata, {
-                //    labels : [55, 20, 13, 32, 5, 1, 2, 10,5 , 10],
-                //     axis : "0 0 1 1",
-                //     axisxlabels :  xdata
-                //     //yvalues : cols,
-                   
-                // });
-//        var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
-//        
-//        this.load(null,xdata,{
-//                axis : "0 0 1 1",
-//                axisxlabels :  xdata
-//                });
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
 
-    },
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
 
-    load : function(graphtype,xdata,opts){
-        this.raphael.clear();
-        if(!graphtype) {
-            graphtype = this.graphtype;
-        }
-        if(!opts){
-            opts = this.opts;
-        }
-        var r = this.raphael,
-            fin = function () {
-                this.flag = r.popup(this.bar.x, this.bar.y, this.bar.value || "0").insertBefore(this);
-            },
-            fout = function () {
-                this.flag.animate({opacity: 0}, 300, function () {this.remove();});
-            },
-            pfin = function() {
-                this.sector.stop();
-                this.sector.scale(1.1, 1.1, this.cx, this.cy);
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 90 : 
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
 
-                if (this.label) {
-                    this.label[0].stop();
-                    this.label[0].attr({ r: 7.5 });
-                    this.label[1].attr({ "font-weight": 800 });
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+                
+                sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 180 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
                 }
-            },
-            pfout = function() {
-                this.sector.animate({ transform: 's1 1 ' + this.cx + ' ' + this.cy }, 500, "bounce");
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
 
-                if (this.label) {
-                    this.label[0].animate({ r: 5 }, 500, "bounce");
-                    this.label[1].attr({ "font-weight": 400 });
-                }
-            };
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
 
-        switch(graphtype){
-            case 'bar':
-                this.raphael.barchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
-                break;
-            case 'hbar':
-                this.raphael.hbarchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
-                break;
-            case 'pie':
-//                opts = { legend: ["%% - Enterprise Users", "% - ddd","Chrome Users"], legendpos: "west", 
-//                href: ["http://raphaeljs.com", "http://g.raphaeljs.com"]};
-//            
-                this.raphael.piechart(this.g_x,this.g_y,this.g_r,xdata,opts).hover(pfin, pfout);
+                sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+                sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
                 
                 break;
+            case 270 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
 
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+                
+                sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            default : 
+                break;
         }
         
-        if(this.title){
-            this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
+        this.cropData = canvas.toDataURL(this.cropType);
+        
+        if(this.fireEvent('crop', this, this.cropData) !== false){
+            this.process(this.file, this.cropData);
         }
         
-    },
-    
-    setTitle: function(o)
-    {
-        this.title = o;
-    },
-    
-    initEvents: function() {
+        return;
         
-        if(!this.href){
-            this.el.on('click', this.onClick, this);
-        }
     },
     
-    onClick : function(e)
+    setThumbBoxSize : function()
     {
-        Roo.log('img onclick');
-        this.fireEvent('click', this, e);
-    }
-   
-});
-
-/*
- * - LGPL
- *
- * numberBox
- * 
- */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
-
-/**
- * @class Roo.bootstrap.dash.NumberBox
- * @extends Roo.bootstrap.Component
- * Bootstrap NumberBox class
- * @cfg {String} headline Box headline
- * @cfg {String} content Box content
- * @cfg {String} icon Box icon
- * @cfg {String} footer Footer text
- * @cfg {String} fhref Footer href
- * 
- * @constructor
- * Create a new NumberBox
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.dash.NumberBox = function(config){
-    Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
-    
-};
-
-Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component,  {
-    
-    headline : '',
-    content : '',
-    icon : '',
-    footer : '',
-    fhref : '',
-    ficon : '',
-    
-    getAutoCreate : function(){
+        var width, height;
         
-        var cfg = {
-            tag : 'div',
-            cls : 'small-box ',
-            cn : [
-                {
-                    tag : 'div',
-                    cls : 'inner',
-                    cn :[
-                        {
-                            tag : 'h3',
-                            cls : 'roo-headline',
-                            html : this.headline
-                        },
-                        {
-                            tag : 'p',
-                            cls : 'roo-content',
-                            html : this.content
-                        }
-                    ]
-                }
-            ]
+        if(this.isDocument && typeof(this.imageEl) != 'undefined'){
+            width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.max(this.minWidth, this.minHeight) : Math.min(this.minWidth, this.minHeight);
+            height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.min(this.minWidth, this.minHeight) : Math.max(this.minWidth, this.minHeight);
+            
+            this.minWidth = width;
+            this.minHeight = height;
+            
+            if(this.rotate == 90 || this.rotate == 270){
+                this.minWidth = height;
+                this.minHeight = width;
+            }
         }
         
-        if(this.icon){
-            cfg.cn.push({
-                tag : 'div',
-                cls : 'icon',
-                cn :[
-                    {
-                        tag : 'i',
-                        cls : 'ion ' + this.icon
-                    }
-                ]
-            });
-        }
+        height = 300;
+        width = Math.ceil(this.minWidth * height / this.minHeight);
         
-        if(this.footer){
-            var footer = {
-                tag : 'a',
-                cls : 'small-box-footer',
-                href : this.fhref || '#',
-                html : this.footer
-            };
-            
-            cfg.cn.push(footer);
-            
+        if(this.minWidth > this.minHeight){
+            width = 300;
+            height = Math.ceil(this.minHeight * width / this.minWidth);
         }
         
-        return  cfg;
-    },
-
-    onRender : function(ct,position){
-        Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
-
+        this.thumbEl.setStyle({
+            width : width + 'px',
+            height : height + 'px'
+        });
 
-       
-                
+        return;
+            
     },
-
-    setHeadline: function (value)
+    
+    setThumbBoxPosition : function()
     {
-        this.el.select('.roo-headline',true).first().dom.innerHTML = value;
+        var x = Math.ceil((this.bodyEl.getWidth() - this.thumbEl.getWidth()) / 2 );
+        var y = Math.ceil((this.bodyEl.getHeight() - this.thumbEl.getHeight()) / 2);
+        
+        this.thumbEl.setLeft(x);
+        this.thumbEl.setTop(y);
+        
     },
     
-    setFooter: function (value, href)
+    baseRotateLevel : function()
     {
-        this.el.select('a.small-box-footer',true).first().dom.innerHTML = value;
+        this.baseRotate = 1;
         
-        if(href){
-            this.el.select('a.small-box-footer',true).first().attr('href', href);
+        if(
+                typeof(this.exif) != 'undefined' &&
+                typeof(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != 'undefined' &&
+                [1, 3, 6, 8].indexOf(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != -1
+        ){
+            this.baseRotate = this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']];
         }
         
+        this.rotate = Roo.bootstrap.UploadCropbox['Orientation'][this.baseRotate];
+        
     },
-
-    setContent: function (value)
+    
+    baseScaleLevel : function()
     {
-        this.el.select('.roo-content',true).first().dom.innerHTML = value;
-    },
-
-    initEvents: function() 
-    {   
+        var width, height;
         
-    }
-    
-});
-
-/*
- * - LGPL
- *
- * TabBox
- * 
- */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+        if(this.isDocument){
+            
+            if(this.baseRotate == 6 || this.baseRotate == 8){
+            
+                height = this.thumbEl.getHeight();
+                this.baseScale = height / this.imageEl.OriginWidth;
 
-/**
- * @class Roo.bootstrap.dash.TabBox
- * @extends Roo.bootstrap.Component
- * Bootstrap TabBox class
- * @cfg {String} title Title of the TabBox
- * @cfg {String} icon Icon of the TabBox
- * @cfg {Boolean} showtabs (true|false) show the tabs default true
- * @cfg {Boolean} tabScrollable (true|false) tab scrollable when mobile view default false
- * 
- * @constructor
- * Create a new TabBox
- * @param {Object} config The config object
- */
+                if(this.imageEl.OriginHeight * this.baseScale > this.thumbEl.getWidth()){
+                    width = this.thumbEl.getWidth();
+                    this.baseScale = width / this.imageEl.OriginHeight;
+                }
 
+                return;
+            }
 
-Roo.bootstrap.dash.TabBox = function(config){
-    Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
-    this.addEvents({
-        // raw events
-        /**
-         * @event addpane
-         * When a pane is added
-         * @param {Roo.bootstrap.dash.TabPane} pane
-         */
-        "addpane" : true,
-        /**
-         * @event activatepane
-         * When a pane is activated
-         * @param {Roo.bootstrap.dash.TabPane} pane
-         */
-        "activatepane" : true
-        
-         
-    });
-    
-    this.panes = [];
-};
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
 
-Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component,  {
+            if(this.imageEl.OriginWidth * this.baseScale > this.thumbEl.getWidth()){
+                width = this.thumbEl.getWidth();
+                this.baseScale = width / this.imageEl.OriginWidth;
+            }
 
-    title : '',
-    icon : false,
-    showtabs : true,
-    tabScrollable : false,
+            return;
+        }
+        
+        if(this.baseRotate == 6 || this.baseRotate == 8){
+            
+            width = this.thumbEl.getHeight();
+            this.baseScale = width / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getWidth()){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+            }
+            
+            if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+                
+                if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getHeight()){
+                    width = this.thumbEl.getHeight();
+                    this.baseScale = width / this.imageEl.OriginWidth;
+                }
+            }
+            
+            return;
+        }
+        
+        width = this.thumbEl.getWidth();
+        this.baseScale = width / this.imageEl.OriginWidth;
+        
+        if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getHeight()){
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+        }
+        
+        if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+            
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getWidth()){
+                width = this.thumbEl.getWidth();
+                this.baseScale = width / this.imageEl.OriginWidth;
+            }
+            
+        }
+        
+        return;
+    },
     
-    getChildContainer : function()
+    getScaleLevel : function()
     {
-        return this.el.select('.tab-content', true).first();
+        return this.baseScale * Math.pow(1.1, this.scale);
     },
     
-    getAutoCreate : function(){
+    onTouchStart : function(e)
+    {
+        if(!this.canvasLoaded){
+            this.beforeSelectFile(e);
+            return;
+        }
         
-        var header = {
-            tag: 'li',
-            cls: 'pull-left header',
-            html: this.title,
-            cn : []
-        };
+        var touches = e.browserEvent.touches;
         
-        if(this.icon){
-            header.cn.push({
-                tag: 'i',
-                cls: 'fa ' + this.icon
-            });
+        if(!touches){
+            return;
         }
         
-        var h = {
-            tag: 'ul',
-            cls: 'nav nav-tabs pull-right',
-            cn: [
-                header
-            ]
-        };
+        if(touches.length == 1){
+            this.onMouseDown(e);
+            return;
+        }
         
-        if(this.tabScrollable){
-            h = {
-                tag: 'div',
-                cls: 'tab-header',
-                cn: [
-                    {
-                        tag: 'ul',
-                        cls: 'nav nav-tabs pull-right',
-                        cn: [
-                            header
-                        ]
-                    }
-                ]
-            }
+        if(touches.length != 2){
+            return;
         }
         
-        var cfg = {
-            tag: 'div',
-            cls: 'nav-tabs-custom',
-            cn: [
-                h,
-                {
-                    tag: 'div',
-                    cls: 'tab-content no-padding',
-                    cn: []
-                }
-            ]
+        var coords = [];
+        
+        for(var i = 0, finger; finger = touches[i]; i++){
+            coords.push(finger.pageX, finger.pageY);
         }
-
-        return  cfg;
-    },
-    initEvents : function()
-    {
-        //Roo.log('add add pane handler');
-        this.on('addpane', this.onAddPane, this);
-    },
-     /**
-     * Updates the box title
-     * @param {String} html to set the title to.
-     */
-    setTitle : function(value)
-    {
-        this.el.select('.nav-tabs .header', true).first().dom.innerHTML = value;
+        
+        var x = Math.pow(coords[0] - coords[2], 2);
+        var y = Math.pow(coords[1] - coords[3], 2);
+        
+        this.startDistance = Math.sqrt(x + y);
+        
+        this.startScale = this.scale;
+        
+        this.pinching = true;
+        this.dragable = false;
+        
     },
-    onAddPane : function(pane)
+    
+    onTouchMove : function(e)
     {
-        this.panes.push(pane);
-        //Roo.log('addpane');
-        //Roo.log(pane);
-        // tabs are rendere left to right..
-        if(!this.showtabs){
+        if(!this.pinching && !this.dragable){
             return;
         }
         
-        var ctr = this.el.select('.nav-tabs', true).first();
-         
-         
-        var existing = ctr.select('.nav-tab',true);
-        var qty = existing.getCount();;
+        var touches = e.browserEvent.touches;
         
+        if(!touches){
+            return;
+        }
         
-        var tab = ctr.createChild({
-            tag : 'li',
-            cls : 'nav-tab' + (qty ? '' : ' active'),
-            cn : [
-                {
-                    tag : 'a',
-                    href:'#',
-                    html : pane.title
-                }
-            ]
-        }, qty ? existing.first().dom : ctr.select('.header', true).first().dom );
-        pane.tab = tab;
+        if(this.dragable){
+            this.onMouseMove(e);
+            return;
+        }
         
-        tab.on('click', this.onTabClick.createDelegate(this, [pane], true));
-        if (!qty) {
-            pane.el.addClass('active');
+        var coords = [];
+        
+        for(var i = 0, finger; finger = touches[i]; i++){
+            coords.push(finger.pageX, finger.pageY);
         }
         
-                
-    },
-    onTabClick : function(ev,un,ob,pane)
-    {
-        //Roo.log('tab - prev default');
-        ev.preventDefault();
+        var x = Math.pow(coords[0] - coords[2], 2);
+        var y = Math.pow(coords[1] - coords[3], 2);
         
+        this.endDistance = Math.sqrt(x + y);
         
-        this.el.select('.nav-tabs li.nav-tab', true).removeClass('active');
-        pane.tab.addClass('active');
-        //Roo.log(pane.title);
-        this.getChildContainer().select('.tab-pane',true).removeClass('active');
-        // technically we should have a deactivate event.. but maybe add later.
-        // and it should not de-activate the selected tab...
-        this.fireEvent('activatepane', pane);
-        pane.el.addClass('active');
-        pane.fireEvent('activate');
+        this.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1));
+        
+        if(!this.zoomable()){
+            this.scale = this.startScale;
+            return;
+        }
         
+        this.draw();
         
     },
     
-    getActivePane : function()
+    onTouchEnd : function(e)
     {
-        var r = false;
-        Roo.each(this.panes, function(p) {
-            if(p.el.hasClass('active')){
-                r = p;
-                return false;
-            }
-            
-            return;
-        });
+        this.pinching = false;
+        this.dragable = false;
         
-        return r;
-    }
-    
+    },
     
-});
-
-/*
- * - LGPL
- *
- * Tab pane
- * 
- */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
-/**
- * @class Roo.bootstrap.TabPane
- * @extends Roo.bootstrap.Component
- * Bootstrap TabPane class
- * @cfg {Boolean} active (false | true) Default false
- * @cfg {String} title title of panel
+    process : function(file, crop)
+    {
+        this.xhr = new XMLHttpRequest();
+        
+        file.xhr = this.xhr;
 
- * 
- * @constructor
- * Create a new TabPane
- * @param {Object} config The config object
- */
+        this.xhr.open(this.method, this.url, true);
+        
+        var headers = {
+            "Accept": "application/json",
+            "Cache-Control": "no-cache",
+            "X-Requested-With": "XMLHttpRequest"
+        };
+        
+        for (var headerName in headers) {
+            var headerValue = headers[headerName];
+            if (headerValue) {
+                this.xhr.setRequestHeader(headerName, headerValue);
+            }
+        }
+        
+        var _this = this;
+        
+        this.xhr.onload = function()
+        {
+            _this.xhrOnLoad(_this.xhr);
+        }
+        
+        this.xhr.onerror = function()
+        {
+            _this.xhrOnError(_this.xhr);
+        }
+        
+        var formData = new FormData();
 
-Roo.bootstrap.dash.TabPane = function(config){
-    Roo.bootstrap.dash.TabPane.superclass.constructor.call(this, config);
+        formData.append('returnHTML', 'NO');
+        
+        if(crop){
+            formData.append('crop', crop);
+        }
+        
+        if(typeof(file) != 'undefined' && (typeof(file.id) == 'undefined' || file.id * 1 < 1)){
+            formData.append(this.paramName, file, file.name);
+        }
+        
+        if(typeof(file.filename) != 'undefined'){
+            formData.append('filename', file.filename);
+        }
+        
+        if(typeof(file.mimetype) != 'undefined'){
+            formData.append('mimetype', file.mimetype);
+        }
+        
+        if(this.fireEvent('arrange', this, formData) != false){
+            this.xhr.send(formData);
+        };
+    },
     
-    this.addEvents({
-        // raw events
-        /**
-         * @event activate
-         * When a pane is activated
-         * @param {Roo.bootstrap.dash.TabPane} pane
-         */
-        "activate" : true
-         
-    });
-};
+    xhrOnLoad : function(xhr)
+    {
+        if (xhr.readyState !== 4) {
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
 
-Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component,  {
+        var response = Roo.decode(xhr.responseText);
+        
+        if(!response.success){
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
+        
+        var response = Roo.decode(xhr.responseText);
+        
+        this.fireEvent('upload', this, response);
+        
+    },
     
-    active : false,
-    title : '',
+    xhrOnError : function()
+    {
+        Roo.log('xhr on error');
+        
+        var response = Roo.decode(xhr.responseText);
+          
+        Roo.log(response);
+        
+    },
+    
+    prepare : function(file)
+    {   
+        this.file = false;
+        this.exif = {};
+        
+        if(typeof(file) === 'string'){
+            this.loadCanvas(file);
+            return;
+        }
+        
+        if(!file || !this.urlAPI){
+            return;
+        }
+        
+        this.file = file;
+        this.cropType = file.type;
+        
+        var _this = this;
+        
+        if(this.fireEvent('prepare', this, this.file) != false){
+            
+            var reader = new FileReader();
+            
+            reader.onload = function (e) {
+                if (e.target.error) {
+                    Roo.log(e.target.error);
+                    return;
+                }
+                
+                var buffer = e.target.result,
+                    dataView = new DataView(buffer),
+                    offset = 2,
+                    maxOffset = dataView.byteLength - 4,
+                    markerBytes,
+                    markerLength;
+                
+                if (dataView.getUint16(0) === 0xffd8) {
+                    while (offset < maxOffset) {
+                        markerBytes = dataView.getUint16(offset);
+                        
+                        if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) || markerBytes === 0xfffe) {
+                            markerLength = dataView.getUint16(offset + 2) + 2;
+                            if (offset + markerLength > dataView.byteLength) {
+                                Roo.log('Invalid meta data: Invalid segment size.');
+                                break;
+                            }
+                            
+                            if(markerBytes == 0xffe1){
+                                _this.parseExifData(
+                                    dataView,
+                                    offset,
+                                    markerLength
+                                );
+                            }
+                            
+                            offset += markerLength;
+                            
+                            continue;
+                        }
+                        
+                        break;
+                    }
+                    
+                }
+                
+                var url = _this.urlAPI.createObjectURL(_this.file);
+                
+                _this.loadCanvas(url);
+                
+                return;
+            }
+            
+            reader.readAsArrayBuffer(this.file);
+            
+        }
+        
+    },
     
-    // the tabBox that this is attached to.
-    tab : false,
-     
-    getAutoCreate : function() 
+    parseExifData : function(dataView, offset, length)
     {
-        var cfg = {
-            tag: 'div',
-            cls: 'tab-pane'
+        var tiffOffset = offset + 10,
+            littleEndian,
+            dirOffset;
+    
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
+            return;
         }
         
-        if(this.active){
-            cfg.cls += ' active';
+        // Check for the ASCII code for "Exif" (0x45786966):
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
+            return;
+        }
+        if (tiffOffset + 8 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid segment size.');
+            return;
+        }
+        // Check for the two null bytes:
+        if (dataView.getUint16(offset + 8) !== 0x0000) {
+            Roo.log('Invalid Exif data: Missing byte alignment offset.');
+            return;
+        }
+        // Check the byte alignment:
+        switch (dataView.getUint16(tiffOffset)) {
+        case 0x4949:
+            littleEndian = true;
+            break;
+        case 0x4D4D:
+            littleEndian = false;
+            break;
+        default:
+            Roo.log('Invalid Exif data: Invalid byte alignment marker.');
+            return;
+        }
+        // Check for the TIFF tag marker (0x002A):
+        if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
+            Roo.log('Invalid Exif data: Missing TIFF marker.');
+            return;
         }
+        // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
+        dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
         
-        return cfg;
+        this.parseExifTags(
+            dataView,
+            tiffOffset,
+            tiffOffset + dirOffset,
+            littleEndian
+        );
     },
-    initEvents  : function()
+    
+    parseExifTags : function(dataView, tiffOffset, dirOffset, littleEndian)
     {
-        //Roo.log('trigger add pane handler');
-        this.parent().fireEvent('addpane', this)
+        var tagsNumber,
+            dirEndOffset,
+            i;
+        if (dirOffset + 6 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory offset.');
+            return;
+        }
+        tagsNumber = dataView.getUint16(dirOffset, littleEndian);
+        dirEndOffset = dirOffset + 2 + 12 * tagsNumber;
+        if (dirEndOffset + 4 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory size.');
+            return;
+        }
+        for (i = 0; i < tagsNumber; i += 1) {
+            this.parseExifTag(
+                dataView,
+                tiffOffset,
+                dirOffset + 2 + 12 * i, // tag offset
+                littleEndian
+            );
+        }
+        // Return the offset to the next directory:
+        return dataView.getUint32(dirEndOffset, littleEndian);
     },
     
-     /**
-     * Updates the tab title 
-     * @param {String} html to set the title to.
-     */
-    setTitle: function(str)
+    parseExifTag : function (dataView, tiffOffset, offset, littleEndian) 
     {
-        if (!this.tab) {
+        var tag = dataView.getUint16(offset, littleEndian);
+        
+        this.exif[tag] = this.getExifValue(
+            dataView,
+            tiffOffset,
+            offset,
+            dataView.getUint16(offset + 2, littleEndian), // tag type
+            dataView.getUint32(offset + 4, littleEndian), // tag length
+            littleEndian
+        );
+    },
+    
+    getExifValue : function (dataView, tiffOffset, offset, type, length, littleEndian)
+    {
+        var tagType = Roo.bootstrap.UploadCropbox.exifTagTypes[type],
+            tagSize,
+            dataOffset,
+            values,
+            i,
+            str,
+            c;
+    
+        if (!tagType) {
+            Roo.log('Invalid Exif data: Invalid tag type.');
             return;
         }
-        this.title = str;
-        this.tab.select('a', true).first().dom.innerHTML = str;
         
+        tagSize = tagType.size * length;
+        // Determine if the value is contained in the dataOffset bytes,
+        // or if the value at the dataOffset is a pointer to the actual data:
+        dataOffset = tagSize > 4 ?
+                tiffOffset + dataView.getUint32(offset + 8, littleEndian) : (offset + 8);
+        if (dataOffset + tagSize > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid data offset.');
+            return;
+        }
+        if (length === 1) {
+            return tagType.getValue(dataView, dataOffset, littleEndian);
+        }
+        values = [];
+        for (i = 0; i < length; i += 1) {
+            values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian);
+        }
+        
+        if (tagType.ascii) {
+            str = '';
+            // Concatenate the chars:
+            for (i = 0; i < values.length; i += 1) {
+                c = values[i];
+                // Ignore the terminating NULL byte(s):
+                if (c === '\u0000') {
+                    break;
+                }
+                str += c;
+            }
+            return str;
+        }
+        return values;
     }
     
+});
+
+Roo.apply(Roo.bootstrap.UploadCropbox, {
+    tags : {
+        'Orientation': 0x0112
+    },
+    
+    Orientation: {
+            1: 0, //'top-left',
+//            2: 'top-right',
+            3: 180, //'bottom-right',
+//            4: 'bottom-left',
+//            5: 'left-top',
+            6: 90, //'right-top',
+//            7: 'right-bottom',
+            8: 270 //'left-bottom'
+    },
     
+    exifTagTypes : {
+        // byte, 8-bit unsigned int:
+        1: {
+            getValue: function (dataView, dataOffset) {
+                return dataView.getUint8(dataOffset);
+            },
+            size: 1
+        },
+        // ascii, 8-bit byte:
+        2: {
+            getValue: function (dataView, dataOffset) {
+                return String.fromCharCode(dataView.getUint8(dataOffset));
+            },
+            size: 1,
+            ascii: true
+        },
+        // short, 16 bit int:
+        3: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint16(dataOffset, littleEndian);
+            },
+            size: 2
+        },
+        // long, 32 bit int:
+        4: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // rational = two long values, first is numerator, second is denominator:
+        5: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian) /
+                    dataView.getUint32(dataOffset + 4, littleEndian);
+            },
+            size: 8
+        },
+        // slong, 32 bit signed int:
+        9: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // srational, two slongs, first is numerator, second is denominator:
+        10: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian) /
+                    dataView.getInt32(dataOffset + 4, littleEndian);
+            },
+            size: 8
+        }
+    },
     
+    footer : {
+        STANDARD : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-picture',
+                action : 'picture',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-picture-o"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        DOCUMENT : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-download',
+                action : 'download',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-download"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-crop',
+                action : 'crop',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-crop"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-trash',
+                action : 'trash',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-trash"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        ROTATOR : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ]
+    }
 });
 
-
-
- /*
- * - LGPL
- *
- * menu
- * 
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+/*
+* Licence: LGPL
+*/
 
 /**
- * @class Roo.bootstrap.menu.Menu
+ * @class Roo.bootstrap.DocumentManager
  * @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
- * 
+ * Bootstrap DocumentManager class
+ * @cfg {String} paramName default 'imageUpload'
+ * @cfg {String} method default POST
+ * @cfg {String} url action url
+ * @cfg {Number} boxes number of boxes, 0 is no limit.. default 0
+ * @cfg {Boolean} multiple multiple upload default true
+ * @cfg {Number} thumbSize default 300
+ * @cfg {String} fieldLabel
+ * @cfg {Number} labelWidth default 4
+ * @cfg {String} labelAlign (left|top) default left
+ * @cfg {Boolean} editable (true|false) allow edit when upload a image default true
  * 
  * @constructor
- * Create a new Menu
+ * Create a new DocumentManager
  * @param {Object} config The config object
  */
 
-
-Roo.bootstrap.menu.Menu = function(config){
-    Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
+Roo.bootstrap.DocumentManager = function(config){
+    Roo.bootstrap.DocumentManager.superclass.constructor.call(this, config);
     
     this.addEvents({
         /**
-         * @event beforeshow
-         * Fires before this menu is displayed
-         * @param {Roo.bootstrap.menu.Menu} this
+         * @event initial
+         * Fire when initial the DocumentManager
+         * @param {Roo.bootstrap.DocumentManager} this
          */
-        beforeshow : true,
+        "initial" : true,
         /**
-         * @event beforehide
-         * Fires before this menu is hidden
-         * @param {Roo.bootstrap.menu.Menu} this
+         * @event inspect
+         * inspect selected file
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {File} file
          */
-        beforehide : true,
+        "inspect" : true,
         /**
-         * @event show
-         * Fires after this menu is displayed
-         * @param {Roo.bootstrap.menu.Menu} this
+         * @event exception
+         * Fire when xhr load exception
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {XMLHttpRequest} xhr
          */
-        show : true,
+        "exception" : true,
         /**
-         * @event hide
-         * Fires after this menu is hidden
-         * @param {Roo.bootstrap.menu.Menu} this
+         * @event prepare
+         * prepare the form data
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} formData
          */
-        hide : true,
+        "prepare" : true,
+        /**
+         * @event remove
+         * Fire when remove the file
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
+         */
+        "remove" : true,
+        /**
+         * @event refresh
+         * Fire after refresh the file
+         * @param {Roo.bootstrap.DocumentManager} this
+         */
+        "refresh" : 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
+         * Fire after click the image
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
          */
-        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
-            })
-        }
-        
+        "click" : true,
+        /**
+         * @event edit
+         * Fire when upload a image and editable set to true
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
+         */
+        "edit" : true,
+        /**
+         * @event beforeselectfile
+         * Fire before select file
+         * @param {Roo.bootstrap.DocumentManager} this
+         */
+        "beforeselectfile" : true,
+        /**
+         * @event process
+         * Fire before process file
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
+         */
+        "process" : true
         
-        var cfg = {
+    });
+};
+
+Roo.extend(Roo.bootstrap.DocumentManager, Roo.bootstrap.Component,  {
+    
+    boxes : 0,
+    inputName : '',
+    thumbSize : 300,
+    multiple : true,
+    files : [],
+    method : 'POST',
+    url : '',
+    paramName : 'imageUpload',
+    fieldLabel : '',
+    labelWidth : 4,
+    labelAlign : 'left',
+    editable : true,
+    delegates : [],
+    
+    getAutoCreate : function()
+    {   
+        var managerWidget = {
             tag : 'div',
-            cls : 'btn-group',
+            cls : 'roo-document-manager',
             cn : [
                 {
-                    tag : 'button',
-                    cls : 'dropdown-button btn btn-' + this.weight,
-                    cn : text
+                    tag : 'input',
+                    cls : 'roo-document-manager-selector',
+                    type : 'file'
                 },
                 {
-                    tag : 'button',
-                    cls : 'dropdown-toggle btn btn-' + this.weight,
+                    tag : 'div',
+                    cls : 'roo-document-manager-uploader',
                     cn : [
                         {
-                            tag : 'span',
-                            cls : 'caret'
+                            tag : 'div',
+                            cls : 'roo-document-manager-upload-btn',
+                            html : '<i class="fa fa-plus"></i>'
                         }
                     ]
-                },
-                {
-                    tag : 'ul',
-                    cls : 'dropdown-menu'
+                    
                 }
             ]
-            
         };
         
-        if(this.pos == 'top'){
-            cfg.cls += ' dropup';
-        }
+        var content = [
+            {
+                tag : 'div',
+                cls : 'column col-md-12',
+                cn : managerWidget
+            }
+        ];
         
-        if(this.isSubMenu){
-            cfg = {
-                tag : 'ul',
-                cls : 'dropdown-menu'
+        if(this.fieldLabel.length){
+            
+            content = [
+                {
+                    tag : 'div',
+                    cls : 'column col-md-12',
+                    html : this.fieldLabel
+                },
+                {
+                    tag : 'div',
+                    cls : 'column col-md-12',
+                    cn : managerWidget
+                }
+            ];
+
+            if(this.labelAlign == 'left'){
+                content = [
+                    {
+                        tag : 'div',
+                        cls : 'column col-md-' + this.labelWidth,
+                        html : this.fieldLabel
+                    },
+                    {
+                        tag : 'div',
+                        cls : 'column col-md-' + (12 - this.labelWidth),
+                        cn : managerWidget
+                    }
+                ];
+                
             }
         }
-       
+        
+        var cfg = {
+            tag : 'div',
+            cls : 'row clearfix',
+            cn : content
+        };
+        
         return cfg;
+        
     },
     
-    onRender : function(ct, position)
+    initEvents : function()
     {
-        this.isSubMenu = ct.hasClass('dropdown-submenu');
+        this.managerEl = this.el.select('.roo-document-manager', true).first();
+        this.managerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
+        this.selectorEl = this.el.select('.roo-document-manager-selector', true).first();
+        this.selectorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.selectorEl.hide();
+        
+        if(this.multiple){
+            this.selectorEl.attr('multiple', 'multiple');
+        }
+        
+        this.selectorEl.on('change', this.onFileSelected, this);
+        
+        this.uploader = this.el.select('.roo-document-manager-uploader', true).first();
+        this.uploader.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.uploader.on('click', this.onUploaderClick, this);
+        
+        this.renderProgressDialog();
+        
+        var _this = this;
+        
+        window.addEventListener("resize", function() { _this.refresh(); } );
+        
+        this.fireEvent('initial', this);
     },
     
-    initEvents : function() 
+    renderProgressDialog : function()
     {
-        if(this.isSubMenu){
-            return;
-        }
+        var _this = this;
         
-        this.hidden = true;
+        this.progressDialog = new Roo.bootstrap.Modal({
+            cls : 'roo-document-manager-progress-dialog',
+            allow_close : false,
+            title : '',
+            buttons : [
+                {
+                    name  :'cancel',
+                    weight : 'danger',
+                    html : 'Cancel'
+                }
+            ], 
+            listeners : { 
+                btnclick : function() {
+                    _this.uploadCancel();
+                    this.hide();
+                }
+            }
+        });
+         
+        this.progressDialog.render(Roo.get(document.body));
+         
+        this.progress = new Roo.bootstrap.Progress({
+            cls : 'roo-document-manager-progress',
+            active : true,
+            striped : true
+        });
         
-        this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
-        this.triggerEl.on('click', this.onTriggerPress, this);
+        this.progress.render(this.progressDialog.getChildContainer());
         
-        this.buttonEl = this.el.select('button.dropdown-button', true).first();
-        this.buttonEl.on('click', this.onClick, this);
+        this.progressBar = new Roo.bootstrap.ProgressBar({
+            cls : 'roo-document-manager-progress-bar',
+            aria_valuenow : 0,
+            aria_valuemin : 0,
+            aria_valuemax : 12,
+            panel : 'success'
+        });
         
+        this.progressBar.render(this.progress.getChildContainer());
     },
     
-    list : function()
+    onUploaderClick : function(e)
     {
-        if(this.isSubMenu){
-            return this.el;
+        e.preventDefault();
+        
+        if(this.fireEvent('beforeselectfile', this) != false){
+            this.selectorEl.dom.click();
         }
         
-        return this.el.select('ul.dropdown-menu', true).first();
     },
     
-    onClick : function(e)
+    onFileSelected : function(e)
     {
-        this.fireEvent("click", this, e);
-    },
-    
-    onTriggerPress  : function(e)
-    {   
-        if (this.isVisible()) {
-            this.hide();
-        } else {
-            this.show();
+        e.preventDefault();
+        
+        if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
+            return;
         }
+        
+        Roo.each(this.selectorEl.dom.files, function(file){
+            if(this.fireEvent('inspect', this, file) != false){
+                this.files.push(file);
+            }
+        }, this);
+        
+        this.queue();
+        
     },
     
-    isVisible : function(){
-        return !this.hidden;
-    },
-    
-    show : function()
+    queue : function()
     {
-        this.fireEvent("beforeshow", this);
+        this.selectorEl.dom.value = '';
         
-        this.hidden = false;
-        this.el.addClass('open');
+        if(!this.files.length){
+            return;
+        }
         
-        Roo.get(document).on("mouseup", this.onMouseUp, this);
+        if(this.boxes > 0 && this.files.length > this.boxes){
+            this.files = this.files.slice(0, this.boxes);
+        }
         
-        this.fireEvent("show", this);
+        this.uploader.show();
         
+        if(this.boxes > 0 && this.files.length > this.boxes - 1){
+            this.uploader.hide();
+        }
         
-    },
-    
-    hide : function()
-    {
-        this.fireEvent("beforehide", this);
+        var _this = this;
         
-        this.hidden = true;
-        this.el.removeClass('open');
+        var files = [];
         
-        Roo.get(document).un("mouseup", this.onMouseUp);
+        var docs = [];
         
-        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
+        Roo.each(this.files, function(file){
+            
+            if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+                var f = this.renderPreview(file);
+                files.push(f);
+                return;
             }
-        ];
+            
+            if(file.type.indexOf('image') != -1){
+                this.delegates.push(
+                    (function(){
+                        _this.process(file);
+                    }).createDelegate(this)
+                );
         
-        if(this.icon){
-            text.unshift({
-                tag : 'i',
-                cls : 'fa ' + this.icon
-            })
-        }
+                return;
+            }
+            
+            docs.push(
+                (function(){
+                    _this.process(file);
+                }).createDelegate(this)
+            );
+            
+        }, this);
         
-        var cfg = {
-            tag : 'li',
-            cn : [
-                {
-                    tag : 'a',
-                    href : this.href || '#',
-                    cn : text
-                }
-            ]
-        };
+        this.files = files;
         
-        if(this.disable){
-            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
-        }
+        this.delegates = this.delegates.concat(docs);
         
-        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');
-            }
+        if(!this.delegates.length){
+            this.refresh();
+            return;
         }
         
-        return cfg;
+        this.progressBar.aria_valuemax = this.delegates.length;
+        
+        this.arrange();
+        
+        return;
     },
     
-    initEvents : function() 
+    arrange : function()
     {
-        this.el.on('mouseover', this.onMouseOver, this);
-        this.el.on('mouseout', this.onMouseOut, this);
+        if(!this.delegates.length){
+            this.progressDialog.hide();
+            this.refresh();
+            return;
+        }
         
-        this.el.select('a', true).first().on('click', this.onClick, this);
+        var delegate = this.delegates.shift();
+        
+        this.progressDialog.show();
+        
+        this.progressDialog.setTitle((this.progressBar.aria_valuemax - this.delegates.length) + ' / ' + this.progressBar.aria_valuemax);
         
+        this.progressBar.update(this.progressBar.aria_valuemax - this.delegates.length);
+        
+        delegate();
     },
     
-    onClick : function(e)
+    refresh : function()
     {
-        if(this.preventDefault){
-            e.preventDefault();
+        this.uploader.show();
+        
+        if(this.boxes > 0 && this.files.length > this.boxes - 1){
+            this.uploader.hide();
         }
         
-        this.fireEvent("click", this, e);
+        Roo.isTouch ? this.closable(false) : this.closable(true);
+        
+        this.fireEvent('refresh', this);
     },
     
-    onMouseOver : function(e)
+    onRemove : function(e, el, o)
     {
-        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);
-        }
+        e.preventDefault();
+        
+        this.fireEvent('remove', this, o);
         
-        this.fireEvent("mouseover", this, e);
     },
     
-    onMouseOut : function(e)
+    remove : function(o)
     {
-        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: 'divider'
-        };
+        var files = [];
         
-        return cfg;
-    }
-   
-});
-
-
- /*
- * - LGPL
- *
- * Tooltip
- * 
- */
-
-/**
- * @class Roo.bootstrap.Tooltip
- * Bootstrap Tooltip class
- * This is basic at present - all componets support it by default, however they should add tooltipEl() method
- * to determine which dom element triggers the tooltip.
- * 
- * It needs to add support for additional attributes like tooltip-position
- * 
- * @constructor
- * Create a new Toolti
- * @param {Object} config The config object
- */
+        Roo.each(this.files, function(file){
+            if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
+                files.push(file);
+                return;
+            }
 
-Roo.bootstrap.Tooltip = function(config){
-    Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
-};
+            o.target.remove();
 
-Roo.apply(Roo.bootstrap.Tooltip, {
-    /**
-     * @function init initialize tooltip monitoring.
-     * @static
-     */
-    currentEl : false,
-    currentTip : false,
-    currentRegion : false,
-    
-    //  init : delay?
+        }, this);
+        
+        this.files = files;
+        
+        this.refresh();
+    },
     
-    init : function()
+    clear : function()
     {
-        Roo.get(document).on('mouseover', this.enter ,this);
-        Roo.get(document).on('mouseout', this.leave, this);
-         
+        Roo.each(this.files, function(file){
+            if(!file.target){
+                return;
+            }
+            
+            file.target.remove();
+
+        }, this);
         
-        this.currentTip = new Roo.bootstrap.Tooltip();
+        this.files = [];
+        
+        this.refresh();
     },
     
-    enter : function(ev)
+    onClick : function(e, el, o)
     {
-        var dom = ev.getTarget();
+        e.preventDefault();
         
-        //Roo.log(['enter',dom]);
-        var el = Roo.fly(dom);
-        if (this.currentEl) {
-            //Roo.log(dom);
-            //Roo.log(this.currentEl);
-            //Roo.log(this.currentEl.contains(dom));
-            if (this.currentEl == el) {
-                return;
-            }
-            if (dom != this.currentEl.dom && this.currentEl.contains(dom)) {
+        this.fireEvent('click', this, o);
+        
+    },
+    
+    closable : function(closable)
+    {
+        Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
+            
+            el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+            
+            if(closable){
+                el.show();
                 return;
             }
+            
+            el.hide();
+            
+        }, this);
+    },
+    
+    xhrOnLoad : function(xhr)
+    {
+        Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
+            el.remove();
+        }, this);
+        
+        if (xhr.readyState !== 4) {
+            this.arrange();
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
 
+        var response = Roo.decode(xhr.responseText);
+        
+        if(!response.success){
+            this.arrange();
+            this.fireEvent('exception', this, xhr);
+            return;
         }
         
+        var file = this.renderPreview(response.data);
         
+        this.files.push(file);
         
-        if (this.currentTip.el) {
-            this.currentTip.el.hide(); // force hiding...
-        }    
-        //Roo.log(ev);
-        var bindEl = el;
+        this.arrange();
         
-        // you can not look for children, as if el is the body.. then everythign is the child..
-        if (!el.attr('tooltip')) { //
-            if (!el.select("[tooltip]").elements.length) {
-                return;
-            }
-            // is the mouse over this child...?
-            bindEl = el.select("[tooltip]").first();
-            var xy = ev.getXY();
-            if (!bindEl.getRegion().contains( { top : xy[1] ,right : xy[0] , bottom : xy[1], left : xy[0]})) {
-                //Roo.log("not in region.");
+    },
+    
+    xhrOnError : function()
+    {
+        Roo.log('xhr on error');
+        
+        var response = Roo.decode(xhr.responseText);
+          
+        Roo.log(response);
+        
+        this.arrange();
+    },
+    
+    process : function(file)
+    {
+        if(this.fireEvent('process', this, file) !== false){
+            if(this.editable && file.type.indexOf('image') != -1){
+                this.fireEvent('edit', this, file);
                 return;
             }
-            //Roo.log("child element over..");
-            
+
+            this.uploadStart(file, false);
+
+            return;
         }
-        this.currentEl = bindEl;
-        this.currentTip.bind(bindEl);
-        this.currentRegion = Roo.lib.Region.getRegion(dom);
-        this.currentTip.enter();
         
     },
-    leave : function(ev)
+    
+    uploadStart : function(file, crop)
     {
-        var dom = ev.getTarget();
-        //Roo.log(['leave',dom]);
-        if (!this.currentEl) {
+        this.xhr = new XMLHttpRequest();
+        
+        if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+            this.arrange();
             return;
         }
         
+        file.xhr = this.xhr;
+            
+        this.managerEl.createChild({
+            tag : 'div',
+            cls : 'roo-document-manager-loading',
+            cn : [
+                {
+                    tag : 'div',
+                    tooltip : file.name,
+                    cls : 'roo-document-manager-thumb',
+                    html : '<i class="fa fa-circle-o-notch fa-spin"></i>'
+                }
+            ]
+
+        });
+
+        this.xhr.open(this.method, this.url, true);
+        
+        var headers = {
+            "Accept": "application/json",
+            "Cache-Control": "no-cache",
+            "X-Requested-With": "XMLHttpRequest"
+        };
         
-        if (dom != this.currentEl.dom) {
-            return;
-        }
-        var xy = ev.getXY();
-        if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0]  ))) {
-            return;
+        for (var headerName in headers) {
+            var headerValue = headers[headerName];
+            if (headerValue) {
+                this.xhr.setRequestHeader(headerName, headerValue);
+            }
         }
-        // only activate leave if mouse cursor is outside... bounding box..
         
+        var _this = this;
+        
+        this.xhr.onload = function()
+        {
+            _this.xhrOnLoad(_this.xhr);
+        }
         
+        this.xhr.onerror = function()
+        {
+            _this.xhrOnError(_this.xhr);
+        }
         
+        var formData = new FormData();
+
+        formData.append('returnHTML', 'NO');
         
-        if (this.currentTip) {
-            this.currentTip.leave();
+        if(crop){
+            formData.append('crop', crop);
         }
-        //Roo.log('clear currentEl');
-        this.currentEl = false;
         
+        formData.append(this.paramName, file, file.name);
         
-    },
-    alignment : {
-        'left' : ['r-l', [-2,0], 'right'],
-        'right' : ['l-r', [2,0], 'left'],
-        'bottom' : ['t-b', [0,2], 'top'],
-        'top' : [ 'b-t', [0,-2], 'bottom']
-    }
-    
-});
-
-
-Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
-    
-    
-    bindEl : false,
-    
-    delay : null, // can be { show : 300 , hide: 500}
-    
-    timeout : null,
-    
-    hoverState : null, //???
-    
-    placement : 'bottom', 
+        if(this.fireEvent('prepare', this, formData) != false){
+            this.xhr.send(formData);
+        };
+    },
     
-    getAutoCreate : function(){
+    uploadCancel : function()
+    {
+        this.xhr.abort();
+        
+        this.delegates = [];
+        
+        Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
+            el.remove();
+        }, this);
+        
+        this.arrange();
+    },
     
-        var cfg = {
-           cls : 'tooltip',
-           role : 'tooltip',
-           cn : [
+    renderPreview : function(file)
+    {
+        if(typeof(file.target) != 'undefined' && file.target){
+            return file;
+        }
+        
+        var previewEl = this.managerEl.createChild({
+            tag : 'div',
+            cls : 'roo-document-manager-preview',
+            cn : [
                 {
-                    cls : 'tooltip-arrow'
+                    tag : 'div',
+                    tooltip : file.filename,
+                    cls : 'roo-document-manager-thumb',
+                    html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + file.id + '/' + file.filename + '">'
                 },
                 {
-                    cls : 'tooltip-inner'
+                    tag : 'button',
+                    cls : 'close',
+                    html : '<i class="fa fa-times-circle"></i>'
                 }
-           ]
-        };
+            ]
+        });
+
+        var close = previewEl.select('button.close', true).first();
+
+        close.on('click', this.onRemove, this, file);
+
+        file.target = previewEl;
+
+        var image = previewEl.select('img', true).first();
+        
+        var _this = this;
+        
+        image.dom.addEventListener("load", function(){ _this.onPreviewLoad(file, image); });
+        
+        image.on('click', this.onClick, this, file);
+        
+        return file;
         
-        return cfg;
-    },
-    bind : function(el)
-    {
-        this.bindEl = el;
     },
-      
     
-    enter : function () {
-       
-        if (this.timeout != null) {
-            clearTimeout(this.timeout);
-        }
-        
-        this.hoverState = 'in';
-         //Roo.log("enter - show");
-        if (!this.delay || !this.delay.show) {
-            this.show();
+    onPreviewLoad : function(file, image)
+    {
+        if(typeof(file.target) == 'undefined' || !file.target){
             return;
         }
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            if (_t.hoverState == 'in') {
-                _t.show();
-            }
-        }, this.delay.show);
-    },
-    leave : function()
-    {
-        clearTimeout(this.timeout);
-    
-        this.hoverState = 'out';
-         if (!this.delay || !this.delay.hide) {
-            this.hide();
+        
+        var width = image.dom.naturalWidth || image.dom.width;
+        var height = image.dom.naturalHeight || image.dom.height;
+        
+        if(width > height){
+            file.target.addClass('wide');
             return;
         }
-       
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            //Roo.log("leave - timeout");
-            
-            if (_t.hoverState == 'out') {
-                _t.hide();
-                Roo.bootstrap.Tooltip.currentEl = false;
-            }
-        }, delay);
+        
+        file.target.addClass('tall');
+        return;
+        
     },
     
-    show : function ()
+    uploadFromSource : function(file, crop)
     {
-        if (!this.el) {
-            this.render(document.body);
-        }
-        // set content.
-        //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
-        
-        var tip = this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
+        this.xhr = new XMLHttpRequest();
         
-        this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
+        this.managerEl.createChild({
+            tag : 'div',
+            cls : 'roo-document-manager-loading',
+            cn : [
+                {
+                    tag : 'div',
+                    tooltip : file.name,
+                    cls : 'roo-document-manager-thumb',
+                    html : '<i class="fa fa-circle-o-notch fa-spin"></i>'
+                }
+            ]
+
+        });
+
+        this.xhr.open(this.method, this.url, true);
         
-        this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
+        var headers = {
+            "Accept": "application/json",
+            "Cache-Control": "no-cache",
+            "X-Requested-With": "XMLHttpRequest"
+        };
         
-        var placement = typeof this.placement == 'function' ?
-            this.placement.call(this, this.el, on_el) :
-            this.placement;
-            
-        var autoToken = /\s?auto?\s?/i;
-        var autoPlace = autoToken.test(placement);
-        if (autoPlace) {
-            placement = placement.replace(autoToken, '') || 'top';
+        for (var headerName in headers) {
+            var headerValue = headers[headerName];
+            if (headerValue) {
+                this.xhr.setRequestHeader(headerName, headerValue);
+            }
         }
         
-        //this.el.detach()
-        //this.el.setXY([0,0]);
-        this.el.show();
-        //this.el.dom.style.display='block';
-        this.el.addClass(placement);
-        
-        //this.el.appendTo(on_el);
+        var _this = this;
         
-        var p = this.getPosition();
-        var box = this.el.getBox();
+        this.xhr.onload = function()
+        {
+            _this.xhrOnLoad(_this.xhr);
+        }
         
-        if (autoPlace) {
-            // fixme..
+        this.xhr.onerror = function()
+        {
+            _this.xhrOnError(_this.xhr);
         }
-        var align = Roo.bootstrap.Tooltip.alignment[placement];
-        this.el.alignTo(this.bindEl, align[0],align[1]);
-        //var arrow = this.el.select('.arrow',true).first();
-        //arrow.set(align[2], 
         
-        this.el.addClass('in fade');
-        this.hoverState = null;
+        var formData = new FormData();
+
+        formData.append('returnHTML', 'NO');
         
-        if (this.el.hasClass('fade')) {
-            // fade it?
+        formData.append('crop', crop);
+        
+        if(typeof(file.filename) != 'undefined'){
+            formData.append('filename', file.filename);
         }
         
-    },
-    hide : function()
-    {
-         
-        if (!this.el) {
-            return;
+        if(typeof(file.mimetype) != 'undefined'){
+            formData.append('mimetype', file.mimetype);
         }
-        //this.el.setXY([0,0]);
-        this.el.removeClass('in');
-        //this.el.hide();
         
+        if(this.fireEvent('prepare', this, formData) != false){
+            this.xhr.send(formData);
+        };
     }
-    
 });
 
- /*
- * - LGPL
- *
- * Location Picker
- * 
- */
+/*
+* Licence: LGPL
+*/
 
 /**
- * @class Roo.bootstrap.LocationPicker
+ * @class Roo.bootstrap.DocumentViewer
  * @extends Roo.bootstrap.Component
- * Bootstrap LocationPicker class
- * @cfg {Number} latitude Position when init default 0
- * @cfg {Number} longitude Position when init default 0
- * @cfg {Number} zoom default 15
- * @cfg {String} mapTypeId default google.maps.MapTypeId.ROADMAP
- * @cfg {Boolean} mapTypeControl default false
- * @cfg {Boolean} disableDoubleClickZoom default false
- * @cfg {Boolean} scrollwheel default true
- * @cfg {Boolean} streetViewControl default false
- * @cfg {Number} radius default 0
- * @cfg {String} locationName
- * @cfg {Boolean} draggable default true
- * @cfg {Boolean} enableAutocomplete default false
- * @cfg {Boolean} enableReverseGeocode default true
- * @cfg {String} markerTitle
+ * Bootstrap DocumentViewer class
  * 
  * @constructor
- * Create a new LocationPicker
+ * Create a new DocumentViewer
  * @param {Object} config The config object
  */
 
-
-Roo.bootstrap.LocationPicker = function(config){
-    
-    Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
+Roo.bootstrap.DocumentViewer = function(config){
+    Roo.bootstrap.DocumentViewer.superclass.constructor.call(this, config);
     
     this.addEvents({
         /**
          * @event initial
-         * Fires when the picker initialized.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Google Location} location
-         */
-        initial : true,
-        /**
-         * @event positionchanged
-         * Fires when the picker position changed.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Google Location} location
-         */
-        positionchanged : true,
-        /**
-         * @event resize
-         * Fires when the map resize.
-         * @param {Roo.bootstrap.LocationPicker} this
+         * Fire after initEvent
+         * @param {Roo.bootstrap.DocumentViewer} this
          */
-        resize : true,
-        /**
-         * @event show
-         * Fires when the map show.
-         * @param {Roo.bootstrap.LocationPicker} this
-         */
-        show : true,
-        /**
-         * @event hide
-         * Fires when the map hide.
-         * @param {Roo.bootstrap.LocationPicker} this
-         */
-        hide : true,
-        /**
-         * @event mapClick
-         * Fires when click the map.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Map event} e
-         */
-        mapClick : true,
-        /**
-         * @event mapRightClick
-         * Fires when right click the map.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Map event} e
-         */
-        mapRightClick : true,
-        /**
-         * @event markerClick
-         * Fires when click the marker.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Map event} e
-         */
-        markerClick : true,
-        /**
-         * @event markerRightClick
-         * Fires when right click the marker.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Map event} e
-         */
-        markerRightClick : true,
-        /**
-         * @event OverlayViewDraw
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
-         */
-        OverlayViewDraw : true,
-        /**
-         * @event OverlayViewOnAdd
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
-         */
-        OverlayViewOnAdd : true,
-        /**
-         * @event OverlayViewOnRemove
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
-         */
-        OverlayViewOnRemove : true,
+        "initial" : true,
         /**
-         * @event OverlayViewShow
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Pixel} cpx
+         * @event click
+         * Fire after click
+         * @param {Roo.bootstrap.DocumentViewer} this
          */
-        OverlayViewShow : true,
+        "click" : true,
         /**
-         * @event OverlayViewHide
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
+         * @event trash
+         * Fire after trash button
+         * @param {Roo.bootstrap.DocumentViewer} this
          */
-        OverlayViewHide : true
-    });
+        "trash" : true
         
+    });
 };
 
-Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component,  {
-    
-    gMapContext: false,
-    
-    latitude: 0,
-    longitude: 0,
-    zoom: 15,
-    mapTypeId: false,
-    mapTypeControl: false,
-    disableDoubleClickZoom: false,
-    scrollwheel: true,
-    streetViewControl: false,
-    radius: 0,
-    locationName: '',
-    draggable: true,
-    enableAutocomplete: false,
-    enableReverseGeocode: true,
-    markerTitle: '',
+Roo.extend(Roo.bootstrap.DocumentViewer, Roo.bootstrap.Component,  {
     
-    getAutoCreate: function()
+    getAutoCreate : function()
     {
-
         var cfg = {
-            tag: 'div',
-            cls: 'roo-location-picker'
+            tag : 'div',
+            cls : 'roo-document-viewer',
+            cn : [
+                {
+                    tag : 'div',
+                    cls : 'roo-document-viewer-body',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-document-viewer-thumb',
+                            cn : [
+                                {
+                                    tag : 'img',
+                                    cls : 'roo-document-viewer-image'
+                                }
+                            ]
+                        }
+                    ]
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-document-viewer-footer',
+                    cn : {
+                        tag : 'div',
+                        cls : 'btn-group btn-group-justified roo-document-viewer-btn-group',
+                        cn : [
+                            {
+                                tag : 'div',
+                                cls : 'btn-group',
+                                cn : [
+                                    {
+                                        tag : 'button',
+                                        cls : 'btn btn-default roo-document-viewer-trash',
+                                        html : '<i class="fa fa-trash"></i>'
+                                    }
+                                ]
+                            }
+                        ]
+                    }
+                }
+            ]
         };
         
-        return cfg
-    },
-    
-    initEvents: function(ct, position)
-    {       
-        if(!this.el.getWidth() || this.isApplied()){
-            return;
-        }
-        
-        this.el.setVisibilityMode(Roo.Element.DISPLAY);
-        
-        this.initial();
+        return cfg;
     },
     
-    initial: function()
+    initEvents : function()
     {
-        if(!this.mapTypeId){
-            this.mapTypeId = google.maps.MapTypeId.ROADMAP;
-        }
         
-        this.gMapContext = this.GMapContext();
+        this.bodyEl = this.el.select('.roo-document-viewer-body', true).first();
+        this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.initOverlayView();
+        this.thumbEl = this.el.select('.roo-document-viewer-thumb', true).first();
+        this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
+        this.imageEl = this.el.select('.roo-document-viewer-image', true).first();
+        this.imageEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        var _this = this;
-                
-        google.maps.event.addListener(this.gMapContext.marker, "dragend", function(event) {
-            _this.setPosition(_this.gMapContext.marker.position);
-        });
+        this.footerEl = this.el.select('.roo-document-viewer-footer', true).first();
+        this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        google.maps.event.addListener(this.gMapContext.map, 'click', function(event){
-            _this.fireEvent('mapClick', this, event);
-            
-        });
-
-        google.maps.event.addListener(this.gMapContext.map, 'rightclick', function(event){
-            _this.fireEvent('mapRightClick', this, event);
-            
-        });
+        this.trashBtn = this.el.select('.roo-document-viewer-trash', true).first();
+        this.trashBtn.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        google.maps.event.addListener(this.gMapContext.marker, 'click', function(event){
-            _this.fireEvent('markerClick', this, event);
-            
-        });
-
-        google.maps.event.addListener(this.gMapContext.marker, 'rightclick', function(event){
-            _this.fireEvent('markerRightClick', this, event);
-            
-        });
+        this.bodyEl.on('click', this.onClick, this);
         
-        this.setPosition(this.gMapContext.location);
+        this.trashBtn.on('click', this.onTrash, this);
         
-        this.fireEvent('initial', this, this.gMapContext.location);
     },
     
-    initOverlayView: function()
+    initial : function()
     {
-        var _this = this;
+//        this.thumbEl.setStyle('line-height', this.thumbEl.getHeight(true) + 'px');
+        
+        
+        this.fireEvent('initial', this);
         
-        Roo.bootstrap.LocationPicker.OverlayView.prototype = Roo.apply(new google.maps.OverlayView(), {
-            
-            draw: function()
-            {
-                _this.fireEvent('OverlayViewDraw', _this);
-            },
-            
-            onAdd: function()
-            {
-                _this.fireEvent('OverlayViewOnAdd', _this);
-            },
-            
-            onRemove: function()
-            {
-                _this.fireEvent('OverlayViewOnRemove', _this);
-            },
-            
-            show: function(cpx)
-            {
-                _this.fireEvent('OverlayViewShow', _this, cpx);
-            },
-            
-            hide: function()
-            {
-                _this.fireEvent('OverlayViewHide', _this);
-            }
-            
-        });
     },
     
-    fromLatLngToContainerPixel: function(event)
+    onClick : function(e)
     {
-        return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
+        e.preventDefault();
+        
+        this.fireEvent('click', this);
     },
     
-    isApplied: function() 
+    onTrash : function(e)
     {
-        return this.getGmapContext() == false ? false : true;
-    },
+        e.preventDefault();
+        
+        this.fireEvent('trash', this);
+    }
     
-    getGmapContext: function() 
-    {
-        return this.gMapContext
-    },
+});
+/*
+ * - 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
+     });
     
-    GMapContext: function() 
-    {
-        var position = new google.maps.LatLng(this.latitude, this.longitude);
-        
-        var _map = new google.maps.Map(this.el.dom, {
-            center: position,
-            zoom: this.zoom,
-            mapTypeId: this.mapTypeId,
-            mapTypeControl: this.mapTypeControl,
-            disableDoubleClickZoom: this.disableDoubleClickZoom,
-            scrollwheel: this.scrollwheel,
-            streetViewControl: this.streetViewControl,
-            locationName: this.locationName,
-            draggable: this.draggable,
-            enableAutocomplete: this.enableAutocomplete,
-            enableReverseGeocode: this.enableReverseGeocode
-        });
-        
-        var _marker = new google.maps.Marker({
-            position: position,
-            map: _map,
-            title: this.markerTitle,
-            draggable: this.draggable
-        });
-        
-        return {
-            map: _map,
-            marker: _marker,
-            circle: null,
-            location: position,
-            radius: this.radius,
-            locationName: this.locationName,
-            addressComponents: {
-                formatted_address: null,
-                addressLine1: null,
-                addressLine2: null,
-                streetName: null,
-                streetNumber: null,
-                city: null,
-                district: null,
-                state: null,
-                stateOrProvince: null
-            },
-            settings: this,
-            domContainer: this.el.dom,
-            geodecoder: new google.maps.Geocoder()
-        };
-    },
+};
+
+Roo.extend(Roo.bootstrap.NavProgressBar, Roo.bootstrap.Component,  {
     
-    drawCircle: function(center, radius, options) 
-    {
-        if (this.gMapContext.circle != null) {
-            this.gMapContext.circle.setMap(null);
-        }
-        if (radius > 0) {
-            radius *= 1;
-            options = Roo.apply({}, options, {
-                strokeColor: "#0000FF",
-                strokeOpacity: .35,
-                strokeWeight: 2,
-                fillColor: "#0000FF",
-                fillOpacity: .2
-            });
-            
-            options.map = this.gMapContext.map;
-            options.radius = radius;
-            options.center = center;
-            this.gMapContext.circle = new google.maps.Circle(options);
-            return this.gMapContext.circle;
-        }
-        
-        return null;
-    },
+    bullets : [],
+    barItems : [],
     
-    setPosition: function(location) 
+    
+    getAutoCreate : function()
     {
-        this.gMapContext.location = location;
-        this.gMapContext.marker.setPosition(location);
-        this.gMapContext.map.panTo(location);
-        this.drawCircle(location, this.gMapContext.radius, {});
-        
-        var _this = this;
+        var cfg = Roo.apply({}, Roo.bootstrap.NavProgressBar.superclass.getAutoCreate.call(this));
         
-        if (this.gMapContext.settings.enableReverseGeocode) {
-            this.gMapContext.geodecoder.geocode({
-                latLng: this.gMapContext.location
-            }, function(results, status) {
-                
-                if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
-                    _this.gMapContext.locationName = results[0].formatted_address;
-                    _this.gMapContext.addressComponents = _this.address_component_from_google_geocode(results[0].address_components);
-                    
-                    _this.fireEvent('positionchanged', this, location);
-                }
-            });
-            
-            return;
+        cfg = {
+            tag : 'ul',
+            cls: 'roo-navigation-bar' 
         }
         
-        this.fireEvent('positionchanged', this, location);
+        return cfg;
+        
     },
     
-    resize: function()
+    onRender : function(ct, position) 
     {
-        google.maps.event.trigger(this.gMapContext.map, "resize");
+        Roo.bootstrap.NavProgressBar.superclass.onRender.call(this, ct, position);
         
-        this.gMapContext.map.setCenter(this.gMapContext.marker.position);
+        if(this.bullets.length){
+            Roo.each(this.bullets, function(b){
+               this.addItem(b);
+            }, this);
+        }
         
-        this.fireEvent('resize', this);
     },
     
-    setPositionByLatLng: function(latitude, longitude)
+    addItem : function(cfg)
     {
-        this.setPosition(new google.maps.LatLng(latitude, longitude));
+        var item = new Roo.bootstrap.NavProgressItem(cfg);
+        
+        item.parentId = this.id;
+        item.render(this.el, null);
+        
+        this.barItems.push(item);
+        
+        this.formatBullets();
+        
+        return item;
     },
     
-    getCurrentPosition: function() 
+    getActive : function()
     {
-        return {
-            latitude: this.gMapContext.location.lat(),
-            longitude: this.gMapContext.location.lng()
-        };
+        var active = false;
+        
+        Roo.each(this.barItems, function(v){
+            
+            if (!v.isActive()) {
+                return;
+            }
+            
+            active = v;
+            return false;
+            
+        });
+        
+        return active;
     },
     
-    getAddressName: function() 
+    setActiveItem : function(item)
     {
-        return this.gMapContext.locationName;
+        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);
     },
     
-    getAddressComponents: function() 
+    getBarItem: function(rid)
     {
-        return this.gMapContext.addressComponents;
+        var ret = false;
+        
+        Roo.each(this.barItems, function(e) {
+            if (e.rid != rid) {
+                return;
+            }
+            
+            ret =  e;
+            return false;
+        });
+        
+        return ret;
     },
     
-    address_component_from_google_geocode: function(address_components) 
+    indexOfItem : function(item)
     {
-        var result = {};
+        var index = false;
         
-        for (var i = 0; i < address_components.length; i++) {
-            var component = address_components[i];
-            if (component.types.indexOf("postal_code") >= 0) {
-                result.postalCode = component.short_name;
-            } else if (component.types.indexOf("street_number") >= 0) {
-                result.streetNumber = component.short_name;
-            } else if (component.types.indexOf("route") >= 0) {
-                result.streetName = component.short_name;
-            } else if (component.types.indexOf("neighborhood") >= 0) {
-                result.city = component.short_name;
-            } else if (component.types.indexOf("locality") >= 0) {
-                result.city = component.short_name;
-            } else if (component.types.indexOf("sublocality") >= 0) {
-                result.district = component.short_name;
-            } else if (component.types.indexOf("administrative_area_level_1") >= 0) {
-                result.stateOrProvince = component.short_name;
-            } else if (component.types.indexOf("country") >= 0) {
-                result.country = component.short_name;
+        Roo.each(this.barItems, function(v, i){
+            
+            if (v.rid != item.rid) {
+                return;
             }
-        }
+            
+            index = i;
+            return false
+        });
         
-        result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
-        result.addressLine2 = "";
-        return result;
+        return index;
     },
     
-    setZoomLevel: function(zoom)
+    setActiveNext : function()
     {
-        this.gMapContext.map.setZoom(zoom);
+        var i = this.indexOfItem(this.getActive());
+        
+        if (i > this.barItems.length) {
+            return;
+        }
+        
+        this.setActiveItem(this.barItems[i+1]);
     },
     
-    show: function()
+    setActivePrev : function()
     {
-        if(!this.el){
+        var i = this.indexOfItem(this.getActive());
+        
+        if (i  < 1) {
             return;
         }
         
-        this.el.show();
-        
-        this.resize();
-        
-        this.fireEvent('show', this);
+        this.setActiveItem(this.barItems[i-1]);
     },
     
-    hide: function()
+    formatBullets : function()
     {
-        if(!this.el){
+        if(!this.barItems.length){
             return;
         }
         
-        this.el.hide();
+        var width = 100 / this.barItems.length;
         
-        this.fireEvent('hide', this);
+        Roo.each(this.barItems, function(i){
+            i.el.setStyle('width', width + '%');
+        }, this);
     }
     
 });
-
-Roo.apply(Roo.bootstrap.LocationPicker, {
-    
-    OverlayView : function(map, options)
-    {
-        options = options || {};
-        
-        this.setMap(map);
-    }
-    
-    
-});/*
+/*
  * - LGPL
  *
- * Alert
+ * Nav Progress Item
  * 
  */
 
 /**
- * @class Roo.bootstrap.Alert
+ * @class Roo.bootstrap.NavProgressItem
  * @extends Roo.bootstrap.Component
- * Bootstrap Alert class
- * @cfg {String} title The title of alert
- * @cfg {String} html The content of alert
- * @cfg {String} weight (  success | info | warning | danger )
- * @cfg {String} faicon font-awesomeicon
+ * 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
+ * @cfg {Boolean} forceIcon (true|false) true to force show icon..if set to false, Roo.isTouch showing icon, otherwish number
  * 
  * @constructor
- * Create a new alert
+ * Create a new NavProgressItem
  * @param {Object} config The config object
  */
-
-
-Roo.bootstrap.Alert = function(config){
-    Roo.bootstrap.Alert.superclass.constructor.call(this, config);
-    
+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.Alert, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.NavProgressItem, Roo.bootstrap.Component,  {
     
-    title: '',
-    html: '',
-    weight: false,
-    faicon: false,
+    rid : '',
+    active : false,
+    disabled : false,
+    html : '',
+    position : 'bottom',
+    icon : false,
+    forceIcon : false,
     
     getAutoCreate : function()
     {
+        var iconCls = 'roo-navigation-bar-item-icon';
+        
+        if((this.forceIcon && this.icon) || !this.forceIcon && Roo.isTouch){
+            iconCls += ' ' + this.icon;
+        }
         
         var cfg = {
-            tag : 'div',
-            cls : 'alert',
+            tag: 'li',
+            cls: 'roo-navigation-bar-item',
             cn : [
                 {
                     tag : 'i',
-                    cls : 'roo-alert-icon'
-                    
-                },
-                {
-                    tag : 'b',
-                    cls : 'roo-alert-title',
-                    html : this.title
+                    cls : iconCls
                 },
                 {
                     tag : 'span',
-                    cls : 'roo-alert-text',
+                    cls : 'roo-navigation-bar-item-text ' + this.position,
                     html : this.html
                 }
             ]
-        };
-        
-        if(this.faicon){
-            cfg.cn[0].cls += ' fa ' + this.faicon;
         }
         
-        if(this.weight){
-            cfg.cls += ' alert-' + this.weight;
+        if(this.active){
+            cfg.cls += ' active';
+        }
+        if(this.disabled){
+            cfg.cls += ' disabled';
         }
         
         return cfg;
     },
     
-    initEvents: function() 
+    disable : function()
     {
-        this.el.setVisibilityMode(Roo.Element.DISPLAY);
+        this.setDisabled(true);
     },
     
-    setTitle : function(str)
+    enable : function()
     {
-        this.el.select('.roo-alert-title',true).first().dom.innerHTML = str;
+        this.setDisabled(false);
     },
     
-    setText : function(str)
+    initEvents: function() 
     {
-        this.el.select('.roo-alert-text',true).first().dom.innerHTML = str;
+        this.iconEl = this.el.select('.roo-navigation-bar-item-icon', true).first();
+        this.textEl = this.el.select('.roo-navigation-bar-item-text', true).first();
+        
+        if(Roo.isTouch){
+            this.textEl.setVisibilityMode(Roo.Element.DISPLAY).hide();
+        }
+        
+        this.iconEl.on('click', this.onClick, this);
+        
     },
     
-    setWeight : function(weight)
+    onClick : function(e)
     {
-        if(this.weight){
-            this.el.select('.alert',true).first().removeClass('alert-' + this.weight);
+        e.preventDefault();
+        
+        if(this.disabled){
+            return;
         }
         
-        this.weight = weight;
+        if(this.fireEvent('click', this, e) === false){
+            return;
+        };
         
-        this.el.select('.alert',true).first().addClass('alert-' + this.weight);
+        this.parent().setActiveItem(this);
     },
     
-    setIcon : function(icon)
+    isActive: function () 
     {
-        if(this.faicon){
-            this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
+        return this.active;
+    },
+    
+    setActive : function(state)
+    {
+        if(this.active == state){
+            return;
         }
         
-        this.faicon = icon
+        this.active = state;
         
-        this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
+        if (state) {
+            this.el.addClass('active');
+            return;
+        }
+        
+        this.el.removeClass('active');
+        
+        return;
     },
     
-    hide: function() 
+    setDisabled : function(state)
     {
-        this.el.hide();   
+        if(this.disabled == state){
+            return;
+        }
+        
+        this.disabled = state;
+        
+        if (state) {
+            this.el.addClass('disabled');
+            return;
+        }
+        
+        this.el.removeClass('disabled');
     },
     
-    show: function() 
-    {  
-        this.el.show();   
+    tooltipEl : function()
+    {
+        return this.el.select('.roo-navigation-bar-item-icon', true).first();;
     }
-    
 });
 
  
\ No newline at end of file