docs/default.css
[roojs1] / roojs-bootstrap-debug.js
index 5adf97c..3f69c3a 100644 (file)
@@ -989,6 +989,7 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
  * @cfg {String} icon (info-sign|check|...) glyphicon name
  * @cfg {Boolean} hidden (true|false) hide the element
  * @cfg {Boolean} expandable (true|false) default false
+ * @cfg {Boolean} expanded (true|false) default true
  * @cfg {String} rheader contet on the right of header
 
  *     
@@ -1116,15 +1117,16 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
                     
                     h.push({
                         tag: 'i',
-                        cls: 'fa fa-minus'
+                        cls: (this.expanded ? 'fa fa-minus' : 'fa fa-plus') 
                     });
+                    
                 }
                 
                 h.push(
                     {
                         tag: 'span',
                         cls : 'panel-title',
-                        html : this.header
+                        html : (this.expandable ? ' ' : '') + this.header
                     },
                     {
                         tag: 'span',
@@ -1135,6 +1137,7 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
                 
                 cfg.cn.push({
                     cls : 'panel-heading',
+                    style : this.expandable ? 'cursor: pointer' : '',
                     cn : h
                 });
                 
@@ -1142,7 +1145,7 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             body = false;
             cfg.cn.push({
-                cls : 'panel-body',
+                cls : 'panel-body' + (this.expanded ? '' : ' hide'),
                 html : this.html
             });
             
@@ -1214,8 +1217,10 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             this.expanded = true;
             
-            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
-        
+            //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
+            
+            this.el.select('.panel-body',true).first().removeClass('hide');
+            
             var toggleEl = this.toggleEl();
 
             if(!toggleEl){
@@ -1233,7 +1238,8 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             this.expanded = false;
             
-            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+            //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+            this.el.select('.panel-body',true).first().addClass('hide');
         
             var toggleEl = this.toggleEl();
 
@@ -1392,7 +1398,9 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
             
             var s = ['xs', 'sm', 'md', 'lg'];
             
-            Roo.each(s.splice(s.indexOf(size), 1), function(ss){
+            s.splice(s.indexOf(size), 1);
+            
+            Roo.each(s, function(ss){
                 img.cls += ' hidden-' + ss;
             });
             
@@ -2419,7 +2427,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
     
         if (this.buttons.length) {
             Roo.each(this.buttons, function(bb) {
-                b = Roo.apply({}, bb);
+                var b = Roo.apply({}, bb);
                 b.xns = b.xns || Roo.bootstrap;
                 b.xtype = b.xtype || 'Button';
                 if (typeof(b.listeners) == 'undefined') {
@@ -2453,6 +2461,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         //this.el.addClass([this.fieldClass, this.cls]);
         
     },
+    
     getAutoCreate : function(){
         
         
@@ -2539,8 +2548,18 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         if (this.allow_close) {
             this.closeEl.on('click', this.hide, this);
         }
+        
+        var _this = this;
+        
+        window.addEventListener("resize", function() { _this.resize(); } );
 
     },
+    
+    resize : function()
+    {
+        this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
+    },
+    
     show : function() {
         
         if (!this.rendered) {
@@ -4173,7 +4192,7 @@ Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
     },
     setActive : function(state, fire, is_was_active)
     {
-        if (this.active && !state & this.navId) {
+        if (this.active && !state && this.navId) {
             this.was_active = true;
             var nv = Roo.bootstrap.NavGroup.get(this.navId);
             if (nv) {
@@ -5366,10 +5385,10 @@ Roo.LoadMask.prototype = {
  * @cfg {boolean} condensed Format condensed
  * @cfg {boolean} responsive Format condensed
  * @cfg {Boolean} loadMask (true|false) default false
- * @cfg {Boolean} tfoot (true|false) generate tfoot, default true
- * @cfg {Boolean} thead (true|false) generate thead, default true
- * @cfg {Boolean} RowSelection (true|false) default false
- * @cfg {Boolean} CellSelection (true|false) default false
+ * @cfg {Boolean} footerShow (true|false) generate tfoot, default true
+ * @cfg {Boolean} headerShow (true|false) generate thead, default true
+ * @cfg {Boolean} rowSelection (true|false) default false
+ * @cfg {Boolean} cellSelection (true|false) default false
  * @cfg {Roo.bootstrap.PagingToolbar} footer  a paging toolbar
  
  * 
@@ -5381,6 +5400,13 @@ Roo.LoadMask.prototype = {
 Roo.bootstrap.Table = function(config){
     Roo.bootstrap.Table.superclass.constructor.call(this, config);
     
+    // BC...
+    this.rowSelection = (typeof(config.RowSelection) != 'undefined') ? config.RowSelection : this.rowSelection;
+    this.cellSelection = (typeof(config.CellSelection) != 'undefined') ? config.CellSelection : this.cellSelection;
+    this.headerShow = (typeof(config.thead) != 'undefined') ? config.thead : this.headerShow;
+    this.footerShow = (typeof(config.tfoot) != 'undefined') ? config.tfoot : this.footerShow;
+    
+    
     if (this.sm) {
         this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table);
         this.sm = this.selModel;
@@ -5501,10 +5527,11 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     cm : false,
     store : false,
     loadMask : false,
-    tfoot : true,
-    thead : true,
-    RowSelection : false,
-    CellSelection : false,
+    footerShow : true,
+    headerShow : true,
+  
+    rowSelection : false,
+    cellSelection : false,
     layout : false,
     
     // Roo.Element - the tbody
@@ -5577,13 +5604,13 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
         }
         
         if(this.store || this.cm){
-            if(this.thead){
+            if(this.headerShow){
                 cfg.cn.push(this.renderHeader());
             }
             
             cfg.cn.push(this.renderBody());
             
-            if(this.tfoot){
+            if(this.footerShow){
                 cfg.cn.push(this.renderFooter());
             }
             
@@ -5675,7 +5702,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     {
         var cell = Roo.get(el);
         
-        if(!cell || (!this.CellSelection && !this.RowSelection)){
+        if(!cell || (!this.cellSelection && !this.rowSelection)){
             return;
         }
         
@@ -5696,11 +5723,12 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
         var cellIndex = cell.dom.cellIndex;
         var rowIndex = this.getRowIndex(row);
         
-        if(this.CellSelection){
+        // why??? - should these not be based on SelectionModel?
+        if(this.cellSelection){
             this.fireEvent('cellclick', this, cell, rowIndex, cellIndex, e);
         }
         
-        if(this.RowSelection){
+        if(this.rowSelection){
             this.fireEvent('rowclick', this, row, rowIndex, e);
         }
         
@@ -5779,13 +5807,35 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
         for(var i = 0, len = cm.getColumnCount(); i < len; i++){
             
             var config = cm.config[i];
-                    
+            
             var c = {
                 tag: 'th',
                 style : '',
                 html: cm.getColumnHeader(i)
             };
             
+            var hh = '';
+            
+            if(typeof(config.lgHeader) != 'undefined'){
+                hh += '<span class="hidden-xs hidden-sm hidden-md">' + config.lgHeader + '</span>';
+            }
+            
+            if(typeof(config.mdHeader) != 'undefined'){
+                hh += '<span class="hidden-xs hidden-sm hidden-lg">' + config.mdHeader + '</span>';
+            }
+            
+            if(typeof(config.smHeader) != 'undefined'){
+                hh += '<span class="hidden-xs hidden-md hidden-lg">' + config.smHeader + '</span>';
+            }
+            
+            if(typeof(config.xsHeader) != 'undefined'){
+                hh += '<span class="hidden-sm hidden-md hidden-lg">' + config.xsHeader + '</span>';
+            }
+            
+            if(hh.length){
+                c.html = hh;
+            }
+            
             if(typeof(config.tooltip) != 'undefined'){
                 c.tooltip = config.tooltip;
             }
@@ -7459,6 +7509,8 @@ Roo.form.VTypes = function(){
  * @cfg {String} autocomplete - default is new-password see: https://developers.google.com/web/fundamentals/input/form/label-and-name-inputs?hl=en
 
  * @cfg {String} align (left|center|right) Default left
+ * @cfg {Boolean} forceFeedback (true|false) Default false
+ * 
  * 
  * 
  * 
@@ -7654,6 +7706,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
     readOnly : false,
     align : false,
     formatedValue : false,
+    forceFeedback : false,
     
     parentLabelAlign : function()
     {
@@ -7874,7 +7927,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         this.inputEl().on("blur", this.onBlur,  this);
         
         this.inputEl().relayEvent('keyup', this);
-
         // reference to original value for reset
         this.originalValue = this.getValue();
         //Roo.form.TextField.superclass.initEvents.call(this);
@@ -8147,13 +8200,19 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         
         this.el.removeClass([this.invalidClass, this.validClass]);
         
+        var feedback = this.el.select('.form-control-feedback', true).first();
+            
+        if(feedback){
+            this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
+        }
+
         if(this.disabled || this.allowBlank){
             return;
         }
         
         this.el.addClass(this.validClass);
         
-        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && this.getValue().length){
+        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && (this.getValue().length || this.forceFeedback)){
             
             var feedback = this.el.select('.form-control-feedback', true).first();
             
@@ -8178,6 +8237,12 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         
         this.el.removeClass([this.invalidClass, this.validClass]);
         
+        var feedback = this.el.select('.form-control-feedback', true).first();
+            
+        if(feedback){
+            this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
+        }
+
         if(this.disabled || this.allowBlank){
             return;
         }
@@ -8191,7 +8256,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             if(feedback){
                 this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
                 
-                if(this.getValue().length){
+                if(this.getValue().length || this.forceFeedback){
                     this.el.select('.form-control-feedback', true).first().addClass([this.invalidFeedbackClass]);
                 }
                 
@@ -8585,7 +8650,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                     ] 
                 };
             }
-              
+
         } else {
             if(this.removable && !this.editable && !this.tickable){
                 inputblock = {
@@ -8774,7 +8839,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                 cfg.cls += ' col-' + size + '-' + settings[size];
             }
         });
-        
+        Roo.log(cfg);
         return cfg;
         
     },
@@ -8832,7 +8897,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
             var close = this.closeTriggerEl();
             
             if(close){
-                close.setVisibilityMode(Roo.Element.DISPALY).hide();
+                close.setVisibilityMode(Roo.Element.DISPLAY).hide();
                 close.on('click', this.removeBtnClick, this, close);
             }
         }
@@ -8855,7 +8920,9 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
     {
         e.preventDefault();
         
-        this.fireEvent("remove", this);
+        if(this.fireEvent("remove", this) !== false){
+            this.reset();
+        }
     },
     
     createList : function()
@@ -11034,6 +11101,8 @@ Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
  * @cfg {Boolean} triggerList trigger show the list or not (true|false) default true
  * @cfg {Boolean} showToggleBtn show toggle button or not (true|false) default true
  * @cfg {String} btnPosition set the position of the trigger button (left | right) default right
+ * @cfg {Boolean} animate default true
+ * @cfg {Boolean} emptyResultText only for touch device
  * @constructor
  * Create a new ComboBox.
  * @param {Object} config Configuration options
@@ -11304,6 +11373,11 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
      */
     specialFilter : false,
     
+    /**
+     * @cfg {Boolean} mobileTouchView (true|false) show mobile touch view when using a mobile default true
+     */
+    mobileTouchView : true,
+    
     //private
     addicon : false,
     editicon: false,
@@ -11317,12 +11391,23 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     btnPosition : 'right',
     triggerList : true,
     showToggleBtn : true,
+    animate : true,
+    emptyResultText: 'Empty',
     // element that contains real text value.. (when hidden is used..)
     
     getAutoCreate : function()
     {
         var cfg = false;
         
+        /*
+         * Touch Devices
+         */
+        
+        if(Roo.isTouch && this.mobileTouchView){
+            cfg = this.getAutoCreateTouchView();
+            return cfg;;
+        }
+        
         /*
          *  Normal ComboBox
          */
@@ -11495,8 +11580,18 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         if (!this.store) {
             throw "can not find store for combo";
         }
+        
         this.store = Roo.factory(this.store, Roo.data);
         
+        /*
+         * Touch Devices
+         */
+        
+        if(Roo.isTouch && this.mobileTouchView){
+            this.initTouchView();
+            return;
+        }
+        
         if(this.tickable){
             this.initTickableEvents();
             return;
@@ -12106,7 +12201,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         var close = this.closeTriggerEl();
         
         if(close){
-            (v.length || v * 1 > 0) ? close.show() : close.hide();
+            (v && (v.length || v * 1 > 0)) ? close.show() : close.hide();
         }
     },
     /**
@@ -12849,13 +12944,22 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         this.syncValue();
         
         this.validate();
+        
+        if(this.tickable && !Roo.isTouch){
+            this.view.refresh();
+        }
     },
     
     inputEl: function ()
     {
+        if(Roo.isTouch && this.mobileTouchView){
+            return this.el.select('input.form-control',true).first();
+        }
+        
         if(this.tickable){
             return this.searchField;
         }
+        
         return this.el.select('input.form-control',true).first();
     },
     
@@ -12908,473 +13012,1045 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         }
         
         return this.inputEl().select('.select2-search-field-input', true).first();
-    }
+    },
     
     
+    getAutoCreateTouchView : function()
+    {
+        var id = Roo.id();
+        
+        var cfg = {
+            cls: 'form-group' //input-group
+        };
+        
+        var input =  {
+            tag: 'input',
+            id : id,
+            type : this.inputType,
+            cls : 'form-control x-combo-noedit',
+            autocomplete: 'new-password',
+            placeholder : this.placeholder || '',
+            readonly : true
+        };
+        
+        if (this.name) {
+            input.name = this.name;
+        }
+        
+        if (this.size) {
+            input.cls += ' input-' + this.size;
+        }
+        
+        if (this.disabled) {
+            input.disabled = true;
+        }
+        
+        var inputblock = {
+            cls : '',
+            cn : [
+                input
+            ]
+        };
+        
+        if(this.before){
+            inputblock.cls += ' input-group';
+            
+            inputblock.cn.unshift({
+                tag :'span',
+                cls : 'input-group-addon',
+                html : this.before
+            });
+        }
+        
+        if(this.removable && !this.multiple){
+            inputblock.cls += ' roo-removable';
+            
+            inputblock.cn.push({
+                tag: 'button',
+                html : 'x',
+                cls : 'roo-combo-removable-btn close'
+            });
+        }
 
-    /** 
-    * @cfg {Boolean} grow 
-    * @hide 
-    */
-    /** 
-    * @cfg {Number} growMin 
-    * @hide 
-    */
-    /** 
-    * @cfg {Number} growMax 
-    * @hide 
-    */
-    /**
-     * @hide
-     * @method autoSize
-     */
-});
-/*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
-
-/**
- * @class Roo.View
- * @extends Roo.util.Observable
- * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template. 
- * This class also supports single and multi selection modes. <br>
- * Create a data model bound view:
- <pre><code>
- var store = new Roo.data.Store(...);
+        if(this.hasFeedback && !this.allowBlank){
+            
+            inputblock.cls += ' has-feedback';
+            
+            inputblock.cn.push({
+                tag: 'span',
+                cls: 'glyphicon form-control-feedback'
+            });
+            
+        }
+        
+        if (this.after) {
+            
+            inputblock.cls += (this.before) ? '' : ' input-group';
+            
+            inputblock.cn.push({
+                tag :'span',
+                cls : 'input-group-addon',
+                html : this.after
+            });
+        }
 
- var view = new Roo.View({
-    el : "my-element",
-    tpl : '&lt;div id="{0}"&gt;{2} - {1}&lt;/div&gt;', // auto create template
-    singleSelect: true,
-    selectedClass: "ydataview-selected",
-    store: store
- });
+        var box = {
+            tag: 'div',
+            cn: [
+                {
+                    tag: 'input',
+                    type : 'hidden',
+                    cls: 'form-hidden-field'
+                },
+                inputblock
+            ]
+            
+        };
+        
+        if(this.multiple){
+            box = {
+                tag: 'div',
+                cn: [
+                    {
+                        tag: 'input',
+                        type : 'hidden',
+                        cls: 'form-hidden-field'
+                    },
+                    {
+                        tag: 'ul',
+                        cls: 'select2-choices',
+                        cn:[
+                            {
+                                tag: 'li',
+                                cls: 'select2-search-field',
+                                cn: [
 
- // listen for node click?
- view.on("click", function(vw, index, node, e){
- alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
- });
+                                    inputblock
+                                ]
+                            }
+                        ]
+                    }
+                ]
+            }
+        };
+        
+        var combobox = {
+            cls: 'select2-container input-group',
+            cn: [
+                box
+            ]
+        };
+        
+        if(this.multiple){
+            combobox.cls += ' select2-container-multi';
+        }
+        
+        var align = this.labelAlign || this.parentLabelAlign();
+        
+        cfg.cn = combobox;
+        
+        if(this.fieldLabel.length){
+            
+            var lw = align === 'left' ? ('col-sm' + this.labelWidth) : '';
+            var cw = align === 'left' ? ('col-sm' + (12 - this.labelWidth)) : '';
+            
+            cfg.cn = [
+                {
+                    tag: 'label',
+                    cls : 'control-label ' + lw,
+                    html : this.fieldLabel
 
- // load XML data
- dataModel.load("foobar.xml");
- </code></pre>
- For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
- * <br><br>
- * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
- * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
- * 
- * Note: old style constructor is still suported (container, template, config)
- * 
- * @constructor
- * Create a new View
- * @param {Object} config The config object
- * 
- */
-Roo.View = function(config, depreciated_tpl, depreciated_config){
-    
-    this.parent = false;
-    
-    if (typeof(depreciated_tpl) == 'undefined') {
-        // new way.. - universal constructor.
-        Roo.apply(this, config);
-        this.el  = Roo.get(this.el);
-    } else {
-        // old format..
-        this.el  = Roo.get(config);
-        this.tpl = depreciated_tpl;
-        Roo.apply(this, depreciated_config);
-    }
-    this.wrapEl  = this.el.wrap().wrap();
-    ///this.el = this.wrapEla.appendChild(document.createElement("div"));
-    
-    
-    if(typeof(this.tpl) == "string"){
-        this.tpl = new Roo.Template(this.tpl);
-    } else {
-        // support xtype ctors..
-        this.tpl = new Roo.factory(this.tpl, Roo);
-    }
-    
+                },
+                {
+                    cls : cw, 
+                    cn: [
+                        combobox
+                    ]
+                }
+            ];
+        }
+        
+        var settings = this;
+        
+        ['xs','sm','md','lg'].map(function(size){
+            if (settings[size]) {
+                cfg.cls += ' col-' + size + '-' + settings[size];
+            }
+        });
+        
+        return cfg;
+    },
     
-    this.tpl.compile();
+    initTouchView : function()
+    {
+        this.renderTouchView();
+        
+        this.touchViewEl.on('scroll', function(){
+            this.el.dom.scrollTop = 0;
+        }, this);
+        
+        this.inputEl().on("click", this.showTouchView, this);
+        this.touchViewFooterEl.select('.roo-touch-view-cancel', true).first().on('click', this.hideTouchView, this);
+        this.touchViewFooterEl.select('.roo-touch-view-ok', true).first().on('click', this.setTouchViewValue, this);
+        
+        this.maskEl = new Roo.LoadMask(this.touchViewEl, { store : this.store, msgCls: 'roo-el-mask-msg' });
+        
+        this.store.on('beforeload', this.onTouchViewBeforeLoad, this);
+        this.store.on('load', this.onTouchViewLoad, this);
+        this.store.on('loadexception', this.onTouchViewLoadException, this);
+        
+        if(this.hiddenName){
+            
+            this.hiddenField = this.el.select('input.form-hidden-field',true).first();
+            
+            this.hiddenField.dom.value =
+                this.hiddenValue !== undefined ? this.hiddenValue :
+                this.value !== undefined ? this.value : '';
+        
+            this.el.dom.removeAttribute('name');
+            this.hiddenField.dom.setAttribute('name', this.hiddenName);
+        }
+        
+        if(this.multiple){
+            this.choices = this.el.select('ul.select2-choices', true).first();
+            this.searchField = this.el.select('ul li.select2-search-field', true).first();
+        }
+        
+        if(this.removable && !this.multiple){
+            var close = this.closeTriggerEl();
+            if(close){
+                close.setVisibilityMode(Roo.Element.DISPLAY).hide();
+                close.on('click', this.removeBtnClick, this, close);
+            }
+        }
+        
+        return;
+        
+        
+    },
     
-    /** @private */
-    this.addEvents({
-        /**
-         * @event beforeclick
-         * Fires before a click is processed. Returns false to cancel the default action.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "beforeclick" : true,
-        /**
-         * @event click
-         * Fires when a template node is clicked.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "click" : true,
-        /**
-         * @event dblclick
-         * Fires when a template node is double clicked.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "dblclick" : true,
-        /**
-         * @event contextmenu
-         * Fires when a template node is right clicked.
-         * @param {Roo.View} this
-         * @param {Number} index The index of the target node
-         * @param {HTMLElement} node The target node
-         * @param {Roo.EventObject} e The raw event object
-         */
-            "contextmenu" : true,
-        /**
-         * @event selectionchange
-         * Fires when the selected nodes change.
-         * @param {Roo.View} this
-         * @param {Array} selections Array of the selected nodes
-         */
-            "selectionchange" : true,
+    renderTouchView : function()
+    {
+        this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.ComboBox.touchViewTemplate);
+        this.touchViewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.touchViewHeaderEl = this.touchViewEl.select('.modal-header', true).first();
+        this.touchViewHeaderEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.touchViewBodyEl = this.touchViewEl.select('.modal-body', true).first();
+        this.touchViewBodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.touchViewBodyEl.setStyle('overflow', 'auto');
+        
+        this.touchViewListGroup = this.touchViewBodyEl.select('.list-group', true).first();
+        this.touchViewListGroup.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.touchViewFooterEl = this.touchViewEl.select('.modal-footer', true).first();
+        this.touchViewFooterEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+    },
     
-        /**
-         * @event beforeselect
-         * Fires before a selection is made. If any handlers return false, the selection is cancelled.
-         * @param {Roo.View} this
-         * @param {HTMLElement} node The node to be selected
-         * @param {Array} selections Array of currently selected nodes
-         */
-            "beforeselect" : true,
-        /**
-         * @event preparedata
-         * Fires on every row to render, to allow you to change the data.
-         * @param {Roo.View} this
-         * @param {Object} data to be rendered (change this)
-         */
-          "preparedata" : true
-          
-          
-        });
+    showTouchView : function()
+    {
+        this.touchViewHeaderEl.hide();
 
+        if(this.fieldLabel.length){
+            this.touchViewHeaderEl.dom.innerHTML = this.fieldLabel;
+            this.touchViewHeaderEl.show();
+        }
 
+        this.touchViewEl.show();
 
-    this.el.on({
-        "click": this.onClick,
-        "dblclick": this.onDblClick,
-        "contextmenu": this.onContextMenu,
-        scope:this
-    });
+        this.touchViewEl.select('.modal-dialog', true).first().setStyle('margin', '0px');
+        this.touchViewEl.select('.modal-dialog > .modal-content', true).first().setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
 
-    this.selections = [];
-    this.nodes = [];
-    this.cmp = new Roo.CompositeElementLite([]);
-    if(this.store){
-        this.store = Roo.factory(this.store, Roo.data);
-        this.setStore(this.store, true);
-    }
-    
-    if ( this.footer && this.footer.xtype) {
-           
-         var fctr = this.wrapEl.appendChild(document.createElement("div"));
+        var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+        if(this.fieldLabel.length){
+            bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+        }
         
-        this.footer.dataSource = this.store
-        this.footer.container = fctr;
-        this.footer = Roo.factory(this.footer, Roo);
-        fctr.insertFirst(this.el);
+        this.touchViewBodyEl.setHeight(bodyHeight);
+
+        if(this.animate){
+            var _this = this;
+            (function(){ _this.touchViewEl.addClass('in'); }).defer(50);
+        }else{
+            this.touchViewEl.addClass('in');
+        }
+
+        this.doTouchViewQuery();
         
-        // this is a bit insane - as the paging toolbar seems to detach the el..
-//        dom.parentNode.parentNode.parentNode
-         // they get detached?
-    }
+    },
     
+    hideTouchView : function()
+    {
+        this.touchViewEl.removeClass('in');
+
+        if(this.animate){
+            var _this = this;
+            (function(){ _this.touchViewEl.setStyle('display', 'none'); }).defer(150);
+        }else{
+            this.touchViewEl.setStyle('display', 'none');
+        }
+        
+    },
     
-    Roo.View.superclass.constructor.call(this);
+    setTouchViewValue : function()
+    {
+        if(this.multiple){
+            this.clearItem();
+        
+            var _this = this;
+
+            Roo.each(this.tickItems, function(o){
+                this.addItem(o);
+            }, this);
+        }
+        
+        this.hideTouchView();
+    },
     
+    doTouchViewQuery : function()
+    {
+        var qe = {
+            query: '',
+            forceAll: true,
+            combo: this,
+            cancel:false
+        };
+        
+        if(this.fireEvent('beforequery', qe) ===false || qe.cancel){
+            return false;
+        }
+        
+        if(!this.alwaysQuery || this.mode == 'local'){
+            this.onTouchViewLoad();
+            return;
+        }
+        
+        this.store.load();
+    },
     
-};
+    onTouchViewBeforeLoad : function(combo,opts)
+    {
+        return;
+    },
 
-Roo.extend(Roo.View, Roo.util.Observable, {
+    // private
+    onTouchViewLoad : function()
+    {
+        if(this.store.getCount() < 1){
+            this.onTouchViewEmptyResults();
+            return;
+        }
+        
+        this.clearTouchView();
+        
+        var rawValue = this.getRawValue();
+        
+        var template = (this.multiple) ? Roo.bootstrap.ComboBox.listItemCheckbox : Roo.bootstrap.ComboBox.listItemRadio;
+        
+        this.tickItems = [];
+        
+        this.store.data.each(function(d, rowIndex){
+            var row = this.touchViewListGroup.createChild(template);
+            
+            if(this.displayField && typeof(d.data[this.displayField]) != 'undefined'){
+                row.select('.roo-combobox-list-group-item-value', true).first().dom.innerHTML = d.data[this.displayField];
+            }
+            
+            if(!this.multiple && this.valueField && typeof(d.data[this.valueField]) != 'undefined' && d.data[this.valueField] == this.getValue()){
+                row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+            }
+            
+            if(this.multiple && this.valueField && typeof(d.data[this.valueField]) != 'undefined' && this.getValue().indexOf(d.data[this.valueField]) != -1){
+                row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+                this.tickItems.push(d.data);
+            }
+            
+            row.on('click', this.onTouchViewClick, this, {row : row, rowIndex : rowIndex});
+            
+        }, this);
+        
+        var firstChecked = this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).first();
+        
+        var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+        if(this.fieldLabel.length){
+            bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+        }
+
+        var listHeight = this.touchViewListGroup.getHeight();
+        
+        var _this = this;
+        
+        if(firstChecked && listHeight > bodyHeight){
+            (function() { firstChecked.findParent('li').scrollIntoView(_this.touchViewListGroup.dom); }).defer(500);
+        }
+        
+    },
     
-     /**
-     * @cfg {Roo.data.Store} store Data store to load data from.
-     */
-    store : false,
+    onTouchViewLoadException : function()
+    {
+        this.hideTouchView();
+    },
     
-    /**
-     * @cfg {String|Roo.Element} el The container element.
-     */
-    el : '',
+    onTouchViewEmptyResults : function()
+    {
+        this.clearTouchView();
+        
+        this.touchViewListGroup.createChild(Roo.bootstrap.ComboBox.emptyResult);
+        
+        this.touchViewListGroup.select('.roo-combobox-touch-view-empty-result', true).first().dom.innerHTML = this.emptyResultText;
+        
+    },
     
-    /**
-     * @cfg {String|Roo.Template} tpl The template used by this View 
-     */
-    tpl : false,
-    /**
-     * @cfg {String} dataName the named area of the template to use as the data area
-     *                          Works with domtemplates roo-name="name"
-     */
-    dataName: false,
-    /**
-     * @cfg {String} selectedClass The css class to add to selected nodes
-     */
-    selectedClass : "x-view-selected",
-     /**
-     * @cfg {String} emptyText The empty text to show when nothing is loaded.
-     */
-    emptyText : "",
-    
-    /**
-     * @cfg {String} text to display on mask (default Loading)
-     */
-    mask : false,
-    /**
-     * @cfg {Boolean} multiSelect Allow multiple selection
-     */
-    multiSelect : false,
-    /**
-     * @cfg {Boolean} singleSelect Allow single selection
-     */
-    singleSelect:  false,
-    
-    /**
-     * @cfg {Boolean} toggleSelect - selecting 
-     */
-    toggleSelect : false,
-    
-    /**
-     * @cfg {Boolean} tickable - selecting 
-     */
-    tickable : false,
-    
-    /**
-     * Returns the element this view is bound to.
-     * @return {Roo.Element}
-     */
-    getEl : function(){
-        return this.wrapEl;
+    clearTouchView : function()
+    {
+        this.touchViewListGroup.dom.innerHTML = '';
     },
     
-    
-
-    /**
-     * Refreshes the view. - called by datachanged on the store. - do not call directly.
-     */
-    refresh : function(){
-        //Roo.log('refresh');
-        var t = this.tpl;
-        
-        // if we are using something like 'domtemplate', then
-        // the what gets used is:
-        // t.applySubtemplate(NAME, data, wrapping data..)
-        // the outer template then get' applied with
-        //     the store 'extra data'
-        // and the body get's added to the
-        //      roo-name="data" node?
-        //      <span class='roo-tpl-{name}'></span> ?????
+    onTouchViewClick : function(e, el, o)
+    {
+        e.preventDefault();
         
+        var row = o.row;
+        var rowIndex = o.rowIndex;
         
+        var r = this.store.getAt(rowIndex);
         
-        this.clearSelections();
-        this.el.update("");
-        var html = [];
-        var records = this.store.getRange();
-        if(records.length < 1) {
-            
-            // is this valid??  = should it render a template??
+        if(!this.multiple){
+            Roo.each(this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).elements, function(c){
+                c.dom.removeAttribute('checked');
+            }, this);
             
-            this.el.update(this.emptyText);
-            return;
-        }
-        var el = this.el;
-        if (this.dataName) {
-            this.el.update(t.apply(this.store.meta)); //????
-            el = this.el.child('.roo-tpl-' + this.dataName);
-        }
+            row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
         
-        for(var i = 0, len = records.length; i < len; i++){
-            var data = this.prepareData(records[i].data, i, records[i]);
-            this.fireEvent("preparedata", this, data, i, records[i]);
-            
-            var d = Roo.apply({}, data);
-            
-            if(this.tickable){
-                Roo.apply(d, {'roo-id' : Roo.id()});
-                
-                var _this = this;
+            this.setFromData(r.data);
             
-                Roo.each(this.parent.item, function(item){
-                    if(item[_this.parent.valueField] != data[_this.parent.valueField]){
-                        return;
-                    }
-                    Roo.apply(d, {'roo-data-checked' : 'checked'});
-                });
+            var close = this.closeTriggerEl();
+        
+            if(close){
+                close.show();
             }
+
+            this.hideTouchView();
             
-            html[html.length] = Roo.util.Format.trim(
-                this.dataName ?
-                    t.applySubtemplate(this.dataName, d, this.store.meta) :
-                    t.apply(d)
-            );
+            this.fireEvent('select', this, r, rowIndex);
+            
+            return;
         }
         
+        if(this.valueField && typeof(r.data[this.valueField]) != 'undefined' && this.getValue().indexOf(r.data[this.valueField]) != -1){
+            row.select('.roo-combobox-list-group-item-box > input', true).first().dom.removeAttribute('checked');
+            this.tickItems.splice(this.tickItems.indexOf(r.data), 1);
+            return;
+        }
         
+        row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+        this.addItem(r.data);
+        this.tickItems.push(r.data);
         
-        el.update(html.join(""));
-        this.nodes = el.dom.childNodes;
-        this.updateIndexes(0);
-    },
+    }
     
 
+    /** 
+    * @cfg {Boolean} grow 
+    * @hide 
+    */
+    /** 
+    * @cfg {Number} growMin 
+    * @hide 
+    */
+    /** 
+    * @cfg {Number} growMax 
+    * @hide 
+    */
     /**
-     * Function to override to reformat the data that is sent to
-     * the template for each node.
-     * DEPRICATED - use the preparedata event handler.
-     * @param {Array/Object} data The raw data (array of colData for a data model bound view or
-     * a JSON object for an UpdateManager bound view).
+     * @hide
+     * @method autoSize
      */
-    prepareData : function(data, index, record)
-    {
-        this.fireEvent("preparedata", this, data, index, record);
-        return data;
-    },
+});
 
-    onUpdate : function(ds, record){
-        // Roo.log('on update');   
-        this.clearSelections();
-        var index = this.store.indexOf(record);
-        var n = this.nodes[index];
-        this.tpl.insertBefore(n, this.prepareData(record.data, index, record));
-        n.parentNode.removeChild(n);
-        this.updateIndexes(index, index);
+Roo.apply(Roo.bootstrap.ComboBox,  {
+    
+    header : {
+        tag: 'div',
+        cls: 'modal-header',
+        cn: [
+            {
+                tag: 'h4',
+                cls: 'modal-title'
+            }
+        ]
     },
-
     
+    body : {
+        tag: 'div',
+        cls: 'modal-body',
+        cn: [
+            {
+                tag: 'ul',
+                cls: 'list-group'
+            }
+        ]
+    },
     
-// --------- FIXME     
-    onAdd : function(ds, records, index)
-    {
-        //Roo.log(['on Add', ds, records, index] );        
-        this.clearSelections();
-        if(this.nodes.length == 0){
-            this.refresh();
-            return;
-        }
-        var n = this.nodes[index];
-        for(var i = 0, len = records.length; i < len; i++){
-            var d = this.prepareData(records[i].data, i, records[i]);
-            if(n){
-                this.tpl.insertBefore(n, d);
-            }else{
-                
-                this.tpl.append(this.el, d);
+    listItemRadio : {
+        tag: 'li',
+        cls: 'list-group-item',
+        cn: [
+            {
+                tag: 'span',
+                cls: 'roo-combobox-list-group-item-value'
+            },
+            {
+                tag: 'div',
+                cls: 'roo-combobox-list-group-item-box pull-xs-right radio-inline radio radio-info',
+                cn: [
+                    {
+                        tag: 'input',
+                        type: 'radio'
+                    },
+                    {
+                        tag: 'label'
+                    }
+                ]
             }
-        }
-        this.updateIndexes(index);
+        ]
     },
-
-    onRemove : function(ds, record, index){
-       // Roo.log('onRemove');
-        this.clearSelections();
-        var el = this.dataName  ?
-            this.el.child('.roo-tpl-' + this.dataName) :
-            this.el; 
-        
-        el.dom.removeChild(this.nodes[index]);
-        this.updateIndexes(index);
+    
+    listItemCheckbox : {
+        tag: 'li',
+        cls: 'list-group-item',
+        cn: [
+            {
+                tag: 'span',
+                cls: 'roo-combobox-list-group-item-value'
+            },
+            {
+                tag: 'div',
+                cls: 'roo-combobox-list-group-item-box pull-xs-right checkbox-inline checkbox checkbox-info',
+                cn: [
+                    {
+                        tag: 'input',
+                        type: 'checkbox'
+                    },
+                    {
+                        tag: 'label'
+                    }
+                ]
+            }
+        ]
     },
-
-    /**
-     * Refresh an individual node.
-     * @param {Number} index
-     */
-    refreshNode : function(index){
-        this.onUpdate(this.store, this.store.getAt(index));
+    
+    emptyResult : {
+        tag: 'div',
+        cls: 'alert alert-danger roo-combobox-touch-view-empty-result'
     },
+    
+    footer : {
+        tag: 'div',
+        cls: 'modal-footer',
+        cn: [
+            {
+                tag: 'div',
+                cls: 'row',
+                cn: [
+                    {
+                        tag: 'div',
+                        cls: 'col-xs-6 text-left',
+                        cn: {
+                            tag: 'button',
+                            cls: 'btn btn-danger roo-touch-view-cancel',
+                            html: 'Cancel'
+                        }
+                    },
+                    {
+                        tag: 'div',
+                        cls: 'col-xs-6 text-right',
+                        cn: {
+                            tag: 'button',
+                            cls: 'btn btn-success roo-touch-view-ok',
+                            html: 'OK'
+                        }
+                    }
+                ]
+            }
+        ]
+        
+    }
+});
 
-    updateIndexes : function(startIndex, endIndex){
-        var ns = this.nodes;
-        startIndex = startIndex || 0;
-        endIndex = endIndex || ns.length - 1;
-        for(var i = startIndex; i <= endIndex; i++){
-            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){
-        var el = this.dataName  ?
-            this.el.child('.roo-tpl-' + this.dataName,true) :
-            this.el.dom; 
-        
-        if(!node || node.parentNode == el){
+    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; 
+        
+        if(!node || node.parentNode == el){
                    return node;
            }
            var p = node.parentNode;
@@ -14608,10 +15284,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.
@@ -14715,7 +15393,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) {
@@ -14752,7 +15430,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?
@@ -14764,6 +15442,7 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
         this.el.setXY([0,0]);
         this.el.removeClass('in');
         this.el.hide();
+        this.hoverState = null;
         
     }
     
@@ -19910,3410 +20589,5761 @@ Roo.extend(Roo.bootstrap.HtmlEditor, Roo.bootstrap.TextArea,  {
     // id of frame..
     frameId: false,
     
-    // private properties
-    validationEvent : false,
-    deferHeight: true,
-    initialized : false,
-    activated : false,
+    // private properties
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
+    
+    onFocus : Roo.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
+    
+    
+    tbContainer : false,
+    
+    toolbarContainer :function() {
+        return this.wrap.select('.x-html-editor-tb',true).first();
+    },
+
+    /**
+     * Protected method that will not generally be called directly. It
+     * is called when the editor creates its toolbar. Override this method if you need to
+     * add custom toolbar buttons.
+     * @param {HtmlEditor} editor
+     */
+    createToolbar : function(){
+        
+        Roo.log("create toolbars");
+        
+        this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
+        this.toolbars[0].render(this.toolbarContainer());
+        
+        return;
+        
+//        if (!editor.toolbars || !editor.toolbars.length) {
+//            editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
+//        }
+//        
+//        for (var i =0 ; i < editor.toolbars.length;i++) {
+//            editor.toolbars[i] = Roo.factory(
+//                    typeof(editor.toolbars[i]) == 'string' ?
+//                        { xtype: editor.toolbars[i]} : editor.toolbars[i],
+//                Roo.bootstrap.HtmlEditor);
+//            editor.toolbars[i].init(editor);
+//        }
+    },
+
+     
+    // private
+    onRender : function(ct, position)
+    {
+       // Roo.log("Call onRender: " + this.xtype);
+        var _t = this;
+        Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
+      
+        this.wrap = this.inputEl().wrap({
+            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
+        });
+        
+        this.editorcore.onRender(ct, position);
+         
+        if (this.resizable) {
+            this.resizeEl = new Roo.Resizable(this.wrap, {
+                pinned : true,
+                wrap: true,
+                dynamic : true,
+                minHeight : this.height,
+                height: this.height,
+                handles : this.resizable,
+                width: this.width,
+                listeners : {
+                    resize : function(r, w, h) {
+                        _t.onResize(w,h); // -something
+                    }
+                }
+            });
+            
+        }
+        this.createToolbar(this);
+       
+        
+        if(!this.width && this.resizable){
+            this.setSize(this.wrap.getSize());
+        }
+        if (this.resizeEl) {
+            this.resizeEl.resizeTo.defer(100, this.resizeEl,[ this.width,this.height ] );
+            // should trigger onReize..
+        }
+        
+    },
+
+    // private
+    onResize : function(w, h)
+    {
+        Roo.log('resize: ' +w + ',' + h );
+        Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
+        var ew = false;
+        var eh = false;
+        
+        if(this.inputEl() ){
+            if(typeof w == 'number'){
+                var aw = w - this.wrap.getFrameWidth('lr');
+                this.inputEl().setWidth(this.adjustWidth('textarea', aw));
+                ew = aw;
+            }
+            if(typeof h == 'number'){
+                 var tbh = -11;  // fixme it needs to tool bar size!
+                for (var i =0; i < this.toolbars.length;i++) {
+                    // fixme - ask toolbars for heights?
+                    tbh += this.toolbars[i].el.getHeight();
+                    //if (this.toolbars[i].footer) {
+                    //    tbh += this.toolbars[i].footer.el.getHeight();
+                    //}
+                }
+              
+                
+                
+                
+                
+                var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
+                ah -= 5; // knock a few pixes off for look..
+                this.inputEl().setHeight(this.adjustWidth('textarea', ah));
+                var eh = ah;
+            }
+        }
+        Roo.log('onResize:' + [w,h,ew,eh].join(',') );
+        this.editorcore.onResize(ew,eh);
+        
+    },
+
+    /**
+     * Toggles the editor between standard and source edit mode.
+     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     */
+    toggleSourceEdit : function(sourceEditMode)
+    {
+        this.editorcore.toggleSourceEdit(sourceEditMode);
+        
+        if(this.editorcore.sourceEditMode){
+            Roo.log('editor - showing textarea');
+            
+//            Roo.log('in');
+//            Roo.log(this.syncValue());
+            this.syncValue();
+            this.inputEl().removeClass(['hide', 'x-hidden']);
+            this.inputEl().dom.removeAttribute('tabIndex');
+            this.inputEl().focus();
+        }else{
+            Roo.log('editor - hiding textarea');
+//            Roo.log('out')
+//            Roo.log(this.pushValue()); 
+            this.pushValue();
+            
+            this.inputEl().addClass(['hide', 'x-hidden']);
+            this.inputEl().dom.setAttribute('tabIndex', -1);
+            //this.deferFocus();
+        }
+         
+        if(this.resizable){
+            this.setSize(this.wrap.getSize());
+        }
+        
+        this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
+    },
+    // private (for BoxComponent)
+    adjustSize : Roo.BoxComponent.prototype.adjustSize,
+
+    // private (for BoxComponent)
+    getResizeEl : function(){
+        return this.wrap;
+    },
+
+    // private (for BoxComponent)
+    getPositionEl : function(){
+        return this.wrap;
+    },
+
+    // private
+    initEvents : function(){
+        this.originalValue = this.getValue();
+    },
+
+//    /**
+//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+//     * @method
+//     */
+//    markInvalid : Roo.emptyFn,
+//    /**
+//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+//     * @method
+//     */
+//    clearInvalid : Roo.emptyFn,
+
+    setValue : function(v){
+        Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
+        this.editorcore.pushValue();
+    },
+
+     
+    // private
+    deferFocus : function(){
+        this.focus.defer(10, this);
+    },
+
+    // doc'ed in Field
+    focus : function(){
+        this.editorcore.focus();
+        
+    },
+      
+
+    // private
+    onDestroy : function(){
+        
+        
+        
+        if(this.rendered){
+            
+            for (var i =0; i < this.toolbars.length;i++) {
+                // fixme - ask toolbars for heights?
+                this.toolbars[i].onDestroy();
+            }
+            
+            this.wrap.dom.innerHTML = '';
+            this.wrap.remove();
+        }
+    },
+
+    // private
+    onFirstFocus : function(){
+        //Roo.log("onFirstFocus");
+        this.editorcore.onFirstFocus();
+         for (var i =0; i < this.toolbars.length;i++) {
+            this.toolbars[i].onFirstFocus();
+        }
+        
+    },
+    
+    // private
+    syncValue : function()
+    {   
+        this.editorcore.syncValue();
+    },
+    
+    pushValue : function()
+    {   
+        this.editorcore.pushValue();
+    }
+     
+    
+    // hide stuff that is not compatible
+    /**
+     * @event blur
+     * @hide
+     */
+    /**
+     * @event change
+     * @hide
+     */
+    /**
+     * @event focus
+     * @hide
+     */
+    /**
+     * @event specialkey
+     * @hide
+     */
+    /**
+     * @cfg {String} fieldClass @hide
+     */
+    /**
+     * @cfg {String} focusClass @hide
+     */
+    /**
+     * @cfg {String} autoCreate @hide
+     */
+    /**
+     * @cfg {String} inputType @hide
+     */
+    /**
+     * @cfg {String} invalidClass @hide
+     */
+    /**
+     * @cfg {String} invalidText @hide
+     */
+    /**
+     * @cfg {String} msgFx @hide
+     */
+    /**
+     * @cfg {String} validateOnBlur @hide
+     */
+});
+    
+   
+   
+   
+      
+Roo.namespace('Roo.bootstrap.htmleditor');
+/**
+ * @class Roo.bootstrap.HtmlEditorToolbar1
+ * Basic Toolbar
+ * 
+ * Usage:
+ *
+ new Roo.bootstrap.HtmlEditor({
+    ....
+    toolbars : [
+        new Roo.bootstrap.HtmlEditorToolbar1({
+            disable : { fonts: 1 , format: 1, ..., ... , ...],
+            btns : [ .... ]
+        })
+    }
+     
+ * 
+ * @cfg {Object} disable List of elements to disable..
+ * @cfg {Array} btns List of additional buttons.
+ * 
+ * 
+ * NEEDS Extra CSS? 
+ * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
+ */
+Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
+{
+    
+    Roo.apply(this, config);
+    
+    // default disabled, based on 'good practice'..
+    this.disable = this.disable || {};
+    Roo.applyIf(this.disable, {
+        fontSize : true,
+        colors : true,
+        specialElements : true
+    });
+    Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
+    
+    this.editor = config.editor;
+    this.editorcore = config.editor.editorcore;
+    
+    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
+    
+    //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
+    // dont call parent... till later.
+}
+Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,  {
+     
+    bar : true,
+    
+    editor : false,
+    editorcore : false,
+    
+    
+    formats : [
+        "p" ,  
+        "h1","h2","h3","h4","h5","h6", 
+        "pre", "code", 
+        "abbr", "acronym", "address", "cite", "samp", "var",
+        'div','span'
+    ],
+    
+    onRender : function(ct, position)
+    {
+       // Roo.log("Call onRender: " + this.xtype);
+        
+       Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
+       Roo.log(this.el);
+       this.el.dom.style.marginBottom = '0';
+       var _this = this;
+       var editorcore = this.editorcore;
+       var editor= this.editor;
+       
+       var children = [];
+       var btn = function(id,cmd , toggle, handler){
+       
+            var  event = toggle ? 'toggle' : 'click';
+       
+            var a = {
+                size : 'sm',
+                xtype: 'Button',
+                xns: Roo.bootstrap,
+                glyphicon : id,
+                cmd : id || cmd,
+                enableToggle:toggle !== false,
+                //html : 'submit'
+                pressed : toggle ? false : null,
+                listeners : {}
+            };
+            a.listeners[toggle ? 'toggle' : 'click'] = function() {
+                handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd ||  id);
+            };
+            children.push(a);
+            return a;
+       }
+        
+        var style = {
+                xtype: 'Button',
+                size : 'sm',
+                xns: Roo.bootstrap,
+                glyphicon : 'font',
+                //html : 'submit'
+                menu : {
+                    xtype: 'Menu',
+                    xns: Roo.bootstrap,
+                    items:  []
+                }
+        };
+        Roo.each(this.formats, function(f) {
+            style.menu.items.push({
+                xtype :'MenuItem',
+                xns: Roo.bootstrap,
+                html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
+                tagname : f,
+                listeners : {
+                    click : function()
+                    {
+                        editorcore.insertTag(this.tagname);
+                        editor.focus();
+                    }
+                }
+                
+            });
+        });
+         children.push(style);   
+            
+            
+        btn('bold',false,true);
+        btn('italic',false,true);
+        btn('align-left', 'justifyleft',true);
+        btn('align-center', 'justifycenter',true);
+        btn('align-right' , 'justifyright',true);
+        btn('link', false, false, function(btn) {
+            //Roo.log("create link?");
+            var url = prompt(this.createLinkText, this.defaultLinkValue);
+            if(url && url != 'http:/'+'/'){
+                this.editorcore.relayCmd('createlink', url);
+            }
+        }),
+        btn('list','insertunorderedlist',true);
+        btn('pencil', false,true, function(btn){
+                Roo.log(this);
+                
+                this.toggleSourceEdit(btn.pressed);
+        });
+        /*
+        var cog = {
+                xtype: 'Button',
+                size : 'sm',
+                xns: Roo.bootstrap,
+                glyphicon : 'cog',
+                //html : 'submit'
+                menu : {
+                    xtype: 'Menu',
+                    xns: Roo.bootstrap,
+                    items:  []
+                }
+        };
+        
+        cog.menu.items.push({
+            xtype :'MenuItem',
+            xns: Roo.bootstrap,
+            html : Clean styles,
+            tagname : f,
+            listeners : {
+                click : function()
+                {
+                    editorcore.insertTag(this.tagname);
+                    editor.focus();
+                }
+            }
+            
+        });
+       */
+        
+         
+       this.xtype = 'NavSimplebar';
+        
+        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);
+            }
+        });
+    },
+
+    // private
+    onRemove : function(v, index, r){
+        this.selections.remove(r);
+    },
+
+    // private
+    onRowUpdated : function(v, index, r){
+        if(this.isSelected(r)){
+            v.onRowSelect(index);
+        }
+    },
+
+    /**
+     * Select records.
+     * @param {Array} records The records to select
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectRecords : function(records, keepExisting){
+        if(!keepExisting){
+            this.clearSelections();
+        }
+        var ds = this.grid.dataSource;
+        for(var i = 0, len = records.length; i < len; i++){
+            this.selectRow(ds.indexOf(records[i]), true);
+        }
+    },
+
+    /**
+     * Gets the number of selected rows.
+     * @return {Number}
+     */
+    getCount : function(){
+        return this.selections.length;
+    },
+
+    /**
+     * 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);
+        }
+    },
+
+    /**
+     * 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);
+        }
+    },
+
+    /**
+     * Returns the selected records
+     * @return {Array} Array of selected records
+     */
+    getSelections : function(){
+        return [].concat(this.selections.items);
+    },
+
+    /**
+     * Returns the first selected record.
+     * @return {Record}
+     */
+    getSelected : function(){
+        return this.selections.itemAt(0);
+    },
+
+
+    /**
+     * Clears all selections.
+     */
+    clearSelections : function(fast){
+        if(this.locked) return;
+        if(fast !== true){
+            var ds = this.grid.dataSource;
+            var s = this.selections;
+            s.each(function(r){
+                this.deselectRow(ds.indexOfId(r.id));
+            }, this);
+            s.clear();
+        }else{
+            this.selections.clear();
+        }
+        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);
+            }
+        }
+        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);
+        }
+    },
+
+    /**
+     * 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);
+            }
+        }
+    },
+
+    /**
+     * 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);
+        }
+    },
+
+    /**
+     * Selects a row.
+     * @param {Number} row The index of the row to select
+     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     */
+    selectRow : function(index, keepExisting, preventViewNotify){
+        if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) return;
+        if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
+            if(!keepExisting || this.singleSelect){
+                this.clearSelections();
+            }
+            var r = this.grid.dataSource.getAt(index);
+            this.selections.add(r);
+            this.last = this.lastActive = index;
+            if(!preventViewNotify){
+                this.grid.getView().onRowSelect(index);
+            }
+            this.fireEvent("rowselect", this, index, r);
+            this.fireEvent("selectionchange", this);
+        }
+    },
+
+    /**
+     * Deselects a row.
+     * @param {Number} row The index of the row to deselect
+     */
+    deselectRow : function(index, preventViewNotify){
+        if(this.locked) return;
+        if(this.last == index){
+            this.last = false;
+        }
+        if(this.lastActive == index){
+            this.lastActive = false;
+        }
+        var r = this.grid.dataSource.getAt(index);
+        this.selections.remove(r);
+        if(!preventViewNotify){
+            this.grid.getView().onRowDeselect(index);
+        }
+        this.fireEvent("rowdeselect", this, index);
+        this.fireEvent("selectionchange", this);
+    },
+
+    // private
+    restoreLast : function(){
+        if(this._last){
+            this.last = this._last;
+        }
+    },
+
+    // private
+    acceptsNav : function(row, col, cm){
+        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    },
+
+    // private
+    onEditorKey : function(field, e){
+        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
+        if(k == e.TAB){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
+            }
+        }else if(k == e.ENTER && !e.ctrlKey){
+            e.stopEvent();
+            ed.completeEdit();
+            if(e.shiftKey){
+                newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
+            }else{
+                newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
+            }
+        }else if(k == e.ESC){
+            ed.cancelEdit();
+        }
+        if(newCell){
+            g.startEditing(newCell[0], newCell[1]);
+        }
+    }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+/**
+ * @class Roo.bootstrap.PagingToolbar
+ * @extends Roo.bootstrap.NavSimplebar
+ * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
+ * @constructor
+ * Create a new PagingToolbar
+ * @param {Object} config The config object
+ * @param {Roo.data.Store} store
+ */
+Roo.bootstrap.PagingToolbar = function(config)
+{
+    // old args format still supported... - xtype is prefered..
+        // created from xtype...
+        
+    var ds = config.dataSource;
+    
+    Roo.log(ds);
+    Roo.log(this.store);
     
-    onFocus : Roo.emptyFn,
-    iframePad:3,
-    hideMode:'offsets',
+    if (this.store && !ds) {
+        Roo.log('run??');
+        this.store= Roo.factory(this.store, Roo.data);
+        ds = this.store;
+        ds.xmodule = this.xmodule || false;
+    }
     
+    this.toolbarItems = [];
+    if (config.items) {
+        this.toolbarItems = config.items;
+//        config.items = [];
+    }
     
-    tbContainer : false,
+    Roo.bootstrap.PagingToolbar.superclass.constructor.call(this, config);
+    this.ds = ds;
+    this.cursor = 0;
+    if (ds) { 
+        this.bind(ds);
+    }
+    Roo.log('ds??');
+    Roo.log(this.ds);
+    this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
     
-    toolbarContainer :function() {
-        return this.wrap.select('.x-html-editor-tb',true).first();
-    },
+};
 
+Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
     /**
-     * Protected method that will not generally be called directly. It
-     * is called when the editor creates its toolbar. Override this method if you need to
-     * add custom toolbar buttons.
-     * @param {HtmlEditor} editor
+     * @cfg {Roo.data.Store} dataSource
+     * The underlying data store providing the paged data
      */
-    createToolbar : function(){
-        
-        Roo.log("create toolbars");
-        
-        this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
-        this.toolbars[0].render(this.toolbarContainer());
-        
-        return;
-        
-//        if (!editor.toolbars || !editor.toolbars.length) {
-//            editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
-//        }
-//        
-//        for (var i =0 ; i < editor.toolbars.length;i++) {
-//            editor.toolbars[i] = Roo.factory(
-//                    typeof(editor.toolbars[i]) == 'string' ?
-//                        { xtype: editor.toolbars[i]} : editor.toolbars[i],
-//                Roo.bootstrap.HtmlEditor);
-//            editor.toolbars[i].init(editor);
-//        }
-    },
+    /**
+     * @cfg {String/HTMLElement/Element} container
+     * container The id or element that will contain the toolbar
+     */
+    /**
+     * @cfg {Boolean} displayInfo
+     * True to display the displayMsg (defaults to false)
+     */
+    /**
+     * @cfg {Number} pageSize
+     * The number of records to display per page (defaults to 20)
+     */
+    pageSize: 20,
+    /**
+     * @cfg {String} displayMsg
+     * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
+     */
+    displayMsg : 'Displaying {0} - {1} of {2}',
+    /**
+     * @cfg {String} emptyMsg
+     * The message to display when no records are found (defaults to "No data to display")
+     */
+    emptyMsg : 'No data to display',
+    /**
+     * Customizable piece of the default paging text (defaults to "Page")
+     * @type String
+     */
+    beforePageText : "Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "of %0")
+     * @type String
+     */
+    afterPageText : "of {0}",
+    /**
+     * Customizable piece of the default paging text (defaults to "First Page")
+     * @type String
+     */
+    firstText : "First Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Previous Page")
+     * @type String
+     */
+    prevText : "Previous Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Next Page")
+     * @type String
+     */
+    nextText : "Next Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Last Page")
+     * @type String
+     */
+    lastText : "Last Page",
+    /**
+     * Customizable piece of the default paging text (defaults to "Refresh")
+     * @type String
+     */
+    refreshText : "Refresh",
 
-     
+    buttons : false,
     // private
-    onRender : function(ct, position)
+    onRender : function(ct, position) 
     {
-       // Roo.log("Call onRender: " + this.xtype);
-        var _t = this;
-        Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
-      
-        this.wrap = this.inputEl().wrap({
-            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
-        });
+        Roo.bootstrap.PagingToolbar.superclass.onRender.call(this, ct, position);
+        this.navgroup.parentId = this.id;
+        this.navgroup.onRender(this.el, null);
+        // add the buttons to the navgroup
         
-        this.editorcore.onRender(ct, position);
-         
-        if (this.resizable) {
-            this.resizeEl = new Roo.Resizable(this.wrap, {
-                pinned : true,
-                wrap: true,
-                dynamic : true,
-                minHeight : this.height,
-                height: this.height,
-                handles : this.resizable,
-                width: this.width,
-                listeners : {
-                    resize : function(r, w, h) {
-                        _t.onResize(w,h); // -something
-                    }
-                }
-            });
-            
+        if(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.createToolbar(this);
-       
         
-        if(!this.width && this.resizable){
-            this.setSize(this.wrap.getSize());
-        }
-        if (this.resizeEl) {
-            this.resizeEl.resizeTo.defer(100, this.resizeEl,[ this.width,this.height ] );
-            // should trigger onReize..
+        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);
+        });
         
-    },
-
-    // private
-    onResize : function(w, h)
-    {
-        Roo.log('resize: ' +w + ',' + h );
-        Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
-        var ew = false;
-        var eh = false;
         
-        if(this.inputEl() ){
-            if(typeof w == 'number'){
-                var aw = w - this.wrap.getFrameWidth('lr');
-                this.inputEl().setWidth(this.adjustWidth('textarea', aw));
-                ew = aw;
-            }
-            if(typeof h == 'number'){
-                 var tbh = -11;  // fixme it needs to tool bar size!
-                for (var i =0; i < this.toolbars.length;i++) {
-                    // fixme - ask toolbars for heights?
-                    tbh += this.toolbars[i].el.getHeight();
-                    //if (this.toolbars[i].footer) {
-                    //    tbh += this.toolbars[i].footer.el.getHeight();
-                    //}
-                }
-              
-                
-                
-                
-                
-                var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
-                ah -= 5; // knock a few pixes off for look..
-                this.inputEl().setHeight(this.adjustWidth('textarea', ah));
-                var eh = ah;
-            }
-        }
-        Roo.log('onResize:' + [w,h,ew,eh].join(',') );
-        this.editorcore.onResize(ew,eh);
+        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();
         
-    },
-
-    /**
-     * Toggles the editor between standard and source edit mode.
-     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
-     */
-    toggleSourceEdit : function(sourceEditMode)
-    {
-        this.editorcore.toggleSourceEdit(sourceEditMode);
         
-        if(this.editorcore.sourceEditMode){
-            Roo.log('editor - showing textarea');
-            
-//            Roo.log('in');
-//            Roo.log(this.syncValue());
-            this.syncValue();
-            this.inputEl().removeClass(['hide', 'x-hidden']);
-            this.inputEl().dom.removeAttribute('tabIndex');
-            this.inputEl().focus();
-        }else{
-            Roo.log('editor - hiding textarea');
-//            Roo.log('out')
-//            Roo.log(this.pushValue()); 
-            this.pushValue();
+        var field = this.navgroup.addItem( {
+            tagtype : 'span',
+            cls : 'x-paging-position',
             
-            this.inputEl().addClass(['hide', 'x-hidden']);
-            this.inputEl().dom.setAttribute('tabIndex', -1);
-            //this.deferFocus();
-        }
-         
-        if(this.resizable){
-            this.setSize(this.wrap.getSize());
-        }
+            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"]) }
+        });
         
-        this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
-    },
-    // private (for BoxComponent)
-    adjustSize : Roo.BoxComponent.prototype.adjustSize,
-
-    // private (for BoxComponent)
-    getResizeEl : function(){
-        return this.wrap;
-    },
-
-    // private (for BoxComponent)
-    getPositionEl : function(){
-        return this.wrap;
     },
 
     // private
-    initEvents : function(){
-        this.originalValue = this.getValue();
+    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);
+        }
     },
 
-//    /**
-//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-//     * @method
-//     */
-//    markInvalid : Roo.emptyFn,
-//    /**
-//     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-//     * @method
-//     */
-//    clearInvalid : Roo.emptyFn,
-
-    setValue : function(v){
-        Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
-        this.editorcore.pushValue();
+    // private
+    onLoad : function(ds, r, o){
+       this.cursor = o.params ? o.params.start : 0;
+       var d = this.getPageData(),
+            ap = d.activePage,
+            ps = d.pages;
+        
+       this.afterTextEl.dom.innerHTML = String.format(this.afterPageText, d.pages);
+       this.field.dom.value = ap;
+       this.first.setDisabled(ap == 1);
+       this.prev.setDisabled(ap == 1);
+       this.next.setDisabled(ap == ps);
+       this.last.setDisabled(ap == ps);
+       this.loading.enable();
+       this.updateInfo();
     },
 
-     
     // private
-    deferFocus : function(){
-        this.focus.defer(10, this);
+    getPageData : function(){
+        var total = this.ds.getTotalCount();
+        return {
+            total : total,
+            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
+            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
+        };
     },
 
-    // doc'ed in Field
-    focus : function(){
-        this.editorcore.focus();
-        
+    // private
+    onLoadError : function(){
+        this.loading.enable();
     },
-      
 
     // private
-    onDestroy : function(){
-        
-        
-        
-        if(this.rendered){
-            
-            for (var i =0; i < this.toolbars.length;i++) {
-                // fixme - ask toolbars for heights?
-                this.toolbars[i].onDestroy();
+    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;
             }
-            
-            this.wrap.dom.innerHTML = '';
-            this.wrap.remove();
+            pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
+            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
+            e.stopEvent();
+        }
+        else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
+        {
+          var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
+          this.field.dom.value = pageNum;
+          this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
+          e.stopEvent();
+        }
+        else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+        {
+          var v = this.field.dom.value, pageNum; 
+          var increment = (e.shiftKey) ? 10 : 1;
+          if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+            increment *= -1;
+          if(!v || isNaN(pageNum = parseInt(v, 10))) {
+            this.field.dom.value = d.activePage;
+            return;
+          }
+          else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
+          {
+            this.field.dom.value = parseInt(v, 10) + increment;
+            pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
+            this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
+          }
+          e.stopEvent();
         }
     },
 
     // private
-    onFirstFocus : function(){
-        //Roo.log("onFirstFocus");
-        this.editorcore.onFirstFocus();
-         for (var i =0; i < this.toolbars.length;i++) {
-            this.toolbars[i].onFirstFocus();
+    beforeLoad : function(){
+        if(this.loading){
+            this.loading.disable();
         }
-        
     },
-    
-    // private
-    syncValue : function()
-    {   
-        this.editorcore.syncValue();
-    },
-    
-    pushValue : function()
-    {   
-        this.editorcore.pushValue();
-    }
-     
-    
-    // hide stuff that is not compatible
-    /**
-     * @event blur
-     * @hide
-     */
-    /**
-     * @event change
-     * @hide
-     */
-    /**
-     * @event focus
-     * @hide
-     */
-    /**
-     * @event specialkey
-     * @hide
-     */
-    /**
-     * @cfg {String} fieldClass @hide
-     */
-    /**
-     * @cfg {String} focusClass @hide
-     */
-    /**
-     * @cfg {String} autoCreate @hide
-     */
-    /**
-     * @cfg {String} inputType @hide
-     */
-    /**
-     * @cfg {String} invalidClass @hide
-     */
-    /**
-     * @cfg {String} invalidText @hide
-     */
+
+    // 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;
+        }
+    },
+
     /**
-     * @cfg {String} msgFx @hide
+     * 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;
+    },
+
     /**
-     * @cfg {String} validateOnBlur @hide
+     * Binds the paging toolbar to the specified {@link Roo.data.Store}
+     * @param {Roo.data.Store} store The data store to bind
      */
-});
-    
-   
-   
-   
-      
-Roo.namespace('Roo.bootstrap.htmleditor');
-/**
- * @class Roo.bootstrap.HtmlEditorToolbar1
- * Basic Toolbar
- * 
- * Usage:
- *
- new Roo.bootstrap.HtmlEditor({
-    ....
-    toolbars : [
-        new Roo.bootstrap.HtmlEditorToolbar1({
-            disable : { fonts: 1 , format: 1, ..., ... , ...],
-            btns : [ .... ]
-        })
+    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;
     }
-     
- * 
- * @cfg {Object} disable List of elements to disable..
- * @cfg {Array} btns List of additional buttons.
+});/*
+ * - LGPL
+ *
+ * element
  * 
+ */
+
+/**
+ * @class Roo.bootstrap.MessageBar
+ * @extends Roo.bootstrap.Component
+ * Bootstrap MessageBar class
+ * @cfg {String} html contents of the MessageBar
+ * @cfg {String} weight (info | success | warning | danger) default info
+ * @cfg {String} beforeClass insert the bar before the given class
+ * @cfg {Boolean} closable (true | false) default false
+ * @cfg {Boolean} fixed (true | false) default false, fix the bar at the top
  * 
- * NEEDS Extra CSS? 
- * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
+ * @constructor
+ * Create a new Element
+ * @param {Object} config The config object
  */
-Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
-{
-    
-    Roo.apply(this, config);
-    
-    // default disabled, based on 'good practice'..
-    this.disable = this.disable || {};
-    Roo.applyIf(this.disable, {
-        fontSize : true,
-        colors : true,
-        specialElements : true
-    });
-    Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
-    
-    this.editor = config.editor;
-    this.editorcore = config.editor.editorcore;
-    
-    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
-    
-    //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
-    // dont call parent... till later.
-}
-Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar,  {
-     
-    bar : true,
-    
-    editor : false,
-    editorcore : false,
-    
+
+Roo.bootstrap.MessageBar = function(config){
+    Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component,  {
     
-    formats : [
-        "p" ,  
-        "h1","h2","h3","h4","h5","h6", 
-        "pre", "code", 
-        "abbr", "acronym", "address", "cite", "samp", "var",
-        'div','span'
-    ],
+    html: '',
+    weight: 'info',
+    closable: false,
+    fixed: false,
+    beforeClass: 'bootstrap-sticky-wrap',
     
-    onRender : function(ct, position)
-    {
-       // Roo.log("Call onRender: " + this.xtype);
-        
-       Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
-       Roo.log(this.el);
-       this.el.dom.style.marginBottom = '0';
-       var _this = this;
-       var editorcore = this.editorcore;
-       var editor= this.editor;
-       
-       var children = [];
-       var btn = function(id,cmd , toggle, handler){
-       
-            var  event = toggle ? 'toggle' : 'click';
-       
-            var a = {
-                size : 'sm',
-                xtype: 'Button',
-                xns: Roo.bootstrap,
-                glyphicon : id,
-                cmd : id || cmd,
-                enableToggle:toggle !== false,
-                //html : 'submit'
-                pressed : toggle ? false : null,
-                listeners : {}
-            }
-            a.listeners[toggle ? 'toggle' : 'click'] = function() {
-                handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd ||  id);
-            }
-            children.push(a);
-            return a;
-       }
-        
-        var style = {
-                xtype: 'Button',
-                size : 'sm',
-                xns: Roo.bootstrap,
-                glyphicon : 'font',
-                //html : 'submit'
-                menu : {
-                    xtype: 'Menu',
-                    xns: Roo.bootstrap,
-                    items:  []
-                }
-        };
-        Roo.each(this.formats, function(f) {
-            style.menu.items.push({
-                xtype :'MenuItem',
-                xns: Roo.bootstrap,
-                html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
-                tagname : f,
-                listeners : {
-                    click : function()
-                    {
-                        editorcore.insertTag(this.tagname);
-                        editor.focus();
-                    }
-                }
-                
-            });
-        });
-         children.push(style);   
-            
-            
-        btn('bold',false,true);
-        btn('italic',false,true);
-        btn('align-left', 'justifyleft',true);
-        btn('align-center', 'justifycenter',true);
-        btn('align-right' , 'justifyright',true);
-        btn('link', false, false, function(btn) {
-            //Roo.log("create link?");
-            var url = prompt(this.createLinkText, this.defaultLinkValue);
-            if(url && url != 'http:/'+'/'){
-                this.editorcore.relayCmd('createlink', url);
-            }
-        }),
-        btn('list','insertunorderedlist',true);
-        btn('pencil', false,true, function(btn){
-                Roo.log(this);
-                
-                this.toggleSourceEdit(btn.pressed);
-        });
-        /*
-        var cog = {
-                xtype: 'Button',
-                size : 'sm',
-                xns: Roo.bootstrap,
-                glyphicon : 'cog',
-                //html : 'submit'
-                menu : {
-                    xtype: 'Menu',
-                    xns: Roo.bootstrap,
-                    items:  []
-                }
-        };
+    getAutoCreate : function(){
         
-        cog.menu.items.push({
-            xtype :'MenuItem',
-            xns: Roo.bootstrap,
-            html : Clean styles,
-            tagname : f,
-            listeners : {
-                click : function()
+        var cfg = {
+            tag: 'div',
+            cls: 'alert alert-dismissable alert-' + this.weight,
+            cn: [
                 {
-                    editorcore.insertTag(this.tagname);
-                    editor.focus();
+                    tag: 'span',
+                    cls: 'message',
+                    html: this.html || ''
                 }
-            }
-            
-        });
-       */
+            ]
+        }
         
-         
-       this.xtype = 'NavSimplebar';
+        if(this.fixed){
+            cfg.cls += ' alert-messages-fixed';
+        }
         
-        for(var i=0;i< children.length;i++) {
+        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();
             
-            this.buttons.add(this.addxtypeChild(children[i]));
+            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);
         }
         
-        editor.on('editorevent', this.updateToolbar, this);
+        this.el.select('>button.close').on('click', this.hide, this);
+        
     },
-    onBtnClick : function(id)
+    
+    show : function()
     {
-       this.editorcore.relayCmd(id);
-       this.editorcore.focus();
+        if (!this.rendered) {
+            this.render();
+        }
+        
+        this.el.show();
+        
+        this.fireEvent('show', this);
+        
     },
     
-    /**
-     * 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(){
+    hide : function()
+    {
+        if (!this.rendered) {
+            this.render();
+        }
+        
+        this.el.hide();
+        
+        this.fireEvent('hide', this);
+    },
+    
+    update : function()
+    {
+//        var e = this.el.dom.firstChild;
+//        
+//        if(this.closable){
+//            e = e.nextSibling;
+//        }
+//        
+//        e.data = this.html || '';
+
+        this.el.select('>.message', true).first().dom.innerHTML = this.html || '';
+    }
+   
+});
+
+
+     /*
+ * - LGPL
+ *
+ * Graph
+ * 
+ */
+
+
+/**
+ * @class Roo.bootstrap.Graph
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Graph class
+> Prameters
+ -sm {number} sm 4
+ -md {number} md 5
+ @cfg {String} graphtype  bar | vbar | pie
+ @cfg {number} g_x coodinator | centre x (pie)
+ @cfg {number} g_y coodinator | centre y (pie)
+ @cfg {number} g_r radius (pie)
+ @cfg {number} g_height height of the chart (respected by all elements in the set)
+ @cfg {number} g_width width of the chart (respected by all elements in the set)
+ @cfg {Object} title The title of the chart
+    
+ -{Array}  values
+ -opts (object) options for the chart 
+     o {
+     o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
+     o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
+     o vgutter (number)
+     o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
+     o stacked (boolean) whether or not to tread values as in a stacked bar chart
+     o to
+     o stretch (boolean)
+     o }
+ -opts (object) options for the pie
+     o{
+     o cut
+     o startAngle (number)
+     o endAngle (number)
+     } 
+ *
+ * @constructor
+ * Create a new Input
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Graph = function(config){
+    Roo.bootstrap.Graph.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // img events
+        /**
+         * @event click
+         * The img click event for the img.
+         * @param {Roo.EventObject} e
+         */
+        "click" : true
+    });
+};
+
+Roo.extend(Roo.bootstrap.Graph, Roo.bootstrap.Component,  {
+    
+    sm: 4,
+    md: 5,
+    graphtype: 'bar',
+    g_height: 250,
+    g_width: 400,
+    g_x: 50,
+    g_y: 50,
+    g_r: 30,
+    opts:{
+        //g_colors: this.colors,
+        g_type: 'soft',
+        g_gutter: '20%'
+
+    },
+    title : false,
+
+    getAutoCreate : function(){
+        
+        var cfg = {
+            tag: 'div',
+            html : null
+        }
+        
+        
+        return  cfg;
+    },
+
+    onRender : function(ct,position){
+        Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
+        this.raphael = Raphael(this.el.dom);
+        
+                    // data1 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    // data2 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    // data3 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+                    // txtattr = { font: "12px 'Fontin Sans', Fontin-Sans, sans-serif" };
+                /*
+                r.text(160, 10, "Single Series Chart").attr(txtattr);
+                r.text(480, 10, "Multiline Series Chart").attr(txtattr);
+                r.text(160, 250, "Multiple Series Stacked Chart").attr(txtattr);
+                r.text(480, 250, 'Multiline Series Stacked Vertical Chart. Type "round"').attr(txtattr);
+                
+                r.barchart(10, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10]], 0, {type: "sharp"});
+                r.barchart(330, 10, 300, 220, data1);
+                r.barchart(10, 250, 300, 220, data2, {stacked: true});
+                r.barchart(330, 250, 300, 220, data3, {stacked: true, type: "round"});
+                */
+                
+                // var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
+                // r.barchart(30, 30, 560, 250,  xdata, {
+                //    labels : [55, 20, 13, 32, 5, 1, 2, 10,5 , 10],
+                //     axis : "0 0 1 1",
+                //     axisxlabels :  xdata
+                //     //yvalues : cols,
+                   
+                // });
+//        var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
+//        
+//        this.load(null,xdata,{
+//                axis : "0 0 1 1",
+//                axisxlabels :  xdata
+//                });
+
+    },
+
+    load : function(graphtype,xdata,opts){
+        this.raphael.clear();
+        if(!graphtype) {
+            graphtype = this.graphtype;
+        }
+        if(!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;
 
-        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;
-                }
-            }
+        if(this.title){
+            this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
         }
         
-        
-        
-        // 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();
-        });
+    
+    setTitle: function(o)
+    {
+        this.title = o;
     },
-    toggleSourceEdit : function(sourceEditMode){
+    
+    initEvents: function() {
         
-          
-        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();
-                });
-            }
-            
+        if(!this.href){
+            this.el.on('click', this.onClick, this);
         }
-        Roo.log("calling toggole on editor");
-        // tell the editor that it's been pressed..
-        this.editor.toggleSourceEdit(sourceEditMode);
-       
+    },
+    
+    onClick : function(e)
+    {
+        Roo.log('img onclick');
+        this.fireEvent('click', this, e);
     }
+   
 });
 
