sync
[roojs1] / roojs-bootstrap-debug.js
index ff6f701..48516fd 100644 (file)
@@ -101,7 +101,7 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
          
         
         var cfg = Roo.apply({},  this.getAutoCreate());
-        cfg.id = Roo.id();
+        cfg.id = this.id || Roo.id();
         
         // fill in the extra attributes 
         if (this.xattr && typeof(this.xattr) =='object') {
@@ -126,8 +126,6 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
             cfg.name = this.name;
         }
         
-       
-        
         this.el = ct.createChild(cfg, position);
         
         if (this.tooltip) {
@@ -262,9 +260,9 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
                 var self_cntr_el = Roo.get(this[cntr](false));
                 var echild =self_cntr_el ? self_cntr_el.child('>*[xtype]') : false;
                 if (echild) { 
-                    Roo.log(Roo.XComponent.build_from_html);
-                    Roo.log("got echild:");
-                    Roo.log(echild);
+                    //Roo.log(Roo.XComponent.build_from_html);
+                    //Roo.log("got echild:");
+                    //Roo.log(echild);
                 }
                 // there is a scenario where some of the child elements are flexy:if (and all of the same type)
                 // and are not displayed -this causes this to use up the wrong element when matching.
@@ -342,9 +340,26 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
         this.fireEvent('childrenrendered', this);
         
         return cn;
-    } 
-    
-    
+    },
+    /**
+     * Show a component - removes 'hidden' class
+     */
+    show : function()
+    {
+        if (this.el) {
+            this.el.removeClass('hidden');
+        }
+    },
+    /**
+     * Hide a component - adds 'hidden' class
+     */
+    hide: function()
+    {
+        if (this.el && !this.el.hasClass('hidden')) {
+            this.el.addClass('hidden');
+        }
+        
+    }
 });
 
  /*
@@ -973,6 +988,8 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
  * @cfg {String} fa (ban|check|...) font awesome icon
  * @cfg {String} icon (info-sign|check|...) glyphicon name
  * @cfg {Boolean} hidden (true|false) hide the element
+ * @cfg {Boolean} expandable (true|false) default false
+ * @cfg {String} rheader contet on the right of header
 
  *     
  * @constructor
@@ -982,6 +999,24 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
 
 Roo.bootstrap.Container = function(config){
     Roo.bootstrap.Container.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // raw events
+         /**
+         * @event expand
+         * After the panel has been expand
+         * 
+         * @param {Roo.bootstrap.Container} this
+         */
+        "expand" : true,
+        /**
+         * @event collapse
+         * After the panel has been collapsed
+         * 
+         * @param {Roo.bootstrap.Container} this
+         */
+        "collapse" : true
+    });
 };
 
 Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
@@ -996,6 +1031,9 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
     alert : false,
     fa: false,
     icon : false,
+    expandable : false,
+    rheader : '',
+    expanded : true,
   
      
     getChildContainer : function() {
@@ -1069,17 +1107,39 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             cfg.cls += ' panel panel-' + this.panel;
             cfg.cn = [];
             if (this.header.length) {
-                cfg.cn.push({
+                
+                var h = [];
+                
+                if(this.expandable){
                     
-                    cls : 'panel-heading',
-                    cn : [{
-                        tag: 'h3',
+                    cfg.cls = cfg.cls + ' expandable';
+                    
+                    h.push({
+                        tag: 'i',
+                        cls: 'fa fa-minus'
+                    });
+                }
+                
+                h.push(
+                    {
+                        tag: 'span',
                         cls : 'panel-title',
                         html : this.header
-                    }]
-                    
+                    },
+                    {
+                        tag: 'span',
+                        cls: 'panel-header-right',
+                        html: this.rheader
+                    }
+                );
+                
+                cfg.cn.push({
+                    cls : 'panel-heading',
+                    cn : h
                 });
+                
             }
+            
             body = false;
             cfg.cn.push({
                 cls : 'panel-body',
@@ -1116,6 +1176,93 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
         return cfg;
     },
     
+    initEvents: function() 
+    {
+        if(!this.expandable){
+            return;
+        }
+        
+        var headerEl = this.headerEl();
+        
+        if(!headerEl){
+            return;
+        }
+        
+        headerEl.on('click', this.onToggleClick, this);
+        
+    },
+    
+    onToggleClick : function()
+    {
+        var headerEl = this.headerEl();
+        
+        if(!headerEl){
+            return;
+        }
+        
+        if(this.expanded){
+            this.collapse();
+            return;
+        }
+        
+        this.expand();
+    },
+    
+    expand : function()
+    {
+        if(this.fireEvent('expand', this)) {
+            
+            this.expanded = true;
+            
+            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
+        
+            var toggleEl = this.toggleEl();
+
+            if(!toggleEl){
+                return;
+            }
+
+            toggleEl.removeClass(['fa-minus', 'fa-plus']).addClass(['fa-minus']);
+        }
+        
+    },
+    
+    collapse : function()
+    {
+        if(this.fireEvent('collapse', this)) {
+            
+            this.expanded = false;
+            
+            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+        
+            var toggleEl = this.toggleEl();
+
+            if(!toggleEl){
+                return;
+            }
+
+            toggleEl.removeClass(['fa-minus', 'fa-plus']).addClass(['fa-plus']);
+        }
+    },
+    
+    toggleEl : function()
+    {
+        if(!this.el || !this.panel.length || !this.header.length || !this.expandable){
+            return;
+        }
+        
+        return this.el.select('.panel-heading .fa',true).first();
+    },
+    
+    headerEl : function()
+    {
+        if(!this.el || !this.panel.length || !this.header.length){
+            return;
+        }
+        
+        return this.el.select('.panel-heading',true).first()
+    },
+    
     titleEl : function()
     {
         if(!this.el || !this.panel.length || !this.header.length){
@@ -1148,14 +1295,15 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
         return titleEl.dom.innerHTML;
     },
     
-    show : function() {
-        this.el.removeClass('hidden');
-    },
-    hide: function() {
-        if (!this.el.hasClass('hidden')) {
-            this.el.addClass('hidden');
+    setRightTitle : function(v)
+    {
+        var t = this.el.select('.panel-header-right',true).first();
+        
+        if(!t){
+            return;
         }
         
+        t.dom.innerHTML = v;
     }
    
 });
@@ -1178,6 +1326,10 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
  * @cfg {String} alt image alternative text
  * @cfg {String} href a tag href
  * @cfg {String} target (_self|_blank|_parent|_top)target for a href.
+ * @cfg {String} xsUrl xs image source
+ * @cfg {String} smUrl sm image source
+ * @cfg {String} mdUrl md image source
+ * @cfg {String} lgUrl lg image source
  * 
  * @constructor
  * Create a new Input
@@ -1205,9 +1357,78 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
     src: '',
     href: false,
     target: false,
+    xsUrl: '',
+    smUrl: '',
+    mdUrl: '',
+    lgUrl: '',
 
-    getAutoCreate : function(){
+    getAutoCreate : function()
+    {   
+        if(this.src || (!this.xsUrl && !this.smUrl && !this.mdUrl && !this.lgUrl)){
+            return this.createSingleImg();
+        }
+        
+        var cfg = {
+            tag: 'div',
+            cls: 'roo-image-responsive-group',
+            cn: []
+        }
+        var _this = this;
+        
+        Roo.each(['xs', 'sm', 'md', 'lg'], function(size){
+            
+            if(!_this[size + 'Url']){
+                return;
+            }
+            
+            var img = {
+                tag: 'img',
+                cls: (_this.imgResponsive) ? 'img-responsive' : '',
+                html: _this.html || cfg.html,
+                src: _this[size + 'Url']
+            }
+            
+            img.cls += ' roo-image-responsive-' + size;
+            
+            var s = ['xs', 'sm', 'md', 'lg'];
+            
+            s.splice(s.indexOf(size), 1);
+            
+            Roo.each(s, function(ss){
+                img.cls += ' hidden-' + ss;
+            });
+            
+            if (['rounded','circle','thumbnail'].indexOf(_this.border)>-1) {
+                cfg.cls += ' img-' + _this.border;
+            }
+            
+            if(_this.alt){
+                cfg.alt = _this.alt;
+            }
+            
+            if(_this.href){
+                var a = {
+                    tag: 'a',
+                    href: _this.href,
+                    cn: [
+                        img
+                    ]
+                }
+
+                if(this.target){
+                    a.target = _this.target;
+                }
+            }
+            
+            cfg.cn.push((_this.href) ? a : img);
+            
+        });
         
+        return cfg;
+    },
+    
+    createSingleImg : function()
+    {
         var cfg = {
             tag: 'img',
             cls: (this.imgResponsive) ? 'img-responsive' : '',
@@ -1241,15 +1462,15 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
             
         }
         
-        
         return (this.href) ? a : cfg;
     },
     
-    initEvents: function() {
-        
+    initEvents: function() 
+    {
         if(!this.href){
             this.el.on('click', this.onClick, this);
         }
+        
     },
     
     onClick : function(e)
@@ -1316,7 +1537,7 @@ Roo.extend(Roo.bootstrap.Link, Roo.bootstrap.Component,  {
         };
         // anchor's do not require html/href...
         if (this.anchor === false) {
-            cfg.html = this.html || 'html-missing';
+            cfg.html = this.html || '';
             cfg.href = this.href || '#';
         } else {
             cfg.name = this.anchor;
@@ -1495,11 +1716,13 @@ Roo.bootstrap.MenuMgr = function(){
        }
    }
 
-   // private
+   // private this should really trigger on mouseup..
    function onMouseDown(e){
-        Roo.log("on MouseDown");
+        Roo.log("on Mouse Up");
         if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu") && !e.getTarget('.user-menu')){
-           hideAll();
+            Roo.log("hideAll");
+            hideAll();
+            e.stopEvent();
         }
         
         
@@ -1733,9 +1956,10 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         
        // Roo.log("ADD event");
        // Roo.log(this.triggerEl.dom);
-        this.triggerEl.on('click', this.onTriggerPress, this);
+        this.triggerEl.on(Roo.isTouch ? 'touchstart' : 'mouseup', this.onTriggerPress, this);
+        
         this.triggerEl.addClass('dropdown-toggle');
-        this.el.on(Roo.isTouch ? 'touchstart' : 'click'   , this.onClick, this);
+        this.el.on(Roo.isTouch ? 'touchstart' : 'click' , this.onClick, this);
 
         this.el.on("mouseover", this.onMouseOver, this);
         this.el.on("mouseout", this.onMouseOut, this);
@@ -1842,14 +2066,19 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         }
         if(_e !== false){
             this.fireEvent("beforeshow", this);
-            
             //xy = this.el.adjustForConstraints(xy);
         }
-        //this.el.setXY(xy);
+        
         //this.el.show();
         this.hideMenuItems();
         this.hidden = false;
         this.triggerEl.addClass('open');
+        
+        if(this.el.getWidth() + xy[0] > Roo.lib.Dom.getViewWidth()){
+            xy[0] = xy[0] - this.el.getWidth() + this.triggerEl.getWidth();
+        }
+        
+        this.el.setXY(xy);
         this.focus();
         this.fireEvent("show", this);
     },
@@ -1898,14 +2127,16 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
             return;
         }
+        
         if (this.isVisible()) {
             Roo.log('hide');
             this.hide();
         } else {
+            Roo.log('show');
             this.show(this.triggerEl, false, false);
         }
         
-        
+        e.stopEvent();
     },
     
          
@@ -2224,6 +2455,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         //this.el.addClass([this.fieldClass, this.cls]);
         
     },
+    
     getAutoCreate : function(){
         
         
@@ -3406,9 +3638,6 @@ Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
           },this);
         }
     }    
-          
-      
-    
     
 });
 
