Roo/form/ComboBoxArray.js
[roojs1] / roojs-bootstrap-debug.js
index 26b5cec..d0ee463 100644 (file)
@@ -101,6 +101,7 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
          
         
         var cfg = Roo.apply({},  this.getAutoCreate());
+        
         cfg.id = this.id || Roo.id();
         
         // fill in the extra attributes 
@@ -923,7 +924,7 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
             if (settings[size] === false) {
                 return;
             }
-            Roo.log(settings[size]);
+            
             if (!settings[size]) { // 0 = hidden
                 cfg.cls += ' hidden-' + size;
                 return;
@@ -985,12 +986,13 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
  * @cfg {String} sticky (footer|wrap|push) block to use as footer or body- needs css-bootstrap/sticky-footer.css
  * @cfg {String} tag (header|aside|section) type of HTML tag.
  * @cfg {String} alert (success|info|warning|danger) type alert (changes background / border...)
- * @cfg {String} fa (ban|check|...) font awesome icon
+ * @cfg {String} fa font awesome icon
  * @cfg {String} icon (info-sign|check|...) glyphicon name
  * @cfg {Boolean} hidden (true|false) hide the element
  * @cfg {Boolean} expandable (true|false) default false
  * @cfg {Boolean} expanded (true|false) default true
  * @cfg {String} rheader contet on the right of header
+ * @cfg {Boolean} clickable (true|false) default false
 
  *     
  * @constructor
@@ -1016,7 +1018,14 @@ Roo.bootstrap.Container = function(config){
          * 
          * @param {Roo.bootstrap.Container} this
          */
-        "collapse" : true
+        "collapse" : true,
+        /**
+         * @event click
+         * When a element is chick
+         * @param {Roo.bootstrap.Container} this
+         * @param {Roo.EventObject} e
+         */
+        "click" : true
     });
 };
 
@@ -1035,6 +1044,7 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
     expandable : false,
     rheader : '',
     expanded : true,
+    clickable: false,
   
      
     getChildContainer : function() {
@@ -1181,17 +1191,17 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
     
     initEvents: function() 
     {
-        if(!this.expandable){
-            return;
-        }
-        
-        var headerEl = this.headerEl();
+        if(this.expandable){
+            var headerEl = this.headerEl();
         
-        if(!headerEl){
-            return;
+            if(headerEl){
+                headerEl.on('click', this.onToggleClick, this);
+            }
         }
         
-        headerEl.on('click', this.onToggleClick, this);
+        if(this.clickable){
+            this.el.on('click', this.onClick, this);
+        }
         
     },
     
@@ -1310,6 +1320,13 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
         }
         
         t.dom.innerHTML = v;
+    },
+    
+    onClick : function(e)
+    {
+        e.preventDefault();
+        
+        this.fireEvent('click', this, e);
     }
    
 });
@@ -1360,7 +1377,7 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
     
     imgResponsive: true,
     border: '',
-    src: '',
+    src: 'about:blank',
     href: false,
     target: false,
     xsUrl: '',
@@ -1438,7 +1455,8 @@ Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
         var cfg = {
             tag: 'img',
             cls: (this.imgResponsive) ? 'img-responsive' : '',
-            html : null
+            html : null,
+            src : 'about:blank'  // just incase src get's set to undefined?!?
         };
         
         cfg.html = this.html || cfg.html;
@@ -1966,9 +1984,6 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         
         this.triggerEl.addClass('dropdown-toggle');
         
-        
-        
-        
         if (Roo.isTouch) {
             this.el.on('touchstart'  , this.onTouch, this);
         }
@@ -1977,9 +1992,10 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         this.el.on("mouseover", this.onMouseOver, this);
         this.el.on("mouseout", this.onMouseOut, this);
         
-        
     },