-
-
-
+/*
+ * - LGPL
+ *
+ * numberBox
+ * 
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
 
 /**
- * @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.
+ * @class Roo.bootstrap.dash.NumberBox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap NumberBox class
+ * @cfg {String} headline Box headline
+ * @cfg {String} content Box content
+ * @cfg {String} icon Box icon
+ * @cfg {String} footer Footer text
+ * @cfg {String} fhref Footer href
+ * 
  * @constructor
+ * Create a new NumberBox
+ * @param {Object} config The config object
  */
-Roo.bootstrap.Table.AbstractSelectionModel = function(){
-    this.locked = false;
-    Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
+
+
+Roo.bootstrap.dash.NumberBox = function(config){
+    Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+    
 };
 
+Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component,  {
+    
+    headline : '',
+    content : '',
+    icon : '',
+    footer : '',
+    fhref : '',
+    ficon : '',
+    
+    getAutoCreate : function(){
+        
+        var cfg = {
+            tag : 'div',
+            cls : 'small-box ',
+            cn : [
+                {
+                    tag : 'div',
+                    cls : 'inner',
+                    cn :[
+                        {
+                            tag : 'h3',
+                            cls : 'roo-headline',
+                            html : this.headline
+                        },
+                        {
+                            tag : 'p',
+                            cls : 'roo-content',
+                            html : this.content
+                        }
+                    ]
+                }
+            ]
+        }
+        
+        if(this.icon){
+            cfg.cn.push({
+                tag : 'div',
+                cls : 'icon',
+                cn :[
+                    {
+                        tag : 'i',
+                        cls : 'ion ' + this.icon
+                    }
+                ]
+            });
+        }
+        
+        if(this.footer){
+            var footer = {
+                tag : 'a',
+                cls : 'small-box-footer',
+                href : this.fhref || '#',
+                html : this.footer
+            };
+            
+            cfg.cn.push(footer);
+            
+        }
+        
+        return  cfg;
+    },
+
+    onRender : function(ct,position){
+        Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
 
-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;
+    setHeadline: function (value)
+    {
+        this.el.select('.roo-headline',true).first().dom.innerHTML = value;
+    },
+    
+    setFooter: function (value, href)
+    {
+        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);
+        }
+        
     },
 
-    /**
-     * Unlocks the selections.
-     */
-    unlock : function(){
-        this.locked = false;
+    setContent: function (value)
+    {
+        this.el.select('.roo-content',true).first().dom.innerHTML = value;
     },
 
-    /**
-     * Returns true if the selections are locked.
-     * @return {Boolean}
-     */
-    isLocked : function(){
-        return this.locked;
+    initEvents: function() 
+    {   
+        
     }
+    
 });
+
+/*
+ * - LGPL
+ *
+ * TabBox
+ * 
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+
 /**
- * @extends Roo.bootstrap.Table.AbstractSelectionModel
- * @class Roo.bootstrap.Table.RowSelectionModel
- * The default SelectionModel used by {@link Roo.bootstrap.Table}.
- * It supports multiple selections and keyboard selection/navigation. 
+ * @class Roo.bootstrap.dash.TabBox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TabBox class
+ * @cfg {String} title Title of the TabBox
+ * @cfg {String} icon Icon of the TabBox
+ * @cfg {Boolean} showtabs (true|false) show the tabs default true
+ * @cfg {Boolean} tabScrollable (true|false) tab scrollable when mobile view default false
+ * 
  * @constructor
- * @param {Object} config
+ * Create a new TabBox
+ * @param {Object} config The config object
  */
 
-Roo.bootstrap.Table.RowSelectionModel = function(config){
-    Roo.apply(this, config);
-    this.selections = new Roo.util.MixedCollection(false, function(o){
-        return o.id;
-    });
-
-    this.last = false;
-    this.lastActive = false;
 
+Roo.bootstrap.dash.TabBox = function(config){
+    Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
     this.addEvents({
+        // raw events
         /**
-            * @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 addpane
+         * When a pane is added
+         * @param {Roo.bootstrap.dash.TabPane} pane
+         */
+        "addpane" : true,
         /**
-            * @event rowdeselect
-            * Fires when a row is deselected.
-            * @param {SelectionModel} this
-            * @param {Number} rowIndex The selected index
-            */
-        "rowdeselect" : true
+         * @event activatepane
+         * When a pane is activated
+         * @param {Roo.bootstrap.dash.TabPane} pane
+         */
+        "activatepane" : true
+        
+         
     });
-    Roo.bootstrap.Table.RowSelectionModel.superclass.constructor.call(this);
-    this.locked = false;
+    
+    this.panes = [];
 };
 
-Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSelectionModel,  {
-    /**
-     * @cfg {Boolean} singleSelect
-     * True to allow selection of only one row at a time (defaults to false)
-     */
-    singleSelect : false,
-
-    // private
-    initEvents : function(){
+Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component,  {
 
-        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);
+    title : '',
+    icon : false,
+    showtabs : true,
+    tabScrollable : false,
+    
+    getChildContainer : function()
+    {
+        return this.el.select('.tab-content', true).first();
+    },
+    
+    getAutoCreate : function(){
+        
+        var header = {
+            tag: 'li',
+            cls: 'pull-left header',
+            html: this.title,
+            cn : []
+        };
+        
+        if(this.icon){
+            header.cn.push({
+                tag: 'i',
+                cls: 'fa ' + this.icon
+            });
         }
-
-        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;
+        
+        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
+                        ]
                     }
-                }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);
+                ]
             }