@@ -3472,8 +3701,8 @@ Roo.extend(Roo.bootstrap.NavSidebar, Roo.bootstrap.Navbar,  {
  * @class Roo.bootstrap.NavGroup
  * @extends Roo.bootstrap.Component
  * Bootstrap NavGroup class
- * @cfg {String} align left | right
- * @cfg {Boolean} inverse false | true
+ * @cfg {String} align (left|right)
+ * @cfg {Boolean} inverse
  * @cfg {String} type (nav|pills|tab) default nav
  * @cfg {String} navId - reference Id for navbar.
 
@@ -3764,7 +3993,7 @@ Roo.apply(Roo.bootstrap.NavGroup, {
  * @cfg {Boolean} preventDefault (true | false) default false
  * @cfg {String} tabId the tab that this item activates.
  * @cfg {String} tagtype (a|span) render as a href or span?
- * @cfg {Boolean} animateRef (true|false) link to element default false
+ * @cfg {Boolean} animateRef (true|false) link to element default false  
   
  * @constructor
  * Create a new Navbar Item
@@ -3885,9 +4114,9 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     {
         if(
                 this.preventDefault || 
-                this.href == '#' ||
-                (this.animateRef && this.href.charAt(0) == '#')
+                this.href == '#' 
         ){
+            
             e.preventDefault();
         }
         
@@ -3901,7 +4130,9 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
             return;
         }
         
-        Roo.log("fire event clicked");
+        
+        
+        //Roo.log("fire event clicked");
         if(this.fireEvent('click', this, e) === false){
             return;
         };
@@ -3910,23 +4141,34 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
             return;
         }
         
-        if(this.animateRef && this.href.charAt(0) == '#'){
+        //Roo.log(this.href);
+        var ael = this.el.select('a',true).first();
+        //Roo.log(ael);
+        
+        if(ael && this.animateRef && this.href.indexOf('#') > -1){
+            //Roo.log(["test:",ael.dom.href.split("#")[0], document.location.toString().split("#")[0]]);
+            if (ael.dom.href.split("#")[0] != document.location.toString().split("#")[0]) {
+                return; // ignore... - it's a 'hash' to another page.
+            }
+            
+            e.preventDefault();
             this.scrollToElement(e);
-            return;
         }
         
-        var p = this.parent();
+        
+        var p =  this.parent();
+   
         if (['tabs','pills'].indexOf(p.type)!==-1) {
             if (typeof(p.setActiveItem) !== 'undefined') {
                 p.setActiveItem(this);
             }
         }
+        
         // if parent is a navbarheader....- and link is probably a '#' page ref.. then remove the expanded menu.
         if (p.parentType == 'NavHeaderbar' && !this.menu) {
             // remove the collapsed menu expand...
             p.parent().el.select('.navbar-collapse',true).removeClass('in');  
         }
-        
     },
     
     isActive: function () {
@@ -4007,7 +4249,14 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     {
         var c = document.body;
         
-        var target = Roo.get(c).select('a[name=' + this.href.replace('#', '') +']', true).first();
+        /*
+         * Firefox / IE places the overflow at the html level, unless specifically styled to behave differently.
+         */
+        if(Roo.isFirefox || Roo.isIE || Roo.isIE11){
+            c = document.documentElement;
+        }
+        
+        var target = Roo.get(c).select('a[name=' + this.href.split('#')[1] +']', true).first();
         
         if(!target){
             return;
@@ -4176,6 +4425,8 @@ Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component,  {
  * @cfg {String} html contents of the element
  * @cfg {String} tag tag of the element
  * @cfg {String} cls class of the element
+ * @cfg {Boolean} preventDefault (true|false) default false
+ * @cfg {Boolean} clickable (true|false) default false
  * 
  * @constructor
  * Create a new Element
@@ -4184,6 +4435,17 @@ Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component,  {
 
 Roo.bootstrap.Element = function(config){
     Roo.bootstrap.Element.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // raw events
+        /**
+         * @event click
+         * When a element is chick
+         * @param {Roo.bootstrap.Element} this
+         * @param {Roo.EventObject} e
+         */
+        "click" : true
+    });
 };
 
 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component,  {
@@ -4191,7 +4453,8 @@ Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component,  {
     tag: 'div',
     cls: '',
     html: '',
-     
+    preventDefault: false, 
+    clickable: false,
     
     getAutoCreate : function(){
         
@@ -4201,11 +4464,28 @@ Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component,  {
             html: this.html
         }
         
-        
-       
         return cfg;
     },
     
+    initEvents: function() 
+    {
+        Roo.bootstrap.Element.superclass.initEvents.call(this);
+        
+        if(this.clickable){
+            this.el.on('click', this.onClick, this);
+        }
+        
+    },
+    
+    onClick : function(e)
+    {
+        if(this.preventDefault){
+            e.preventDefault();
+        }
+        
+        this.fireEvent('click', this, e);
+    },
+    
     getValue : function()
     {
         return this.el.dom.innerHTML;
@@ -5537,6 +5817,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
                 c.style += ' width:' + config.width + 'px;';
             }
             
+            if(typeof(config.cls) != 'undefined'){
+                c.cls = (typeof(c.cls) == 'undefined') ? config.cls : (c.cls + ' ' + config.cls);
+            }
+            
             header.cn.push(c)
         }
         
@@ -5809,6 +6093,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
             if(typeof(config.cursor) != 'undefined'){
                 td.style += ' cursor:' +  config.cursor + ';';
             }
+            
+            if(typeof(config.cls) != 'undefined'){
+                td.cls = (typeof(td.cls) == 'undefined') ? config.cls : (td.cls + ' ' + config.cls);
+            }
              
             row.cn.push(td);
            
@@ -7437,13 +7725,13 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         
         var inputblock = input;
         
+        var feedback = {
+            tag: 'span',
+            cls: 'glyphicon form-control-feedback'
+        };
+            
         if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
             
-            var feedback = {
-                tag: 'span',
-                cls: 'glyphicon form-control-feedback'
-            };
-
             inputblock = {
                 cls : 'has-feedback',
                 cn :  [
@@ -7452,8 +7740,6 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 ] 
             };  
         }
-         
-//        var inputblock = input;
         
         if (this.before || this.after) {
             
@@ -7482,11 +7768,6 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             
             inputblock.cn.push(input);
             
-            if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
-                inputblock.cls += ' has-feedback';
-                inputblock.cn.push(feedback);
-            }
-            
             if (this.after && typeof(this.after) == 'string') {
                 inputblock.cn.push({
                     tag :'span',
@@ -7503,6 +7784,11 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                         (this.after.xtype == 'Button' ? 'btn' : 'addon')  //?? what about checkboxes - that looks like a bit of a hack thought? 
                 });
             }
+            
+            if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
+                inputblock.cls += ' has-feedback';
+                inputblock.cn.push(feedback);
+            }
         };
         
         if (align ==='left' && this.fieldLabel.length) {
@@ -8215,6 +8501,11 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
      */
     hideTrigger:false,
 
+    /**
+     * @cfg {Boolean} removable (true|false) special filter default false
+     */
+    removable : false,
+    
     /** @cfg {Boolean} grow @hide */
     /** @cfg {Number} growMin @hide */
     /** @cfg {Number} growMax @hide */
@@ -8274,14 +8565,44 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                 tag: 'span',
                 cls: 'glyphicon form-control-feedback'
             };
+            
+            if(this.removable && !this.editable && !this.tickable){
+                inputblock = {
+                    cls : 'has-feedback',
+                    cn :  [
+                        inputblock,
+                        {
+                            tag: 'button',
+                            html : 'x',
+                            cls : 'roo-combo-removable-btn close'
+                        },
+                        feedback
+                    ] 
+                };
+            } else {
+                inputblock = {
+                    cls : 'has-feedback',
+                    cn :  [
+                        inputblock,
+                        feedback
+                    ] 
+                };
+            }
 
-            inputblock = {
-                cls : 'has-feedback',
-                cn :  [
-                    input,
-                    feedback
-                ] 
-            };  
+        } else {
+            if(this.removable && !this.editable && !this.tickable){
+                inputblock = {
+                    cls : 'roo-removable',
+                    cn :  [
+                        inputblock,
+                        {
+                            tag: 'button',
+                            html : 'x',
+                            cls : 'roo-combo-removable-btn close'
+                        }
+                    ] 
+                };
+            }
         }
         
         if (this.before || this.after) {
@@ -8456,7 +8777,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                 cfg.cls += ' col-' + size + '-' + settings[size];
             }
         });
-        
+        Roo.log(cfg);
         return cfg;
         
     },
@@ -8510,6 +8831,15 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             this.inputEl().on("click", this.onTriggerClick, this, {preventDefault:true});
         }
         
+        if(this.removable && !this.editable && !this.tickable){
+            var close = this.closeTriggerEl();
+            
+            if(close){
+                close.setVisibilityMode(Roo.Element.DISPLAY).hide();
+                close.on('click', this.removeBtnClick, this, close);
+            }
+        }
+        
         //this.trigger.addClassOnOver('x-form-trigger-over');
         //this.trigger.addClassOnClick('x-form-trigger-click');
         
@@ -8518,6 +8848,21 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
         //}
     },
     
+    closeTriggerEl : function()
+    {
+        var close = this.el.select('.roo-combo-removable-btn', true).first();
+        return close ? close : false;
+    },
+    
+    removeBtnClick : function(e, h, el)
+    {
+        e.preventDefault();
+        
+        if(this.fireEvent("remove", this) !== false){
+            this.reset();
+        }
+    },
+    
     createList : function()
     {
         this.list = Roo.get(document.body).createChild({
@@ -10436,6 +10781,7 @@ var myReader = new Roo.data.JsonReader({
  * @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
  * @cfg {String} root name of the property which contains the Array of row objects.
  * @cfg {String} id Name of the property within a row object that contains a record identifier value.
+ * @cfg {Array} fields Array of field definition objects
  * @constructor
  * Create a new JsonReader
  * @param {Object} meta Metadata configuration options
@@ -10693,6 +11039,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
@@ -10757,7 +11105,13 @@ Roo.bootstrap.ComboBox = function(config){
          * Fires when the remove value from the combobox array
             * @param {Roo.bootstrap.ComboBox} combo This combo box
             */
-        'remove' : true
+        'remove' : true,
+        /**
+         * @event specialfilter
+         * Fires when specialfilter
+            * @param {Roo.bootstrap.ComboBox} combo This combo box
+            */
+        'specialfilter' : true
         
     });
     
@@ -10806,6 +11160,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
      * mode = 'remote' or 'text' if mode = 'local')
      */
     displayField: undefined,
+    
     /**
      * @cfg {String} valueField The underlying data value name to bind to this CombBox (defaults to undefined if
      * mode = 'remote' or 'value' if mode = 'local'). 
@@ -10951,6 +11306,16 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
      */
     validClass : "has-success",
     
+    /**
+     * @cfg {Boolean} specialFilter (true|false) special filter default false
+     */
+    specialFilter : false,
+    
+    /**
+     * @cfg {Boolean} mobileTouchView (true|false) show mobile touch view when using a mobile default true
+     */
+    mobileTouchView : true,
+    
     //private
     addicon : false,
     editicon: false,
@@ -10964,12 +11329,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
          */
@@ -11142,8 +11518,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;
@@ -11713,6 +12099,12 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         this.lastSelectionText = '';
         this.lastData = false;
         
+        var close = this.closeTriggerEl();
+        
+        if(close){
+            close.hide();
+        }
+        
     },
 
     /**
@@ -11743,6 +12135,12 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         }
         Roo.bootstrap.ComboBox.superclass.setValue.call(this, text);
         this.value = v;
+        
+        var close = this.closeTriggerEl();
+        
+        if(close){
+            (v && (v.length || v * 1 > 0)) ? close.show() : close.hide();
+        }
     },
     /**
      * @property {Object} the last set data for the element
@@ -11774,6 +12172,12 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             vv = !o || typeof(o[this.valueField]) == 'undefined' ? dv : o[this.valueField];
         }
         
+        var close = this.closeTriggerEl();
+        
+        if(close){
+            (vv.length || vv * 1 > 0) ? close.show() : close.hide();
+        }
+        
         if(this.hiddenField){
             this.hiddenField.dom.value = vv;
             
@@ -11789,6 +12193,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         this.value = vv;
         
         
+        
     },
     // private
     reset : function(){
@@ -12062,9 +12467,21 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                     if(forceAll){
                         this.store.clearFilter();
                     }else{
+                        
+                        if(this.specialFilter){
+                            this.fireEvent('specialfilter', this);
+                            this.onLoad();
+                            return;
+                        }
+                        
                         this.store.filter(this.displayField, q);
                     }
+                    
+                    this.store.fireEvent("datachanged", this.store);
+                    
                     this.onLoad();
+                    
+                    
                 }else{
                     
                     this.store.baseParams[this.queryParam] = q;
@@ -12093,7 +12510,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         
         this.loadNext = false;
     },
-
+    
     // private
     getParams : function(q){
         var p = {};
@@ -12446,6 +12863,8 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         if(this.hiddenField){
             this.hiddenField.dom.value = this.value;
         }
+        
+        this.store.fireEvent("datachanged", this.store);
     },
     
     clearItem : function()
@@ -12467,9 +12886,14 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     
     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();
     },
     
@@ -12522,468 +12946,1038 @@ 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, {
-    
-     /**
-     * @cfg {Roo.data.Store} store Data store to load data from.
-     */
-    store : false,
+    // 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();
+        
+        if(firstChecked && listHeight > bodyHeight){
+            (function() { firstChecked.findParent('li').scrollIntoView(this.touchViewListGroup.dom); }).defer(500);
+        }
+        
+    },
     
-    /**
-     * @cfg {String|Roo.Element} el The container element.
-     */
-    el : '',
+    onTouchViewLoadException : function()
+    {
+        this.hideTouchView();
+    },
     
-    /**
-     * @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;
+    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;
+        
     },
     
+    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;
+    onTouchViewClick : function(e, el, o)
+    {
+        e.preventDefault();
         
-        // 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> ?????
+        var row = o.row;
+        var rowIndex = o.rowIndex;
         
+        var r = this.store.getAt(rowIndex);
         
+        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);
+            
+            row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
         
-        this.clearSelections();
-        this.el.update("");
-        var html = [];
-        var records = this.store.getRange();
-        if(records.length < 1) {
+            this.setFromData(r.data);
             
-            // is this valid??  = should it render a template??
+            var close = this.closeTriggerEl();
+        
+            if(close){
+                close.show();
+            }
+
+            this.hideTouchView();
             
-            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)
-            );
+        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++){
-            ns[i].nodeIndex = 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">
+ */
 
-    /**
-     * 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){
+/**
+ * @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
           
-            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);
-        }
+          
+        });
+
+
+
+    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"));
         
-        if(store){
-            this.refresh();
-        }
-    },
+        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,
+    
     /**
-     * onbeforeLoad - masks the loading area.
-     *
+     * @cfg {String|Roo.Element} el The container element.
      */
-    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();
-    },
+    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
+     * @cfg {String|Roo.Template} tpl The template used by this View 
      */
-    findItemFromChild : function(node){
+    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);
+        }
+        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; 
@@ -14222,10 +15216,12 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
     },
     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.
