roojs-ui.js
[roojs1] / Roo / form / ComboBox.js
index 1773bc6..0117cc2 100644 (file)
@@ -67,10 +67,10 @@ Roo.form.ComboBox = function(config){
             */
         'add' : true,
         /**
-         * @event add
+         * @event edit
          * Fires when the 'edit' icon is pressed (add a listener to enable add button)
             * @param {Roo.form.ComboBox} combo This combo box
-            * @param {Roo.data.Record} record The data record returned from the underlying store (or false on clear)
+            * @param {Roo.data.Record|false} record The data record returned from the underlying store (or false on nothing selected)
             */
         'edit' : true
         
@@ -169,6 +169,8 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
      * in order for a value to be mapped.
      */
     valueField: undefined,
+    
+    
     /**
      * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the
      * field's data value (defaults to the underlying DOM element's name)
@@ -282,15 +284,25 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
      */
     valueNotFoundText : undefined,
     /**
-     * @cfg {bool} blockFocus Prevents all focus calls, so it can work with things like HTML edtor bar
+     * @cfg {Boolean} blockFocus Prevents all focus calls, so it can work with things like HTML edtor bar
      */
     blockFocus : false,
     
     /**
-     * @cfg {bool} disableClear Disable showing of clear button.
+     * @cfg {Boolean} disableClear Disable showing of clear button.
      */
     disableClear : false,
+    /**
+     * @cfg {Boolean} alwaysQuery  Disable caching of results, and always send query
+     */
+    alwaysQuery : false,
+    
+    //private
+    addicon : false,
+    editicon: false,
     
+    // element that contains real text value.. (when hidden is used..)
+     
     // private
     onRender : function(ct, position){
         Roo.form.ComboBox.superclass.onRender.call(this, ct, position);
@@ -303,6 +315,8 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
 
             // prevent input submission
             this.el.dom.removeAttribute('name');
+             
+             
         }
         if(Roo.isGecko){
             this.el.dom.setAttribute('autocomplete', 'off');
@@ -371,7 +385,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
 
         this.store.on('beforeload', this.onBeforeLoad, this);
         this.store.on('load', this.onLoad, this);
-        this.store.on('loadexception', this.collapse, this);
+        this.store.on('loadexception', this.onLoadException, this);
 
         if(this.resizable){
             this.resizer = new Roo.Resizable(this.list,  {
@@ -388,19 +402,32 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         if(!this.editable){
             this.editable = true;
             this.setEditable(false);
-        }
+        }  
         
         
         if (typeof(this.events.add.listeners) != 'undefined') {
             
             this.addicon = this.wrap.createChild(
-                {tag: 'img', src: Ext.BLANK_IMAGE_URL, cls: 'x-form-combo-add' });  
+                {tag: 'img', src: Roo.BLANK_IMAGE_URL, cls: 'x-form-combo-add' });  
        
-            this.adder.on('click', function(e) {
-                this.fireEvent('adderclick', this, e);
+            this.addicon.on('click', function(e) {
+                this.fireEvent('add', this);
+            }, this);
+        }
+        if (typeof(this.events.edit.listeners) != 'undefined') {
+            
+            this.editicon = this.wrap.createChild(
+                {tag: 'img', src: Roo.BLANK_IMAGE_URL, cls: 'x-form-combo-edit' });  
+            if (this.addicon) {
+                this.editicon.setStyle('margin-left', '40px');
+            }
+            this.editicon.on('click', function(e) {
+                
+                // we fire even  if inothing is selected..
+                this.fireEvent('edit', this, this.lastData );
+                
             }, this);
         }
-        
         
         
         
@@ -436,6 +463,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
 
             "tab" : function(e){
                 this.onViewClick(false);
+                this.fireEvent("specialkey", this, e);
                 return true;
             },
 
@@ -477,7 +505,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         if(this.store){
             this.store.un('beforeload', this.onBeforeLoad, this);
             this.store.un('load', this.onLoad, this);
-            this.store.un('loadexception', this.collapse, this);
+            this.store.un('loadexception', this.onLoadException, this);
         }
         Roo.form.ComboBox.superclass.onDestroy.call(this);
     },
@@ -492,11 +520,27 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
     // private
     onResize: function(w, h){
         Roo.form.ComboBox.superclass.onResize.apply(this, arguments);
+        
+        if(typeof w != 'number'){
+            // we do not handle it!?!?
+            return;
+        }
+        var tw = this.trigger.getWidth();
+        tw += this.addicon ? this.addicon.getWidth() : 0;
+        tw += this.editicon ? this.editicon.getWidth() : 0;
+        var x = w - tw;
+        this.el.setWidth( this.adjustWidth('input', x));
+            
+        this.trigger.setStyle('left', x+'px');
+        
         if(this.list && this.listWidth === undefined){
-            var lw = Math.max(w, this.minListWidth);
+            var lw = Math.max(x + this.trigger.getWidth(), this.minListWidth);
             this.list.setWidth(lw);
             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
         }
+        
+    
+        
     },
 
     /**
@@ -558,7 +602,17 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         }
         //this.el.focus();
     },
-
+    // private
+    onLoadException : function()
+    {
+        this.collapse();
+        Roo.log(this.store.reader.jsonData);
+        if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
+            Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
+        }
+        
+        
+    },
     // private
     onTypeAhead : function(){
         if(this.store.getCount() > 0){
@@ -589,9 +643,8 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
     getValue : function(){
         if(this.valueField){
             return typeof this.value != 'undefined' ? this.value : '';
-        }else{
-            return Roo.form.ComboBox.superclass.getValue.call(this);
         }
+        return Roo.form.ComboBox.superclass.getValue.call(this);
     },
 
     /**
@@ -604,7 +657,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         this.value = '';
         this.setRawValue('');
         this.lastSelectionText = '';
-        this.applyEmptyText();
+        
     },
 
     /**
@@ -648,7 +701,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
             dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
         } else {
             // this is an error condition!!!
-            console.log('no value field set for '+ this.name);
+            Roo.log('no  displayField value set for '+ (this.name ? this.name : this.id));
         }
         
         if(this.valueField){
@@ -673,9 +726,13 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
     // private
     reset : function(){
         // overridden so that last data is reset..
-        this.setValue(this.originalValue);
+        this.setValue(this.resetValue);
+        this.originalValue = this.getValue();
         this.clearInvalid();
         this.lastData = false;
+        if (this.view) {
+            this.view.clearSelections();
+        }
     },
     // private
     findRecord : function(prop, value){
@@ -686,11 +743,19 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
                     record = r;
                     return false;
                 }
+                return true;
             });
         }
         return record;
     },
-
+    
+    getName: function()
+    {
+        // returns hidden if it's set..
+        if (!this.rendered) {return ''};
+        return !this.hiddenName && this.el.dom.name  ? this.el.dom.name : (this.hiddenName || '');
+        
+    },
     // private
     onViewMove : function(e, t){
         this.inKeyMode = false;
@@ -709,7 +774,8 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
     },
 
     // private
-    onViewClick : function(doFocus){
+    onViewClick : function(doFocus)
+    {
         var index = this.view.getSelectedIndexes()[0];
         var r = this.store.getAt(index);
         if(r){
@@ -828,7 +894,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         if(this.el.dom.value.length > 0){
             this.el.dom.value =
                 this.lastSelectionText === undefined ? '' : this.lastSelectionText;
-            this.applyEmptyText();
+             
         }
     },
 
@@ -856,7 +922,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         q = qe.query;
         forceAll = qe.forceAll;
         if(forceAll === true || (q.length >= this.minChars)){
-            if(this.lastQuery != q){
+            if(this.lastQuery != q || this.alwaysQuery){
                 this.lastQuery = q;
                 if(this.mode == 'local'){
                     this.selectedIndex = -1;
@@ -901,6 +967,9 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         this.list.hide();
         Roo.get(document).un('mousedown', this.collapseIf, this);
         Roo.get(document).un('mousewheel', this.collapseIf, this);
+        if (!this.editable) {
+            Roo.get(document).un('keydown', this.listKeyPress, this);
+        }
         this.fireEvent('collapse', this);
     },
 
@@ -922,6 +991,10 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         this.list.show();
         Roo.get(document).on('mousedown', this.collapseIf, this);
         Roo.get(document).on('mousewheel', this.collapseIf, this);
+        if (!this.editable) {
+            Roo.get(document).on('keydown', this.listKeyPress, this);
+        }
+        
         this.fireEvent('expand', this);
     },
 
@@ -948,7 +1021,51 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
                 this.el.focus();
             }
         }
-    }
+    },
+    listKeyPress : function(e)
+    {
+        //Roo.log('listkeypress');
+        // scroll to first matching element based on key pres..
+        if (e.isSpecialKey()) {
+            return false;
+        }
+        var k = String.fromCharCode(e.getKey()).toUpperCase();
+        //Roo.log(k);
+        var match  = false;
+        var csel = this.view.getSelectedNodes();
+        var cselitem = false;
+        if (csel.length) {
+            var ix = this.view.indexOf(csel[0]);
+            cselitem  = this.store.getAt(ix);
+            if (!cselitem.get(this.displayField) || cselitem.get(this.displayField).substring(0,1).toUpperCase() != k) {
+                cselitem = false;
+            }
+            
+        }
+        
+        this.store.each(function(v) { 
+            if (cselitem) {
+                // start at existing selection.
+                if (cselitem.id == v.id) {
+                    cselitem = false;
+                }
+                return;
+            }
+                
+            if (v.get(this.displayField) && v.get(this.displayField).substring(0,1).toUpperCase() == k) {
+                match = this.store.indexOf(v);
+                return false;
+            }
+        }, this);
+        
+        if (match === false) {
+            return true; // no more action?
+        }
+        // scroll to?
+        this.view.select(match);
+        var sn = Roo.get(this.view.getSelectedNodes()[0]);
+        sn.scrollIntoView(sn.dom.parentNode, false);
+    } 
 
     /** 
     * @cfg {Boolean} grow