-        });
-    },
+        }
+        
+        var cfg = {
+            tag: 'div',
+            cls: 'nav-tabs-custom',
+            cn: [
+                h,
+                {
+                    tag: 'div',
+                    cls: 'tab-content no-padding',
+                    cn: []
+                }
+            ]
+        }
 
-    // private
-    onRemove : function(v, index, r){
-        this.selections.remove(r);
+        return  cfg;
     },
-
-    // private
-    onRowUpdated : function(v, index, r){
-        if(this.isSelected(r)){
-            v.onRowSelect(index);
-        }
+    initEvents : function()
+    {
+        //Roo.log('add add pane handler');
+        this.on('addpane', this.onAddPane, this);
     },
-
-    /**
-     * Select records.
-     * @param {Array} records The records to select
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
+     /**
+     * Updates the box title
+     * @param {String} html to set the title to.
      */
-    selectRecords : function(records, keepExisting){
-        if(!keepExisting){
-            this.clearSelections();
+    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;
         }
-        var ds = this.grid.dataSource;
-        for(var i = 0, len = records.length; i < len; i++){
-            this.selectRow(ds.indexOf(records[i]), true);
+        
+        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');
         }
+        
+                
+    },
+    onTabClick : function(ev,un,ob,pane)
+    {
+        //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');
+        
+        
     },
+    
+    getActivePane : function()
+    {
+        var r = false;
+        Roo.each(this.panes, function(p) {
+            if(p.el.hasClass('active')){
+                r = p;
+                return false;
+            }
+            
+            return;
+        });
+        
+        return r;
+    }
+    
+    
+});
 