@@ -14329,7 +15325,7 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
         // 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.select('.popover-content',true).first().dom.innerHtml = this.html;
         }
         this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
         if (!this.title.length) {
@@ -14366,7 +15362,7 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
         //arrow.set(align[2], 
         
         this.el.addClass('in');
-        this.hoverState = null;
+        
         
         if (this.el.hasClass('fade')) {
             // fade it?
@@ -14378,6 +15374,7 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
         this.el.setXY([0,0]);
         this.el.removeClass('in');
         this.el.hide();
+        this.hoverState = null;
         
     }
     
@@ -14550,7 +15547,8 @@ Roo.extend(Roo.bootstrap.ProgressBar, Roo.bootstrap.Component,  {
  * @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 {Boolena} autoslide (true|false) auto slide .. default false
+ * @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
@@ -14576,6 +15574,7 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
     timer : 0,
     autoslide : false,
     slideFn : false,
+    slideOnTouch : false,
     
     getAutoCreate : function()
     {
@@ -14583,6 +15582,8 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
         
         cfg.cls += ' tab-content';
         
+        Roo.log('get auto create...............');
+        
         if (this.carousel) {
             cfg.cls += ' carousel slide';
             
@@ -14590,13 +15591,17 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
                cls : 'carousel-inner'
             }];
         
-            if(this.bullets > 0){
+            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
@@ -14618,33 +15623,33 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
     {
         Roo.log('-------- init events on tab group ---------');
         
-        var _this = this;
+        if(this.bullets > 0 && !Roo.isTouch){
+            this.initBullet();
+        }
         
-        if(this.bullets > 0){
-            
-            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);
-                    
-                }).createDelegate(this, [i, bullet], true));
-                
-            }
+        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);
         }
+        
+    },
+    
+    onTouchStart : function(e, el, o)
+    {
+        if(!this.slideOnTouch || !Roo.isTouch || Roo.get(e.getTarget()).hasClass('roo-button-text')){
+            return;
+        }
+        
+        this.showPanelNext();
     },
     
     getChildContainer : function()
@@ -14727,7 +15732,7 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
             return false;
         }
         
-        if(this.bullets > 0){
+        if(this.bullets > 0 && !Roo.isTouch){
             this.setActiveBullet(this.indexOfPanel(pan));
         }
         
@@ -14794,8 +15799,44 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
         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){
+
+                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));
+        }
+    },
+    
     setActiveBullet : function(i)
     {
+        if(Roo.isTouch){
+            return;
+        }
+        
         Roo.each(this.el.select('.bullet', true).elements, function(el){
             el.removeClass('selected');
         });
@@ -18195,7 +19236,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         this.execCmd('FontSize', v  );
     },
 
-    onEditorEvent : function(e){
+    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
@@ -18834,21 +19876,12 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         
     },
+    
     /**
      * Clean up MS wordisms...
      */
     cleanWord : function(node)
     {
-        var _t = this;
-        var cleanWordChildren = function()
-        {
-            if (!node.childNodes.length) {
-                return;
-            }
-            for (var i = node.childNodes.length-1; i > -1 ; i--) {
-               _t.cleanWord(node.childNodes[i]);
-            }
-        }
         
         
         if (!node) {
@@ -18878,7 +19911,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 node.parentNode.insertBefore(cn, node);
             }
             node.parentNode.removeChild(node);
-            cleanWordChildren();
+            this.iterateChildren(node, this.cleanWord);
             return;
         }
         // clean styles
@@ -18922,11 +19955,87 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 node.removeAttribute('style');
             }
         }
+        this.iterateChildren(node, this.cleanWord);
+        
+        
+        
+    },
+    /**
+     * iterateChildren of a Node, calling fn each time, using this as the scole..
+     * @param {DomNode} node node to iterate children of.
+     * @param {Function} fn method of this class to call on each item.
+     */
+    iterateChildren : function(node, fn)
+    {
+        if (!node.childNodes.length) {
+                return;
+        }
+        for (var i = node.childNodes.length-1; i > -1 ; i--) {
+           fn.call(this, node.childNodes[i])
+        }
+    },
+    
+    
+    /**
+     * cleanTableWidths.
+     *
+     * Quite often pasting from word etc.. results in tables with column and widths.
+     * This does not work well on fluid HTML layouts - like emails. - so this code should hunt an destroy them..
+     *
+     */
+    cleanTableWidths : function(node)
+    {
+         
+         
+        if (!node) {
+            this.cleanTableWidths(this.doc.body);
+            return;
+        }
+        
+        // ignore list...
+        if (node.nodeName == "#text" || node.nodeName == "#comment") {
+            return; 
+        }
+        Roo.log(node.tagName);
+        if (!node.tagName.toLowerCase().match(/^(table|td|tr)$/)) {
+            this.iterateChildren(node, this.cleanTableWidths);
+            return;
+        }
+        if (node.hasAttribute('width')) {
+            node.removeAttribute('width');
+        }
+        
+         
+        if (node.hasAttribute("style")) {
+            // pretty basic...
+            
+            var styles = node.getAttribute("style").split(";");
+            var nstyle = [];
+            Roo.each(styles, function(s) {
+                if (!s.match(/:/)) {
+                    return;
+                }
+                var kv = s.split(":");
+                if (kv[0].match(/^\s*(width|min-width)\s*$/)) {
+                    return;
+                }
+                // what ever is left... we allow.
+                nstyle.push(s);
+            });
+            node.setAttribute("style", nstyle.length ? nstyle.join(';') : '');
+            if (!nstyle.length) {
+                node.removeAttribute('style');
+            }
+        }
         
-        cleanWordChildren();
+        this.iterateChildren(node, this.cleanTableWidths);
         
         
     },
+    
+    
+    
+    
     domToHTML : function(currentElement, depth, nopadtext) {
         
         depth = depth || 0;
@@ -19798,10 +20907,10 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
                 //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;
        }
@@ -19881,2941 +20990,3551 @@ Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,
                     editor.focus();
                 }
             }
-            
+            
+        });
+       */
+        
+         
+       this.xtype = 'NavSimplebar';
+        
+        for(var i=0;i< children.length;i++) {
+            
+            this.buttons.add(this.addxtypeChild(children[i]));
+            
+        }
+        
+        editor.on('editorevent', this.updateToolbar, this);
+    },
+    onBtnClick : function(id)
+    {
+       this.editorcore.relayCmd(id);
+       this.editorcore.focus();
+    },
+    
+    /**
+     * Protected method that will not generally be called directly. It triggers
+     * a toolbar update by reading the markup state of the current selection in the editor.
+     */
+    updateToolbar: function(){
+
+        if(!this.editorcore.activated){
+            this.editor.onFirstFocus(); // is this neeed?
+            return;
+        }
+
+        var btns = this.buttons; 
+        var doc = this.editorcore.doc;
+        btns.get('bold').setActive(doc.queryCommandState('bold'));
+        btns.get('italic').setActive(doc.queryCommandState('italic'));
+        //btns.get('underline').setActive(doc.queryCommandState('underline'));
+        
+        btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
+        btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
+        btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
+        
+        //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
+        btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
+         /*
+        
+        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;
+                }
+            }
+        }
+        
+        
+        
+        // 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(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);
+       
+    }
+});
+
+
+
+
+
+/**
+ * @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();
+    },
+
+    /**
+     * 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. 
+ * @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,  {
+    /**
+     * @cfg {Boolean} singleSelect
+     * True to allow selection of only one row at a time (defaults to false)
+     */
+    singleSelect : false,
+
+    // private
+    initEvents : 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);
+        }
+
+        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);
+    },
+
+    // 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.xtype = 'NavSimplebar';
-        
-        for(var i=0;i< children.length;i++) {
-            
-            this.buttons.add(this.addxtypeChild(children[i]));
-            
+    },
+
+    // private
+    onRemove : function(v, index, r){
+        this.selections.remove(r);
+    },
+
+    // private
+    onRowUpdated : function(v, index, r){
+        if(this.isSelected(r)){
+            v.onRowSelect(index);
         }
-        
-        editor.on('editorevent', this.updateToolbar, this);
     },
-    onBtnClick : function(id)
-    {
-       this.editorcore.relayCmd(id);
-       this.editorcore.focus();
+
+    /**
+     * 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);
+        }
     },
-    
+
     /**
-     * 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.
+     * Gets the number of selected rows.
+     * @return {Number}
      */
-    updateToolbar: function(){
+    getCount : function(){
+        return this.selections.length;
+    },
 
-        if(!this.editorcore.activated){
-            this.editor.onFirstFocus(); // is this neeed?
-            return;
+    /**
+     * Selects the first row in the grid.
+     */
+    selectFirstRow : function(){
+        this.selectRow(0);
+    },
+
+    /**
+     * 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);
         }
+    },
 
-        var btns = this.buttons; 
-        var doc = this.editorcore.doc;
-        btns.get('bold').setActive(doc.queryCommandState('bold'));
-        btns.get('italic').setActive(doc.queryCommandState('italic'));
-        //btns.get('underline').setActive(doc.queryCommandState('underline'));
-        
-        btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
-        btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
-        btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
-        
-        //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
-        btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
-         /*
-        
-        var ans = this.editorcore.getAllAncestors();
-        if (this.formatCombo) {
-            
-            
-            var store = this.formatCombo.store;
-            this.formatCombo.setValue("");
-            for (var i =0; i < ans.length;i++) {
-                if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
-                    // select it..
-                    this.formatCombo.setValue(ans[i].tagName.toLowerCase());
-                    break;
-                }
-            }
+    /**
+     * 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);
         }
-        
-        
-        
-        // 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();
-        });
+
+    /**
+     * Returns the selected records
+     * @return {Array} Array of selected records
+     */
+    getSelections : function(){
+        return [].concat(this.selections.items);
     },
-    toggleSourceEdit : function(sourceEditMode){
-        
-          
-        if(sourceEditMode){
-            Roo.log("disabling buttons");
-           this.buttons.each( function(item){
-                if(item.cmd != 'pencil'){
-                    item.disable();
-                }
-            });
-          
+
+    /**
+     * 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{
-            Roo.log("enabling buttons");
-            if(this.editorcore.initialized){
-                this.buttons.each( function(item){
-                    item.enable();
-                });
+            this.selections.clear();
+        }
+        this.last = false;
+    },
+
+
+    /**
+     * 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);
+        }
+    },
+
+    /**
+     * 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}
+     */
+    isSelected : function(index){
+        var r = typeof index == "number" ? this.grid.dataSource.getAt(index) : index;
+        return (r && this.selections.key(r.id) ? true : false);
+    },
+
+    /**
+     * 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);
+    },
+
+    // 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);
             }
-            
         }
-        Roo.log("calling toggole on editor");
-        // tell the editor that it's been pressed..
-        this.editor.toggleSourceEdit(sourceEditMode);
-       
-    }
-});
-
-
-
-
-
-/**
- * @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();
+        this.fireEvent("afterselectionchange", this);
+    },
+    // private
+    handleDragableRowClick :  function(grid, rowIndex, e) 
+    {
+        if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
+            this.selectRow(rowIndex, false);
+            grid.view.focusRow(rowIndex);
+             this.fireEvent("afterselectionchange", this);
+        }
+    },
+    
+    /**
+     * 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);
+        }
     },
 
     /**
-     * Locks the selections.
+     * 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
      */
-    lock : function(){
-        this.locked = true;
+    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);
+            }
+        }
     },
 
     /**
-     * Unlocks the selections.
+     * 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
      */
-    unlock : function(){
-        this.locked = false;
+    deselectRange : function(startRow, endRow, preventViewNotify){
+        if(this.locked) return;
+        for(var i = startRow; i <= endRow; i++){
+            this.deselectRow(i, preventViewNotify);
+        }
     },
 
     /**
-     * Returns true if the selections are locked.
-     * @return {Boolean}
+     * Selects a row.
+     * @param {Number} row The index of the row to select
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
      */
-    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;
-};
+    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);
+        }
+    },
 
-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)
+     * Deselects a row.
+     * @param {Number} row The index of the row to deselect
      */
-    singleSelect : false,
-
-    // private
-    initEvents : 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);
+    deselectRow : function(index, preventViewNotify){
+        if(this.locked) return;
+        if(this.last == index){
+            this.last = false;
         }
-
-        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);
+        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
-    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);
-            }
-        });
+    restoreLast : function(){
+        if(this._last){
+            this.last = this._last;
+        }
     },
 
     // private
-    onRemove : function(v, index, r){
-        this.selections.remove(r);
+    acceptsNav : function(row, col, cm){
+        return !cm.isHidden(col) && cm.isCellEditable(col, row);
     },
 
     // private
-    onRowUpdated : function(v, index, r){
-        if(this.isSelected(r)){
-            v.onRowSelect(index);
+    onEditorKey : function(field, e){
+        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
+        if(k == e.TAB){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
+            }
+        }else if(k == e.ENTER && !e.ctrlKey){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
+            }
+        }else if(k == e.ESC){
+            ed.cancelEdit();
         }
-    },
+        if(newCell){
+            g.startEditing(newCell[0], newCell[1]);
+        }
+    }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+/**
+ * @class Roo.bootstrap.PagingToolbar
+ * @extends Roo.Row
+ * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
+ * @constructor
+ * Create a new PagingToolbar
+ * @param {Object} config The config object
+ */
+Roo.bootstrap.PagingToolbar = function(config)
+{
+    // old args format still supported... - xtype is prefered..
+        // created from xtype...
+    var ds = config.dataSource;
+    this.toolbarItems = [];
+    if (config.items) {
+        this.toolbarItems = config.items;
+//        config.items = [];
+    }
+    
+    Roo.bootstrap.PagingToolbar.superclass.constructor.call(this, config);
+    this.ds = ds;
+    this.cursor = 0;
+    if (ds) { 
+        this.bind(ds);
+    }
+    
+    this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
+    
+};
 
+Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
     /**
-     * Select records.
-     * @param {Array} records The records to select
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     * @cfg {Roo.data.Store} dataSource
+     * The underlying data store providing the paged data
      */
-    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);
-        }
-    },
-
     /**
-     * Gets the number of selected rows.
-     * @return {Number}
+     * @cfg {String/HTMLElement/Element} container
+     * container The id or element that will contain the toolbar
      */
-    getCount : function(){
-        return this.selections.length;
-    },
-
     /**
-     * Selects the first row in the grid.
+     * @cfg {Boolean} displayInfo
+     * True to display the displayMsg (defaults to false)
      */
