Roo/bootstrap/ComboBox.js
[roojs1] / Roo / bootstrap / ComboBox.js
index ada2969..e97c140 100644 (file)
@@ -9,6 +9,9 @@
  * A combobox control with support for autocomplete, remote-loading, paging and many other features.
  * @cfg {Boolean} append (true|false) default false
  * @cfg {Boolean} autoFocus (true|false) auto focus the first item, default true
+ * @cfg {Boolean} tickable ComboBox with tickable selections (true|false), default false
+ * @cfg {Boolean} editNotList allow text type,but not show pull down, default false
+ * @cfg {String} btnPosition set the position of the trigger button (left | right) default right
  * @constructor
  * Create a new ComboBox.
  * @param {Object} config Configuration options
@@ -78,6 +81,7 @@ Roo.bootstrap.ComboBox = function(config){
     });
     
     this.item = [];
+    this.tickItems = [];
     
     this.selectedIndex = -1;
     if(this.mode == 'local'){
@@ -265,18 +269,176 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     append: false,
     loadNext: false,
     autoFocus : true,
-    
+    tickable : false,
+    btnPosition : 'right',
+    editNotList : false,
     // element that contains real text value.. (when hidden is used..)
-     
+    
+    getAutoCreate : function()
+    {
+        var cfg = false;
+        
+        /*
+         *  Normal ComboBox
+         */
+        if(!this.tickable){
+            cfg = Roo.bootstrap.ComboBox.superclass.getAutoCreate.call(this);
+            return cfg;
+        }
+        
+        /*
+         *  ComboBox with tickable selections
+         */
+             
+        var align = this.labelAlign || this.parentLabelAlign();
+        
+        cfg = {
+            cls : 'form-group roo-combobox-tickable' //input-group
+        };
+        
+        
+        var buttons = {
+            tag : 'div',
+            cls : 'tickable-buttons',
+            cn : [
+                {
+                    tag : 'button',
+                    type : 'button',
+                    cls : 'btn btn-link btn-edit pull-' + this.btnPosition,
+                    html : 'Edit'
+                },
+                {
+                    tag : 'button',
+                    type : 'button',
+                    name : 'ok',
+                    cls : 'btn btn-link btn-ok pull-' + this.btnPosition,
+                    html : 'Done'
+                },
+                {
+                    tag : 'button',
+                    type : 'button',
+                    name : 'cancel',
+                    cls : 'btn btn-link btn-cancel pull-' + this.btnPosition,
+                    html : 'Cancel'
+                }
+            ]
+        };
+        
+        var _this = this;
+        Roo.each(buttons.cn, function(c){
+            if (_this.size) {
+                c.cls += ' btn-' + _this.size;
+            }
+
+            if (_this.disabled) {
+                c.disabled = true;
+            }
+        });
+        
+        var 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: [
+
+                                buttons
+                            ]
+                        }
+                    ]
+                }
+            ]
+        }
+        
+        var combobox = {
+            cls: 'select2-container input-group select2-container-multi',
+            cn: [
+                box,
+                {
+                    tag: 'ul',
+                    cls: 'typeahead typeahead-long dropdown-menu',
+                    style: 'display:none; max-height:' + this.maxHeight + 'px;'
+                }
+            ]
+        };
+        
+        if (align ==='left' && this.fieldLabel.length) {
+            
+                Roo.log("left and has label");
+                cfg.cn = [
+                    
+                    {
+                        tag: 'label',
+                        'for' :  id,
+                        cls : 'control-label col-sm-' + this.labelWidth,
+                        html : this.fieldLabel
+                        
+                    },
+                    {
+                        cls : "col-sm-" + (12 - this.labelWidth), 
+                        cn: [
+                            combobox
+                        ]
+                    }
+                    
+                ];
+        } else if ( this.fieldLabel.length) {
+                Roo.log(" label");
+                 cfg.cn = [
+                   
+                    {
+                        tag: 'label',
+                        //cls : 'input-group-addon',
+                        html : this.fieldLabel
+                        
+                    },
+                    
+                    combobox
+                    
+                ];
+
+        } else {
+            
+                Roo.log(" no label && no align");
+                cfg = combobox
+                     
+                
+        }
+         
+        var settings=this;
+        ['xs','sm','md','lg'].map(function(size){
+            if (settings[size]) {
+                cfg.cls += ' col-' + size + '-' + settings[size];
+            }
+        });
+        
+        return cfg;
+        
+    },
+    
     // private