-    /**
-     * Gets the number of selected rows.
-     * @return {Number}
-     */
-    getCount : function(){
-        return this.selections.length;
-    },
+/*
+ * - LGPL
+ *
+ * Tab pane
+ * 
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+/**
+ * @class Roo.bootstrap.TabPane
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TabPane class
+ * @cfg {Boolean} active (false | true) Default false
+ * @cfg {String} title title of panel
 
-    /**
-     * Selects the first row in the grid.
-     */
-    selectFirstRow : function(){
-        this.selectRow(0);
-    },
+ * 
+ * @constructor
+ * Create a new TabPane
+ * @param {Object} config The config object
+ */
 
-    /**
-     * Select the last row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectLastRow : function(keepExisting){
-        this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting);
-    },
+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
+         
+    });
+};
 
-    /**
-     * 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);
+Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component,  {
+    
+    active : false,
+    title : '',
+    
+    // the tabBox that this is attached to.
+    tab : false,
+     
+    getAutoCreate : function() 
+    {
+        var cfg = {
+            tag: 'div',
+            cls: 'tab-pane'
         }
-    },
-
-    /**
-     * Selects the row that precedes the last selected row.
-     * @param {Boolean} keepExisting (optional) True to keep existing selections
-     */
-    selectPrevious : function(keepExisting){
-        if(this.last){
-            this.selectRow(this.last-1, keepExisting);
-            this.grid.getView().focusRow(this.last);
+        
+        if(this.active){
+            cfg.cls += ' active';
         }
+        
+        return cfg;
     },
-
-    /**
-     * Returns the selected records
-     * @return {Array} Array of selected records
-     */
-    getSelections : function(){
-        return [].concat(this.selections.items);
-    },
-
-    /**
-     * Returns the first selected record.
-     * @return {Record}
-     */
-    getSelected : function(){
-        return this.selections.itemAt(0);
+    initEvents  : function()
+    {
+        //Roo.log('trigger add pane handler');
+        this.parent().fireEvent('addpane', this)
     },
-
-
-    /**
-     * Clears all selections.
+    
+     /**
+     * Updates the tab title 
+     * @param {String} html to set the title to.
      */
-    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();
+    setTitle: function(str)
+    {
+        if (!this.tab) {
+            return;
         }
-        this.last = false;
-    },
+        this.title = str;
+        this.tab.select('a', true).first().dom.innerHTML = str;
+        
+    }
+    
+    
+    
+});
 
 
-    /**
-     * 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;
-    },
/*
+ * - LGPL
+ *
+ * menu
+ * 
+ */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
 
-    /**
-     * 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);
-    },
+/**
+ * @class Roo.bootstrap.menu.Menu
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Menu class - container for Menu
+ * @cfg {String} html Text of the menu
+ * @cfg {String} weight (default | primary | success | info | warning | danger | inverse)
+ * @cfg {String} icon Font awesome icon
+ * @cfg {String} pos Menu align to (top | bottom) default bottom
+ * 
+ * 
+ * @constructor
+ * Create a new Menu
+ * @param {Object} config The config object
+ */
 