-    selectFirstRow : function(){
-        this.selectRow(0);
-    },
-
     /**
-     * Select the last row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     * @cfg {Number} pageSize
+     * The number of records to display per page (defaults to 20)
      */
-    selectLastRow : function(keepExisting){
-        this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting);
-    },
-
+    pageSize: 20,
     /**
-     * Selects the row immediately following the last selected row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     * @cfg {String} displayMsg
+     * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
      */
-    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);
-        }
-    },
-
+    displayMsg : 'Displaying {0} - {1} of {2}',
     /**
-     * Selects the row that precedes the last selected row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     * @cfg {String} emptyMsg
+     * The message to display when no records are found (defaults to "No data to display")
      */
-    selectPrevious : function(keepExisting){
-        if(this.last){
-            this.selectRow(this.last-1, keepExisting);
-            this.grid.getView().focusRow(this.last);
-        }
-    },
-
+    emptyMsg : 'No data to display',
     /**
-     * Returns the selected records
-     * @return {Array} Array of selected records
+     * Customizable piece of the default paging text (defaults to "Page")
+     * @type String
      */
-    getSelections : function(){
-        return [].concat(this.selections.items);
-    },
-
+    beforePageText : "Page",
     /**
-     * Returns the first selected record.
-     * @return {Record}
+     * Customizable piece of the default paging text (defaults to "of %0")
+     * @type String
      */
-    getSelected : function(){
-        return this.selections.itemAt(0);
-    },
-
-
+    afterPageText : "of {0}",
     /**
-     * Clears all selections.
+     * Customizable piece of the default paging text (defaults to "First Page")
+     * @type String
      */
-    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();
+    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();
         }
-        this.last = false;
-    },
+        
+        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);
+        });
+        
+        
+        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"]) }
+        });
+        
+        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();
+        
+        
+        var field = this.navgroup.addItem( {
+            tagtype : 'span',
+            cls : 'x-paging-position',
+            
+            html : this.beforePageText  +
+                '<input type="text" size="3" value="1" class="x-grid-page-number">' +
+                '<span class="x-paging-after">' +  String.format(this.afterPageText, 1) + '</span>'
+         } ); //?? escaped?
+        
+        this.field = field.el.select('input', true).first();
+        this.field.on("keydown", this.onPagingKeydown, this);
+        this.field.on("focus", function(){this.dom.select();});
+    
+    
+        this.afterTextEl =  field.el.select('.x-paging-after',true).first();
+        //this.field.setHeight(18);
+        //this.addSeparator();
+        this.next = this.navgroup.addItem({
+            tooltip: this.nextText,
+            cls: "next",
+            html : ' <i class="fa fa-step-forward">',
+            disabled: true,
+            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"]) }
+        });
 
+    },
 
-    /**
-     * 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);
+    // 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);
         }
     },
 
-    /**
-     * Returns True if there is a selection.
-     * @return {Boolean}
-     */
-    hasSelection : function(){
-        return this.selections.length > 0;
+    // private
+    onLoad : function(ds, r, o){
+       this.cursor = o.params ? o.params.start : 0;
+       var d = this.getPageData(),
+            ap = d.activePage,
+            ps = d.pages;
+        
+       this.afterTextEl.dom.innerHTML = String.format(this.afterPageText, d.pages);
+       this.field.dom.value = ap;
+       this.first.setDisabled(ap == 1);
+       this.prev.setDisabled(ap == 1);
+       this.next.setDisabled(ap == ps);
+       this.last.setDisabled(ap == ps);
+       this.loading.enable();
+       this.updateInfo();
     },
 
-    /**
-     * 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);
+    // 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)
+        };
     },
 
-    /**
-     * 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);
+    // private
+    onLoadError : function(){
+        this.loading.enable();
     },
 
     // 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);
+    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();
         }
-        this.fireEvent("afterselectionchange", this);
-    },
-    // private
-    handleDragableRowClick :  function(grid, rowIndex, e) 
-    {
-        if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
-            this.selectRow(rowIndex, false);
-            grid.view.focusRow(rowIndex);
-             this.fireEvent("afterselectionchange", this);
-        }
-    },
-    
-    /**
-     * 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();
+        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();
         }
-        for(var i = 0, len = rows.length; i < len; i++){
-            this.selectRow(rows[i], true);
+        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();
         }
     },
 
-    /**
-     * 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);
-            }
+    // private
+    beforeLoad : function(){
+        if(this.loading){
+            this.loading.disable();
         }
     },
 
-    /**
-     * 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);
+    // private
+    onClick : function(which){
+        
+        var ds = this.ds;
+        if (!ds) {
+            return;
         }
-    },
-
-    /**
-     * 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);
+        
+        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;
         }
     },
 
     /**
-     * Deselects a row.
-     * @param {Number} row The index of the row to deselect
+     * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
+     * @param {Roo.data.Store} store The data store to unbind
      */
-    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);
+    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;
     },
 
-    // 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]);
-        }
+    /**
+     * 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;
     }
 });/*
- * 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.
+ * - LGPL
  *
- * Fork - LGPL
- * <script type="text/javascript">
+ * element
+ * 
  */
+
 /**
- * @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.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 PagingToolbar
+ * Create a new Element
  * @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.MessageBar = function(config){
+    Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
+};
 
-    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
+Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component,  {
+    
+    html: '',
+    weight: 'info',
+    closable: false,
+    fixed: false,
+    beforeClass: 'bootstrap-sticky-wrap',
+    
+    getAutoCreate : function(){
         
-        if(this.displayInfo){
-            Roo.log(this.el.select('ul.navbar-nav',true).first());
-            this.el.select('ul.navbar-nav',true).first().createChild({cls:'x-paging-info'});
-            this.displayEl = this.el.select('.x-paging-info', true).first();
-//            var navel = this.navgroup.addItem( { tagtype : 'span', html : '', cls : 'x-paging-info', preventDefault : true } );
-//            this.displayEl = navel.el.select('span',true).first();
+        var cfg = {
+            tag: 'div',
+            cls: 'alert alert-dismissable alert-' + this.weight,
+            cn: [
+                {
+                    tag: 'span',
+                    cls: 'message',
+                    html: this.html || ''
+                }
+            ]
         }
         
-        var _this = this;
+        if(this.fixed){
+            cfg.cls += ' alert-messages-fixed';
+        }
         
-        if(this.buttons){
-            Roo.each(_this.buttons, function(e){
-               Roo.factory(e).onRender(_this.el, null);
+        if(this.closable){
+            cfg.cn.push({
+                tag: 'button',
+                cls: 'close',
+                html: 'x'
             });
         }
+        
+        return cfg;
+    },
+    
+    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();
             
-        Roo.each(_this.toolbarItems, function(e) {
-            _this.navgroup.addItem(e);
-        });
+            if (this.cls) {
+                cfg.cls += ' ' + this.cls;
+            }
+            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);
         
-        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"]) }
-        });
+    },
+    
+    show : function()
+    {
+        if (!this.rendered) {
+            this.render();
+        }
         
-        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();
+        this.el.show();
+        
+        this.fireEvent('show', this);
         
+    },
+    
+    hide : function()
+    {
+        if (!this.rendered) {
+            this.render();
+        }
         
-        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.el.hide();
         
-        this.field = field.el.select('input', true).first();
-        this.field.on("keydown", this.onPagingKeydown, this);
-        this.field.on("focus", function(){this.dom.select();});
+        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
     
-        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"]) }
-        });
+ -{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%'
 
-    // 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);
-        }
     },
+    title : false,
 
-    // private
-    onLoad : function(ds, r, o){
-       this.cursor = o.params ? o.params.start : 0;
-       var d = this.getPageData(),
-            ap = d.activePage,
-            ps = d.pages;
+    getAutoCreate : function(){
         
-       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();
+        var cfg = {
+            tag: 'div',
+            html : null
+        }
+        
+        
+        return  cfg;
     },
 
-    // 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)
-        };
-    },
+    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
+//                });
 
-    // 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();
+    load : function(graphtype,xdata,opts){
+        this.raphael.clear();
+        if(!graphtype) {
+            graphtype = this.graphtype;
         }
-    },
-
-    // private
-    beforeLoad : function(){
-        if(this.loading){
-            this.loading.disable();
+        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);
+
+                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;
 
-    // private
-    onClick : function(which){
-        
-        var ds = this.ds;
-        if (!ds) {
-            return;
         }
         
-        switch(which){
-            case "first":
-                ds.load({params:{start: 0, limit: this.pageSize}});
-            break;
-            case "prev":
-                ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
-            break;
-            case "next":
-                ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
-            break;
-            case "last":
-                var total = ds.getTotalCount();
-                var extra = total % this.pageSize;
-                var lastStart = extra ? (total - extra) : total-this.pageSize;
-                ds.load({params:{start: lastStart, limit: this.pageSize}});
-            break;
-            case "refresh":
-                ds.load({params:{start: this.cursor, limit: this.pageSize}});
-            break;
+        if(this.title){
+            this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
         }
+        
     },
-
-    /**
-     * 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;
+    
+    setTitle: function(o)
+    {
+        this.title = o;
     },
-
-    /**
-     * 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;
+    
+    initEvents: function() {
+        
+        if(!this.href){
+            this.el.on('click', this.onClick, this);
+        }
+    },
+    
+    onClick : function(e)
+    {
+        Roo.log('img onclick');
+        this.fireEvent('click', this, e);
     }
-});/*
+   
+});
+
+/*
  * - LGPL
  *
- * element
+ * numberBox
  * 
  */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
 
 /**
- * @class Roo.bootstrap.MessageBar
+ * @class Roo.bootstrap.dash.NumberBox
  * @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
+ * 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 Element
+ * Create a new NumberBox
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.MessageBar = function(config){
-    Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
+
+Roo.bootstrap.dash.NumberBox = function(config){
+    Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+    
 };
 
-Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component,  {
     
-    html: '',
-    weight: 'info',
-    closable: false,
-    fixed: false,
-    beforeClass: 'bootstrap-sticky-wrap',
+    headline : '',
+    content : '',
+    icon : '',
+    footer : '',
+    fhref : '',
+    ficon : '',
     
     getAutoCreate : function(){
         
         var cfg = {
-            tag: 'div',
-            cls: 'alert alert-dismissable alert-' + this.weight,
-            cn: [
+            tag : 'div',
+            cls : 'small-box ',
+            cn : [
                 {
-                    tag: 'span',
-                    cls: 'message',
-                    html: this.html || ''
+                    tag : 'div',
+                    cls : 'inner',
+                    cn :[
+                        {
+                            tag : 'h3',
+                            cls : 'roo-headline',
+                            html : this.headline
+                        },
+                        {
+                            tag : 'p',
+                            cls : 'roo-content',
+                            html : this.content
+                        }
+                    ]
                 }
             ]
         }
         
-        if(this.fixed){
-            cfg.cls += ' alert-messages-fixed';
-        }
-        
-        if(this.closable){
+        if(this.icon){
             cfg.cn.push({
-                tag: 'button',
-                cls: 'close',
-                html: 'x'
+                tag : 'div',
+                cls : 'icon',
+                cn :[
+                    {
+                        tag : 'i',
+                        cls : 'ion ' + this.icon
+                    }
+                ]
             });
         }
         
-        return cfg;
-    },
-    
-    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.footer){
+            var footer = {
+                tag : 'a',
+                cls : 'small-box-footer',
+                href : this.fhref || '#',
+                html : this.footer
+            };
             
-            if (this.cls) {
-                cfg.cls += ' ' + this.cls;
-            }
-            if (this.style) {
-                cfg.style = this.style;
-            }
-            this.el = Roo.get(document.body).createChild(cfg, Roo.select('.'+this.beforeClass, true).first());
+            cfg.cn.push(footer);
             
-            this.el.setVisibilityMode(Roo.Element.DISPLAY);
         }
         
-        this.el.select('>button.close').on('click', this.hide, this);
-        
+        return  cfg;
     },
-    
-    show : function()
+
+    onRender : function(ct,position){
+        Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
+
+
+       
+                
+    },
+
+    setHeadline: function (value)
     {
-        if (!this.rendered) {
-            this.render();
-        }
-        
-        this.el.show();
-        
-        this.fireEvent('show', this);
-        
+        this.el.select('.roo-headline',true).first().dom.innerHTML = value;
     },
     
-    hide : function()
+    setFooter: function (value, href)
     {
-        if (!this.rendered) {
-            this.render();
-        }
+        this.el.select('a.small-box-footer',true).first().dom.innerHTML = value;
         
-        this.el.hide();
+        if(href){
+            this.el.select('a.small-box-footer',true).first().attr('href', href);
+        }
         
-        this.fireEvent('hide', this);
     },
-    
-    update : function()
+
+    setContent: function (value)
     {
-//        var e = this.el.dom.firstChild;
-//        
-//        if(this.closable){
-//            e = e.nextSibling;
-//        }
-//        
-//        e.data = this.html || '';
+        this.el.select('.roo-content',true).first().dom.innerHTML = value;
+    },
 
-        this.el.select('>.message', true).first().dom.innerHTML = this.html || '';
+    initEvents: function() 
+    {   
+        
     }
-   
+    
 });
 
  
-
-     /*
+/*
  * - LGPL
  *
- * Graph
+ * TabBox
  * 
  */
-
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
 
 /**
- * @class Roo.bootstrap.Graph
+ * @class Roo.bootstrap.dash.TabBox
  * @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)
-     } 
- *
+ * 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 Input
+ * Create a new TabBox
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.Graph = function(config){
-    Roo.bootstrap.Graph.superclass.constructor.call(this, config);
-    
+
+Roo.bootstrap.dash.TabBox = function(config){
+    Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
     this.addEvents({
-        // img events
+        // raw events
         /**
-         * @event click
-         * The img click event for the img.
-         * @param {Roo.EventObject} e
+         * @event addpane
+         * When a pane is added
+         * @param {Roo.bootstrap.dash.TabPane} pane
          */