-    findTargetItem : function(e){
+    
+    findTargetItem : function(e)
+    {
         var t = e.getTarget(".dropdown-menu-item", this.el,  true);
         if(!t){
             return false;
@@ -1995,12 +2011,14 @@ Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
         return false;
     },
     
-    onTouch : function(e) {
-        e.stopEvent();
+    onTouch : function(e) 
+    {
+        //e.stopEvent(); this make the user popdown broken
         this.onClick(e);
     },
     
-    onClick : function(e){
+    onClick : function(e)
+    {
         Roo.log("menu.onClick");
         var t = this.findTargetItem(e);
         if(!t || t.isContainer){
@@ -2419,8 +2437,6 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         //var type = this.el.dom.type;
         
         
-        
-        
         if(this.tabIndex !== undefined){
             this.el.dom.setAttribute('tabIndex', this.tabIndex);
         }
@@ -2581,11 +2597,14 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         
         this.el.setStyle('display', 'block');
         
-        if(this.animate){
+        if(this.animate){  // element has 'fade'  - so stuff happens after .3s ?- not sure why the delay?
             var _this = this;
-            (function(){ _this.el.addClass('in'); }).defer(50);
+            (function(){
+                this.el.addClass('in');
+            }).defer(50, this);
         }else{
             this.el.addClass('in');
+            
         }
         
         // not sure how we can show data in here.. 
@@ -2599,6 +2618,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         this.el.setStyle('zIndex', '10001');
        
         this.fireEvent('show', this);
+         
         
         
     },
@@ -2607,8 +2627,9 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         this.maskEl.hide();
         Roo.get(document.body).removeClass("x-body-masked");
         this.el.removeClass('in');
+        this.el.select('.modal-dialog', true).first().setStyle('transform','');
         
-        if(this.animate){
+        if(this.animate){ // why
             var _this = this;
             (function(){ _this.el.setStyle('display', 'none'); }).defer(150);
         }else{
@@ -2874,7 +2895,7 @@ Roo.bootstrap.MessageBox = function(){
                 buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
                 buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
                 buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
-                Roo.log(buttons)
+                //Roo.log(buttons);
                 bodyEl = dlg.bodyEl.createChild({
 
                     html:'<span class="roo-mb-text"></span><br /><input type="text" class="roo-mb-input" />' +
@@ -5269,7 +5290,7 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
     /**
      * Returns true if the cell is editable.
      * @param {Number} colIndex The column index
-     * @param {Number} rowIndex The row index
+     * @param {Number} rowIndex The row index - this is nto actually used..?
      * @return {Boolean}
      */
     isCellEditable : function(colIndex, rowIndex){
@@ -5995,11 +6016,11 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
                 }
                 
                 if (!config[size]) { // 0 = hidden
-                    cfg.cls += ' hidden-' + size;
+                    c.cls += ' hidden-' + size;
                     return;
                 }
                 
-                cfg.cls += ' col-' + size + '-' + config[size];
+                c.cls += ' col-' + size + '-' + config[size];
 
             });
             
@@ -6053,7 +6074,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
     
     onLoad : function()
     {
-        Roo.log('ds onload');
+//        Roo.log('ds onload');
         this.clear();
         
         var _this = this;
@@ -7555,7 +7576,7 @@ Roo.form.VTypes = function(){
     // closure these in so they are only created once.
     var alpha = /^[a-zA-Z_]+$/;
     var alphanum = /^[a-zA-Z0-9_]+$/;
-    var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
+    var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,24}$/;
     var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
 
     // All these messages and functions are configurable
@@ -7956,7 +7977,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             }
             if (this.before && typeof(this.before) == 'object') {
                 this.before = Roo.factory(this.before);
-                Roo.log(this.before);
+                
                 inputblock.cn.push({
                     tag :'span',
                     cls : 'roo-input-before input-group-' +
@@ -7975,7 +7996,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             }
             if (this.after && typeof(this.after) == 'object') {
                 this.after = Roo.factory(this.after);
-                Roo.log(this.after);
+                
                 inputblock.cn.push({
                     tag :'span',
                     cls : 'roo-input-after input-group-' +
@@ -7990,7 +8011,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         };
         
         if (align ==='left' && this.fieldLabel.length) {
-                Roo.log("left and has label");
+                
                 cfg.cn = [
                     
                     {
@@ -8009,7 +8030,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                     
                 ];
         } else if ( this.fieldLabel.length) {
-                Roo.log(" label");
+                
                  cfg.cn = [
                    
                     {
@@ -8025,7 +8046,6 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
 
         } else {
             
-                Roo.log(" no label && no align");
                 cfg.cn = [
                     
                         inputblock
@@ -8034,11 +8054,9 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
                 
                 
         };
-        Roo.log('input-parentType: ' + this.parentType);
         
         if (this.parentType === 'Navbar' &&  this.parent().bar) {
            cfg.cls += ' navbar-form';
-           Roo.log(cfg);
         }
         
         return cfg;
@@ -8351,7 +8369,8 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
      /**
      * Mark this field as valid
      */
-    markValid : function(){
+    markValid : function()
+    {
         if(!this.el  || this.preventMark){ // not rendered
             return;
         }
@@ -8368,6 +8387,18 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             return;
         }
         
+        var formGroup = this.el.findParent('.form-group', false, true);
+        
+        if(formGroup){
+            
+            var label = formGroup.select('label', true).first();
+            var icon = formGroup.select('i.fa-star', true).first();
+            
+            if(label && icon){
+                icon.remove();
+            }
+        }
+        
         this.el.addClass(this.validClass);
         
         if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && (this.getValue().length || this.forceFeedback)){
@@ -8406,6 +8437,23 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             return;
         }
         
+        var formGroup = this.el.findParent('.form-group', false, true);
+        
+        if(formGroup){
+            var label = formGroup.select('label', true).first();
+            var icon = formGroup.select('i.fa-star', true).first();
+
+            if(!this.getValue().length && label && !icon){
+                this.el.findParent('.form-group', false, true).createChild({
+                    tag : 'i',
+                    cls : 'text-danger fa fa-lg fa-star',
+                    tooltip : 'This field is required',
+                    style : 'margin-right:5px;'
+                }, label, true);
+            }
+        }
+        
+        
         this.el.addClass(this.invalidClass);
         
         if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
@@ -8615,7 +8663,7 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
         }
         
         if (align ==='left' && this.fieldLabel.length) {
-                Roo.log("left and has label");
+//                Roo.log("left and has label");
                 cfg.cn = [
                     
                     {
@@ -8634,7 +8682,7 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
                     
                 ];
         } else if ( this.fieldLabel.length) {
-                Roo.log(" label");
+//                Roo.log(" label");
                  cfg.cn = [
                    
                     {
@@ -8650,7 +8698,7 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
 
         } else {
             
-                   Roo.log(" no label && no align");
+//                   Roo.log(" no label && no align");
                 cfg.cn = [
                     
                         inputblock
@@ -8673,6 +8721,136 @@ Roo.extend(Roo.bootstrap.TextArea, Roo.bootstrap.Input,  {
     inputEl: function ()
     {
         return this.el.select('textarea.form-control',true).first();
+    },
+    
+    /**
+     * Clear any invalid styles/messages for this field
+     */
+    clearInvalid : function()
+    {
+        
+        if(!this.el || this.preventMark){ // not rendered
+            return;
+        }
+        
+        var label = this.el.select('label', true).first();
+        var icon = this.el.select('i.fa-star', true).first();
+        
+        if(label && icon){
+            icon.remove();
+        }
+        
+        this.el.removeClass(this.invalidClass);
+        
+        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
+            
+            var feedback = this.el.select('.form-control-feedback', true).first();
+            
+            if(feedback){
+                this.el.select('.form-control-feedback', true).first().removeClass(this.invalidFeedbackClass);
+            }
+            
+        }
+        
+        this.fireEvent('valid', this);
+    },
+    
+     /**
+     * Mark this field as valid
+     */
+    markValid : function()
+    {
+        if(!this.el  || this.preventMark){ // not rendered
+            return;
+        }
+        
+        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;
+        }
+        
+        var label = this.el.select('label', true).first();
+        var icon = this.el.select('i.fa-star', true).first();
+        
+        if(label && icon){
+            icon.remove();
+        }
+        
+        this.el.addClass(this.validClass);
+        
+        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && (this.getValue().length || this.forceFeedback)){
+            
+            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]);
+                this.el.select('.form-control-feedback', true).first().addClass([this.validFeedbackClass]);
+            }
+            
+        }
+        
+        this.fireEvent('valid', this);
+    },
+    
+     /**
+     * Mark this field as invalid
+     * @param {String} msg The validation message
+     */
+    markInvalid : function(msg)
+    {
+        if(!this.el  || this.preventMark){ // not rendered
+            return;
+        }
+        
+        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;
+        }
+        
+        var label = this.el.select('label', true).first();
+        var icon = this.el.select('i.fa-star', true).first();
+        
+        if(!this.getValue().length && label && !icon){
+            this.el.createChild({
+                tag : 'i',
+                cls : 'text-danger fa fa-lg fa-star',
+                tooltip : 'This field is required',
+                style : 'margin-right:5px;'
+            }, label, true);
+        }
+
+        this.el.addClass(this.invalidClass);
+        
+        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
+            
+            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.getValue().length || this.forceFeedback){
+                    this.el.select('.form-control-feedback', true).first().addClass([this.invalidFeedbackClass]);
+                }
+                
+            }
+            
+        }
+        
+        this.fireEvent('invalid', this, msg);
     }
 });
 
@@ -8871,8 +9049,6 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
         };
         
         if(this.multiple){
-            Roo.log('multiple');
-            
             box = {
                 tag: 'div',
                 cn: [
@@ -8951,7 +9127,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
         
         if (align ==='left' && this.fieldLabel.length) {
             
-                Roo.log("left and has label");
+//                Roo.log("left and has label");
                 cfg.cn = [
                     
                     {
@@ -8970,7 +9146,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                     
                 ];
         } else if ( this.fieldLabel.length) {
-                Roo.log(" label");
+//                Roo.log(" label");
                  cfg.cn = [
                    
                     {
@@ -8986,7 +9162,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
 
         } else {
             
-                Roo.log(" no label && no align");
+//                Roo.log(" no label && no align");
                 cfg = combobox
                      
                 
@@ -8998,7 +9174,7 @@ Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
                 cfg.cls += ' col-' + size + '-' + settings[size];
             }
         });
-        Roo.log(cfg);
+        
         return cfg;
         
     },
@@ -9292,7 +9468,9 @@ Roo.data.SortTypes = {
      */
     asFloat : function(s) {
        var val = parseFloat(String(s).replace(/,/g, ""));
-        if(isNaN(val)) val = 0;
+        if(isNaN(val)) {
+            val = 0;
+        }
        return val;
     },
     
@@ -9303,7 +9481,9 @@ Roo.data.SortTypes = {
      */
     asInt : function(s) {
         var val = parseInt(String(s).replace(/,/g, ""));
-        if(isNaN(val)) val = 0;
+        if(isNaN(val)) {
+            val = 0;
+        }
        return val;
     }
 };/*
@@ -11333,7 +11513,20 @@ Roo.bootstrap.ComboBox = function(config){
          * Fires when specialfilter
             * @param {Roo.bootstrap.ComboBox} combo This combo box
             */
-        'specialfilter' : true
+        'specialfilter' : true,
+        /**
+         * @event tick
+         * Fires when tick the element
+            * @param {Roo.bootstrap.ComboBox} combo This combo box
+            */
+        'tick' : true,
+        /**
+         * @event touchviewdisplay
+         * Fires when touch view require special display (default is using displayField)
+            * @param {Roo.bootstrap.ComboBox} combo This combo box
+            * @param {Object} cfg set html .
+            */
+        'touchviewdisplay' : true
         
     });
     
@@ -11683,7 +11876,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         
         if (align ==='left' && this.fieldLabel.length) {
             
-                Roo.log("left and has label");
+//                Roo.log("left and has label");
                 cfg.cn = [
                     
                     {
@@ -11702,7 +11895,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                     
                 ];
         } else if ( this.fieldLabel.length) {
-                Roo.log(" label");
+//                Roo.log(" label");
                  cfg.cn = [
                    
                     {
@@ -11718,7 +11911,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
 
         } else {
             
-                Roo.log(" no label && no align");
+//                Roo.log(" no label && no align");
                 cfg = combobox
                      
                 
@@ -12286,12 +12479,12 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         }
         
         this.collapse();
-        
-        Roo.log(this.store.reader.jsonData);
-        if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
+        // only causes errors at present
+        //Roo.log(this.store.reader.jsonData);
+        //if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
             // fixme
             //Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
-        }
+        //}
         
         
     },
@@ -12522,6 +12715,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             Roo.each(this.tickItems, function(v,k){
                 
                 if(typeof(v) != 'undefined' && v[_this.valueField] == r.data[_this.valueField]){
+                    Roo.log(v);
                     _this.tickItems.splice(k, 1);
                     
                     if(typeof(e) == 'undefined' && view == false){
@@ -12537,7 +12731,9 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                 return;
             }
             
-            this.tickItems.push(r.data);
+            if(this.fireEvent('tick', this, r, index, Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked) !== false){
+                this.tickItems.push(r.data);
+            }
             
             if(typeof(e) == 'undefined' && view == false){
                 Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked = true;
@@ -12980,7 +13176,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         }
         // scroll to?
         this.view.select(match);
-        var sn = Roo.get(this.view.getSelectedNodes()[0])
+        var sn = Roo.get(this.view.getSelectedNodes()[0]);
         sn.scrollIntoView(sn.dom.parentNode, false);
     },
     
@@ -12999,7 +13195,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                 tag: 'div',
                 cls: 'loading select2-more-results select2-active',
                 html: 'Loading more results...'
-            })
+            });
             
             this.loading = this.list.select('.loading', true).first();
             
@@ -13053,7 +13249,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             
         }, this.searchField);
         
-        var close = choice.select('a.select2-search-choice-close', true).first()
+        var close = choice.select('a.select2-search-choice-close', true).first();
         
         close.on('click', this.onRemoveItem, this, { item : choice, data : o} );
         
@@ -13379,7 +13575,10 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             this.el.dom.scrollTop = 0;
         }, this);
         
+        this.originalValue = this.getValue();
+        
         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);
         
@@ -13413,6 +13612,12 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
                 close.on('click', this.removeBtnClick, this, close);
             }
         }
+        /*
+         * fix the bug in Safari iOS8
+         */
+        this.inputEl().on("focus", function(e){
+            document.activeElement.blur();
+        }, this);
         
         return;
         
@@ -13441,6 +13646,10 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     
     showTouchView : function()
     {
+        if(this.disabled){
+            return;
+        }
+        
         this.touchViewHeaderEl.hide();
 
         if(this.fieldLabel.length){
@@ -13546,7 +13755,14 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             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];
+                var cfg = {
+                    data : d.data,
+                    html : d.data[this.displayField]
+                };
+                
+                if(this.fireEvent('touchviewdisplay', this, cfg) !== false){
+                    row.select('.roo-combobox-list-group-item-value', true).first().dom.innerHTML = cfg.html;
+                }
             }
             
             if(!this.multiple && this.valueField && typeof(d.data[this.valueField]) != 'undefined' && d.data[this.valueField] == this.getValue()){
@@ -13781,6 +13997,7 @@ Roo.apply(Roo.bootstrap.ComboBox,  {
             {
                 tag: 'div',
                 cls: 'modal-dialog',
+                style : 'position:fixed', // we have to fix position....
                 cn: [
                     {
                         tag: 'div',
@@ -15444,7 +15661,7 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
     },
     
     getAutoCreate : function(){
-         Roo.log('make popover?');
+         
         var cfg = {
            cls : 'popover roo-dynamic',
            style: 'display:block',
@@ -15496,9 +15713,9 @@ Roo.extend(Roo.bootstrap.Popover, Roo.bootstrap.Component,  {
             if (this.style) {
                 cfg.style = this.style;
             }
-            Roo.log("adding to ")
+            //Roo.log("adding to ");
             this.el = Roo.get(document.body).createChild(cfg, position);
-            Roo.log(this.el);
+//            Roo.log(this.el);
         }
         this.initEvents();
     },
@@ -15804,7 +16021,7 @@ Roo.extend(Roo.bootstrap.ProgressBar, Roo.bootstrap.Component,  {
  * Bootstrap Column class
  * @cfg {String} navId the navigation id (for use with navbars) - will be auto generated if it does not exist..
  * @cfg {Boolean} carousel true to make the group behave like a carousel
- * @cfg {Number} bullets show the panel pointer.. default 0
+ * @cfg {Boolean} bullets show bullets for the panels
  * @cfg {Boolean} autoslide (true|false) auto slide .. default false
  * @cfg {Boolean} slideOnTouch (true|false) slide on touch .. default false
  * @cfg {Number} timer auto slide timer .. default 0 millisecond
@@ -15840,8 +16057,6 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
         
         cfg.cls += ' tab-content';
         
-        Roo.log('get auto create...............');
-        
         if (this.carousel) {
             cfg.cls += ' carousel slide';
             
@@ -15849,23 +16064,23 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
                cls : 'carousel-inner'
             }];
         
-            if(this.bullets > 0 && !Roo.isTouch){
+            if(this.bullets  && !Roo.isTouch){
                 
                 var bullets = {
                     cls : 'carousel-bullets',
                     cn : []
                 };
-                
+               
                 if(this.bullets_cls){
                     bullets.cls = bullets.cls + ' ' + this.bullets_cls;
                 }
-                
+                 /*
                 for (var i = 0; i < this.bullets; i++){
                     bullets.cn.push({
                         cls : 'bullet bullet-' + i
                     });
                 }
-                
+                */
                 bullets.cn.push({
                     cls : 'clear'
                 });
@@ -15879,14 +16094,6 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
     
     initEvents:  function()
     {
-        Roo.log('-------- init events on tab group ---------');
-        
-        if(this.bullets > 0 && !Roo.isTouch){
-            this.initBullet();
-        }
-        
-        Roo.log(this);
-        
         if(Roo.isTouch && this.slideOnTouch){
             this.el.on("touchstart", this.onTouchStart, this);
         }
@@ -15923,6 +16130,7 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
     {
         this.tabs.push( item);
         item.navId = this.navId; // not really needed..
+        this.addBullet();
     
     },
     
@@ -15970,7 +16178,7 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
      */
     showPanel : function (pan)
     {
-        if(this.transition){
+        if(this.transition || typeof(pan) == 'undefined'){
             Roo.log("waiting for the transitionend");
             return;
         }
@@ -15978,13 +16186,21 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
         if (typeof(pan) == 'number') {
             pan = this.tabs[pan];
         }
+        
         if (typeof(pan) == 'string') {
             pan = this.getPanelByName(pan);
         }
+        
+        var cur = this.getActivePanel();
+        
+        if(!pan || !cur){
+            Roo.log('pan or acitve pan is undefined');
+            return false;
+        }
+        
         if (pan.tabId == this.getActivePanel().tabId) {
             return true;
         }
-        var cur = this.getActivePanel();
         
         if (false === cur.fireEvent('beforedeactivate')) {
             return false;
@@ -16057,38 +16273,39 @@ Roo.extend(Roo.bootstrap.TabGroup, Roo.bootstrap.Column,  {
         this.showPanel(this.tabs[i-1]);
     },
     
-    initBullet : function()
+    
+    addBullet: function()
     {
-        if(Roo.isTouch){
+        if(!this.bullets || Roo.isTouch){
             return;
         }
+        var ctr = this.el.select('.carousel-bullets',true).first();
+        var i = this.el.select('.carousel-bullets .bullet',true).getCount() ;
+        var bullet = ctr.createChild({
+            cls : 'bullet bullet-' + i
+        },ctr.dom.lastChild);
+        
         
         var _this = this;
         
-        for (var i = 0; i < this.bullets; i++){
-            var bullet = this.el.select('.bullet-' + i, true).first();
-
-            if(!bullet){
-                continue;
-            }
+        bullet.on('click', (function(e, el, o, ii, t){
 
-            bullet.on('click', (function(e, el, o, ii, t){
-
-                e.preventDefault();
+            e.preventDefault();
 
-                _this.showPanel(ii);
+            this.showPanel(ii);
 
-                if(_this.autoslide && _this.slideFn){
-                    clearInterval(_this.slideFn);
-                    _this.slideFn = window.setInterval(function() {
-                        _this.showPanelNext();
-                    }, _this.timer);
-                }
+            if(this.autoslide && this.slideFn){
+                clearInterval(this.slideFn);
+                this.slideFn = window.setInterval(function() {
+                    _this.showPanelNext();
+                }, this.timer);
+            }
 
-            }).createDelegate(this, [i, bullet], true));
-        }
+        }).createDelegate(this, [i, bullet], true));
+                
+        
     },
-    
+     
     setActiveBullet : function(i)
     {
         if(Roo.isTouch){
@@ -16221,15 +16438,13 @@ Roo.extend(Roo.bootstrap.TabPanel, Roo.bootstrap.Component,  {
     
     initEvents:  function()
     {
-        Roo.log('-------- init events on tab panel ---------');
-        
         var p = this.parent();
         this.navId = this.navId || p.navId;
         
         if (typeof(this.navId) != 'undefined') {
             // not really needed.. but just in case.. parent should be a NavGroup.
             var tg = Roo.bootstrap.TabGroup.get(this.navId);
-            Roo.log(['register', tg, this]);
+            
             tg.register(this);
             
             var i = tg.tabs.length - 1;
@@ -16469,7 +16684,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
         
         if(this.singleMode){
             Roo.each(this.picker().select('thead > tr > th', true).elements, function(v){
-                v.setVisibilityMode(Roo.Element.DISPLAY)
+                v.setVisibilityMode(Roo.Element.DISPLAY);
                 v.hide();
             });
             
@@ -16488,7 +16703,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
             v.attr('colspan', function(i, val){
                 return parseInt(val) + 1;
             });
-        })
+        });
                        
         
         this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
@@ -16678,7 +16893,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                 tag: 'td',
                 cls: 'day ' + clsName,
                 html: prevMonth.getDate()
-            })
+            });
             
             prevMonth.setDate(prevMonth.getDate()+1);
         }
@@ -16714,7 +16929,7 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                 tag: 'span',
                 cls: 'year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + (year < startYear || year > endYear ? ' disabled' : ''),
                 html: year
-            })
+            });
             
             year += 1;
         }
@@ -16735,9 +16950,11 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     
     place: function()
     {
-        if(this.isInline) return;
-        
-        this.picker().removeClass(['bottom', 'top']);
+        if(this.isInline) {
+            return;
+        }
+        
+        this.picker().removeClass(['bottom', 'top']);
         
         if((Roo.lib.Dom.getViewHeight() + Roo.get(document.body).getScroll().top) - (this.inputEl().getBottom() + this.picker().getHeight()) < 0){
             /*
@@ -16810,7 +17027,9 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     
     hide : function()
     {
-        if(this.isInline) return;
+        if(this.isInline) {
+            return;
+        }
         this.picker().hide();
         this.viewMode = this.startViewMode;
         this.showMode();
@@ -16862,8 +17081,9 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     fireKey: function(e)
     {
         if (!this.picker().isVisible()){
-            if (e.keyCode == 27) // allow escape to hide and re-show picker
+            if (e.keyCode == 27) // allow escape to hide and re-show picker
                 this.show();
+            }
             return;
         }
         
@@ -16878,7 +17098,9 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                 break;
             case 37: // left
             case 39: // right
-                if (!this.keyboardNavigation) break;
+                if (!this.keyboardNavigation) {
+                    break;
+                }
                 dir = e.keyCode == 37 ? -1 : 1;
                 
                 if (e.ctrlKey){
@@ -16904,7 +17126,9 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
                 break;
             case 38: // up
             case 40: // down
-                if (!this.keyboardNavigation) break;
+                if (!this.keyboardNavigation) {
+                    break;
+                }
                 dir = e.keyCode == 38 ? -1 : 1;
                 if (e.ctrlKey){
                     newDate = this.moveYear(this.date, dir);
@@ -17131,7 +17355,9 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
     
     moveMonth: function(date, dir)
     {
-        if (!dir) return date;
+        if (!dir) {
+            return date;
+        }
         var new_date = new Date(date.valueOf()),
         day = new_date.getUTCDate(),
         month = new_date.getUTCMonth(),
@@ -17153,13 +17379,15 @@ Roo.extend(Roo.bootstrap.DateField, Roo.bootstrap.Input,  {
             new_month = month + dir;
             new_date.setUTCMonth(new_month);
             // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
-            if (new_month < 0 || new_month > 11)
+            if (new_month < 0 || new_month > 11) {
                 new_month = (new_month + 12) % 12;
+            }
         } else {
             // For magnitudes >1, move one month at a time...
-            for (var i=0; i<mag; i++)
+            for (var i=0; i<mag; i++) {
                 // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
                 new_date = this.moveMonth(new_date, dir);
+            }
             // ...then reset the day, keeping it in the new month
             new_month = new_date.getUTCMonth();
             new_date.setUTCDate(day);
@@ -18029,7 +18257,9 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
     
     place: function()
     {
-        if(this.isInline) return;
+        if(this.isInline) {
+            return;
+        }
         
         this.picker().removeClass(['bottom', 'top']);
         
@@ -18079,7 +18309,9 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
     
     hide : function()
     {
-        if(this.isInline) return;
+        if(this.isInline) {
+            return;
+        }
         this.picker().hide();
         this.fireEvent('hide', this, this.date);
         
@@ -18100,8 +18332,9 @@ Roo.extend(Roo.bootstrap.MonthField, Roo.bootstrap.Input,  {
     fireKey: function(e)
     {
         if (!this.picker().isVisible()){
-            if (e.keyCode == 27) // allow escape to hide and re-show picker
+            if (e.keyCode == 27)   {// allow escape to hide and re-show picker
                 this.show();
+            }
             return;
         }
         
@@ -18370,7 +18603,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
         }
         
         if (align ==='left' && this.fieldLabel.length) {
-                Roo.log("left and has label");
+//                Roo.log("left and has label");
                 cfg.cn = [
                     
                     {
@@ -18389,7 +18622,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
                     
                 ];
         } else if ( this.fieldLabel.length) {
-                Roo.log(" label");
+//                Roo.log(" label");
                 cfg.cn = [
                    
                     {
@@ -18407,7 +18640,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
 
         } else {
             
-                Roo.log(" no label && no align");
+//                Roo.log(" no label && no align");
                 cfg.cn = [  inputblock ] ;
                 
                 
@@ -18632,6 +18865,16 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
         
         this.fireEvent('valid', this);
         
+        var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+        
+        if(this.groupId){
+            label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
+        }
+        
+        if(label){
+            label.markValid();
+        }
+        
         if(this.inputType == 'radio'){
             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
                 e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
@@ -18673,6 +18916,16 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
         
         this.fireEvent('invalid', this, msg);
         
+        var label = Roo.bootstrap.FieldLabel.get(this.name + '-group');
+        
+        if(this.groupId){
+            label = Roo.bootstrap.FieldLabel.get(this.groupId + '-group');
+        }
+        
+        if(label){
+            label.markInvalid();
+        }
+            
         if(this.inputType == 'radio'){
             Roo.each(this.el.up('form').select('input[name='+this.name+']', true).elements, function(e){
                 e.findParent('.form-group', false, true).removeClass([_this.invalidClass, _this.validClass]);
@@ -18689,7 +18942,7 @@ Roo.extend(Roo.bootstrap.CheckBox, Roo.bootstrap.Input,  {
         }
         
         var group = Roo.bootstrap.CheckBox.get(this.groupId);
-            
+        
         if(!group){
             return;
         }
@@ -18926,7 +19179,7 @@ Roo.extend(Roo.bootstrap.Radio, Roo.bootstrap.CheckBox,  {
         
         this.inputEl().on('click', this.onClick,  this);
         if (this.boxLabel) {
-            Roo.log('find label')
+            //Roo.log('find label');
             this.el.select('span.radio label span',true).first().on('click', this.onClick,  this);
         }
         
@@ -19925,13 +20178,16 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         var nodeIsBefore   =  ss == 1;
         var nodeIsAfter    = ee == -1;
         
-        if (nodeIsBefore && nodeIsAfter)
+        if (nodeIsBefore && nodeIsAfter) {
             return 0; // outer
-        if (!nodeIsBefore && nodeIsAfter)
+        }
+        if (!nodeIsBefore && nodeIsAfter) {
             return 1; //right trailed.
+        }
         
-        if (nodeIsBefore && !nodeIsAfter)
+        if (nodeIsBefore && !nodeIsAfter) {
             return 2;  // left trailed.
+        }
         // fully contined.
         return 3;
     },
@@ -21620,7 +21876,9 @@ Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSe
      * Clears all selections.
      */
     clearSelections : function(fast){
-        if(this.locked) return;
+        if(this.locked) {
+            return;
+        }
         if(fast !== true){
             var ds = this.grid.dataSource;
             var s = this.selections;
@@ -21639,7 +21897,9 @@ Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSe
      * Selects all rows.
      */
     selectAll : function(){
-        if(this.locked) return;
+        if(this.locked) {
+            return;
+        }
         this.selections.clear();
         for(var i = 0, len = this.grid.dataSource.getCount(); i < len; i++){
             this.selectRow(i, true);
@@ -21728,7 +21988,9 @@ Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSe
      * @param {Boolean} keepExisting (optional) True to retain existing selections
      */
     selectRange : function(startRow, endRow, keepExisting){
-        if(this.locked) return;
+        if(this.locked) {
+            return;
+        }
         if(!keepExisting){
             this.clearSelections();
         }
@@ -21749,7 +22011,9 @@ Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSe
      * @param {Number} endRow The index of the last row in the range
      */
     deselectRange : function(startRow, endRow, preventViewNotify){
-        if(this.locked) return;
+        if(this.locked) {
+            return;
+        }
         for(var i = startRow; i <= endRow; i++){
             this.deselectRow(i, preventViewNotify);
         }
@@ -21761,7 +22025,9 @@ Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSe
      * @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.locked || (index < 0 || index >= this.grid.dataSource.getCount())) {
+            return;
+        }
         if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
             if(!keepExisting || this.singleSelect){
                 this.clearSelections();
@@ -21782,7 +22048,9 @@ Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSe
      * @param {Number} row The index of the row to deselect
      */
     deselectRow : function(index, preventViewNotify){
-        if(this.locked) return;
+        if(this.locked) {
+            return;
+        }
         if(this.last == index){
             this.last = false;
         }
@@ -21960,7 +22228,6 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
         // 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 } );
@@ -22114,8 +22381,9 @@ Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
         {
           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(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;
@@ -27252,10 +27520,11 @@ Roo.extend(Roo.bootstrap.NavProgressItem, Roo.bootstrap.Component,  {
  * @cfg {String} html contents of the element
  * @cfg {String} tag tag of the element default label
  * @cfg {String} cls class of the element
- * @cfg {String} for label target 
+ * @cfg {String} target label target 
  * @cfg {Boolean} allowBlank (true|false) target allowBlank default true
  * @cfg {String} invalidClass default "text-danger fa fa-lg fa-exclamation-triangle"
  * @cfg {String} validClass default "text-success fa fa-lg fa-check"
+ * @cfg {String} iconTooltip default "This field is required"
  * 
  * @constructor
  * Create a new FieldLabel
@@ -27287,21 +27556,23 @@ Roo.extend(Roo.bootstrap.FieldLabel, Roo.bootstrap.Component,  {
     tag: 'label',
     cls: '',
     html: '',
-    for: '',
+    target: '',
     allowBlank : true,
     invalidClass : 'text-danger fa fa-lg fa-exclamation-triangle',
     validClass : 'text-success fa fa-lg fa-check',
+    iconTooltip : 'This field is required',
     
     getAutoCreate : function(){
         
         var cfg = {
             tag : this.tag,
-            cls : this.cls,
-            for : this.for,
+            cls : 'roo-bootstrap-field-label ' + this.cls,
+            for : this.target,
             cn : [
                 {
                     tag : 'i',
-                    cls : ''
+                    cls : '',
+                    tooltip : this.iconTooltip
                 },
                 {
                     tag : 'span',
@@ -27321,89 +27592,456 @@ Roo.extend(Roo.bootstrap.FieldLabel, Roo.bootstrap.Component,  {
         
         this.iconEl.setVisibilityMode(Roo.Element.DISPLAY).hide();
         
+        Roo.bootstrap.FieldLabel.register(this);
     },
     
     /**
      * Mark this field as valid
      */
-    markValid : function(){
-        if(!this.el  || this.preventMark){ // not rendered
+    markValid : function()
+    {
+        this.iconEl.show();
+        
+        this.iconEl.removeClass(this.invalidClass);
+        
+        this.iconEl.addClass(this.validClass);
+        
+        this.fireEvent('valid', this);
+    },
+    
+    /**
+     * Mark this field as invalid
+     * @param {String} msg The validation message
+     */
+    markInvalid : function(msg)
+    {
+        this.iconEl.show();
+        
+        this.iconEl.removeClass(this.validClass);
+        
+        this.iconEl.addClass(this.invalidClass);
+        
+        this.fireEvent('invalid', this, msg);
+    }
+    
+   
+});
+
+Roo.apply(Roo.bootstrap.FieldLabel, {
+    
+    groups: {},
+    
+     /**
+    * register a FieldLabel Group
+    * @param {Roo.bootstrap.FieldLabel} the FieldLabel to add
+    */
+    register : function(label)
+    {
+        if(this.groups.hasOwnProperty(label.target)){
             return;
         }
+     
+        this.groups[label.target] = label;
+       
+    },
+    /**
+    * fetch a FieldLabel Group based on the target
+    * @param {string} target
+    * @returns {Roo.bootstrap.FieldLabel} the CheckBox group
+    */
+    get: function(target) {
+        if (typeof(this.groups[target]) == 'undefined') {
+            return false;
+        }
         
-        this.el.removeClass([this.invalidClass, this.validClass]);
+        return this.groups[target] ;
+    }
+});
+
+
+ /*
+ * - LGPL
+ *
+ * page DateSplitField.
+ * 
+ */
+
+
+/**
+ * @class Roo.bootstrap.DateSplitField
+ * @extends Roo.bootstrap.Component
+ * Bootstrap DateSplitField class
+ * @cfg {string} fieldLabel - the label associated
+ * @cfg {Number} labelWidth set the width of label (0-12)
+ * @cfg {String} labelAlign (top|left)
+ * @cfg {Boolean} dayAllowBlank (true|false) default false
+ * @cfg {Boolean} monthAllowBlank (true|false) default false
+ * @cfg {Boolean} yearAllowBlank (true|false) default false
+ * @cfg {string} dayPlaceholder 
+ * @cfg {string} monthPlaceholder
+ * @cfg {string} yearPlaceholder
+ * @cfg {string} dayFormat default 'd'
+ * @cfg {string} monthFormat default 'm'
+ * @cfg {string} yearFormat default 'Y'
+
+ *     
+ * @constructor
+ * Create a new DateSplitField
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.DateSplitField = function(config){
+    Roo.bootstrap.DateSplitField.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        // raw events
+         /**
+         * @event years
+         * getting the data of years
+         * @param {Roo.bootstrap.DateSplitField} this
+         * @param {Object} years
+         */
+        "years" : true,
+        /**
+         * @event days
+         * getting the data of days
+         * @param {Roo.bootstrap.DateSplitField} this
+         * @param {Object} days
+         */
+        "days" : true,
+        /**
+         * @event invalid
+         * Fires after the field has been marked as invalid.
+         * @param {Roo.form.Field} this
+         * @param {String} msg The validation message
+         */
+        invalid : true,
+       /**
+         * @event valid
+         * Fires after the field has been validated with no errors.
+         * @param {Roo.form.Field} this
+         */
+        valid : true
+    });
+};
+
+Roo.extend(Roo.bootstrap.DateSplitField, Roo.bootstrap.Component,  {
+    
+    fieldLabel : '',
+    labelAlign : 'top',
+    labelWidth : 3,
+    dayAllowBlank : false,
+    monthAllowBlank : false,
+    yearAllowBlank : false,
+    dayPlaceholder : '',
+    monthPlaceholder : '',
+    yearPlaceholder : '',
+    dayFormat : 'd',
+    monthFormat : 'm',
+    yearFormat : 'Y',
+    isFormField : true,
+    
+    getAutoCreate : function()
+    {
+        var cfg = {
+            tag : 'div',
+            cls : 'row roo-date-split-field-group',
+            cn : [
+                {
+                    tag : 'input',
+                    type : 'hidden',
+                    cls : 'form-hidden-field roo-date-split-field-group-value',
+                    name : this.name
+                }
+            ]
+        };
         
-        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.fieldLabel){
+            cfg.cn.push({
+                tag : 'div',
+                cls : 'column roo-date-split-field-label col-md-' + ((this.labelAlign == 'top') ? '12' : this.labelWidth),
+                cn : [
+                    {
+                        tag : 'label',
+                        html : this.fieldLabel
+                    }
+                ]
+            });
         }
+        
+        Roo.each(['day', 'month', 'year'], function(t){
+            cfg.cn.push({
+                tag : 'div',
+                cls : 'column roo-date-split-field-' + t + ' col-md-' + ((this.labelAlign == 'top') ? '4' : ((12 - this.labelWidth) / 3))
+            });
+        }, this);
+        
+        return cfg;
+    },
+    
+    inputEl: function ()
+    {
+        return this.el.select('.roo-date-split-field-group-value', true).first();
+    },
+    
+    onRender : function(ct, position) 
+    {
+        var _this = this;
+        
+        Roo.bootstrap.NavProgressBar.superclass.onRender.call(this, ct, position);
+        
+        this.inputEl = this.el.select('.roo-date-split-field-group-value', true).first();
+        
+        this.dayField = new Roo.bootstrap.ComboBox({
+            allowBlank : this.dayAllowBlank,
+            alwaysQuery : true,
+            displayField : 'value',
+            editable : false,
+            fieldLabel : '',
+            forceSelection : true,
+            mode : 'local',
+            placeholder : this.dayPlaceholder,
+            selectOnFocus : true,
+            tpl : '<div class="select2-result"><b>{value}</b></div>',
+            triggerAction : 'all',
+            typeAhead : true,
+            valueField : 'value',
+            store : new Roo.data.SimpleStore({
+                data : (function() {    
+                    var days = [];
+                    _this.fireEvent('days', _this, days);
+                    return days;
+                })(),
+                fields : [ 'value' ]
+            }),
+            listeners : {
+                select : function (_self, record, index)
+                {
+                    _this.setValue(_this.getValue());
+                }
+            }
+        });
 
-        if(this.disabled || this.allowBlank){
+        this.dayField.render(this.el.select('.roo-date-split-field-day', true).first(), null);
+        
+        this.monthField = new Roo.bootstrap.MonthField({
+            after : '<i class=\"fa fa-calendar\"></i>',
+            allowBlank : this.monthAllowBlank,
+            placeholder : this.monthPlaceholder,
+            readOnly : true,
+            listeners : {
+                render : function (_self)
+                {
+                    this.el.select('span.input-group-addon', true).first().on('click', function(e){
+                        e.preventDefault();
+                        _self.focus();
+                    });
+                },
+                select : function (_self, oldvalue, newvalue)
+                {
+                    _this.setValue(_this.getValue());
+                }
+            }
+        });
+        
+        this.monthField.render(this.el.select('.roo-date-split-field-month', true).first(), null);
+        
+        this.yearField = new Roo.bootstrap.ComboBox({
+            allowBlank : this.yearAllowBlank,
+            alwaysQuery : true,
+            displayField : 'value',
+            editable : false,
+            fieldLabel : '',
+            forceSelection : true,
+            mode : 'local',
+            placeholder : this.yearPlaceholder,
+            selectOnFocus : true,
+            tpl : '<div class="select2-result"><b>{value}</b></div>',
+            triggerAction : 'all',
+            typeAhead : true,
+            valueField : 'value',
+            store : new Roo.data.SimpleStore({
+                data : (function() {
+                    var years = [];
+                    _this.fireEvent('years', _this, years);
+                    return years;
+                })(),
+                fields : [ 'value' ]
+            }),
+            listeners : {
+                select : function (_self, record, index)
+                {
+                    _this.setValue(_this.getValue());
+                }
+            }
+        });
+
+        this.yearField.render(this.el.select('.roo-date-split-field-year', true).first(), null);
+    },
+    
+    setValue : function(v, format)
+    {
+        this.inputEl.dom.value = v;
+        
+        var f = format || (this.yearFormat + '-' + this.monthFormat + '-' + this.dayFormat);
+        
+        var d = Date.parseDate(v, f);
+        
+        if(!d){
+            this.validate();
             return;
         }
         
-        this.el.addClass(this.validClass);
+        this.setDay(d.format(this.dayFormat));
+        this.setMonth(d.format(this.monthFormat));
+        this.setYear(d.format(this.yearFormat));
         
-        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && (this.getValue().length || this.forceFeedback)){
-            
-            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]);
-                this.el.select('.form-control-feedback', true).first().addClass([this.validFeedbackClass]);
-            }
-            
+        this.validate();
+        
+        return;
+    },
+    
+    setDay : function(v)
+    {
+        this.dayField.setValue(v);
+        this.inputEl.dom.value = this.getValue();
+        this.validate();
+        return;
+    },
+    
+    setMonth : function(v)
+    {
+        this.monthField.setValue(v, true);
+        this.inputEl.dom.value = this.getValue();
+        this.validate();
+        return;
+    },
+    
+    setYear : function(v)
+    {
+        this.yearField.setValue(v);
+        this.inputEl.dom.value = this.getValue();
+        this.validate();
+        return;
+    },
+    
+    getDay : function()
+    {
+        return this.dayField.getValue();
+    },
+    
+    getMonth : function()
+    {
+        return this.monthField.getValue();
+    },
+    
+    getYear : function()
+    {
+        return this.yearField.getValue();
+    },
+    
+    getValue : function()
+    {
+        var f = this.yearFormat + '-' + this.monthFormat + '-' + this.dayFormat;
+        
+        var date = this.yearField.getValue() + '-' + this.monthField.getValue() + '-' + this.dayField.getValue();
+        
+        return date;
+    },
+    
+    reset : function()
+    {
+        this.setDay('');
+        this.setMonth('');
+        this.setYear('');
+        this.inputEl.dom.value = '';
+        this.validate();
+        return;
+    },
+    
+    validate : function()
+    {
+        var d = this.dayField.validate();
+        var m = this.monthField.validate();
+        var y = this.yearField.validate();
+        
+        var valid = true;
+        
+        if(
+                (!this.dayAllowBlank && !d) ||
+                (!this.monthAllowBlank && !m) ||
+                (!this.yearAllowBlank && !y)
+        ){
+            valid = false;
+        }
+        
+        if(this.dayAllowBlank && this.monthAllowBlank && this.yearAllowBlank){
+            return valid;
+        }
+        
+        if(valid){
+            this.markValid();
+            return valid;
+        }
+        
+        this.markInvalid();
+        
+        return valid;
+    },
+    
+    markValid : function()
+    {
+        
+        var label = this.el.select('label', true).first();
+        var icon = this.el.select('i.fa-star', true).first();
+
+        if(label && icon){
+            icon.remove();
         }
         
         this.fireEvent('valid', this);
     },
     
-    /**
+     /**
      * Mark this field as invalid
      * @param {String} msg The validation message
      */
     markInvalid : function(msg)
     {
-        if(!this.el  || this.preventMark){ // not rendered
-            return;
-        }
         
-        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]);
-        }
+        var label = this.el.select('label', true).first();
+        var icon = this.el.select('i.fa-star', true).first();
 
-        if(this.disabled || this.allowBlank){
-            return;
+        if(label && !icon){
+            this.el.select('.roo-date-split-field-label', true).createChild({
+                tag : 'i',
+                cls : 'text-danger fa fa-lg fa-star',
+                tooltip : 'This field is required',
+                style : 'margin-right:5px;'
+            }, label, true);
         }
         
-        this.el.addClass(this.invalidClass);
-        
-        if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
-            
-            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.getValue().length || this.forceFeedback){
-                    this.el.select('.form-control-feedback', true).first().addClass([this.invalidFeedbackClass]);
-                }
-                
-            }
-            
+        this.fireEvent('invalid', this, msg);
+    },
+    
+    clearInvalid : function()
+    {
+        var label = this.el.select('label', true).first();
+        var icon = this.el.select('i.fa-star', true).first();
+
+        if(label && icon){
+            icon.remove();
         }
         
-        this.fireEvent('invalid', this, msg);
+        this.fireEvent('valid', this);
+    },
+    
+    getName: function()
+    {
+        return this.name;
     }
     
-   
 });
 
-
  
\ No newline at end of file