-    /**
-     * 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);
-            }
-        }
-        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);
-        }
-    },
+Roo.bootstrap.menu.Menu = function(config){
+    Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        /**
+         * @event beforeshow
+         * Fires before this menu is displayed
+         * @param {Roo.bootstrap.menu.Menu} this
+         */
+        beforeshow : true,
+        /**
+         * @event beforehide
+         * Fires before this menu is hidden
+         * @param {Roo.bootstrap.menu.Menu} this
+         */
+        beforehide : true,
+        /**
+         * @event show
+         * Fires after this menu is displayed
+         * @param {Roo.bootstrap.menu.Menu} this
+         */
+        show : true,
+        /**
+         * @event hide
+         * Fires after this menu is hidden
+         * @param {Roo.bootstrap.menu.Menu} this
+         */
+        hide : true,
+        /**
+         * @event click
+         * Fires when this menu is clicked (or when the enter key is pressed while it is active)
+         * @param {Roo.bootstrap.menu.Menu} this
+         * @param {Roo.EventObject} e
+         */
+        click : true
+    });
+    
+};
+
+Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component,  {
     
-    /**
-     * 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);
+    submenu : false,
+    html : '',
+    weight : 'default',
+    icon : false,
+    pos : 'bottom',
+    
+    
+    getChildContainer : function() {
+        if(this.isSubMenu){
+            return this.el;
         }
+        
+        return this.el.select('ul.dropdown-menu', true).first();  
     },
-
-    /**
-     * 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);
+    
+    getAutoCreate : function()
+    {
+        var text = [
+            {
+                tag : 'span',
+                cls : 'roo-menu-text',
+                html : this.html
             }
+        ];
+        
+        if(this.icon){
+            text.unshift({
+                tag : 'i',
+                cls : 'fa ' + this.icon
+            })
         }
-    },
-
-    /**
-     * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
-     * @param {Number} startRow The index of the first row in the range
-     * @param {Number} endRow The index of the last row in the range
-     */
-    deselectRange : function(startRow, endRow, preventViewNotify){
-        if(this.locked) return;
-        for(var i = startRow; i <= endRow; i++){
-            this.deselectRow(i, preventViewNotify);
+        
+        
+        var 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';
         }
-    },
-
-    /**
-     * 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);
+        
+        if(this.isSubMenu){
+            cfg = {
+                tag : 'ul',
+                cls : 'dropdown-menu'
             }
-            this.fireEvent("rowselect", this, index, r);
-            this.fireEvent("selectionchange", this);
         }
+       
+        return cfg;
     },
-
-    /**
-     * Deselects a row.
-     * @param {Number} row The index of the row to deselect
-     */
-    deselectRow : function(index, preventViewNotify){
-        if(this.locked) return;
-        if(this.last == index){
-            this.last = false;
-        }
-        if(this.lastActive == index){
-            this.lastActive = false;
-        }
-        var r = this.grid.dataSource.getAt(index);
-        this.selections.remove(r);
-        if(!preventViewNotify){
-            this.grid.getView().onRowDeselect(index);
+    
+    onRender : function(ct, position)
+    {
+        this.isSubMenu = ct.hasClass('dropdown-submenu');
+        
+        Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
+    },
+    
+    initEvents : function() 
+    {
+        if(this.isSubMenu){
+            return;
         }
-        this.fireEvent("rowdeselect", this, index);
-        this.fireEvent("selectionchange", this);
+        
+        this.hidden = true;
+        
+        this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
+        this.triggerEl.on('click', this.onTriggerPress, this);
+        
+        this.buttonEl = this.el.select('button.dropdown-button', true).first();
+        this.buttonEl.on('click', this.onClick, this);
+        
     },
-
-    // private
-    restoreLast : function(){
-        if(this._last){
-            this.last = this._last;
+    
+    list : function()
+    {
+        if(this.isSubMenu){
+            return this.el;
         }
+        
+        return this.el.select('ul.dropdown-menu', true).first();
     },
-
-    // private
-    acceptsNav : function(row, col, cm){
-        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    
+    onClick : function(e)
+    {
+        this.fireEvent("click", this, e);
     },
-
-    // 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]);
+    
+    onTriggerPress  : function(e)
+    {   
+        if (this.isVisible()) {
+            this.hide();
+        } else {
+            this.show();
         }
+    },
+    
+    isVisible : function(){
+        return !this.hidden;
+    },
+    
+    show : function()
+    {
+        this.fireEvent("beforeshow", this);
+        
+        this.hidden = false;
+        this.el.addClass('open');
+        
+        Roo.get(document).on("mouseup", this.onMouseUp, this);
+        
+        this.fireEvent("show", this);
+        
+        
+    },
+    
+    hide : function()
+    {
+        this.fireEvent("beforehide", this);
+        
+        this.hidden = true;
+        this.el.removeClass('open');
+        
+        Roo.get(document).un("mouseup", this.onMouseUp);
+        
+        this.fireEvent("hide", this);
+    },
+    
+    onMouseUp : function()
+    {
+        this.hide();
     }
-});/*
- * 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">
+ * menu item
+ * 
  */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+
 /**
- * @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.menu.Item
+ * @extends Roo.bootstrap.Component
+ * Bootstrap MenuItem class
+ * @cfg {Boolean} submenu (true | false) default false
+ * @cfg {String} html text of the item
+ * @cfg {String} href the link
+ * @cfg {Boolean} disable (true | false) default false
+ * @cfg {Boolean} preventDefault (true | false) default true
+ * @cfg {String} icon Font awesome icon
+ * @cfg {String} pos Submenu align to (left | right) default right 
+ * 
+ * 
  * @constructor
- * Create a new PagingToolbar
+ * Create a new Item
  * @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",
 
-    buttons : false,
-    // private
-    onRender : function(ct, position) 
+Roo.bootstrap.menu.Item = function(config){
+    Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
+    this.addEvents({
+        /**
+         * @event mouseover
+         * Fires when the mouse is hovering over this menu
+         * @param {Roo.bootstrap.menu.Item} this
+         * @param {Roo.EventObject} e
+         */
+        mouseover : true,
+        /**
+         * @event mouseout
+         * Fires when the mouse exits this menu
+         * @param {Roo.bootstrap.menu.Item} this
+         * @param {Roo.EventObject} e
+         */
+        mouseout : true,
+        // raw events
+        /**
+         * @event click
+         * The raw click event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        click : true
+    });
+};
+
+Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component,  {
+    
+    submenu : false,
+    href : '',
+    html : '',
+    preventDefault: true,
+    disable : false,
+    icon : false,
+    pos : 'right',
+    
+    getAutoCreate : function()
     {
-        Roo.bootstrap.PagingToolbar.superclass.onRender.call(this, ct, position);
-        this.navgroup.parentId = this.id;
-        this.navgroup.onRender(this.el, null);
-        // add the buttons to the navgroup
-        
-        if(this.displayInfo){
-            Roo.log(this.el.select('ul.navbar-nav',true).first());
-            this.el.select('ul.navbar-nav',true).first().createChild({cls:'x-paging-info'});
-            this.displayEl = this.el.select('.x-paging-info', true).first();
-//            var navel = this.navgroup.addItem( { tagtype : 'span', html : '', cls : 'x-paging-info', preventDefault : true } );
-//            this.displayEl = navel.el.select('span',true).first();
-        }
-        
-        var _this = this;
+        var text = [
+            {
+                tag : 'span',
+                cls : 'roo-menu-item-text',
+                html : this.html
+            }
+        ];
         
-        if(this.buttons){
-            Roo.each(_this.buttons, function(e){
-               Roo.factory(e).onRender(_this.el, null);
-            });
+        if(this.icon){
+            text.unshift({
+                tag : 'i',
+                cls : 'fa ' + this.icon
+            })
         }
-            
-        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 cfg = {
+            tag : 'li',
+            cn : [
+                {
+                    tag : 'a',
+                    href : this.href || '#',
+                    cn : text
+                }
+            ]
+        };
         
+        if(this.disable){
+            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
+        }
         
-        var field = this.navgroup.addItem( {
-            tagtype : 'span',
-            cls : 'x-paging-position',
+        if(this.submenu){
+            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
             
-            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?
+            if(this.pos == 'left'){
+                cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
+            }
+        }
         
-        this.field = field.el.select('input', true).first();
-        this.field.on("keydown", this.onPagingKeydown, this);
-        this.field.on("focus", function(){this.dom.select();});
-    
+        return cfg;
+    },
     
-        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"]) }
-        });
-
+    initEvents : function() 
+    {
+        this.el.on('mouseover', this.onMouseOver, this);
+        this.el.on('mouseout', this.onMouseOut, this);
+        
+        this.el.select('a', true).first().on('click', this.onClick, this);
+        
     },
-
-    // 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);
+    
+    onClick : function(e)
+    {
+        if(this.preventDefault){
+            e.preventDefault();
         }
+        
+        this.fireEvent("click", this, e);
     },
-
-    // private
-    onLoad : function(ds, r, o){
-       this.cursor = o.params ? o.params.start : 0;
-       var d = this.getPageData(),
-            ap = d.activePage,
-            ps = d.pages;
+    
+    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.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();
+        this.fireEvent("mouseover", this, e);
     },
+    
+    onMouseOut : function(e)
+    {
+        this.fireEvent("mouseout", this, e);
+    }
+});
 
-    // private
-    getPageData : function(){
-        var total = this.ds.getTotalCount();
-        return {
-            total : total,
-            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
-            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
-        };
-    },
 
-    // private
-    onLoadError : function(){
-        this.loading.enable();
-    },
+ /*
+ * - LGPL
+ *
+ * menu separator
+ * 
+ */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
 
-    // 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();
-        }
-    },
+/**
+ * @class Roo.bootstrap.menu.Separator
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Separator class
+ * 
+ * @constructor
+ * Create a new Separator
+ * @param {Object} config The config object
+ */
 
-    // private
-    beforeLoad : function(){
-        if(this.loading){
-            this.loading.disable();
-        }
-    },
 
-    // private
-    onClick : function(which){
-        
-        var ds = this.ds;
-        if (!ds) {
-            return;
-        }
+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'
+        };
         
-        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;
-        }
-    },
+        return cfg;
+    }
+   
+});
 
-    /**
-     * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
-     * @param {Roo.data.Store} store The data store to unbind
-     */
-    unbind : function(ds){
-        ds.un("beforeload", this.beforeLoad, this);
-        ds.un("load", this.onLoad, this);
-        ds.un("loadexception", this.onLoadError, this);
-        ds.un("remove", this.updateInfo, this);
-        ds.un("add", this.updateInfo, this);
-        this.ds = undefined;
-    },
 
-    /**
-     * Binds the paging toolbar to the specified {@link Roo.data.Store}
-     * @param {Roo.data.Store} store The data store to bind
-     */
-    bind : function(ds){
-        ds.on("beforeload", this.beforeLoad, this);
-        ds.on("load", this.onLoad, this);
-        ds.on("loadexception", this.onLoadError, this);
-        ds.on("remove", this.updateInfo, this);
-        ds.on("add", this.updateInfo, this);
-        this.ds = ds;
-    }
-});/*
+ /*
  * - LGPL
  *
- * element
+ * Tooltip
  * 
  */
 
 /**
- * @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
+ * @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 Element
+ * Create a new Toolti
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.MessageBar = function(config){
-    Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
+Roo.bootstrap.Tooltip = function(config){
+    Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
 };
 
-Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component,  {
+Roo.apply(Roo.bootstrap.Tooltip, {
+    /**
+     * @function init initialize tooltip monitoring.
+     * @static
+     */
+    currentEl : false,
+    currentTip : false,
+    currentRegion : false,
     
-    html: '',
-    weight: 'info',
-    closable: false,
-    fixed: false,
-    beforeClass: 'bootstrap-sticky-wrap',
+    //  init : delay?
     
-    getAutoCreate : function(){
+    init : function()
+    {
+        Roo.get(document).on('mouseover', this.enter ,this);
+        Roo.get(document).on('mouseout', this.leave, this);
+         
+        
+        this.currentTip = new Roo.bootstrap.Tooltip();
+    },
+    
+    enter : function(ev)
+    {
+        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.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..");
+            
+        }
+        this.currentEl = bindEl;
+        this.currentTip.bind(bindEl);
+        this.currentRegion = Roo.lib.Region.getRegion(dom);
+        this.currentTip.enter();
+        
+    },
+    leave : function(ev)
+    {
+        var dom = ev.getTarget();
+        //Roo.log(['leave',dom]);
+        if (!this.currentEl) {
+            return;
+        }
+        
+        
+        if (dom != this.currentEl.dom) {
+            return;
+        }
+        var xy = ev.getXY();
+        if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0]  ))) {
+            return;
+        }
+        // only activate leave if mouse cursor is outside... bounding box..
+        
+        
+        
+        
+        if (this.currentTip) {
+            this.currentTip.leave();
+        }
+        //Roo.log('clear currentEl');
+        this.currentEl = false;
         