-        "click" : true
+        "addpane" : true,
+        /**
+         * @event activatepane
+         * When a pane is activated
+         * @param {Roo.bootstrap.dash.TabPane} pane
+         */
+        "activatepane" : true
+        
+         
     });
+    
+    this.panes = [];
 };
 
-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%'
+Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component,  {
 
+    title : '',
+    icon : false,
+    showtabs : true,
+    tabScrollable : false,
+    
+    getChildContainer : function()
+    {
+        return this.el.select('.tab-content', true).first();
     },
-    title : false,
-
+    
     getAutoCreate : function(){
         
-        var cfg = {
-            tag: 'div',
-            html : null
-        }
+        var header = {
+            tag: 'li',
+            cls: 'pull-left header',
+            html: this.title,
+            cn : []
+        };
         
+        if(this.icon){
+            header.cn.push({
+                tag: 'i',
+                cls: 'fa ' + this.icon
+            });
+        }
         
-        return  cfg;
-    },
-
-    onRender : function(ct,position){
-        Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
-        this.raphael = Raphael(this.el.dom);
+        var h = {
+            tag: 'ul',
+            cls: 'nav nav-tabs pull-right',
+            cn: [
+                header
+            ]
+        };
         
-                    // 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(!opts){
-            opts = this.opts;
+        if(this.tabScrollable){
+            h = {
+                tag: 'div',
+                cls: 'tab-header',
+                cn: [
+                    {
+                        tag: 'ul',
+                        cls: 'nav nav-tabs pull-right',
+                        cn: [
+                            header
+                        ]
+                    }
+                ]
+            }
+        }
+        
+        var cfg = {
+            tag: 'div',
+            cls: 'nav-tabs-custom',
+            cn: [
+                h,
+                {
+                    tag: 'div',
+                    cls: 'tab-content no-padding',
+                    cn: []
+                }
+            ]
         }
-        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;
 
+        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;
+    },
+    onAddPane : function(pane)
+    {
+        this.panes.push(pane);
+        //Roo.log('addpane');
+        //Roo.log(pane);
+        // tabs are rendere left to right..
+        if(!this.showtabs){
+            return;
         }
         
-        if(this.title){
-            this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
+        var ctr = this.el.select('.nav-tabs', true).first();
+         
+         
+        var existing = ctr.select('.nav-tab',true);
+        var qty = existing.getCount();;
+        
+        
+        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;
+        
+        tab.on('click', this.onTabClick.createDelegate(this, [pane], true));
+        if (!qty) {
+            pane.el.addClass('active');
         }
         
+                
     },
-    
-    setTitle: function(o)
+    onTabClick : function(ev,un,ob,pane)
     {
-        this.title = o;
-    },
-    
-    initEvents: function() {
+        //Roo.log('tab - prev default');
+        ev.preventDefault();
+        
+        
+        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');
+        
         
-        if(!this.href){
-            this.el.on('click', this.onClick, this);
-        }
     },
     
-    onClick : function(e)
+    getActivePane : function()
     {
-        Roo.log('img onclick');
-        this.fireEvent('click', this, e);
+        var r = false;
+        Roo.each(this.panes, function(p) {
+            if(p.el.hasClass('active')){
+                r = p;
+                return false;
+            }
+            
+            return;
+        });
+        
+        return r;
     }
-   
+    
+    
 });
 
  
 /*
  * - LGPL
  *
- * numberBox
+ * Tab pane
  * 
  */
 Roo.bootstrap.dash = Roo.bootstrap.dash || {};
-
 /**
- * @class Roo.bootstrap.dash.NumberBox
+ * @class Roo.bootstrap.TabPane
  * @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
+ * Bootstrap TabPane class
+ * @cfg {Boolean} active (false | true) Default false
+ * @cfg {String} title title of panel
+
  * 
  * @constructor
- * Create a new NumberBox
+ * Create a new TabPane
  * @param {Object} config The config object
  */
 
-
-Roo.bootstrap.dash.NumberBox = function(config){
-    Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+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.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component,  {
     
-    headline : '',
-    content : '',
-    icon : '',
-    footer : '',
-    fhref : '',
-    ficon : '',
+    active : false,
+    title : '',
     
-    getAutoCreate : function(){
-        
+    // the tabBox that this is attached to.
+    tab : false,
+     
+    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
-                        }
-                    ]
-                }
-            ]
-        }
-        
-        if(this.icon){
-            cfg.cn.push({
-                tag : 'div',
-                cls : 'icon',
-                cn :[
-                    {
-                        tag : 'i',
-                        cls : 'ion ' + this.icon
-                    }
-                ]
-            });
+            tag: 'div',
+            cls: 'tab-pane'
         }
         
-        if(this.footer){
-            var footer = {
-                tag : 'a',
-                cls : 'small-box-footer',
-                href : this.fhref || '#',
-                html : this.footer
-            };
-            
-            cfg.cn.push(footer);
-            
+        if(this.active){
+            cfg.cls += ' active';
         }
         
-        return  cfg;
-    },
-
-    onRender : function(ct,position){
-        Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
-
-
-       
-                
+        return cfg;
     },
-
-    setHeadline: function (value)
+    initEvents  : function()
     {
-        this.el.select('.roo-headline',true).first().dom.innerHTML = value;
+        //Roo.log('trigger add pane handler');
+        this.parent().fireEvent('addpane', this)
     },
     
-    setFooter: function (value, href)
+     /**
+     * Updates the tab title 
+     * @param {String} html to set the title to.
+     */
+    setTitle: function(str)
     {
-        this.el.select('a.small-box-footer',true).first().dom.innerHTML = value;
-        
-        if(href){
-            this.el.select('a.small-box-footer',true).first().attr('href', href);
+        if (!this.tab) {
+            return;
         }
-        
-    },
-
-    setContent: function (value)
-    {
-        this.el.select('.roo-content',true).first().dom.innerHTML = value;
-    },
-
-    initEvents: function() 
-    {   
+        this.title = str;
+        this.tab.select('a', true).first().dom.innerHTML = str;
         
     }
     
+    
+    
 });
 
  
-/*
+
+
+ /*
  * - LGPL
  *
- * TabBox
+ * menu
  * 
  */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
 
 /**
- * @class Roo.bootstrap.dash.TabBox
+ * @class Roo.bootstrap.menu.Menu
  * @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
+ * 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 TabBox
+ * Create a new Menu
  * @param {Object} config The config object
  */
 
 
-Roo.bootstrap.dash.TabBox = function(config){
-    Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
+Roo.bootstrap.menu.Menu = function(config){
+    Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
+    
     this.addEvents({
-        // raw events
         /**
-         * @event addpane
-         * When a pane is added
-         * @param {Roo.bootstrap.dash.TabPane} pane
+         * @event beforeshow
+         * Fires before this menu is displayed
+         * @param {Roo.bootstrap.menu.Menu} this
          */
-        "addpane" : true,
+        beforeshow : true,
         /**
-         * @event activatepane
-         * When a pane is activated
-         * @param {Roo.bootstrap.dash.TabPane} pane
+         * @event beforehide
+         * Fires before this menu is hidden
+         * @param {Roo.bootstrap.menu.Menu} this
          */
-        "activatepane" : true
-        
-         
+        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
     });
     
-    this.panes = [];
 };
 
-Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component,  {
-
-    title : '',
+Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component,  {
+    
+    submenu : false,
+    html : '',
+    weight : 'default',
     icon : false,
-    showtabs : true,
-    tabScrollable : false,
+    pos : 'bottom',
     
-    getChildContainer : function()
-    {
-        return this.el.select('.tab-content', true).first();
-    },
     
-    getAutoCreate : function(){
+    getChildContainer : function() {
+        if(this.isSubMenu){
+            return this.el;
+        }
         
-        var header = {
-            tag: 'li',
-            cls: 'pull-left header',
-            html: this.title,
-            cn : []
-        };
+        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){
-            header.cn.push({
-                tag: 'i',
-                cls: 'fa ' + this.icon
-            });
+            text.unshift({
+                tag : 'i',
+                cls : 'fa ' + this.icon
+            })
         }
         
-        var h = {
-            tag: 'ul',
-            cls: 'nav nav-tabs pull-right',
-            cn: [
-                header
-            ]
-        };
-        
-        if(this.tabScrollable){
-            h = {
-                tag: 'div',
-                cls: 'tab-header',
-                cn: [
-                    {
-                        tag: 'ul',
-                        cls: 'nav nav-tabs pull-right',
-                        cn: [
-                            header
-                        ]
-                    }
-                ]
-            }
-        }
         
         var cfg = {
-            tag: 'div',
-            cls: 'nav-tabs-custom',
-            cn: [
-                h,
+            tag : 'div',
+            cls : 'btn-group',
+            cn : [
                 {
-                    tag: 'div',
-                    cls: 'tab-content no-padding',
-                    cn: []
+                    tag : 'button',
+                    cls : 'dropdown-button btn btn-' + this.weight,
+                    cn : text
+                },
+                {
+                    tag : 'button',
+                    cls : 'dropdown-toggle btn btn-' + this.weight,
+                    cn : [
+                        {
+                            tag : 'span',
+                            cls : 'caret'
+                        }
+                    ]
+                },
+                {
+                    tag : 'ul',
+                    cls : 'dropdown-menu'
                 }
             ]
+            
+        };
+        
+        if(this.pos == 'top'){
+            cfg.cls += ' dropup';
         }
-
-        return  cfg;
-    },
-    initEvents : function()
-    {
-        //Roo.log('add add pane handler');
-        this.on('addpane', this.onAddPane, this);
+        
+        if(this.isSubMenu){
+            cfg = {
+                tag : 'ul',
+                cls : 'dropdown-menu'
+            }
+        }
+       
+        return cfg;
     },
-     /**
-     * Updates the box title
-     * @param {String} html to set the title to.
-     */
-    setTitle : function(value)
+    
+    onRender : function(ct, position)
     {
-        this.el.select('.nav-tabs .header', true).first().dom.innerHTML = value;
+        this.isSubMenu = ct.hasClass('dropdown-submenu');
+        
+        Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
     },
-    onAddPane : function(pane)
+    
+    initEvents : function() 
     {
-        this.panes.push(pane);
-        //Roo.log('addpane');
-        //Roo.log(pane);
-        // tabs are rendere left to right..
-        if(!this.showtabs){
+        if(this.isSubMenu){
             return;
         }
         
-        var ctr = this.el.select('.nav-tabs', true).first();
-         
-         
-        var existing = ctr.select('.nav-tab',true);
-        var qty = existing.getCount();;
+        this.hidden = true;
         
+        this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
+        this.triggerEl.on('click', this.onTriggerPress, this);
         
-        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.buttonEl = this.el.select('button.dropdown-button', true).first();
+        this.buttonEl.on('click', this.onClick, this);
         
-        tab.on('click', this.onTabClick.createDelegate(this, [pane], true));
-        if (!qty) {
-            pane.el.addClass('active');
+    },
+    
+    list : function()
+    {
+        if(this.isSubMenu){
+            return this.el;
         }
         
-                
+        return this.el.select('ul.dropdown-menu', true).first();
     },
-    onTabClick : function(ev,un,ob,pane)
+    
+    onClick : function(e)
     {
-        //Roo.log('tab - prev default');
-        ev.preventDefault();
+        this.fireEvent("click", this, e);
+    },
+    
+    onTriggerPress  : function(e)
+    {   
+        if (this.isVisible()) {
+            this.hide();
+        } else {
+            this.show();
+        }
+    },
+    
+    isVisible : function(){
+        return !this.hidden;
+    },
+    
+    show : function()
+    {
+        this.fireEvent("beforeshow", this);
+        
+        this.hidden = false;
+        this.el.addClass('open');
         
+        Roo.get(document).on("mouseup", this.onMouseUp, this);
         
-        this.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.fireEvent("show", this);
+        
+        
+    },
+    
+    hide : function()
+    {
+        this.fireEvent("beforehide", this);
+        
+        this.hidden = true;
+        this.el.removeClass('open');
         
+        Roo.get(document).un("mouseup", this.onMouseUp);
         
+        this.fireEvent("hide", this);
     },
     
-    getActivePane : function()
+    onMouseUp : function()
     {
-        var r = false;
-        Roo.each(this.panes, function(p) {
-            if(p.el.hasClass('active')){
-                r = p;
-                return false;
-            }
-            
-            return;
-        });
-        
-        return r;
+        this.hide();
     }
     
-    
 });
 
  
-/*
+ /*
  * - LGPL
  *
- * Tab pane
+ * menu item
  * 
  */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+
 /**
- * @class Roo.bootstrap.TabPane
+ * @class Roo.bootstrap.menu.Item
  * @extends Roo.bootstrap.Component
- * Bootstrap TabPane class
- * @cfg {Boolean} active (false | true) Default false
- * @cfg {String} title title of panel
-
+ * 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 TabPane
+ * Create a new Item
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.dash.TabPane = function(config){
-    Roo.bootstrap.dash.TabPane.superclass.constructor.call(this, config);
-    
+
+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 activate
-         * When a pane is activated
-         * @param {Roo.bootstrap.dash.TabPane} pane
+         * @event click
+         * The raw click event for the entire grid.
+         * @param {Roo.EventObject} e
          */
-        "activate" : true
-         
+        click : true
     });
 };
 
-Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component,  {
     
-    active : false,
-    title : '',
+    submenu : false,
+    href : '',
+    html : '',
+    preventDefault: true,
+    disable : false,
+    icon : false,
+    pos : 'right',
     
-    // the tabBox that this is attached to.
-    tab : false,
-     
-    getAutoCreate : function() 
+    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: 'div',
-            cls: 'tab-pane'
+            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.active){
-            cfg.cls += ' active';
+        if(this.submenu){
+            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
+            
+            if(this.pos == 'left'){
+                cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
+            }
         }
         
         return cfg;
     },
-    initEvents  : function()
+    
+    initEvents : function() 
     {
-        //Roo.log('trigger add pane handler');
-        this.parent().fireEvent('addpane', this)
+        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);
+        
     },
     