-    initEvents: function(){
+    initEvents: function()
+    {
         
         if (!this.store) {
             throw "can not find store for combo";
         }
         this.store = Roo.factory(this.store, Roo.data);
         
-        
+        if(this.tickable){
+            this.initTickableEvnets();
+            return;
+        }
         
         Roo.bootstrap.ComboBox.superclass.initEvents.call(this);
         
@@ -310,17 +472,9 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         
         (function(){
             var lw = _this.listWidth || Math.max(_this.inputEl().getWidth(), _this.minListWidth);
-            
-            Roo.log('checking the width!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
-            
-            Roo.log(_this);
-            Roo.log(_this.inputEl())
-            Roo.log(lw);
-            
             _this.list.setWidth(lw);
         }).defer(100);
         
-        
         this.list.on('mouseover', this.onViewOver, this);
         this.list.on('mousemove', this.onViewMove, this);
         
@@ -506,6 +660,141 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             this.searchField = this.el.select('ul li.select2-search-field', true).first();
         }
     },
+    
+    initTickableEvnets: function()
+    {   
+        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 : '';
+
+            // prevent input submission
+            this.el.dom.removeAttribute('name');
+            this.hiddenField.dom.setAttribute('name', this.hiddenName);
+             
+             
+        }
+        
+        this.list = this.el.select('ul.dropdown-menu',true).first();
+        
+        this.choices = this.el.select('ul.select2-choices', true).first();
+        this.searchField = this.el.select('ul li.select2-search-field', true).first();
+        if(this.editNotList){
+            this.searchField.on("click", this.onSearchFieldClick, this, {preventDefault:true});
+        }
+         
+        this.trigger = this.el.select('.tickable-buttons > .btn-edit', true).first();
+        this.trigger.on("click", this.onTickableTriggerClick, this, {preventDefault:true});
+        
+        this.okBtn = this.el.select('.tickable-buttons > .btn-ok', true).first();
+        this.cancelBtn = this.el.select('.tickable-buttons > .btn-cancel', true).first();
+        
+        this.okBtn.on('click', this.onTickableFooterButtonClick, this, this.okBtn);
+        this.cancelBtn.on('click', this.onTickableFooterButtonClick, this, this.cancelBtn);
+        
+        this.trigger.setVisibilityMode(Roo.Element.DISPLAY);
+        this.okBtn.setVisibilityMode(Roo.Element.DISPLAY);
+        this.cancelBtn.setVisibilityMode(Roo.Element.DISPLAY);
+        
+        this.okBtn.hide();
+        this.cancelBtn.hide();
+        
+        var _this = this;
+        
+        (function(){
+            var lw = _this.listWidth || Math.max(_this.inputEl().getWidth(), _this.minListWidth);
+            _this.list.setWidth(lw);
+        }).defer(100);
+        
+        this.list.on('mouseover', this.onViewOver, this);
+        this.list.on('mousemove', this.onViewMove, this);
+        
+        this.list.on('scroll', this.onViewScroll, this);
+        
+        if(!this.tpl){
+            this.tpl = '<li class="select2-result"><div class="checkbox"><input id="{roo-id}" type="checkbox" {roo-data-checked}><label for="{roo-id}"><b>{' + this.displayField + '}</b></label></li>';
+        }
+
+        this.view = new Roo.View(this.el.select('ul.dropdown-menu',true).first(), this.tpl, {
+            singleSelect:true, tickable:true, parent:this, store: this.store, selectedClass: this.selectedClass
+        });
+        
+        //this.view.wrapEl.setDisplayed(false);
+        this.view.on('click', this.onViewClick, this);
+        
+        
+        
+        this.store.on('beforeload', this.onBeforeLoad, this);
+        this.store.on('load', this.onLoad, this);
+        this.store.on('loadexception', this.onLoadException, this);
+        
+//        this.keyNav = new Roo.KeyNav(this.inputEl(), {
+//            "up" : function(e){
+//                this.inKeyMode = true;
+//                this.selectPrev();
+//            },
+//
+//            "down" : function(e){
+//                if(!this.isExpanded()){
+//                    this.onTriggerClick();
+//                }else{
+//                    this.inKeyMode = true;
+//                    this.selectNext();
+//                }
+//            },
+//
+//            "enter" : function(e){
+////                this.onViewClick();
+//                //return true;
+//                this.collapse();
+//                
+//                if(this.fireEvent("specialkey", this, e)){
+//                    this.onViewClick(false);
+//                }
+//                
+//                return true;
+//            },
+//
+//            "esc" : function(e){
+//                this.collapse();
+//            },
+//
+//            "tab" : function(e){
+//                this.collapse();
+//                
+//                if(this.fireEvent("specialkey", this, e)){
+//                    this.onViewClick(false);
+//                }
+//                
+//                return true;
+//            },
+//
+//            scope : this,
+//
+//            doRelay : function(foo, bar, hname){
+//                if(hname == 'down' || this.scope.isExpanded()){
+//                   return Roo.KeyNav.prototype.doRelay.apply(this, arguments);
+//                }
+//                return true;
+//            },
+//
+//            forceKeyDown: true
+//        });
+        
+        
+        this.queryDelay = Math.max(this.queryDelay || 10,
+                this.mode == 'local' ? 10 : 250);
+        
+        
+        this.dqTask = new Roo.util.DelayedTask(this.initQuery, this);
+        
+        if(this.typeAhead){
+            this.taTask = new Roo.util.DelayedTask(this.onTypeAhead, this);
+        }
+    },
 
     onDestroy : function(){
         if(this.view){
@@ -517,6 +806,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         if(this.list){
             this.list.dom.innerHTML  = '';
         }
+        
         if(this.store){
             this.store.un('beforeload', this.onBeforeLoad, this);
             this.store.un('load', this.onLoad, this);
@@ -610,7 +900,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             this.expand();
             this.restrictHeight();
             if(this.lastQuery == this.allQuery){
-                if(this.editable){
+                if(this.editable && !this.tickable){
                     this.inputEl().dom.select();
                 }
                 if(!this.selectByValue(this.value, true) && this.autoFocus){
@@ -823,6 +1113,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             return;
         }
         var item = this.view.findItemFromChild(t);
+        
         if(item){
             var index = this.view.indexOf(item);
             this.select(index, false);
@@ -830,10 +1121,38 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
     },
 
     // private
-    onViewClick : function(doFocus)
+    onViewClick : function(view, doFocus, el, e)
     {
         var index = this.view.getSelectedIndexes()[0];
+        
         var r = this.store.getAt(index);
+        
+        if(this.tickable){
+            
+            if(e.getTarget().nodeName.toLowerCase() != 'input'){
+                return;
+            }
+            
+            var rm = false;
+            var _this = this;
+            
+            Roo.each(this.tickItems, function(v,k){
+                
+                if(typeof(v) != 'undefined' && v[_this.valueField] == r.data[_this.valueField]){
+                    _this.tickItems.splice(k, 1);
+                    rm = true;
+                    return;
+                }
+            })
+            
+            if(rm){
+                return;
+            }
+            
+            this.tickItems.push(r.data);
+            return;
+        }
+        
         if(r){
             this.onSelect(r, index);
         }
@@ -1041,7 +1360,16 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             return;
         }
         
+        this.hasFocus = false;
+        
         this.list.hide();
+        
+        if(this.tickable){
+            this.okBtn.hide();
+            this.cancelBtn.hide();
+            this.trigger.show();
+        }
+        
         Roo.get(document).un('mousedown', this.collapseIf, this);
         Roo.get(document).un('mousewheel', this.collapseIf, this);
         if (!this.editable) {
@@ -1059,6 +1387,10 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             //e.stopPropagation();
             return;
         }
+        
+        if(this.tickable){
+            this.onTickableFooterButtonClick(e, false, false);
+        }
 
         this.collapse();
         
@@ -1075,6 +1407,17 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
          Roo.log('expand');
         this.list.alignTo(this.inputEl(), this.listAlign);
         this.list.show();
+        
+        if(this.tickable){
+            
+            this.tickItems = Roo.apply([], this.item);
+            
+            this.okBtn.show();
+            this.cancelBtn.show();
+            this.trigger.hide();
+            
+        }
+        
         Roo.get(document).on('mousedown', this.collapseIf, this);
         Roo.get(document).on('mousewheel', this.collapseIf, this);
         if (!this.editable) {
@@ -1086,7 +1429,7 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
 
     // private
     // Implements the default empty TriggerField.onTriggerClick function
-    onTriggerClick : function()
+    onTriggerClick : function(e)
     {
         Roo.log('trigger click');
         
@@ -1115,6 +1458,41 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
             }
         }
     },
+    
+    onTickableTriggerClick : function(e)
+    {
+        if(this.disabled){
+            return;
+        }
+        
+        this.page = 0;
+        this.loadNext = false;
+        this.hasFocus = true;
+        
+        if(this.triggerAction == 'all') {
+            this.doQuery(this.allQuery, true);
+        } else {
+            this.doQuery(this.getRawValue());
+        }
+    },
+    
+    onSearchFieldClick : function(e)
+    {
+        if(this.hasFocus || this.disabled || e.getTarget().nodeName.toLowerCase() == 'button'){
+            return;
+        }
+        
+        this.page = 0;
+        this.loadNext = false;
+        this.hasFocus = true;
+        
+        if(this.triggerAction == 'all') {
+            this.doQuery(this.allQuery, true);
+        } else {
+            this.doQuery(this.getRawValue());
+        }
+    },
+    
     listKeyPress : function(e)
     {
         //Roo.log('listkeypress');
@@ -1301,6 +1679,37 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         });
         
         this.syncValue();
+    },
+    
+    inputEl: function ()
+    {
+        if(this.tickable){
+            return this.searchField;
+        }
+        return this.el.select('input.form-control',true).first();
+    },
+    
+    
+    onTickableFooterButtonClick : function(e, btn, el)
+    {
+        e.preventDefault();
+        
+        if(btn && btn.name == 'cancel'){
+            this.tickItems = Roo.apply([], this.item);
+            this.collapse();
+            return;
+        }
+        
+        this.clearItem();
+        
+        var _this = this;
+        
+        Roo.each(this.tickItems, function(o){
+            _this.addItem(o);
+        });
+        
+        this.collapse();
+        
     }