+        
+    },
+    alignment : {
+        'left' : ['r-l', [-2,0], 'right'],
+        'right' : ['l-r', [2,0], 'left'],
+        'bottom' : ['t-b', [0,2], 'top'],
+        'top' : [ 'b-t', [0,-2], 'bottom']
+    }
+    
+});
+
+
+Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
+    
+    
+    bindEl : false,
+    
+    delay : null, // can be { show : 300 , hide: 500}
+    
+    timeout : null,
+    
+    hoverState : null, //???
+    
+    placement : 'bottom', 
+    
+    getAutoCreate : function(){
+    
         var cfg = {
-            tag: 'div',
-            cls: 'alert alert-dismissable alert-' + this.weight,
-            cn: [
+           cls : 'tooltip',
+           role : 'tooltip',
+           cn : [
                 {
-                    tag: 'span',
-                    cls: 'message',
-                    html: this.html || ''
+                    cls : 'tooltip-arrow'
+                },
+                {
+                    cls : 'tooltip-inner'
                 }
-            ]
+           ]
+        };
+        
+        return cfg;
+    },
+    bind : function(el)
+    {
+        this.bindEl = el;
+    },
+      
+    
+    enter : function () {
+       
+        if (this.timeout != null) {
+            clearTimeout(this.timeout);
         }
         
-        if(this.fixed){
-            cfg.cls += ' alert-messages-fixed';
+        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);
+    
+        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 ()
+    {
+        if (!this.el) {
+            this.render(document.body);
         }
+        // set content.
+        //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
         
-        if(this.closable){
-            cfg.cn.push({
-                tag: 'button',
-                cls: 'close',
-                html: 'x'
-            });
+        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';
         }
         
-        return cfg;
-    },
-    
-    onRender : function(ct, position)
-    {
-        Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
+        //this.el.detach()
+        //this.el.setXY([0,0]);
+        this.el.show();
+        //this.el.dom.style.display='block';
+        
+        //this.el.appendTo(on_el);
+        
+        var p = this.getPosition();
+        var box = this.el.getBox();
+        
+        if (autoPlace) {
+            // fixme..
+        }
+        
+        var align = Roo.bootstrap.Tooltip.alignment[placement];
+        
+        var xy = this.el.getAlignToXY(this.bindEl, align[0], align[1]);
         
-        if(!this.el){
-            var cfg = Roo.apply({},  this.getAutoCreate());
-            cfg.id = Roo.id();
-            
-            if (this.cls) {
-                cfg.cls += ' ' + this.cls;
+        if(placement == 'top' || placement == 'bottom'){
+            if(xy[0] < 0){
+                placement = 'right';
             }
-            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);
+            if(xy[0] + this.el.getWidth() > Roo.lib.Dom.getViewWidth()){
+                placement = 'left';
+            }
         }
         
-        this.el.select('>button.close').on('click', this.hide, this);
+        align = Roo.bootstrap.Tooltip.alignment[placement];
         
-    },
-    
-    show : function()
-    {
-        if (!this.rendered) {
-            this.render();
-        }
+        this.el.alignTo(this.bindEl, align[0],align[1]);
+        //var arrow = this.el.select('.arrow',true).first();
+        //arrow.set(align[2], 
         
-        this.el.show();
+        this.el.addClass(placement);
         
-        this.fireEvent('show', this);
+        this.el.addClass('in fade');
+        
+        this.hoverState = null;
+        
+        if (this.el.hasClass('fade')) {
+            // fade it?
+        }
         
     },
-    
     hide : function()
     {
-        if (!this.rendered) {
-            this.render();
+         
+        if (!this.el) {
+            return;
         }
+        //this.el.setXY([0,0]);
+        this.el.removeClass('in');
+        //this.el.hide();
         
-        this.el.hide();
-        
-        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
+ * Location Picker
  * 
  */
 
-
 /**
- * @class Roo.bootstrap.Graph
+ * @class Roo.bootstrap.LocationPicker
  * @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 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 Input
+ * Create a new LocationPicker
  * @param {Object} config The config object
  */
 
-Roo.bootstrap.Graph = function(config){
-    Roo.bootstrap.Graph.superclass.constructor.call(this, config);
+
+Roo.bootstrap.LocationPicker = function(config){
+    
+    Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
     
     this.addEvents({
-        // img events
         /**
-         * @event click
-         * The img click event for the img.
-         * @param {Roo.EventObject} e
+         * @event initial
+         * Fires when the picker initialized.
+         * @param {Roo.bootstrap.LocationPicker} this
+         * @param {Google Location} location
          */
-        "click" : true
+        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
+         */
+        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.Graph, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component,  {
     
-    sm: 4,
-    md: 5,
-    graphtype: 'bar',
-    g_height: 250,
-    g_width: 400,
-    g_x: 50,
-    g_y: 50,
-    g_r: 30,
-    opts:{
-        //g_colors: this.colors,
-        g_type: 'soft',
-        g_gutter: '20%'
-
-    },
-    title : false,
+    gMapContext: false,
+    
+    latitude: 0,
+    longitude: 0,
+    zoom: 15,
+    mapTypeId: false,
+    mapTypeControl: false,
+    disableDoubleClickZoom: false,
+    scrollwheel: true,
+    streetViewControl: false,
+    radius: 0,
+    locationName: '',
+    draggable: true,
+    enableAutocomplete: false,
+    enableReverseGeocode: true,
+    markerTitle: '',
+    
+    getAutoCreate: function()
+    {
 
-    getAutoCreate : function(){
-        
         var cfg = {
             tag: 'div',
-            html : null
+            cls: 'roo-location-picker'
+        };
+        
+        return cfg
+    },
+    
+    initEvents: function(ct, position)
+    {       
+        if(!this.el.getWidth() || this.isApplied()){
+            return;
         }
         
+        this.el.setVisibilityMode(Roo.Element.DISPLAY);
         
-        return  cfg;
+        this.initial();
     },
-
-    onRender : function(ct,position){
-        Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
-        this.raphael = Raphael(this.el.dom);
+    
+    initial: function()
+    {
+        if(!this.mapTypeId){
+            this.mapTypeId = google.maps.MapTypeId.ROADMAP;
+        }
         
-                    // 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"});
-                */
+        this.gMapContext = this.GMapContext();
+        
+        this.initOverlayView();
+        
+        this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
+        
+        var _this = this;
                 
-                // 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
-//                });
+        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);
+            
+        });
 
-    load : function(graphtype,xdata,opts){
-        this.raphael.clear();
-        if(!graphtype) {
-            graphtype = this.graphtype;
-        }
-        if(!opts){
-            opts = this.opts;
-        }
-        var r = this.raphael,
-            fin = function () {
-                this.flag = r.popup(this.bar.x, this.bar.y, this.bar.value || "0").insertBefore(this);
+        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);
+    },
+    
+    initOverlayView: function()
+    {
+        var _this = this;
+        
+        Roo.bootstrap.LocationPicker.OverlayView.prototype = Roo.apply(new google.maps.OverlayView(), {
+            
+            draw: function()
+            {
+                _this.fireEvent('OverlayViewDraw', _this);
             },
-            fout = function () {
-                this.flag.animate({opacity: 0}, 300, function () {this.remove();});
+            
+            onAdd: function()
+            {
+                _this.fireEvent('OverlayViewOnAdd', _this);
             },
-            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 });
-                }
+            
+            onRemove: function()
+            {
+                _this.fireEvent('OverlayViewOnRemove', _this);
             },
-            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);
+            
+            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);
+        
+        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()
+        };
+    },
+    
+    drawCircle: function(center, radius, options) 
+    {
+        if (this.gMapContext.circle != null) {
+            this.gMapContext.circle.setMap(null);
+        }
+        if (radius > 0) {
+            radius *= 1;
+            options = Roo.apply({}, options, {
+                strokeColor: "#0000FF",
+                strokeOpacity: .35,
+                strokeWeight: 2,
+                fillColor: "#0000FF",
+                fillOpacity: .2
+            });
+            
+            options.map = this.gMapContext.map;
+            options.radius = radius;
+            options.center = center;
+            this.gMapContext.circle = new google.maps.Circle(options);
+            return this.gMapContext.circle;
+        }
+        
+        return null;
+    },
+    
+    setPosition: function(location) 
+    {
+        this.gMapContext.location = location;
+        this.gMapContext.marker.setPosition(location);
+        this.gMapContext.map.panTo(location);
+        this.drawCircle(location, this.gMapContext.radius, {});
+        
+        var _this = this;
+        
+        if (this.gMapContext.settings.enableReverseGeocode) {
+            this.gMapContext.geodecoder.geocode({
+                latLng: this.gMapContext.location
+            }, function(results, status) {
                 
-                break;
-
+                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.title){
-            this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
-        }
+        this.fireEvent('positionchanged', this, location);
+    },
+    
+    resize: function()
+    {
+        google.maps.event.trigger(this.gMapContext.map, "resize");
+        
+        this.gMapContext.map.setCenter(this.gMapContext.marker.position);
         
+        this.fireEvent('resize', this);
     },
     
-    setTitle: function(o)
+    setPositionByLatLng: function(latitude, longitude)
     {
-        this.title = o;
+        this.setPosition(new google.maps.LatLng(latitude, longitude));
     },
     
-    initEvents: function() {
+    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 = {};
         
-        if(!this.href){
-            this.el.on('click', this.onClick, this);
+        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;
+            }
         }
+        
+        result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
+        result.addressLine2 = "";
+        return result;
     },
     
-    onClick : function(e)
+    setZoomLevel: function(zoom)
     {
-        Roo.log('img onclick');
-        this.fireEvent('click', this, e);
+        this.gMapContext.map.setZoom(zoom);
+    },
+    
+    show: function()
+    {
+        if(!this.el){
+            return;
+        }
+        
+        this.el.show();
+        
+        this.resize();
+        
+        this.fireEvent('show', this);
+    },
+    
+    hide: function()
+    {
+        if(!this.el){
+            return;
+        }
+        
+        this.el.hide();
+        
+        this.fireEvent('hide', this);
     }
-   
+    
 });
 
-/*
+Roo.apply(Roo.bootstrap.LocationPicker, {
+    
+    OverlayView : function(map, options)
+    {
+        options = options || {};
+        
+        this.setMap(map);
+    }
+    
+    
+});/*
  * - LGPL
  *
- * numberBox
+ * Alert
  * 
  */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
 
 /**
- * @class Roo.bootstrap.dash.NumberBox
+ * @class Roo.bootstrap.Alert
  * @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 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 NumberBox
+ * Create a new alert
  * @param {Object} config The config object
  */
 
 
-Roo.bootstrap.dash.NumberBox = function(config){
-    Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+Roo.bootstrap.Alert = function(config){
+    Roo.bootstrap.Alert.superclass.constructor.call(this, config);
     
 };
 
-Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component,  {
+Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component,  {
     
-    headline : '',
-    content : '',
-    icon : '',
-    footer : '',
-    fhref : '',
-    ficon : '',
+    title: '',
+    html: '',
+    weight: false,
+    faicon: false,
     
-    getAutoCreate : function(){
+    getAutoCreate : function()
+    {
         
         var cfg = {
             tag : 'div',
-            cls : 'small-box ',
+            cls : 'alert',
             cn : [
                 {
-                    tag : 'div',
-                    cls : 'inner',
-                    cn :[
-                        {
-                            tag : 'h3',
-                            cls : 'roo-headline',
-                            html : this.headline
-                        },
-                        {
-                            tag : 'p',
-                            cls : 'roo-content',
-                            html : this.content
-                        }
-                    ]
+                    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.icon){
-            cfg.cn.push({
-                tag : 'div',
-                cls : 'icon',
-                cn :[
-                    {
-                        tag : 'i',
-                        cls : 'ion ' + this.icon
-                    }
-                ]
-            });
+        if(this.faicon){
+            cfg.cn[0].cls += ' fa ' + this.faicon;
         }
         
-        if(this.footer){
-            var footer = {
-                tag : 'a',
-                cls : 'small-box-footer',
-                href : this.fhref || '#',
-                html : this.footer
-            };
-            
-            cfg.cn.push(footer);
-            
+        if(this.weight){
+            cfg.cls += ' alert-' + this.weight;
         }
         
-        return  cfg;
+        return cfg;
     },
-
-    onRender : function(ct,position){
-        Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
-
-
-       
-                
+    
+    initEvents: function() 
+    {
+        this.el.setVisibilityMode(Roo.Element.DISPLAY);
     },
-
-    setHeadline: function (value)
+    
+    setTitle : function(str)
     {
-        this.el.select('.roo-headline',true).first().dom.innerHTML = value;
+        this.el.select('.roo-alert-title',true).first().dom.innerHTML = str;
+    },
+    
+    setText : function(str)
+    {
+        this.el.select('.roo-alert-text',true).first().dom.innerHTML = str;
+    },
+    
+    setWeight : function(weight)
+    {
+        if(this.weight){
+            this.el.select('.alert',true).first().removeClass('alert-' + this.weight);
+        }
+        
+        this.weight = weight;
+        
+        this.el.select('.alert',true).first().addClass('alert-' + this.weight);
     },
     
-    setFooter: function (value, href)
+    setIcon : function(icon)
     {
-        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.faicon){
+            this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
         }
         
+        this.faicon = icon
+        
+        this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
     },
-
-    setContent: function (value)
+    
+    hide: function() 
     {
-        this.el.select('.roo-content',true).first().dom.innerHTML = value;
+        this.el.hide();   
     },
-
-    initEvents: function() 
-    {   
-        
+    
+    show: function() 
+    {  
+        this.el.show();   
     }
     
 });
 
  
 /*
- * - LGPL
- *
- * TabBox
- * 
- */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+* Licence: LGPL
+*/
 
 /**
- * @class Roo.bootstrap.dash.TabBox
+ * @class Roo.bootstrap.UploadCropbox
  * @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 UploadCropbox class
+ * @cfg {String} emptyText show when image has been loaded
+ * @cfg {String} rotateNotify show when image too small to rotate
+ * @cfg {Number} errorTimeout default 3000
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
+ * @cfg {Array} buttons default ['rotateLeft', 'pictureBtn', 'rotateRight']
+ * @cfg {Boolean} isDocument (true|false) default false
  * 
  * @constructor
- * Create a new TabBox
+ * Create a new UploadCropbox
  * @param {Object} config The config object
  */
 
-
-Roo.bootstrap.dash.TabBox = function(config){
-    Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
+Roo.bootstrap.UploadCropbox = function(config){
+    Roo.bootstrap.UploadCropbox.superclass.constructor.call(this, config);
+    
     this.addEvents({
-        // raw events
         /**
-         * @event addpane
-         * When a pane is added
-         * @param {Roo.bootstrap.dash.TabPane} pane
+         * @event beforeselectfile
+         * Fire before select file
+         * @param {Roo.bootstrap.UploadCropbox} this
          */
-        "addpane" : true,
+        "beforeselectfile" : true,
         /**
-         * @event activatepane
-         * When a pane is activated
-         * @param {Roo.bootstrap.dash.TabPane} pane
+         * @event initial
+         * Fire after initEvent
+         * @param {Roo.bootstrap.UploadCropbox} this
          */
-        "activatepane" : true
-        
-         
+        "initial" : true,
+        /**
+         * @event crop
+         * Fire after initEvent
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} data
+         */
+        "crop" : true,
+        /**
+         * @event prepare
+         * Fire when preparing the file data
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {Object} file
+         */
+        "prepare" : true,
+        /**
+         * @event exception
+         * Fire when get exception
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {Object} options
+         */
+        "exception" : true,
+        /**
+         * @event beforeloadcanvas
+         * Fire before load the canvas
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} src
+         */
+        "beforeloadcanvas" : true,
+        /**
+         * @event trash
+         * Fire when trash image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "trash" : true,
+        /**
+         * @event download
+         * Fire when download the image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "download" : true,
+        /**
+         * @event footerbuttonclick
+         * Fire when footerbuttonclick
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} type
+         */
+        "footerbuttonclick" : true,
+        /**
+         * @event resize
+         * Fire when resize
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "resize" : true,
+        /**
+         * @event rotate
+         * Fire when rotate the image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} pos
+         */
+        "rotate" : true
     });
     
-    this.panes = [];
+    this.buttons = this.buttons || Roo.bootstrap.UploadCropbox.footer.STANDARD;
 };
 
-Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component,  {
-
-    title : '',
-    icon : false,
-    showtabs : true,
-    tabScrollable : false,
+Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
+    
+    emptyText : 'Click to upload image',
+    rotateNotify : 'Image is too small to rotate',
+    errorTimeout : 3000,
+    scale : 0,
+    baseScale : 1,
+    rotate : 0,
+    dragable : false,
+    pinching : false,
+    mouseX : 0,
+    mouseY : 0,
+    cropData : false,
+    minWidth : 300,
+    minHeight : 300,
+    file : false,
+    exif : {},
+    baseRotate : 1,
+    cropType : 'image/jpeg',
+    buttons : false,
+    canvasLoaded : false,
+    isDocument : false,
     
-    getChildContainer : function()
+    getAutoCreate : function()
     {
-        return this.el.select('.tab-content', true).first();
+        var cfg = {
+            tag : 'div',
+            cls : 'roo-upload-cropbox',
+            cn : [
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-body',
+                    style : 'cursor:pointer',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-preview'
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-thumb'
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-empty-notify',
+                            html : this.emptyText
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-error-notify alert alert-danger',
+                            html : this.rotateNotify
+                        }
+                    ]
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-upload-cropbox-footer',
+                    cn : {
+                        tag : 'div',
+                        cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group',
+                        cn : []
+                    }
+                }
+            ]
+        };
+        
+        return cfg;
     },
     
-    getAutoCreate : function(){
-        
-        var header = {
-            tag: 'li',
-            cls: 'pull-left header',
-            html: this.title,
-            cn : []
-        };
+    onRender : function(ct, position)
+    {
+        Roo.bootstrap.UploadCropbox.superclass.onRender.call(this, ct, position);
         
-        if(this.icon){
-            header.cn.push({
-                tag: 'i',
-                cls: 'fa ' + this.icon
-            });
+        if (this.buttons.length) {
+            
+            Roo.each(this.buttons, function(bb) {
+                
+                var btn = this.el.select('.roo-upload-cropbox-footer div.roo-upload-cropbox-btn-group').first().createChild(bb);
+                
+                btn.on('click', this.onFooterButtonClick.createDelegate(this, [bb.action], true));
+                
+            }, this);
         }
+    },
+    
+    initEvents : function()
+    {
+        this.urlAPI = (window.createObjectURL && window) || 
+                                (window.URL && URL.revokeObjectURL && URL) || 
+                                (window.webkitURL && webkitURL);
+                        
+        this.bodyEl = this.el.select('.roo-upload-cropbox-body', true).first();
+        this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        var h = {
-            tag: 'ul',
-            cls: 'nav nav-tabs pull-right',
-            cn: [
-                header
-            ]
-        };
+        this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first();
+        this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        if(this.tabScrollable){
-            h = {
-                tag: 'div',
-                cls: 'tab-header',
-                cn: [
-                    {
-                        tag: 'ul',
-                        cls: 'nav nav-tabs pull-right',
-                        cn: [
-                            header
-                        ]
-                    }
-                ]
-            }
+        this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first();
+        this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.thumbEl.hide();
+        
+        this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first();
+        this.notifyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.errorEl = this.el.select('.roo-upload-cropbox-error-notify', true).first();
+        this.errorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.errorEl.hide();
+        
+        this.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first();
+        this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.footerEl.hide();
+        
+        this.setThumbBoxSize();
+        
+        this.bind();
+        
+        this.resize();
+        
+        this.fireEvent('initial', this);
+    },
+
+    bind : function()
+    {
+        var _this = this;
+        
+        window.addEventListener("resize", function() { _this.resize(); } );
+        
+        this.bodyEl.on('click', this.beforeSelectFile, this);
+        
+        if(Roo.isTouch){
+            this.bodyEl.on('touchstart', this.onTouchStart, this);
+            this.bodyEl.on('touchmove', this.onTouchMove, this);
+            this.bodyEl.on('touchend', this.onTouchEnd, this);
         }
         
-        var cfg = {
-            tag: 'div',
-            cls: 'nav-tabs-custom',
-            cn: [
-                h,
-                {
-                    tag: 'div',
-                    cls: 'tab-content no-padding',
-                    cn: []
-                }
-            ]
+        if(!Roo.isTouch){
+            this.bodyEl.on('mousedown', this.onMouseDown, this);
+            this.bodyEl.on('mousemove', this.onMouseMove, this);
+            var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
+            this.bodyEl.on(mousewheel, this.onMouseWheel, this);
+            Roo.get(document).on('mouseup', this.onMouseUp, this);
         }
-
-        return  cfg;
     },
-    initEvents : function()
+    
+    reset : function()
+    {    
+        this.scale = 0;
+        this.baseScale = 1;
+        this.rotate = 0;
+        this.baseRotate = 1;
+        this.dragable = false;
+        this.pinching = false;
+        this.mouseX = 0;
+        this.mouseY = 0;
+        this.cropData = false;
+        this.notifyEl.dom.innerHTML = this.emptyText;
+        
+    },
+    
+    resize : function()
     {
-        //Roo.log('add add pane handler');
-        this.on('addpane', this.onAddPane, this);
+        if(this.fireEvent('resize', this) != false){
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
+        }
     },
-     /**
-     * Updates the box title
-     * @param {String} html to set the title to.
-     */
-    setTitle : function(value)
+    
+    onFooterButtonClick : function(e, el, o, type)
     {
-        this.el.select('.nav-tabs .header', true).first().dom.innerHTML = value;
+        switch (type) {
+            case 'rotate-left' :
+                this.onRotateLeft(e);
+                break;
+            case 'rotate-right' :
+                this.onRotateRight(e);
+                break;
+            case 'picture' :
+                this.beforeSelectFile(e);
+                break;
+            case 'trash' :
+                this.trash(e);
+                break;
+            case 'crop' :
+                this.crop(e);
+                break;
+            case 'download' :
+                this.download(e);
+                break;
+            default :
+                break;
+        }
+        
+        this.fireEvent('footerbuttonclick', this, type);
     },
-    onAddPane : function(pane)
+    
+    beforeSelectFile : function(e)
     {
-        this.panes.push(pane);
-        //Roo.log('addpane');
-        //Roo.log(pane);
-        // tabs are rendere left to right..
-        if(!this.showtabs){
+        this.fireEvent('beforeselectfile', this);
+    },
+    
+    trash : function(e)
+    {
+        this.fireEvent('trash', this);
+    },
+    
+    download : function(e)
+    {
+        this.fireEvent('download', this);
+    },
+    
+    loadCanvas : function(src)
+    {   
+        if(this.fireEvent('beforeloadcanvas', this, src) != false){
+            
+            this.reset();
+            
+            this.imageEl = document.createElement('img');
+            
+            var _this = this;
+            
+            this.imageEl.addEventListener("load", function(){ _this.onLoadCanvas(); });
+            
+            this.imageEl.src = src;
+        }
+    },
+    
+    onLoadCanvas : function()
+    {   
+        this.bodyEl.un('click', this.beforeSelectFile, this);
+        
+        this.notifyEl.hide();
+        this.thumbEl.show();
+        this.footerEl.show();
+        
+        this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width;
+        this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height;
+        
+        this.baseRotateLevel();
+        
+        if(this.isDocument){
+            this.setThumbBoxSize();
+        }
+        
+        this.setThumbBoxPosition();
+        
+        this.baseScaleLevel();
+        
+        this.draw();
+        
+        this.resize();
+        
+        this.canvasLoaded = true;
+        
+    },
+    
+    setCanvasPosition : function()
+    {   
+        if(!this.canvasEl){
             return;
         }
         
-        var ctr = this.el.select('.nav-tabs', true).first();
-         
-         
-        var existing = ctr.select('.nav-tab',true);
-        var qty = existing.getCount();;
+        var pw = Math.ceil((this.bodyEl.getWidth() - this.canvasEl.width) / 2);
+        var ph = Math.ceil((this.bodyEl.getHeight() - this.canvasEl.height) / 2);
         
+        this.previewEl.setLeft(pw);
+        this.previewEl.setTop(ph);
         
-        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;
+    },
+    
+    onMouseDown : function(e)
+    {   
+        e.stopEvent();
         
-        tab.on('click', this.onTabClick.createDelegate(this, [pane], true));
-        if (!qty) {
-            pane.el.addClass('active');
+        this.dragable = true;
+        this.pinching = false;
+        
+        if(this.isDocument && (this.canvasEl.width < this.thumbEl.getWidth() || this.canvasEl.height < this.thumbEl.getHeight())){
+            this.dragable = false;
+            return;
         }
         
-                
+        this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+        
     },
-    onTabClick : function(ev,un,ob,pane)
-    {
-        //Roo.log('tab - prev default');
-        ev.preventDefault();
+    
+    onMouseMove : function(e)
+    {   
+        e.stopEvent();
         
+        if(!this.canvasLoaded){
+            return;
+        }
         
-        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.dragable){
+            return;
+        }
+        
+        var minX = Math.ceil(this.thumbEl.getLeft(true));
+        var minY = Math.ceil(this.thumbEl.getTop(true));
+        
+        var maxX = Math.ceil(minX + this.thumbEl.getWidth() - this.canvasEl.width);
+        var maxY = Math.ceil(minY + this.thumbEl.getHeight() - this.canvasEl.height);
+        
+        var x = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        var y = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
         
+        x = x - this.mouseX;
+        y = y - this.mouseY;
         
+        var bgX = Math.ceil(x + this.previewEl.getLeft(true));
+        var bgY = Math.ceil(y + this.previewEl.getTop(true));
+        
+        bgX = (minX < bgX) ? minX : ((maxX > bgX) ? maxX : bgX);
+        bgY = (minY < bgY) ? minY : ((maxY > bgY) ? maxY : bgY);
+        
+        this.previewEl.setLeft(bgX);
+        this.previewEl.setTop(bgY);
+        
+        this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+        this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
     },
     
-    getActivePane : function()
-    {
-        var r = false;
-        Roo.each(this.panes, function(p) {
-            if(p.el.hasClass('active')){
-                r = p;
-                return false;
-            }
-            
-            return;
-        });
+    onMouseUp : function(e)
+    {   
+        e.stopEvent();
         
-        return r;
-    }
-    
-    
-});
-
-/*
- * - LGPL
- *
- * Tab pane
- * 
- */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
-/**
- * @class Roo.bootstrap.TabPane
- * @extends Roo.bootstrap.Component
- * Bootstrap TabPane class
- * @cfg {Boolean} active (false | true) Default false
- * @cfg {String} title title of panel
-
- * 
- * @constructor
- * Create a new TabPane
- * @param {Object} config The config object
- */
-
-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.TabPane, Roo.bootstrap.Component,  {
-    
-    active : false,
-    title : '',
+        this.dragable = false;
+    },
     
-    // the tabBox that this is attached to.
-    tab : false,
-     
-    getAutoCreate : function() 
-    {
-        var cfg = {
-            tag: 'div',
-            cls: 'tab-pane'
-        }
+    onMouseWheel : function(e)
+    {   
+        e.stopEvent();
         
-        if(this.active){
-            cfg.cls += ' active';
+        this.startScale = this.scale;
+        
+        this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1);
+        
+        if(!this.zoomable()){
+            this.scale = this.startScale;
+            return;
         }
         
-        return cfg;
-    },
-    initEvents  : function()
-    {
-        //Roo.log('trigger add pane handler');
-        this.parent().fireEvent('addpane', this)
+        this.draw();
+        
+        return;
     },
     
-     /**
-     * Updates the tab title 
-     * @param {String} html to set the title to.
-     */
-    setTitle: function(str)
+    zoomable : function()
     {
-        if (!this.tab) {
-            return;
+        var minScale = this.thumbEl.getWidth() / this.minWidth;
+        
+        if(this.minWidth < this.minHeight){
+            minScale = this.thumbEl.getHeight() / this.minHeight;
         }
-        this.title = str;
-        this.tab.select('a', true).first().dom.innerHTML = str;
         
-    }
-    
-    
+        var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale);
+        var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale);
+        
+        if(
+                this.isDocument &&
+                (this.rotate == 0 || this.rotate == 180) && 
+                (
+                    width > this.imageEl.OriginWidth || 
+                    height > this.imageEl.OriginHeight ||
+                    (width < this.minWidth && height < this.minHeight)
+                )
+        ){
+            return false;
+        }
+        
+        if(
+                this.isDocument &&
+                (this.rotate == 90 || this.rotate == 270) && 
+                (
+                    width > this.imageEl.OriginWidth || 
+                    height > this.imageEl.OriginHeight ||
+                    (width < this.minHeight && height < this.minWidth)
+                )
+        ){
+            return false;
+        }
+        
+        if(
+                !this.isDocument &&
+                (this.rotate == 0 || this.rotate == 180) && 
+                (
+                    width < this.minWidth || 
+                    width > this.imageEl.OriginWidth || 
+                    height < this.minHeight || 
+                    height > this.imageEl.OriginHeight
+                )
+        ){
+            return false;
+        }
+        
+        if(
+                !this.isDocument &&
+                (this.rotate == 90 || this.rotate == 270) && 
+                (
+                    width < this.minHeight || 
+                    width > this.imageEl.OriginWidth || 
+                    height < this.minWidth || 
+                    height > this.imageEl.OriginHeight
+                )
+        ){
+            return false;
+        }
+        
+        return true;
+        
+    },
     
-});
-
-
-
- /*
- * - LGPL
- *
- * menu
- * 
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Menu
- * @extends Roo.bootstrap.Component
- * Bootstrap Menu class - container for Menu
- * @cfg {String} html Text of the menu
- * @cfg {String} weight (default | primary | success | info | warning | danger | inverse)
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Menu align to (top | bottom) default bottom
- * 
- * 
- * @constructor
- * Create a new Menu
- * @param {Object} config The config object
- */
-
+    onRotateLeft : function(e)
+    {   
+        if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+            
+            var minScale = this.thumbEl.getWidth() / this.minWidth;
+            
+            var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+            var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
+            
+            this.startScale = this.scale;
+            
+            while (this.getScaleLevel() < minScale){
+            
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
+                }
+                
+                if(
+                        Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+                        Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
 
-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
-    });
-    
-};
+                this.draw();
+                
+                return;
+            }
+            
+            this.scale = this.startScale;
+            
+            this.onRotateFail();
+            
+            return false;
+        }
+        
+        this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
 
-Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component,  {
-    
-    submenu : false,
-    html : '',
-    weight : 'default',
-    icon : false,
-    pos : 'bottom',
-    
-    
-    getChildContainer : function() {
-        if(this.isSubMenu){
-            return this.el;
+        if(this.isDocument){
+            this.setThumbBoxSize();
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
         }
         
-        return this.el.select('ul.dropdown-menu', true).first();  
+        this.draw();
+        
+        this.fireEvent('rotate', this, 'left');
+        
     },
     
-    getAutoCreate : function()
+    onRotateRight : function(e)
     {
-        var text = [
-            {
-                tag : 'span',
-                cls : 'roo-menu-text',
-                html : this.html
-            }
-        ];
-        
-        if(this.icon){
-            text.unshift({
-                tag : 'i',
-                cls : 'fa ' + this.icon
-            })
-        }
-        
+        if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+            
+            var minScale = this.thumbEl.getWidth() / this.minWidth;
         
-        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'
+            var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+            var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
+            
+            this.startScale = this.scale;
+            
+            while (this.getScaleLevel() < minScale){
+            
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
                 }
-            ]
+                
+                if(
+                        Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+                        Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+                this.draw();
+                
+                return;
+            }
             
-        };
-        
-        if(this.pos == 'top'){
-            cfg.cls += ' dropup';
+            this.scale = this.startScale;
+            
+            this.onRotateFail();
+            
+            return false;
         }
         
-        if(this.isSubMenu){
-            cfg = {
-                tag : 'ul',
-                cls : 'dropdown-menu'
-            }
+        this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+        if(this.isDocument){
+            this.setThumbBoxSize();
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
         }
-       
-        return cfg;
+        
+        this.draw();
+        
+        this.fireEvent('rotate', this, 'right');
     },
     
-    onRender : function(ct, position)
+    onRotateFail : function()
     {
-        this.isSubMenu = ct.hasClass('dropdown-submenu');
+        this.errorEl.show(true);
         
-        Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
+        var _this = this;
+        
+        (function() { _this.errorEl.hide(true); }).defer(this.errorTimeout);
     },
     
-    initEvents : function() 
+    draw : function()
     {
-        if(this.isSubMenu){
-            return;
+        this.previewEl.dom.innerHTML = '';
+        
+        var canvasEl = document.createElement("canvas");
+        
+        var contextEl = canvasEl.getContext("2d");
+        
+        canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+        canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        var center = this.imageEl.OriginWidth / 2;
+        
+        if(this.imageEl.OriginWidth < this.imageEl.OriginHeight){
+            canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+            canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+            center = this.imageEl.OriginHeight / 2;
         }
         
-        this.hidden = true;
+        contextEl.scale(this.getScaleLevel(), this.getScaleLevel());
         
-        this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
-        this.triggerEl.on('click', this.onTriggerPress, this);
+        contextEl.translate(center, center);
+        contextEl.rotate(this.rotate * Math.PI / 180);
+
+        contextEl.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
         
-        this.buttonEl = this.el.select('button.dropdown-button', true).first();
-        this.buttonEl.on('click', this.onClick, this);
+        this.canvasEl = document.createElement("canvas");
         
-    },
-    
-    list : function()
-    {
-        if(this.isSubMenu){
-            return this.el;
+        this.contextEl = this.canvasEl.getContext("2d");
+        
+        switch (this.rotate) {
+            case 0 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 90 : 
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 180 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 270 :
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            default : 
+                break;
         }
         
-        return this.el.select('ul.dropdown-menu', true).first();
+        this.previewEl.appendChild(this.canvasEl);
+        
+        this.setCanvasPosition();
     },
     
-    onClick : function(e)
+    crop : function()
     {
-        this.fireEvent("click", this, e);
-    },
-    
-    onTriggerPress  : function(e)
-    {   
-        if (this.isVisible()) {
-            this.hide();
-        } else {
-            this.show();
+        if(!this.canvasLoaded){
+            return;
         }
-    },
-    
-    isVisible : function(){
-        return !this.hidden;
-    },
-    
-    show : function()
-    {
-        this.fireEvent("beforeshow", this);
         
-        this.hidden = false;
-        this.el.addClass('open');
+        var imageCanvas = document.createElement("canvas");
         
-        Roo.get(document).on("mouseup", this.onMouseUp, this);
+        var imageContext = imageCanvas.getContext("2d");
         
-        this.fireEvent("show", this);
+        imageCanvas.width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
+        imageCanvas.height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
         
+        var center = imageCanvas.width / 2;
         
-    },
-    
-    hide : function()
-    {
-        this.fireEvent("beforehide", this);
+        imageContext.translate(center, center);
         
-        this.hidden = true;
-        this.el.removeClass('open');
+        imageContext.rotate(this.rotate * Math.PI / 180);
         
-        Roo.get(document).un("mouseup", this.onMouseUp);
+        imageContext.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
         
-        this.fireEvent("hide", this);
-    },
-    
-    onMouseUp : function()
-    {
-        this.hide();
-    }
-    
-});
+        var canvas = document.createElement("canvas");
+        
+        var context = canvas.getContext("2d");
+                
+        canvas.width = this.minWidth;
+        canvas.height = this.minHeight;
 
- /*
- * - LGPL
- *
- * menu item
- * 
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+        switch (this.rotate) {
+            case 0 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
 
-/**
- * @class Roo.bootstrap.menu.Item
- * @extends Roo.bootstrap.Component
- * Bootstrap MenuItem class
- * @cfg {Boolean} submenu (true | false) default false
- * @cfg {String} html text of the item
- * @cfg {String} href the link
- * @cfg {Boolean} disable (true | false) default false
- * @cfg {Boolean} preventDefault (true | false) default true
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Submenu align to (left | right) default right 
- * 
- * 
- * @constructor
- * Create a new Item
- * @param {Object} config The config object
- */
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 90 : 
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
+
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+                
+                sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 180 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
 
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
 
-Roo.bootstrap.menu.Item = function(config){
-    Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
-    this.addEvents({
-        /**
-         * @event mouseover
-         * Fires when the mouse is hovering over this menu
-         * @param {Roo.bootstrap.menu.Item} this
-         * @param {Roo.EventObject} e
-         */
-        mouseover : true,
-        /**
-         * @event mouseout
-         * Fires when the mouse exits this menu
-         * @param {Roo.bootstrap.menu.Item} this
-         * @param {Roo.EventObject} e
-         */
-        mouseout : true,
-        // raw events
-        /**
-         * @event click
-         * The raw click event for the entire grid.
-         * @param {Roo.EventObject} e
-         */
-        click : true
-    });
-};
+                sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+                sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            case 270 :
+                
+                var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+                var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+                
+                var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+                var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+                
+                var targetWidth = this.minWidth - 2 * x;
+                var targetHeight = this.minHeight - 2 * y;
+                
+                var scale = 1;
+                
+                if((x == 0 && y == 0) || (x == 0 && y > 0)){
+                    scale = targetWidth / width;
+                }
+                
+                if(x > 0 && y == 0){
+                    scale = targetHeight / height;
+                }
+                
+                if(x > 0 && y > 0){
+                    scale = targetWidth / width;
+                    
+                    if(width < height){
+                        scale = targetHeight / height;
+                    }
+                }
+                
+                context.scale(scale, scale);
+                
+                var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+                var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
 
-Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component,  {
-    
-    submenu : false,
-    href : '',
-    html : '',
-    preventDefault: true,
-    disable : false,
-    icon : false,
-    pos : 'right',
+                sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+                sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+                
+                sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+                
+                context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+                
+                break;
+            default : 
+                break;
+        }
+        
+        this.cropData = canvas.toDataURL(this.cropType);
+        
+        this.fireEvent('crop', this, this.cropData);
+        
+    },
     
-    getAutoCreate : function()
+    setThumbBoxSize : function()
     {
-        var text = [
-            {
-                tag : 'span',
-                cls : 'roo-menu-item-text',
-                html : this.html
-            }
-        ];
+        var width, height;
         
-        if(this.icon){
-            text.unshift({
-                tag : 'i',
-                cls : 'fa ' + this.icon
-            })
+        if(this.isDocument && typeof(this.imageEl) != 'undefined'){
+            width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.max(this.minWidth, this.minHeight) : Math.min(this.minWidth, this.minHeight);
+            height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.min(this.minWidth, this.minHeight) : Math.max(this.minWidth, this.minHeight);
+            
+            this.minWidth = width;
+            this.minHeight = height;
+            
+            if(this.rotate == 90 || this.rotate == 270){
+                this.minWidth = height;
+                this.minHeight = width;
+            }
         }
         
-        var cfg = {
-            tag : 'li',
-            cn : [
-                {
-                    tag : 'a',
-                    href : this.href || '#',
-                    cn : text
-                }
-            ]
-        };
+        height = 300;
+        width = Math.ceil(this.minWidth * height / this.minHeight);
         
-        if(this.disable){
-            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
+        if(this.minWidth > this.minHeight){
+            width = 300;
+            height = Math.ceil(this.minHeight * width / this.minWidth);
         }
         
-        if(this.submenu){
-            cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
+        this.thumbEl.setStyle({
+            width : width + 'px',
+            height : height + 'px'
+        });
+
+        return;
             
-            if(this.pos == 'left'){
-                cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
-            }
-        }
-        
-        return cfg;
     },
     
-    initEvents : function() 
+    setThumbBoxPosition : function()
     {
-        this.el.on('mouseover', this.onMouseOver, this);
-        this.el.on('mouseout', this.onMouseOut, this);
+        var x = Math.ceil((this.bodyEl.getWidth() - this.thumbEl.getWidth()) / 2 );
+        var y = Math.ceil((this.bodyEl.getHeight() - this.thumbEl.getHeight()) / 2);
         
-        this.el.select('a', true).first().on('click', this.onClick, this);
+        this.thumbEl.setLeft(x);
+        this.thumbEl.setTop(y);
         
     },
     
-    onClick : function(e)
+    baseRotateLevel : function()
     {
-        if(this.preventDefault){
-            e.preventDefault();
-        }
+        this.baseRotate = 1;
         
-        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);
+        if(
+                typeof(this.exif) != 'undefined' &&
+                typeof(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != 'undefined' &&
+                [1, 3, 6, 8].indexOf(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != -1
+        ){
+            this.baseRotate = this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']];
         }
         
-        this.fireEvent("mouseover", this, e);
+        this.rotate = Roo.bootstrap.UploadCropbox['Orientation'][this.baseRotate];
+        
     },
     
-    onMouseOut : function(e)
+    baseScaleLevel : function()
     {
-        this.fireEvent("mouseout", this, e);
-    }
-});
-
-
- /*
- * - LGPL
- *
- * menu separator
- * 
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Separator
- * @extends Roo.bootstrap.Component
- * Bootstrap Separator class
- * 
- * @constructor
- * Create a new Separator
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Separator = function(config){
-    Roo.bootstrap.menu.Separator.superclass.constructor.call(this, config);
-};
-
-Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component,  {
-    
-    getAutoCreate : function(){
-        var cfg = {
-            tag : 'li',
-            cls: 'divider'
-        };
+        var width, height;
         
-        return cfg;
-    }
-   
-});
+        if(this.isDocument){
+            
+            if(this.baseRotate == 6 || this.baseRotate == 8){
+            
+                height = this.thumbEl.getHeight();
+                this.baseScale = height / this.imageEl.OriginWidth;
 
+                if(this.imageEl.OriginHeight * this.baseScale > this.thumbEl.getWidth()){
+                    width = this.thumbEl.getWidth();
+                    this.baseScale = width / this.imageEl.OriginHeight;
+                }
 
- /*
- * - LGPL
- *
- * Tooltip
- * 
- */
+                return;
+            }
 
-/**
- * @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
- */
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
 
-Roo.bootstrap.Tooltip = function(config){
-    Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
-};
+            if(this.imageEl.OriginWidth * this.baseScale > this.thumbEl.getWidth()){
+                width = this.thumbEl.getWidth();
+                this.baseScale = width / this.imageEl.OriginWidth;
+            }
 
-Roo.apply(Roo.bootstrap.Tooltip, {
-    /**
-     * @function init initialize tooltip monitoring.
-     * @static
-     */
-    currentEl : false,
-    currentTip : false,
-    currentRegion : false,
-    
-    //  init : delay?
+            return;
+        }
+        
+        if(this.baseRotate == 6 || this.baseRotate == 8){
+            
+            width = this.thumbEl.getHeight();
+            this.baseScale = width / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getWidth()){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+            }
+            
+            if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+                
+                if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getHeight()){
+                    width = this.thumbEl.getHeight();
+                    this.baseScale = width / this.imageEl.OriginWidth;
+                }
+            }
+            
+            return;
+        }
+        
+        width = this.thumbEl.getWidth();
+        this.baseScale = width / this.imageEl.OriginWidth;
+        
+        if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getHeight()){
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+        }
+        
+        if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+            
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getWidth()){
+                width = this.thumbEl.getWidth();
+                this.baseScale = width / this.imageEl.OriginWidth;
+            }
+            
+        }
+        
+        return;
+    },
     
-    init : function()
+    getScaleLevel : function()
     {
-        Roo.get(document).on('mouseover', this.enter ,this);
-        Roo.get(document).on('mouseout', this.leave, this);
-         
-        
-        this.currentTip = new Roo.bootstrap.Tooltip();
+        return this.baseScale * Math.pow(1.1, this.scale);
     },
     
-    enter : function(ev)
+    onTouchStart : function(e)
     {
-        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.canvasLoaded){
+            this.beforeSelectFile(e);
+            return;
         }
         
+        var touches = e.browserEvent.touches;
         
+        if(!touches){
+            return;
+        }
         
-        if (this.currentTip.el) {
-            this.currentTip.el.hide(); // force hiding...
-        }    
-        //Roo.log(ev);
-        var bindEl = el;
+        if(touches.length == 1){
+            this.onMouseDown(e);
+            return;
+        }
         
-        // 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(touches.length != 2){
+            return;
+        }
+        
+        var coords = [];
+        
+        for(var i = 0, finger; finger = touches[i]; i++){
+            coords.push(finger.pageX, finger.pageY);
         }
-        this.currentEl = bindEl;
-        this.currentTip.bind(bindEl);
-        this.currentRegion = Roo.lib.Region.getRegion(dom);
-        this.currentTip.enter();
+        
+        var x = Math.pow(coords[0] - coords[2], 2);
+        var y = Math.pow(coords[1] - coords[3], 2);
+        
+        this.startDistance = Math.sqrt(x + y);
+        
+        this.startScale = this.scale;
+        
+        this.pinching = true;
+        this.dragable = false;
         
     },
-    leave : function(ev)
+    
+    onTouchMove : function(e)
     {
-        var dom = ev.getTarget();
-        //Roo.log(['leave',dom]);
-        if (!this.currentEl) {
+        if(!this.pinching && !this.dragable){
             return;
         }
         
+        var touches = e.browserEvent.touches;
         
-        if (dom != this.currentEl.dom) {
+        if(!touches){
             return;
         }
-        var xy = ev.getXY();
-        if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0]  ))) {
+        
+        if(this.dragable){
+            this.onMouseMove(e);
             return;
         }
-        // only activate leave if mouse cursor is outside... bounding box..
         
+        var coords = [];
         
+        for(var i = 0, finger; finger = touches[i]; i++){
+            coords.push(finger.pageX, finger.pageY);
+        }
         
+        var x = Math.pow(coords[0] - coords[2], 2);
+        var y = Math.pow(coords[1] - coords[3], 2);
         
-        if (this.currentTip) {
-            this.currentTip.leave();
+        this.endDistance = Math.sqrt(x + y);
+        
+        this.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1));
+        
+        if(!this.zoomable()){
+            this.scale = this.startScale;
+            return;
         }
-        //Roo.log('clear currentEl');
-        this.currentEl = false;
         
+        this.draw();
         
     },
-    alignment : {
-        'left' : ['r-l', [-2,0], 'right'],
-        'right' : ['l-r', [2,0], 'left'],
-        'bottom' : ['t-b', [0,2], 'top'],
-        'top' : [ 'b-t', [0,-2], 'bottom']
-    }
-    
-});
-
-
-Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component,  {
-    
-    
-    bindEl : false,
-    
-    delay : null, // can be { show : 300 , hide: 500}
-    
-    timeout : null,
     
-    hoverState : null, //???
-    
-    placement : 'bottom', 
-    
-    getAutoCreate : function(){
-    
-        var cfg = {
-           cls : 'tooltip',
-           role : 'tooltip',
-           cn : [
-                {
-                    cls : 'tooltip-arrow'
-                },
-                {
-                    cls : 'tooltip-inner'
-                }
-           ]
-        };
-        
-        return cfg;
-    },
-    bind : function(el)
+    onTouchEnd : function(e)
     {
-        this.bindEl = el;
+        this.pinching = false;
+        this.dragable = false;
+        
     },
-      
     
-    enter : function () {
-       
-        if (this.timeout != null) {
-            clearTimeout(this.timeout);
+    prepare : function(file)
+    {   
+        this.file = false;
+        this.exif = {};
+        
+        if(typeof(file) === 'string'){
+            this.loadCanvas(file);
+            return;
         }
         
-        this.hoverState = 'in';
-         //Roo.log("enter - show");
-        if (!this.delay || !this.delay.show) {
-            this.show();
+        if(!file || !this.urlAPI){
             return;
         }
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            if (_t.hoverState == 'in') {
-                _t.show();
+        
+        this.file = file;
+        this.cropType = file.type;
+        
+        var _this = this;
+        
+        if(this.fireEvent('prepare', this, this.file) != false){
+            
+            var reader = new FileReader();
+            
+            reader.onload = function (e) {
+                if (e.target.error) {
+                    Roo.log(e.target.error);
+                    return;
+                }
+                
+                var buffer = e.target.result,
+                    dataView = new DataView(buffer),
+                    offset = 2,
+                    maxOffset = dataView.byteLength - 4,
+                    markerBytes,
+                    markerLength;
+                
+                if (dataView.getUint16(0) === 0xffd8) {
+                    while (offset < maxOffset) {
+                        markerBytes = dataView.getUint16(offset);
+                        
+                        if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) || markerBytes === 0xfffe) {
+                            markerLength = dataView.getUint16(offset + 2) + 2;
+                            if (offset + markerLength > dataView.byteLength) {
+                                Roo.log('Invalid meta data: Invalid segment size.');
+                                break;
+                            }
+                            
+                            if(markerBytes == 0xffe1){
+                                _this.parseExifData(
+                                    dataView,
+                                    offset,
+                                    markerLength
+                                );
+                            }
+                            
+                            offset += markerLength;
+                            
+                            continue;
+                        }
+                        
+                        break;
+                    }
+                    
+                }
+                
+                var url = _this.urlAPI.createObjectURL(_this.file);
+                
+                _this.loadCanvas(url);
+                
+                return;
             }
-        }, this.delay.show);
+            
+            reader.readAsArrayBuffer(this.file);
+            
+        }
+        
     },
-    leave : function()
+    
+    parseExifData : function(dataView, offset, length)
     {
-        clearTimeout(this.timeout);
+        var tiffOffset = offset + 10,
+            littleEndian,
+            dirOffset;
     
-        this.hoverState = 'out';
-         if (!this.delay || !this.delay.hide) {
-            this.hide();
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
             return;
         }
-       
-        var _t = this;
-        this.timeout = setTimeout(function () {
-            //Roo.log("leave - timeout");
-            
-            if (_t.hoverState == 'out') {
-                _t.hide();
-                Roo.bootstrap.Tooltip.currentEl = false;
-            }
-        }, delay);
+        
+        // Check for the ASCII code for "Exif" (0x45786966):
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
+            return;
+        }
+        if (tiffOffset + 8 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid segment size.');
+            return;
+        }
+        // Check for the two null bytes:
+        if (dataView.getUint16(offset + 8) !== 0x0000) {
+            Roo.log('Invalid Exif data: Missing byte alignment offset.');
+            return;
+        }
+        // Check the byte alignment:
+        switch (dataView.getUint16(tiffOffset)) {
+        case 0x4949:
+            littleEndian = true;
+            break;
+        case 0x4D4D:
+            littleEndian = false;
+            break;
+        default:
+            Roo.log('Invalid Exif data: Invalid byte alignment marker.');
+            return;
+        }
+        // Check for the TIFF tag marker (0x002A):
+        if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
+            Roo.log('Invalid Exif data: Missing TIFF marker.');
+            return;
+        }
+        // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
+        dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
+        
+        this.parseExifTags(
+            dataView,
+            tiffOffset,
+            tiffOffset + dirOffset,
+            littleEndian
+        );
     },
     