-     /**
-     * Updates the tab title 
-     * @param {String} html to set the title to.
-     */
-    setTitle: function(str)
+    onClick : function(e)
     {
-        if (!this.tab) {
-            return;
+        if(this.preventDefault){
+            e.preventDefault();
         }
-        this.title = str;
-        this.tab.select('a', true).first().dom.innerHTML = str;
         
-    }
-    
+        this.fireEvent("click", this, e);
+    },
     
+    onMouseOver : function(e)
+    {
+        if(this.submenu && this.pos == 'left'){
+            this.el.select('ul.dropdown-menu', true).first().setLeft(this.el.select('ul.dropdown-menu', true).first().getWidth() * -1);
+        }
+        
+        this.fireEvent("mouseover", this, e);
+    },
     
+    onMouseOut : function(e)
+    {
+        this.fireEvent("mouseout", this, e);
+    }
 });
 
  
 
-
  /*
  * - LGPL
  *
- * menu
+ * menu separator
  * 
  */
 Roo.bootstrap.menu = Roo.bootstrap.menu || {};
 
 /**
- * @class Roo.bootstrap.menu.Menu
+ * @class Roo.bootstrap.menu.Separator
  * @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 Separator class
  * 
  * @constructor
- * Create a new Menu
+ * Create a new Separator
  * @param {Object} config The config object
  */
 
 
-Roo.bootstrap.menu.Menu = function(config){
-    Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
-    
-    this.addEvents({
-        /**
-         * @event beforeshow
-         * Fires before this menu is displayed
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        beforeshow : true,
-        /**
-         * @event beforehide
-         * Fires before this menu is hidden
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        beforehide : true,
-        /**
-         * @event show
-         * Fires after this menu is displayed
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        show : true,
-        /**
-         * @event hide
-         * Fires after this menu is hidden
-         * @param {Roo.bootstrap.menu.Menu} this
-         */
-        hide : true,
-        /**
-         * @event click
-         * Fires when this menu is clicked (or when the enter key is pressed while it is active)
-         * @param {Roo.bootstrap.menu.Menu} this
-         * @param {Roo.EventObject} e
-         */
-        click : true
-    });
+Roo.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
+ * 
+ */
+
+/**
+ * @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.bootstrap.Tooltip = function(config){
+    Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component,  {
-    
-    submenu : false,
-    html : '',
-    weight : 'default',
-    icon : false,
-    pos : 'bottom',
+Roo.apply(Roo.bootstrap.Tooltip, {
+    /**
+     * @function init initialize tooltip monitoring.
+     * @static
+     */
+    currentEl : false,
+    currentTip : false,
+    currentRegion : false,
     
+    //  init : delay?
     
-    getChildContainer : function() {
-        if(this.isSubMenu){
-            return this.el;
-        }
+    init : function()
+    {
+        Roo.get(document).on('mouseover', this.enter ,this);
+        Roo.get(document).on('mouseout', this.leave, this);
+         
         
-        return this.el.select('ul.dropdown-menu', true).first();  
+        this.currentTip = new Roo.bootstrap.Tooltip();
     },
     
-    getAutoCreate : function()
+    enter : function(ev)
     {
-        var text = [
-            {
-                tag : 'span',
-                cls : 'roo-menu-text',
-                html : this.html
-            }
-        ];
+        var dom = ev.getTarget();
         
-        if(this.icon){
-            text.unshift({
-                tag : 'i',
-                cls : 'fa ' + this.icon
-            })
+        //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)) {
+                return;
+            }
+
         }
         
         
-        var cfg = {
-            tag : 'div',
-            cls : 'btn-group',
-            cn : [
-                {
-                    tag : 'button',
-                    cls : 'dropdown-button btn btn-' + this.weight,
-                    cn : text
-                },
-                {
-                    tag : 'button',
-                    cls : 'dropdown-toggle btn btn-' + this.weight,
-                    cn : [
-                        {
-                            tag : 'span',
-                            cls : 'caret'
-                        }
-                    ]
-                },
-                {
-                    tag : 'ul',
-                    cls : 'dropdown-menu'
-                }
-            ]
-            
-        };
         
-        if(this.pos == 'top'){
-            cfg.cls += ' dropup';
-        }
+        if (this.currentTip.el) {
+            this.currentTip.el.hide(); // force hiding...
+        }    
+        //Roo.log(ev);
+        var bindEl = el;
         
-        if(this.isSubMenu){
-            cfg = {
-                tag : 'ul',
-                cls : 'dropdown-menu'
+        // 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.");
+                return;
             }
+            //Roo.log("child element over..");
+            
         }
-       
-        return cfg;
-    },
-    
-    onRender : function(ct, position)
-    {
-        this.isSubMenu = ct.hasClass('dropdown-submenu');
+        this.currentEl = bindEl;
+        this.currentTip.bind(bindEl);
+        this.currentRegion = Roo.lib.Region.getRegion(dom);
+        this.currentTip.enter();
         
-        Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
     },
-    
-    initEvents : function() 
+    leave : function(ev)
     {
-        if(this.isSubMenu){
+        var dom = ev.getTarget();
+        //Roo.log(['leave',dom]);
+        if (!this.currentEl) {
             return;
         }
         
-        this.hidden = true;
         
-        this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
-        this.triggerEl.on('click', this.onTriggerPress, this);
+        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..
         
-        this.buttonEl = this.el.select('button.dropdown-button', true).first();
-        this.buttonEl.on('click', this.onClick, this);
         
-    },
-    
-    list : function()
-    {
-        if(this.isSubMenu){
-            return this.el;
+        
+        
+        if (this.currentTip) {
+            this.currentTip.leave();
         }
+        //Roo.log('clear currentEl');
+        this.currentEl = false;
+        
         
-        return this.el.select('ul.dropdown-menu', true).first();
     },
+    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']
+    }
     
-    onClick : function(e)
+});
+
+
+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 : [
+                {
+                    cls : 'tooltip-arrow'
+                },
+                {
+                    cls : 'tooltip-inner'
+                }
+           ]
+        };
+        
+        return cfg;
+    },
+    bind : function(el)
     {
-        this.fireEvent("click", this, e);
+        this.bindEl = el;
     },
+      
     
-    onTriggerPress  : function(e)
-    {   
-        if (this.isVisible()) {
-            this.hide();
-        } else {
+    enter : function () {
+       
+        if (this.timeout != null) {
+            clearTimeout(this.timeout);
+        }
+        
+        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);
     },
+    leave : function()
+    {
+        clearTimeout(this.timeout);
     
-    isVisible : function(){
-        return !this.hidden;
+        this.hoverState = 'out';
+         if (!this.delay || !this.delay.hide) {
+            this.hide();
+            return;
+        }
+       
+        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()
+    show : function ()
     {
-        this.fireEvent("beforeshow", this);
+        if (!this.el) {
+            this.render(document.body);
+        }
+        // set content.
+        //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
         
-        this.hidden = false;
-        this.el.addClass('open');
+        var tip = this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
+        
+        this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
+        
+        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 autoToken = /\s?auto?\s?/i;
+        var autoPlace = autoToken.test(placement);
+        if (autoPlace) {
+            placement = placement.replace(autoToken, '') || 'top';
+        }
         
-        Roo.get(document).on("mouseup", this.onMouseUp, this);
+        //this.el.detach()
+        //this.el.setXY([0,0]);
+        this.el.show();
+        //this.el.dom.style.display='block';
+        this.el.addClass(placement);
         
-        this.fireEvent("show", this);
+        //this.el.appendTo(on_el);
         
+        var p = this.getPosition();
+        var box = this.el.getBox();
         
-    },
-    
-    hide : function()
-    {
-        this.fireEvent("beforehide", this);
+        if (autoPlace) {
+            // fixme..
+        }
+        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.hidden = true;
-        this.el.removeClass('open');
+        this.el.addClass('in fade');
+        this.hoverState = null;
         
-        Roo.get(document).un("mouseup", this.onMouseUp);
+        if (this.el.hasClass('fade')) {
+            // fade it?
+        }
         
-        this.fireEvent("hide", this);
     },
-    
-    onMouseUp : function()
+    hide : function()
     {
-        this.hide();
+         
+        if (!this.el) {
+            return;
+        }
+        //this.el.setXY([0,0]);
+        this.el.removeClass('in');
+        //this.el.hide();
+        
     }
     
 });
-
  
+
  /*
  * - LGPL
  *
- * menu item
+ * Location Picker
  * 
  */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
 
 /**
- * @class Roo.bootstrap.menu.Item
+ * @class Roo.bootstrap.LocationPicker
  * @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 
- * 
+ * 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
- * Create a new Item
+ * Create a new LocationPicker
  * @param {Object} config The config object
  */
 
 
-Roo.bootstrap.menu.Item = function(config){
-    Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
+Roo.bootstrap.LocationPicker = function(config){
+    
+    Roo.bootstrap.LocationPicker.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
+         * @event initial
+         * Fires when the picker initialized.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Google Location} location
          */
-        mouseover : true,
+        initial : true,
         /**
-         * @event mouseout
-         * Fires when the mouse exits this menu
-         * @param {Roo.bootstrap.menu.Item} this
-         * @param {Roo.EventObject} e
+         * @event positionchanged
+         * Fires when the picker position changed.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Google Location} location
          */
-        mouseout : true,
-        // raw events
+        positionchanged : true,
         /**
-         * @event click
-         * The raw click event for the entire grid.
-         * @param {Roo.EventObject} e
+         * @event resize
+         * Fires when the map resize.
+         * @param {Roo.bootstrap.LocationPicker} this
          */
-        click : true
+        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,
+        /**
+         * @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.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component,  {
     
-    submenu : false,
-    href : '',
-    html : '',
-    preventDefault: true,
-    disable : false,
-    icon : false,
-    pos : 'right',
+    gMapContext: false,
     
-    getAutoCreate : function()
+    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()
     {
-        var text = [
-            {
-                tag : 'span',
-                cls : 'roo-menu-item-text',
-                html : this.html
-            }
-        ];
-        
-        if(this.icon){
-            text.unshift({
-                tag : 'i',
-                cls : 'fa ' + this.icon
-            })
-        }
-        
+
         var cfg = {
-            tag : 'li',
-            cn : [
-                {
-                    tag : 'a',
-                    href : this.href || '#',
-                    cn : text
-                }
-            ]
-        };
-        
-        if(this.disable){
-            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
-        }
-        
-        if(this.submenu){
-            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
-            
-            if(this.pos == 'left'){
-                cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
-            }
-        }
+            tag: 'div',
+            cls: 'roo-location-picker'
+        };
         
-        return cfg;
+        return cfg
     },
     
-    initEvents : function() 
-    {
-        this.el.on('mouseover', this.onMouseOver, this);
-        this.el.on('mouseout', this.onMouseOut, this);
+    initEvents: function(ct, position)
+    {       
+        if(!this.el.getWidth() || this.isApplied()){
+            return;
+        }
         
-        this.el.select('a', true).first().on('click', this.onClick, this);
+        this.el.setVisibilityMode(Roo.Element.DISPLAY);
         
+        this.initial();
     },
     
-    onClick : function(e)
+    initial: function()
     {
-        if(this.preventDefault){
-            e.preventDefault();
+        if(!this.mapTypeId){
+            this.mapTypeId = google.maps.MapTypeId.ROADMAP;
         }
         
-        this.fireEvent("click", this, e);
+        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);
+            
+        });
+
+        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);
     },
     
-    onMouseOver : function(e)
+    initOverlayView: function()
     {
-        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);
-        }
+        var _this = this;
         
-        this.fireEvent("mouseover", this, e);
+        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);
+            }
+            
+        });
     },
     
-    onMouseOut : function(e)
+    fromLatLngToContainerPixel: function(event)
     {
-        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,  {
+        return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
+    },
     
-    getAutoCreate : function(){
-        var cfg = {
-            tag : 'li',
-            cls: 'divider'
-        };
-        
-        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.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,
+    isApplied: function() 
+    {
+        return this.getGmapContext() == false ? false : true;
+    },
     
-    //  init : delay?
+    getGmapContext: function() 
+    {
+        return this.gMapContext
+    },
     
-    init : function()
+    GMapContext: function() 
     {
-        Roo.get(document).on('mouseover', this.enter ,this);
-        Roo.get(document).on('mouseout', this.leave, this);
-         
+        var position = new google.maps.LatLng(this.latitude, this.longitude);
         
-        this.currentTip = new Roo.bootstrap.Tooltip();
+        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()
+        };
     },
     
-    enter : function(ev)
+    drawCircle: function(center, radius, options) 
     {
-        var dom = ev.getTarget();
-        
-        //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)) {
-                return;
-            }
-
+        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;
+    },
+    
+    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.currentTip.el) {
-            this.currentTip.el.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;
-            }
-            // 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..");
+        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.currentEl = bindEl;
-        this.currentTip.bind(bindEl);
-        this.currentRegion = Roo.lib.Region.getRegion(dom);
-        this.currentTip.enter();
         
+        this.fireEvent('positionchanged', this, location);
     },
-    leave : function(ev)
+    
+    resize: function()
     {
-        var dom = ev.getTarget();
-        //Roo.log(['leave',dom]);
-        if (!this.currentEl) {
-            return;
-        }
+        google.maps.event.trigger(this.gMapContext.map, "resize");
         
+        this.gMapContext.map.setCenter(this.gMapContext.marker.position);
         
-        if (dom != this.currentEl.dom) {
-            return;
+        this.fireEvent('resize', this);
+    },
+    
+    setPositionByLatLng: function(latitude, longitude)
+    {
+        this.setPosition(new google.maps.LatLng(latitude, longitude));
+    },
+    
+    getCurrentPosition: function() 
+    {
+        return {
+            latitude: this.gMapContext.location.lat(),
+            longitude: this.gMapContext.location.lng()
+        };
+    },
+    
+    getAddressName: function() 
+    {
+        return this.gMapContext.locationName;
+    },
+    
+    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;
+            }
         }
-        var xy = ev.getXY();
-        if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0]  ))) {
+        
+        result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
+        result.addressLine2 = "";
+        return result;
+    },
+    
+    setZoomLevel: function(zoom)
+    {
+        this.gMapContext.map.setZoom(zoom);
+    },
+    
+    show: function()
+    {
+        if(!this.el){
             return;
         }
-        // only activate leave if mouse cursor is outside... bounding box..
-        
         
+        this.el.show();
         
+        this.resize();
         
-        if (this.currentTip) {
-            this.currentTip.leave();
+        this.fireEvent('show', this);
+    },
+    
+    hide: function()
+    {
+        if(!this.el){
+            return;
         }
-        //Roo.log('clear currentEl');
-        this.currentEl = false;
         
+        this.el.hide();
         
-    },
-    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']
+        this.fireEvent('hide', this);
     }
     
 });
 
-
-Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
-    
-    
-    bindEl : false,
+Roo.apply(Roo.bootstrap.LocationPicker, {
     
-    delay : null, // can be { show : 300 , hide: 500}
+    OverlayView : function(map, options)
+    {
+        options = options || {};
+        
+        this.setMap(map);
+    }
     
-    timeout : null,
     
-    hoverState : null, //???
+});/*
+ * - 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);
     
-    placement : 'bottom', 
+};
+
+Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component,  {
     
-    getAutoCreate : function(){
+    title: '',
+    html: '',
+    weight: false,
+    faicon: false,
     
+    getAutoCreate : function()
+    {
+        
         var cfg = {
-           cls : 'tooltip',
-           role : 'tooltip',
-           cn : [
+            tag : 'div',
+            cls : 'alert',
+            cn : [
                 {
-                    cls : 'tooltip-arrow'
+                    tag : 'i',
+                    cls : 'roo-alert-icon'
+                    
                 },
                 {
-                    cls : 'tooltip-inner'
+                    tag : 'b',
+                    cls : 'roo-alert-title',
+                    html : this.title
+                },
+                {
+                    tag : 'span',
+                    cls : 'roo-alert-text',
+                    html : this.html
                 }
-           ]
+            ]
         };
         
-        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();
-            return;
-        }
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            if (_t.hoverState == 'in') {
-                _t.show();
-            }
-        }, this.delay.show);
+        if(this.faicon){
+            cfg.cn[0].cls += ' fa ' + this.faicon;
+        }
+        
+        if(this.weight){
+            cfg.cls += ' alert-' + this.weight;
+        }
+        
+        return cfg;
     },
-    leave : function()
+    
+    initEvents: function() 
     {
-        clearTimeout(this.timeout);
+        this.el.setVisibilityMode(Roo.Element.DISPLAY);
+    },
     
-        this.hoverState = 'out';
-         if (!this.delay || !this.delay.hide) {
-            this.hide();
-            return;
-        }
-       
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            //Roo.log("leave - timeout");
-            
-            if (_t.hoverState == 'out') {
-                _t.hide();
-                Roo.bootstrap.Tooltip.currentEl = false;
-            }
-        }, delay);
+    setTitle : function(str)
+    {
+        this.el.select('.roo-alert-title',true).first().dom.innerHTML = str;
     },
     
-    show : function ()
+    setText : function(str)
     {
-        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.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
-        
-        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 autoToken = /\s?auto?\s?/i;
-        var autoPlace = autoToken.test(placement);
-        if (autoPlace) {
-            placement = placement.replace(autoToken, '') || 'top';
+        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.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();
+        this.weight = weight;
         
-        if (autoPlace) {
-            // fixme..
+        this.el.select('.alert',true).first().addClass('alert-' + this.weight);
+    },
+    
+    setIcon : function(icon)
+    {
+        if(this.faicon){
+            this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
         }
-        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;
-        
-        if (this.el.hasClass('fade')) {
-            // fade it?
-        }
+        this.faicon = icon
         
+        this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
     },
-    hide : function()
+    
+    hide: function() 
     {
-         
-        if (!this.el) {
-            return;
-        }
-        //this.el.setXY([0,0]);
-        this.el.removeClass('in');
-        //this.el.hide();
-        
+        this.el.hide();   
+    },
+    
+    show: function() 
+    {  
+        this.el.show();   
     }
     
 });
 
- /*
- * - LGPL
- *
- * Location Picker
- * 
- */
+/*
+* Licence: LGPL
+*/
 
 /**
- * @class Roo.bootstrap.LocationPicker
+ * @class Roo.bootstrap.UploadCropbox
  * @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 UploadCropbox class
+ * @cfg {String} emptyText show when image has been loaded
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
  * 
  * @constructor
- * Create a new LocationPicker
+ * Create a new UploadCropbox
  * @param {Object} config The config object
  */
 
-
-Roo.bootstrap.LocationPicker = function(config){
-    
-    Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
+Roo.bootstrap.UploadCropbox = function(config){
+    Roo.bootstrap.UploadCropbox.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
-         */
-        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
+         * @event beforeSelectFile
+         * Fire before select file
+         * @param {Roo.bootstrap.UploadCropbox} this
          */
-        OverlayViewOnRemove : true,
+        "beforeSelectFile" : true,
         /**
-         * @event OverlayViewShow
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Pixel} cpx
+         * @event initial
+         * Fire after initEvent
+         * @param {Roo.bootstrap.UploadCropbox} this
          */
-        OverlayViewShow : true,
+        "initial" : true,
         /**
-         * @event OverlayViewHide
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
+         * @event crop
+         * Fire after initEvent
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} imageData
          */
-        OverlayViewHide : true
-    });
+        "crop" : true
         
+    });
 };
 
-Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component,  {
-    
-    gMapContext: false,
+Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
     
-    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: '',
+    emptyText : 'Click to upload image',
+    scale : 0,
+    baseScale : 1,
+    rotate : 0,
+    dragable : false,
+    mouseX : 0,
+    mouseY : 0,
+    cropImageData : false,
+    cropType : 'image/png',
+    minWidth : 300,
+    minHeight : 300,
     
-    getAutoCreate: function()
+    getAutoCreate : function()
     {
-
         var cfg = {
-            tag: 'div',
-            cls: 'roo-location-picker'
+            tag : 'div',
+            cls : 'roo-upload-cropbox',
+            cn : [
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-image-section',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-canvas',
+                            cn : [
+                                {
+                                    tag : 'img',
+                                    cls : 'roo-upload-cropbox-image'
+                                }
+                            ]
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-thumb'
+                        }
+                    ]
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-footer-section',
+                    cn : {
+                        tag : 'div',
+                        cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group',
+                        cn : [
+                            {
+                                tag : 'div',
+                                cls : 'btn-group',
+                                cn : [
+                                    {
+                                        tag : 'button',
+                                        cls : 'btn btn-default roo-upload-cropbox-rotate-left',
+                                        html : '<i class="fa fa-undo"></i>'
+                                    }
+                                ]
+                            },
+                            {
+                                tag : 'div',
+                                cls : 'btn-group',
+                                cn : [
+                                    {
+                                        tag : 'button',
+                                        cls : 'btn btn-default roo-upload-cropbox-picture',
+                                        html : '<i class="fa fa-picture-o"></i>'
+                                    }
+                                ]
+                            },
+                            {
+                                tag : 'div',
+                                cls : 'btn-group',
+                                cn : [
+                                    {
+                                        tag : 'button',
+                                        cls : 'btn btn-default roo-upload-cropbox-rotate-right',
+                                        html : '<i class="fa fa-repeat"></i>'
+                                    }
+                                ]
+                            }
+                        ]
+                    }
+                }
+            ]
         };
         
-        return cfg
+        return cfg;
     },
     
-    initEvents: function(ct, position)
-    {       
-        if(!this.el.getWidth() || this.isApplied()){
-            return;
-        }
+    initEvents : function()
+    {
+        this.imageSection = this.el.select('.roo-upload-cropbox-image-section', true).first();
+        this.imageSection.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.el.setVisibilityMode(Roo.Element.DISPLAY);
+        this.imageCanvas = this.el.select('.roo-upload-cropbox-canvas', true).first();
+        this.imageCanvas.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.initial();
-    },
-    
-    initial: function()
-    {
-        if(!this.mapTypeId){
-            this.mapTypeId = google.maps.MapTypeId.ROADMAP;
-        }
+        this.image = this.el.select('.roo-upload-cropbox-image', true).first();
+        this.image.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.gMapContext = this.GMapContext();
+        this.thumb = this.el.select('.roo-upload-cropbox-thumb', true).first();
+        this.thumb.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.initOverlayView();
+        this.footerSection = this.el.select('.roo-upload-cropbox-footer-section', true).first();
+        this.footerSection.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.footerSection.hide();
         
-        this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
+        this.rotateLeft = this.el.select('.roo-upload-cropbox-rotate-left', true).first();
+        this.rotateLeft.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.pictureBtn = this.el.select('.roo-upload-cropbox-picture', true).first();
+        this.pictureBtn.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.rotateRight = this.el.select('.roo-upload-cropbox-rotate-right', true).first();
+        this.rotateRight.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.calcThumbBoxSize();
         
-        this.setPosition(this.gMapContext.location);
+        this.bind();
         
-        this.fireEvent('initial', this, this.gMapContext.location);
+        this.fireEvent('initial', this);
     },
-    
-    initOverlayView: function()
+
+    bind : function()
     {
-        var _this = this;
+        this.image.on('load', this.onLoadCanvasImage, 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)
-    {
-        return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
-    },
-    
-    isApplied: function() 
-    {
-        return this.getGmapContext() == false ? false : true;
-    },
-    
-    getGmapContext: function() 
-    {
-        return this.gMapContext
-    },
-    
-    GMapContext: function() 
-    {
-        var position = new google.maps.LatLng(this.latitude, this.longitude);
+        if(!this.imageSectionHasOnClickEvent){
+            this.imageSection.on('click', this.beforeSelectFile, this);
+            this.imageSectionHasOnClickEvent = true;
+        }
         
-        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
-        });
+        this.imageSection.on('mousedown', this.onMouseDown, this);
         
-        var _marker = new google.maps.Marker({
-            position: position,
-            map: _map,
-            title: this.markerTitle,
-            draggable: this.draggable
-        });
+        this.imageSection.on('mousemove', this.onMouseMove, this);
+        
+        var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
+        
+        this.imageSection.on(mousewheel, this.onMouseWheel, this);
+
+        Roo.get(document).on('mouseup', this.onMouseUp, this);
+        
+        this.pictureBtn.on('click', this.beforeSelectFile, this);
+        
+        this.rotateLeft.on('click', this.onRotateLeft, this);
+        
+        this.rotateRight.on('click', this.onRotateRight, this);
         
-        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()
-        };
     },
     
-    drawCircle: function(center, radius, options) 
+    unbind : function()
     {
-        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;
+        this.image.un('load', this.onLoadCanvasImage, this);
+        
+        if(this.imageSectionHasOnClickEvent){
+            this.imageSection.un('click', this.beforeSelectFile, this);
+            this.imageSectionHasOnClickEvent = false;
         }
         
-        return null;
+        this.imageSection.un('mousedown', this.onMouseDown, this);
+        
+        this.imageSection.un('mousemove', this.onMouseMove, this);
+        
+        var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
+        
+        this.imageSection.un(mousewheel, this.onMouseWheel, this);
+
+        Roo.get(document).un('mouseup', this.onMouseUp, this);
+        
+        this.pictureBtn.un('click', this.beforeSelectFile, this);
+        
+        this.rotateLeft.un('click', this.onRotateLeft, this);
+        
+        this.rotateRight.un('click', this.onRotateRight, this);
     },
     