-    show : function ()
+    parseExifTags : function(dataView, tiffOffset, dirOffset, littleEndian)
     {
-        if (!this.el) {
-            this.render(document.body);
+        var tagsNumber,
+            dirEndOffset,
+            i;
+        if (dirOffset + 6 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory offset.');
+            return;
         }
-        // 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';
+        tagsNumber = dataView.getUint16(dirOffset, littleEndian);
+        dirEndOffset = dirOffset + 2 + 12 * tagsNumber;
+        if (dirEndOffset + 4 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory size.');
+            return;
         }
-        
-        //this.el.detach()
-        //this.el.setXY([0,0]);
-        this.el.show();
-        //this.el.dom.style.display='block';
-        this.el.addClass(placement);
-        
-        //this.el.appendTo(on_el);
-        
-        var p = this.getPosition();
-        var box = this.el.getBox();
-        
-        if (autoPlace) {
-            // fixme..
+        for (i = 0; i < tagsNumber; i += 1) {
+            this.parseExifTag(
+                dataView,
+                tiffOffset,
+                dirOffset + 2 + 12 * i, // tag offset
+                littleEndian
+            );
         }
-        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], 
+        // Return the offset to the next directory:
+        return dataView.getUint32(dirEndOffset, littleEndian);
+    },
+    
+    parseExifTag : function (dataView, tiffOffset, offset, littleEndian) 
+    {
+        var tag = dataView.getUint16(offset, littleEndian);
         
-        this.el.addClass('in fade');
-        this.hoverState = null;
+        this.exif[tag] = this.getExifValue(
+            dataView,
+            tiffOffset,
+            offset,
+            dataView.getUint16(offset + 2, littleEndian), // tag type
+            dataView.getUint32(offset + 4, littleEndian), // tag length
+            littleEndian
+        );
+    },
+    
+    getExifValue : function (dataView, tiffOffset, offset, type, length, littleEndian)
+    {
+        var tagType = Roo.bootstrap.UploadCropbox.exifTagTypes[type],
+            tagSize,
+            dataOffset,
+            values,
+            i,
+            str,
+            c;
+    
+        if (!tagType) {
+            Roo.log('Invalid Exif data: Invalid tag type.');
+            return;
+        }
         
-        if (this.el.hasClass('fade')) {
-            // fade it?
+        tagSize = tagType.size * length;
+        // Determine if the value is contained in the dataOffset bytes,
+        // or if the value at the dataOffset is a pointer to the actual data:
+        dataOffset = tagSize > 4 ?
+                tiffOffset + dataView.getUint32(offset + 8, littleEndian) : (offset + 8);
+        if (dataOffset + tagSize > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid data offset.');
+            return;
+        }
+        if (length === 1) {
+            return tagType.getValue(dataView, dataOffset, littleEndian);
+        }
+        values = [];
+        for (i = 0; i < length; i += 1) {
+            values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian);
         }
         
+        if (tagType.ascii) {
+            str = '';
+            // Concatenate the chars:
+            for (i = 0; i < values.length; i += 1) {
+                c = values[i];
+                // Ignore the terminating NULL byte(s):
+                if (c === '\u0000') {
+                    break;
+                }
+                str += c;
+            }
+            return str;
+        }
+        return values;
+    }
+    
+});
+
+Roo.apply(Roo.bootstrap.UploadCropbox, {
+    tags : {
+        'Orientation': 0x0112
     },
-    hide : function()
-    {
-         
-        if (!this.el) {
-            return;
+    
+    Orientation: {
+            1: 0, //'top-left',
+//            2: 'top-right',
+            3: 180, //'bottom-right',
+//            4: 'bottom-left',
+//            5: 'left-top',
+            6: 90, //'right-top',
+//            7: 'right-bottom',
+            8: 270 //'left-bottom'
+    },
+    
+    exifTagTypes : {
+        // byte, 8-bit unsigned int:
+        1: {
+            getValue: function (dataView, dataOffset) {
+                return dataView.getUint8(dataOffset);
+            },
+            size: 1
+        },
+        // ascii, 8-bit byte:
+        2: {
+            getValue: function (dataView, dataOffset) {
+                return String.fromCharCode(dataView.getUint8(dataOffset));
+            },
+            size: 1,
+            ascii: true
+        },
+        // short, 16 bit int:
+        3: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint16(dataOffset, littleEndian);
+            },
+            size: 2
+        },
+        // long, 32 bit int:
+        4: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // rational = two long values, first is numerator, second is denominator:
+        5: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian) /
+                    dataView.getUint32(dataOffset + 4, littleEndian);
+            },
+            size: 8
+        },
+        // slong, 32 bit signed int:
+        9: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // srational, two slongs, first is numerator, second is denominator:
+        10: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian) /
+                    dataView.getInt32(dataOffset + 4, littleEndian);
+            },
+            size: 8
         }
-        //this.el.setXY([0,0]);
-        this.el.removeClass('in');
-        //this.el.hide();
-        
-    }
+    },
     
+    footer : {
+        STANDARD : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-picture',
+                action : 'picture',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-picture-o"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        DOCUMENT : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-download',
+                action : 'download',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-download"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-crop',
+                action : 'crop',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-crop"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-trash',
+                action : 'trash',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-trash"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        ROTATOR : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ]
+    }
 });
 
- /*
- * - LGPL
- *
- * Location Picker
- * 
- */
+/*
+* Licence: LGPL
+*/
 
 /**
- * @class Roo.bootstrap.LocationPicker
+ * @class Roo.bootstrap.DocumentManager
  * @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 DocumentManager class
+ * @cfg {String} paramName default 'imageUpload'
+ * @cfg {String} method default POST
+ * @cfg {String} url action url
+ * @cfg {Number} boxes number of boxes default 12
+ * @cfg {Boolean} multiple multiple upload default true
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
+ * @cfg {Number} thumbSize default 300
+ * @cfg {String} fieldLabel
+ * @cfg {Number} labelWidth default 4
+ * @cfg {String} labelAlign (left|top) default left
+ * @cfg {Boolean} editable (true|false) allow edit when upload a image default true
  * 
  * @constructor
- * Create a new LocationPicker
+ * Create a new DocumentManager
  * @param {Object} config The config object
  */
 
-
-Roo.bootstrap.LocationPicker = function(config){
-    
-    Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
+Roo.bootstrap.DocumentManager = function(config){
+    Roo.bootstrap.DocumentManager.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
+         * Fire when initial the DocumentManager
+         * @param {Roo.bootstrap.DocumentManager} this
          */
-        mapClick : true,
-        /**
-         * @event mapRightClick
-         * Fires when right click the map.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Map event} e
-         */
-        mapRightClick : true,
+        "initial" : true,
         /**
-         * @event markerClick
-         * Fires when click the marker.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Map event} e
+         * @event inspect
+         * inspect selected file
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {File} file
          */
-        markerClick : true,
+        "inspect" : true,
         /**
-         * @event markerRightClick
-         * Fires when right click the marker.
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Map event} e
+         * @event exception
+         * Fire when xhr load exception
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {XMLHttpRequest} xhr
          */
-        markerRightClick : true,
+        "exception" : true,
         /**
-         * @event OverlayViewDraw
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
+         * @event prepare
+         * prepare the form data
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} formData
          */
-        OverlayViewDraw : true,
+        "prepare" : true,
         /**
-         * @event OverlayViewOnAdd
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
+         * @event remove
+         * Fire when remove the file
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
          */
-        OverlayViewOnAdd : true,
+        "remove" : true,
         /**
-         * @event OverlayViewOnRemove
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
+         * @event refresh
+         * Fire after refresh the file
+         * @param {Roo.bootstrap.DocumentManager} this
          */
-        OverlayViewOnRemove : true,
+        "refresh" : true,
         /**
-         * @event OverlayViewShow
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
-         * @param {Pixel} cpx
+         * @event click
+         * Fire after click the image
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
          */
-        OverlayViewShow : true,
+        "click" : true,
         /**
-         * @event OverlayViewHide
-         * Fires when OverlayView Draw
-         * @param {Roo.bootstrap.LocationPicker} this
+         * @event edit
+         * Fire when upload a image and editable set to true
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
          */
-        OverlayViewHide : true
-    });
+        "edit" : true
         
+    });
 };
 
-Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component,  {
-    
-    gMapContext: false,
+Roo.extend(Roo.bootstrap.DocumentManager, 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: '',
+    boxes : 12,
+    inputName : '',
+    minWidth : 300,
+    minHeight : 300,
+    thumbSize : 300,
+    multiple : true,
+    files : [],
+    method : 'POST',
+    url : '',
+    paramName : 'imageUpload',
+    fieldLabel : '',
+    labelWidth : 4,
+    labelAlign : 'left',
+    editable : true,
+    delegates : [],
     
-    getAutoCreate: function()
-    {
+    getAutoCreate : function()
+    {   
+        var managerWidget = {
+            tag : 'div',
+            cls : 'roo-document-manager',
+            cn : [
+                {
+                    tag : 'input',
+                    cls : 'roo-document-manager-selector',
+                    type : 'file'
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-document-manager-uploader',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-document-manager-upload-btn',
+                            html : '<i class="fa fa-plus"></i>'
+                        }
+                    ]
+                    
+                }
+            ]
+        };
+        
+        var content = [
+            {
+                tag : 'div',
+                cls : 'column col-md-12',
+                cn : managerWidget
+            }
+        ];
+        
+        if(this.fieldLabel.length){
+            
+            content = [
+                {
+                    tag : 'div',
+                    cls : 'column col-md-12',
+                    html : this.fieldLabel
+                },
+                {
+                    tag : 'div',
+                    cls : 'column col-md-12',
+                    cn : managerWidget
+                }
+            ];
 
+            if(this.labelAlign == 'left'){
+                content = [
+                    {
+                        tag : 'div',
+                        cls : 'column col-md-' + this.labelWidth,
+                        html : this.fieldLabel
+                    },
+                    {
+                        tag : 'div',
+                        cls : 'column col-md-' + (12 - this.labelWidth),
+                        cn : managerWidget
+                    }
+                ];
+                
+            }
+        }
+        
         var cfg = {
-            tag: 'div',
-            cls: 'roo-location-picker'
+            tag : 'div',
+            cls : 'row clearfix',
+            cn : content
         };
         
-        return cfg
-    },
-    
-    initEvents: function(ct, position)
-    {       
-        if(!this.el.getWidth() || this.isApplied()){
-            return;
-        }
-        
-        this.el.setVisibilityMode(Roo.Element.DISPLAY);
+        return cfg;
         
-        this.initial();
     },
     
-    initial: function()
+    initEvents : function()
     {
-        if(!this.mapTypeId){
-            this.mapTypeId = google.maps.MapTypeId.ROADMAP;
+        this.managerEl = this.el.select('.roo-document-manager', true).first();
+        this.managerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.selectorEl = this.el.select('.roo-document-manager-selector', true).first();
+        this.selectorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.selectorEl.hide();
+        
+        if(this.multiple){
+            this.selectorEl.attr('multiple', 'multiple');
         }
         
-        this.gMapContext = this.GMapContext();
+        this.selectorEl.on('change', this.onFileSelected, this);
         
-        this.initOverlayView();
+        this.uploader = this.el.select('.roo-document-manager-uploader', true).first();
+        this.uploader.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
+        this.uploader.on('click', this.onUploaderClick, this);
+        
+        this.renderProgressDialog();
         
         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);
-            
+        window.addEventListener("resize", function() { _this.refresh(); } );
+        
+        this.fireEvent('initial', this);
+    },
+    
+    renderProgressDialog : function()
+    {
+        var _this = this;
+        
+        this.progressDialog = new Roo.bootstrap.Modal({
+            cls : 'roo-document-manager-progress-dialog',
+            allow_close : false,
+            title : '',
+            buttons : [
+                {
+                    name  :'cancel',
+                    weight : 'danger',
+                    html : 'Cancel'
+                }
+            ], 
+            listeners : { 
+                btnclick : function() {
+                    _this.uploadCancel();
+                    this.hide();
+                }
+            }
         });
-
-        google.maps.event.addListener(this.gMapContext.map, 'rightclick', function(event){
-            _this.fireEvent('mapRightClick', this, event);
-            
+         
+        this.progressDialog.render(Roo.get(document.body));
+         
+        this.progress = new Roo.bootstrap.Progress({
+            cls : 'roo-document-manager-progress',
+            active : true,
+            striped : true
         });
         
-        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.progress.render(this.progressDialog.getChildContainer());
+        
+        this.progressBar = new Roo.bootstrap.ProgressBar({
+            cls : 'roo-document-manager-progress-bar',
+            aria_valuenow : 0,
+            aria_valuemin : 0,
+            aria_valuemax : 12,
+            panel : 'success'
         });
         
-        this.setPosition(this.gMapContext.location);
+        this.progressBar.render(this.progress.getChildContainer());
+    },
+    
+    onUploaderClick : function(e)
+    {
+        e.preventDefault();
+        this.selectorEl.dom.click();
+    },
+    
+    onFileSelected : function(e)
+    {
+        e.preventDefault();
+        
+        if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
+            return;
+        }
+        
+        Roo.each(this.selectorEl.dom.files, function(file){
+            if(this.fireEvent('inspect', this, file) != false){
+                this.files.push(file);
+            }
+        }, this);
+        
+        this.queue();
         
-        this.fireEvent('initial', this, this.gMapContext.location);
     },
     
-    initOverlayView: function()
+    queue : function()
     {
+        this.selectorEl.dom.value = '';
+        
+        if(!this.files.length){
+            return;
+        }
+        
+        if(this.files.length > this.boxes){
+            this.files = this.files.slice(0, this.boxes);
+        }
+        
+        this.uploader.show();
+        
+        if(this.files.length > this.boxes - 1){
+            this.uploader.hide();
+        }
+        
         var _this = this;
         
-        Roo.bootstrap.LocationPicker.OverlayView.prototype = Roo.apply(new google.maps.OverlayView(), {
-            
-            draw: function()
-            {
-                _this.fireEvent('OverlayViewDraw', _this);
-            },
-            
-            onAdd: function()
-            {
-                _this.fireEvent('OverlayViewOnAdd', _this);
-            },
-            
-            onRemove: function()
-            {
-                _this.fireEvent('OverlayViewOnRemove', _this);
-            },
-            
-            show: function(cpx)
-            {
-                _this.fireEvent('OverlayViewShow', _this, cpx);
-            },
+        var files = [];
+        
+        Roo.each(this.files, function(file){
             
-            hide: function()
-            {
-                _this.fireEvent('OverlayViewHide', _this);
+            if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+                var f = this.renderPreview(file);
+                files.push(f);
+                return;
             }
             
-        });
+            this.delegates.push(
+                (function(){
+                    _this.process(file);
+                }).createDelegate(this)
+            );
+            
+        }, this);
+        
+        this.files = files;
+        
+        if(!this.delegates.length){
+            this.refresh();
+            return;
+        }
+        
+        this.progressBar.aria_valuemax = this.delegates.length;
+        
+        this.arrange();
+        
+        return;
     },
     
-    fromLatLngToContainerPixel: function(event)
+    arrange : function()
     {
-        return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
+        if(!this.delegates.length){
+            this.progressDialog.hide();
+            this.refresh();
+            return;
+        }
+        
+        var delegate = this.delegates.shift();
+        
+        this.progressDialog.show();
+        
+        this.progressDialog.setTitle((this.progressBar.aria_valuemax - this.delegates.length) + ' / ' + this.progressBar.aria_valuemax);
+        
+        this.progressBar.update(this.progressBar.aria_valuemax - this.delegates.length);
+        
+        delegate();
     },
     
-    isApplied: function() 
+    refresh : function()
     {
-        return this.getGmapContext() == false ? false : true;
+        this.uploader.show();
+        
+        if(this.files.length > this.boxes - 1){
+            this.uploader.hide();
+        }
+        
+        Roo.isTouch ? this.closable(false) : this.closable(true);
+        
+        this.fireEvent('refresh', this);
     },
     
-    getGmapContext: function() 
+    onRemove : function(e, el, o)
     {
-        return this.gMapContext
+        e.preventDefault();
+        
+        this.fireEvent('remove', this, o);
+        
     },
     
-    GMapContext: function() 
+    remove : function(o)
     {
-        var position = new google.maps.LatLng(this.latitude, this.longitude);
+        var files = [];
         
-        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
-        });
+        Roo.each(this.files, function(file){
+            if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
+                files.push(file);
+                return;
+            }
+
+            o.target.remove();
+
+        }, this);
         
-        var _marker = new google.maps.Marker({
-            position: position,
-            map: _map,
-            title: this.markerTitle,
-            draggable: this.draggable
-        });
+        this.files = files;
         
-        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()
-        };
+        this.refresh();
     },
     
-    drawCircle: function(center, radius, options) 
+    onClick : function(e, el, o)
     {
-        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;
-        }
+        e.preventDefault();
+        
+        this.fireEvent('click', this, o);
         
-        return null;
     },
     
-    setPosition: function(location) 
+    closable : function(closable)
     {
-        this.gMapContext.location = location;
-        this.gMapContext.marker.setPosition(location);
-        this.gMapContext.map.panTo(location);
-        this.drawCircle(location, this.gMapContext.radius, {});
+        Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
+            
+            el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+            
+            if(closable){
+                el.show();
+                return;
+            }
+            
+            el.hide();
+            
+        }, this);
+    },
+    
+    xhrOnLoad : function(xhr)
+    {
+        Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
+            el.remove();
+        }, this);
         
-        var _this = this;
+        if (xhr.readyState !== 4) {
+            this.arrange();
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
+
+        var response = Roo.decode(xhr.responseText);
         
-        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);
-                }
-            });
-            
+        if(!response.success){
+            this.arrange();
+            this.fireEvent('exception', this, xhr);
             return;
         }
         
-        this.fireEvent('positionchanged', this, location);
+        var file = this.renderPreview(response.data);
+        
+        this.files.push(file);
+        
+        this.arrange();
+        
     },
     
-    resize: function()
+    xhrOnError : function()
     {
-        google.maps.event.trigger(this.gMapContext.map, "resize");
+        Roo.log('xhr on error');
         
-        this.gMapContext.map.setCenter(this.gMapContext.marker.position);
+        var response = Roo.decode(xhr.responseText);
+          
+        Roo.log(response);
         
-        this.fireEvent('resize', this);
+        this.arrange();
     },
     
-    setPositionByLatLng: function(latitude, longitude)
+    process : function(file)
     {
-        this.setPosition(new google.maps.LatLng(latitude, longitude));
+        if(this.editable && file.type.indexOf('image') != -1){
+            this.fireEvent('edit', this, file);
+            return;
+        }
+        
+        this.uploadStart(file, false);
+        
+        return;
     },
     
-    getCurrentPosition: function() 
+    uploadStart : function(file, crop)
     {
-        return {
-            latitude: this.gMapContext.location.lat(),
-            longitude: this.gMapContext.location.lng()
+        this.xhr = new XMLHttpRequest();
+        
+        if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+            this.arrange();
+            return;
+        }
+        
+        file.xhr = this.xhr;
+            
+        this.managerEl.createChild({
+            tag : 'div',
+            cls : 'roo-document-manager-loading',
+            cn : [
+                {
+                    tag : 'div',
+                    tooltip : file.name,
+                    cls : 'roo-document-manager-thumb',
+                    html : '<i class="fa fa-circle-o-notch fa-spin"></i>'
+                }
+            ]
+
+        });
+
+        this.xhr.open(this.method, this.url, true);
+        
+        var headers = {
+            "Accept": "application/json",
+            "Cache-Control": "no-cache",
+            "X-Requested-With": "XMLHttpRequest"
         };
-    },
-    
-    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;
+        for (var headerName in headers) {
+            var headerValue = headers[headerName];
+            if (headerValue) {
+                this.xhr.setRequestHeader(headerName, headerValue);
             }
         }
         
-        result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
-        result.addressLine2 = "";
-        return result;
+        var _this = this;
+        
+        this.xhr.onload = function()
+        {
+            _this.xhrOnLoad(_this.xhr);
+        }
+        
+        this.xhr.onerror = function()
+        {
+            _this.xhrOnError(_this.xhr);
+        }
+        
+        var formData = new FormData();
+
+        formData.append('returnHTML', 'NO');
+        
+        if(crop){
+            formData.append('crop', crop);
+        }
+        
+        formData.append(this.paramName, file, file.name);
+        
+        if(this.fireEvent('prepare', this, formData) != false){
+            this.xhr.send(formData);
+        };
     },
     
-    setZoomLevel: function(zoom)
+    uploadCancel : function()
     {
-        this.gMapContext.map.setZoom(zoom);
+        this.xhr.abort();
+        
+        this.delegates = [];
+        
+        Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
+            el.remove();
+        }, this);
+        
+        this.arrange();
     },
     
-    show: function()
+    renderPreview : function(file)
     {
-        if(!this.el){
-            return;
+        if(typeof(file.target) != 'undefined' && file.target){
+            return file;
         }
         
-        this.el.show();
+        var previewEl = this.managerEl.createChild({
+            tag : 'div',
+            cls : 'roo-document-manager-preview',
+            cn : [
+                {
+                    tag : 'div',
+                    tooltip : file.filename,
+                    cls : 'roo-document-manager-thumb',
+                    html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + file.id + '/' + file.filename + '">'
+                },
+                {
+                    tag : 'button',
+                    cls : 'close',
+                    html : '<i class="fa fa-times-circle"></i>'
+                }
+            ]
+        });
+
+        var close = previewEl.select('button.close', true).first();
+
+        close.on('click', this.onRemove, this, file);
+
+        file.target = previewEl;
+
+        var image = previewEl.select('img', true).first();
         
-        this.resize();
+        var _this = this;
+        
+        image.dom.addEventListener("load", function(){ _this.onPreviewLoad(file, image); });
+        
+        image.on('click', this.onClick, this, file);
+        
+        return file;
         
-        this.fireEvent('show', this);
     },
     
-    hide: function()
+    onPreviewLoad : function(file, image)
     {
-        if(!this.el){
+        if(typeof(file.target) == 'undefined' || !file.target){
             return;
         }
         
-        this.el.hide();
+        var width = image.dom.naturalWidth || image.dom.width;
+        var height = image.dom.naturalHeight || image.dom.height;
+        
+        if(width > height){
+            file.target.addClass('wide');
+            return;
+        }
+        
+        file.target.addClass('tall');
+        return;
         
-        this.fireEvent('hide', this);
     }
-    
 });
 
-Roo.apply(Roo.bootstrap.LocationPicker, {
-    
-    OverlayView : function(map, options)
-    {
-        options = options || {};
-        
-        this.setMap(map);
-    }
-    
-    
-});/*
- * - LGPL
- *
- * Alert
- * 
- */
+/*
+* Licence: LGPL
+*/
 
 /**
- * @class Roo.bootstrap.Alert
+ * @class Roo.bootstrap.DocumentViewer
  * @extends Roo.bootstrap.Component
- * Bootstrap Alert class
- * @cfg {String} title The title of alert
- * @cfg {String} html The content of alert
- * @cfg {String} weight (  success | info | warning | danger )
- * @cfg {String} faicon font-awesomeicon
+ * Bootstrap DocumentViewer class
  * 
  * @constructor
- * Create a new alert
+ * Create a new DocumentViewer
  * @param {Object} config The config object
  */
 
-
-Roo.bootstrap.Alert = function(config){
-    Roo.bootstrap.Alert.superclass.constructor.call(this, config);
+Roo.bootstrap.DocumentViewer = function(config){
+    Roo.bootstrap.DocumentViewer.superclass.constructor.call(this, config);
     
+    this.addEvents({
+        /**
+         * @event initial
+         * Fire after initEvent
+         * @param {Roo.bootstrap.DocumentViewer} this
+         */
+        "initial" : true,
+        /**
+         * @event click
+         * Fire after click
+         * @param {Roo.bootstrap.DocumentViewer} this
+         */
+        "click" : true,
+        /**
+         * @event trash
+         * Fire after trash button
+         * @param {Roo.bootstrap.DocumentViewer} this
+         */
+        "trash" : true
+        
+    });
 };
 
-Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component,  {
-    
-    title: '',
-    html: '',
-    weight: false,
-    faicon: false,
+Roo.extend(Roo.bootstrap.DocumentViewer, Roo.bootstrap.Component,  {
     
     getAutoCreate : function()
     {
-        
         var cfg = {
             tag : 'div',
-            cls : 'alert',
+            cls : 'roo-document-viewer',
             cn : [
                 {
-                    tag : 'i',
-                    cls : 'roo-alert-icon'
-                    
-                },
-                {
-                    tag : 'b',
-                    cls : 'roo-alert-title',
-                    html : this.title
+                    tag : 'div',
+                    cls : 'roo-document-viewer-body',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-document-viewer-thumb',
+                            cn : [
+                                {
+                                    tag : 'img',
+                                    cls : 'roo-document-viewer-image'
+                                }
+                            ]
+                        }
+                    ]
                 },
                 {
-                    tag : 'span',
-                    cls : 'roo-alert-text',
-                    html : this.html
+                    tag : 'div',
+                    cls : 'roo-document-viewer-footer',
+                    cn : {
+                        tag : 'div',
+                        cls : 'btn-group btn-group-justified roo-document-viewer-btn-group',
+                        cn : [
+                            {
+                                tag : 'div',
+                                cls : 'btn-group',
+                                cn : [
+                                    {
+                                        tag : 'button',
+                                        cls : 'btn btn-default roo-document-viewer-trash',
+                                        html : '<i class="fa fa-trash"></i>'
+                                    }
+                                ]
+                            }
+                        ]
+                    }
                 }
             ]
         };
         
-        if(this.faicon){
-            cfg.cn[0].cls += ' fa ' + this.faicon;
-        }
-        
-        if(this.weight){
-            cfg.cls += ' alert-' + this.weight;
-        }
-        
         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;
-    },
-    
-    setWeight : function(weight)
+    initEvents : function()
     {
-        if(this.weight){
-            this.el.select('.alert',true).first().removeClass('alert-' + this.weight);
-        }
         
-        this.weight = weight;
+        this.bodyEl = this.el.select('.roo-document-viewer-body', true).first();
+        this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.thumbEl = this.el.select('.roo-document-viewer-thumb', true).first();
+        this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.imageEl = this.el.select('.roo-document-viewer-image', true).first();
+        this.imageEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.footerEl = this.el.select('.roo-document-viewer-footer', true).first();
+        this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.trashBtn = this.el.select('.roo-document-viewer-trash', true).first();
+        this.trashBtn.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.bodyEl.on('click', this.onClick, this);
+        
+        this.trashBtn.on('click', this.onTrash, this);
         
-        this.el.select('.alert',true).first().addClass('alert-' + this.weight);
     },
     
-    setIcon : function(icon)
+    initial : function()
     {
-        if(this.faicon){
-            this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
-        }
+//        this.thumbEl.setStyle('line-height', this.thumbEl.getHeight(true) + 'px');
         
-        this.faicon = icon
         
-        this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
+        this.fireEvent('initial', this);
+        
     },
     
-    hide: function() 
+    onClick : function(e)
     {
-        this.el.hide();   
+        e.preventDefault();
+        
+        this.fireEvent('click', this);
     },
     
-    show: function() 
-    {  
-        this.el.show();   
+    onTrash : function(e)
+    {
+        e.preventDefault();
+        
+        this.fireEvent('trash', this);
     }
     
 });
-
\ No newline at end of file