-    setPosition: function(location) 
-    {
-        this.gMapContext.location = location;
-        this.gMapContext.marker.setPosition(location);
-        this.gMapContext.map.panTo(location);
-        this.drawCircle(location, this.gMapContext.radius, {});
+    reset : function()
+    {    
+        this.scale = 0;
+        this.baseScale = 1;
+        this.rotate = 0;
+        this.dragable = false;
+        this.mouseX = 0;
+        this.mouseY = 0;
+        this.cropImageData = false;
         
-        var _this = this;
+        this.imageCanvas.dom.removeAttribute('style');
+        this.image.dom.removeAttribute('style');
+        this.image.attr('src', '');
         
-        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;
+        if(!this.imageSectionHasOnClickEvent){
+            this.imageSection.on('click', this.beforeSelectFile, this);
+            this.imageSectionHasOnClickEvent = true;
         }
         
-        this.fireEvent('positionchanged', this, location);
     },
     
-    resize: function()
+    beforeSelectFile : function(e)
     {
-        google.maps.event.trigger(this.gMapContext.map, "resize");
-        
-        this.gMapContext.map.setCenter(this.gMapContext.marker.position);
-        
-        this.fireEvent('resize', this);
+        e.preventDefault();
+        this.fireEvent('beforeSelectFile', this);
     },
     
-    setPositionByLatLng: function(latitude, longitude)
-    {
-        this.setPosition(new google.maps.LatLng(latitude, longitude));
+    loadCanvasImage : function(src)
+    {   
+        this.reset();
+        
+        this.image.attr('src', src);
     },
     
-    getCurrentPosition: function() 
-    {
-        return {
-            latitude: this.gMapContext.location.lat(),
-            longitude: this.gMapContext.location.lng()
-        };
+    onLoadCanvasImage : function(src)
+    {   
+        if(this.imageSectionHasOnClickEvent){
+            this.imageSection.un('click', this.beforeSelectFile, this);
+            this.imageSectionHasOnClickEvent = false;
+        }
+        
+        this.image.OriginWidth = this.image.getWidth();
+        this.image.OriginHeight = this.image.getHeight();
+        
+        this.fitThumbBox();
+        
+        this.image.setWidth(this.image.OriginWidth * this.getScaleLevel(false));
+        this.image.setHeight(this.image.OriginHeight * this.getScaleLevel(false));
+                
+        this.footerSection.show();
+        
+        this.setCanvasPosition();
     },
     
-    getAddressName: function() 
-    {
-        return this.gMapContext.locationName;
+    setCanvasPosition : function()
+    {   
+        var pw = (this.imageSection.getWidth(true) - this.image.getWidth()) / 2;
+        var ph = (this.imageSection.getHeight(true) - this.image.getHeight()) / 2;
+        
+        this.imageCanvas.setLeft(pw);
+        this.imageCanvas.setTop(ph);
     },
     
-    getAddressComponents: function() 
-    {
-        return this.gMapContext.addressComponents;
+    onMouseDown : function(e)
+    {   
+        e.stopEvent();
+        
+        this.dragable = true;
+        this.mouseX = e.getPageX();
+        this.mouseY = e.getPageY();
+        
     },
     
-    address_component_from_google_geocode: function(address_components) 
-    {
-        var result = {};
+    onMouseMove : function(e)
+    {   
+        e.stopEvent();
         
-        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;
-            }
+        if (!this.dragable){
+            return;
         }
         
-        result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
-        result.addressLine2 = "";
-        return result;
+        var transform = new WebKitCSSMatrix(window.getComputedStyle(this.thumb.dom).webkitTransform);
+        
+        var minX = this.thumb.getLeft(true) + transform.m41;
+        var minY = this.thumb.getTop(true) + transform.m42;
+        
+        var maxX = minX + this.thumb.getWidth() - this.image.getWidth();
+        var maxY = minY + this.thumb.getHeight() - this.image.getHeight();
+        
+        if(this.rotate == 90 || this.rotate == 270){
+            minX = this.thumb.getLeft(true) + transform.m41 - (this.image.getWidth() - this.image.getHeight()) / 2;
+            minY = this.thumb.getTop(true) + transform.m42 + (this.image.getWidth() - this.image.getHeight()) / 2;
+            
+            maxX = minX + this.thumb.getWidth() - this.image.getHeight();
+            maxY = minY + this.thumb.getHeight() - this.image.getWidth();
+        }
+        
+        var x = e.getPageX() - this.mouseX;
+        var y = e.getPageY() - this.mouseY;
+        
+        var bgX = x + this.imageCanvas.getLeft(true);
+        var bgY = y + this.imageCanvas.getTop(true);
+        
+        bgX = (minX < bgX) ? minX : ((maxX > bgX) ? maxX : bgX);
+        bgY = (minY < bgY) ? minY : ((maxY > bgY) ? maxY : bgY);
+        
+        this.imageCanvas.setLeft(bgX);
+        this.imageCanvas.setTop(bgY);
+        
+        this.mouseX = e.getPageX();
+        this.mouseY = e.getPageY();
     },
     
-    setZoomLevel: function(zoom)
-    {
-        this.gMapContext.map.setZoom(zoom);
+    onMouseUp : function(e)
+    {   
+        e.stopEvent();
+        
+        this.dragable = false;
     },
     
-    show: function()
-    {
-        if(!this.el){
+    onMouseWheel : function(e)
+    {   
+        e.stopEvent();
+        
+        this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1);
+        
+        var width = this.image.OriginWidth * this.getScaleLevel(false);
+        var height = this.image.OriginHeight * this.getScaleLevel(false);
+        
+        if(
+                e.getWheelDelta() == -1 &&
+                (
+                    (
+                        (this.rotate == 0 || this.rotate == 180) && (width < this.thumb.getWidth() || height < this.thumb.getHeight())
+                    )
+                    ||
+                    (
+                        (this.rotate == 90 || this.rotate == 270) && (height < this.thumb.getWidth() || width < this.thumb.getHeight())
+                    )
+                )
+        ){
+            this.scale = (e.getWheelDelta() == 1) ? (this.scale - 1) : (this.scale + 1);
             return;
         }
         
-        this.el.show();
+        this.image.setWidth(width);
+        this.image.setHeight(height);
         
-        this.resize();
+        this.setCanvasPosition();
         
-        this.fireEvent('show', this);
     },
     
-    hide: function()
+    onRotateLeft : function(e)
     {
-        if(!this.el){
+        e.stopEvent();
+        
+        if(
+                (
+                    (this.rotate == 0 || this.rotate == 180) 
+                    &&
+                    (this.image.getHeight() < this.thumb.getWidth() || this.image.getWidth() < this.thumb.getHeight())
+                )
+                ||
+                (
+                    (this.rotate == 90 || this.rotate == 270) 
+                    &&
+                    (this.image.getWidth() < this.thumb.getWidth() || this.image.getHeight() < this.thumb.getHeight())
+                )
+                
+        ){
             return;
         }
         
-        this.el.hide();
-        
-        this.fireEvent('hide', this);
-    }
-    
-});
+        this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
 
-Roo.apply(Roo.bootstrap.LocationPicker, {
+        this.imageCanvas.setStyle({
+            '-ms-transform' : 'rotate(' + this.rotate + 'deg)',
+            '-webkit-transform' : 'rotate(' + this.rotate + 'deg)',
+            'transform' : 'rotate(' + this.rotate + 'deg)'
+        });
+
+        this.setCanvasPosition();
+        
+    },
     
-    OverlayView : function(map, options)
+    onRotateRight : function(e)
     {
-        options = options || {};
+        e.stopEvent();
         
-        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
- */
+        if(
+                (
+                    (this.rotate == 0 || this.rotate == 180) 
+                    &&
+                    (this.image.getHeight() < this.thumb.getWidth() || this.image.getWidth() < this.thumb.getHeight())
+                )
+                ||
+                (
+                    (this.rotate == 90 || this.rotate == 270) 
+                    &&
+                    (this.image.getWidth() < this.thumb.getWidth() || this.image.getHeight() < this.thumb.getHeight())
+                )
+                
+        ){
+            return false;
+        }
+        
+        this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
 
+        this.imageCanvas.setStyle({
+            '-ms-transform' : 'rotate(' + this.rotate + 'deg)',
+            '-webkit-transform' : 'rotate(' + this.rotate + 'deg)',
+            'transform' : 'rotate(' + this.rotate + 'deg)'
+        });
 
-Roo.bootstrap.Alert = function(config){
-    Roo.bootstrap.Alert.superclass.constructor.call(this, config);
+        this.setCanvasPosition();
+        
+        
+    },
     
-};
+    crop : function()
+    {
+        var canvas = document.createElement("canvas");
+        
+        var context = canvas.getContext("2d");
+        
+        canvas.width = this.minWidth;
+        canvas.height = this.minHeight;
+        
+        var centerX = this.minWidth / 2;
+        var centerY = this.minHeight / 2;
+        
+        var cropWidth = this.thumb.getWidth() * this.getScaleLevel(true);
+        var cropHeight = this.thumb.getHeight() * this.getScaleLevel(true);
+        
+        var transform = new WebKitCSSMatrix(window.getComputedStyle(this.thumb.dom).webkitTransform);
+        var thumbX = this.thumb.getLeft(true) + transform.m41;
+        var thumbY = this.thumb.getTop(true) + transform.m42;
+        
+        var x = (thumbX - this.imageCanvas.getLeft(true)) * this.getScaleLevel(true);
+        var y = (thumbY - this.imageCanvas.getTop(true)) * this.getScaleLevel(true);
+        
+        if(this.rotate == 90){
+            
+            x = thumbY + (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getTop(true);
+            y = this.image.getHeight() - this.thumb.getWidth() - (thumbX - (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getLeft(true));
+            
+            x = x * this.getScaleLevel(true);
+            y = y * this.getScaleLevel(true);
+            
+            x = x < 0 ? 0 : x;
+            y = y < 0 ? 0 : y;
+            
+            cropWidth = this.thumb.getHeight() * this.getScaleLevel(true);
+            cropHeight = this.thumb.getWidth() * this.getScaleLevel(true);
+            
+            canvas.width = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
+            canvas.height = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
 
-Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component,  {
-    
-    title: '',
-    html: '',
-    weight: false,
-    faicon: false,
+            centerX = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
+            centerY = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
+            
+            context.translate(centerX, centerY);
+            context.rotate(this.rotate * Math.PI / 180);
+            
+            context.drawImage(this.image.dom, x, y, cropWidth, cropHeight, centerX * -1, centerY * -1, this.minHeight, this.minWidth);
+        
+            var canvas2 = document.createElement("canvas");
+            var context2 = canvas2.getContext("2d");
+            
+            canvas2.width = this.minWidth;
+            canvas2.height = this.minHeight;
+            
+            context2.drawImage(canvas, Math.abs(this.minWidth - this.minHeight), 0, this.minWidth, this.minHeight, 0, 0, this.minWidth, this.minHeight);
     
-    getAutoCreate : function()
-    {
+            this.cropImageData = canvas2.toDataURL(this.cropType);
+
+            this.fireEvent('crop', this, this.cropImageData);
+            
+            return;
+            
+        }
         
-        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.rotate == 270){
+            
+            x = thumbY + (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getTop(true);
+            y = thumbX - (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getLeft(true);
+            
+            x = (this.image.getWidth() - this.thumb.getHeight() - x) * this.getScaleLevel(true);
+            y = y * this.getScaleLevel(true);
+            
+            x = x < 0 ? 0 : x;
+            y = y < 0 ? 0 : y;
+            
+            cropWidth = this.thumb.getHeight() * this.getScaleLevel(true);
+            cropHeight = this.thumb.getWidth() * this.getScaleLevel(true);
+            
+            canvas.width = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
+            canvas.height = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
+
+            centerX = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
+            centerY = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
+            
+            context.translate(centerX, centerY);
+            context.rotate(this.rotate * Math.PI / 180);
+            
+            context.drawImage(this.image.dom, x, y, cropWidth, cropHeight, centerX * -1, centerY * -1, this.minHeight, this.minWidth);
         
-        if(this.faicon){
-            cfg.cn[0].cls += ' fa ' + this.faicon;
+            var canvas2 = document.createElement("canvas");
+            var context2 = canvas2.getContext("2d");
+            
+            canvas2.width = this.minWidth;
+            canvas2.height = this.minHeight;
+            
+            context2.drawImage(canvas, 0, 0, this.minWidth, this.minHeight, 0, 0, this.minWidth, this.minHeight);
+    
+            this.cropImageData = canvas2.toDataURL(this.cropType);
+            
+            this.fireEvent('crop', this, this.cropImageData);
+            
+            return;
+            
         }
         
-        if(this.weight){
-            cfg.cls += ' alert-' + this.weight;
+        if(this.rotate == 180){
+            x = this.image.OriginWidth - this.thumb.getWidth() * this.getScaleLevel(true) - x;
+            y = this.image.OriginHeight - this.thumb.getHeight() * this.getScaleLevel(true) - y;
         }
         
-        return cfg;
-    },
-    
-    initEvents: function() 
-    {
-        this.el.setVisibilityMode(Roo.Element.DISPLAY);
-    },
-    
-    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;
+        x = x < 0 ? 0 : x;
+        y = y < 0 ? 0 : y;
+            
+        context.translate(centerX, centerY);
+
+        context.rotate(this.rotate * Math.PI / 180);
+        
+        context.drawImage(this.image.dom, x, y, cropWidth, cropHeight, centerX * -1, centerY * -1, canvas.width, canvas.height);
+        
+        this.cropImageData = canvas.toDataURL(this.cropType);
+        
+        this.fireEvent('crop', this, this.cropImageData);
     },
     
-    setWeight : function(weight)
+    calcThumbBoxSize : function()
     {
-        if(this.weight){
-            this.el.select('.alert',true).first().removeClass('alert-' + this.weight);
-        }
+        var width, height;
         
-        this.weight = weight;
+        height = 300;
+        width = this.minWidth * height / this.minHeight;
         
-        this.el.select('.alert',true).first().addClass('alert-' + this.weight);
+        if(this.minWidth > this.minHeight){
+            width = 300;
+            height = this.minHeight * width / this.minWidth;
+        }
+        
+        this.thumb.setStyle({
+            width : width + 'px',
+            height : height + 'px'
+        });
+
+        return;
+            
     },
     
-    setIcon : function(icon)
+    fitThumbBox : function()
     {
-        if(this.faicon){
-            this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
-        }
+        var width = this.thumb.getWidth();
+        var height = this.image.OriginHeight * width / this.image.OriginWidth;
         
-        this.faicon = icon
+        this.baseScale = width / this.image.OriginWidth;
         
-        this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
+        if(this.image.OriginWidth > this.image.OriginHeight){
+            height = this.thumb.getHeight();
+            width = this.image.OriginWidth * height / this.image.OriginHeight;
+            
+            this.baseScale = height / this.image.OriginHeight;
+        }
+        
+        return;
     },
     
-    hide: function() 
+    getScaleLevel : function(reverse)
     {
-        this.el.hide();   
-    },
-    
-    show: function() 
-    {  
-        this.el.show();   
+        if(reverse){
+            return Math.pow(1.1, this.scale * -1) / this.baseScale;
+        }
+        
+        return this.baseScale * Math.pow(1.1, this.scale);
     }
     
 });
-
\ No newline at end of file