allow string based values for comboboxarray
[roojs1] / Roo / form / TriggerField.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11  
12 /**
13  * @class Roo.form.TriggerField
14  * @extends Roo.form.TextField
15  * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
16  * The trigger has no default action, so you must assign a function to implement the trigger click handler by
17  * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox
18  * for which you can provide a custom implementation.  For example:
19  * <pre><code>
20 var trigger = new Roo.form.TriggerField();
21 trigger.onTriggerClick = myTriggerFn;
22 trigger.applyTo('my-field');
23 </code></pre>
24  *
25  * However, in general you will most likely want to use TriggerField as the base class for a reusable component.
26  * {@link Roo.form.DateField} and {@link Roo.form.ComboBox} are perfect examples of this.
27  * @cfg {String} triggerClass An additional CSS class used to style the trigger button.  The trigger will always get the
28  * class 'x-form-trigger' by default and triggerClass will be <b>appended</b> if specified.
29  * @constructor
30  * Create a new TriggerField.
31  * @param {Object} config Configuration options (valid {@Roo.form.TextField} config options will also be applied
32  * to the base TextField)
33  */
34 Roo.form.TriggerField = function(config){
35     this.mimicing = false;
36     Roo.form.TriggerField.superclass.constructor.call(this, config);
37 };
38
39 Roo.extend(Roo.form.TriggerField, Roo.form.TextField,  {
40     /**
41      * @cfg {String} triggerClass A CSS class to apply to the trigger
42      */
43     /**
44      * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
45      * {tag: "input", type: "text", size: "16", autocomplete: "off"})
46      */
47     defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "new-password"},
48     /**
49      * @cfg {Boolean} hideTrigger True to hide the trigger element and display only the base text field (defaults to false)
50      */
51     hideTrigger:false,
52
53     /** @cfg {Boolean} grow @hide */
54     /** @cfg {Number} growMin @hide */
55     /** @cfg {Number} growMax @hide */
56
57     /**
58      * @hide 
59      * @method
60      */
61     autoSize: Roo.emptyFn,
62     // private
63     monitorTab : true,
64     // private
65     deferHeight : true,
66
67     
68     actionMode : 'wrap',
69     // private
70     onResize : function(w, h){
71         Roo.form.TriggerField.superclass.onResize.apply(this, arguments);
72         if(typeof w == 'number'){
73             var x = w - this.trigger.getWidth();
74             this.el.setWidth(this.adjustWidth('input', x));
75             this.trigger.setStyle('left', x+'px');
76         }
77     },
78
79     // private
80     adjustSize : Roo.BoxComponent.prototype.adjustSize,
81
82     // private
83     getResizeEl : function(){
84         return this.wrap;
85     },
86
87     // private
88     getPositionEl : function(){
89         return this.wrap;
90     },
91
92     // private
93     alignErrorIcon : function(){
94         this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
95     },
96
97     // private
98     onRender : function(ct, position){
99         Roo.form.TriggerField.superclass.onRender.call(this, ct, position);
100         this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
101         this.trigger = this.wrap.createChild(this.triggerConfig ||
102                 {tag: "img", src: Roo.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
103         if(this.hideTrigger){
104             this.trigger.setDisplayed(false);
105         }
106         this.initTrigger();
107         if(!this.width){
108             this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
109         }
110     },
111
112     // private
113     initTrigger : function(){
114         this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
115         this.trigger.addClassOnOver('x-form-trigger-over');
116         this.trigger.addClassOnClick('x-form-trigger-click');
117     },
118
119     // private
120     onDestroy : function(){
121         if(this.trigger){
122             this.trigger.removeAllListeners();
123             this.trigger.remove();
124         }
125         if(this.wrap){
126             this.wrap.remove();
127         }
128         Roo.form.TriggerField.superclass.onDestroy.call(this);
129     },
130
131     // private
132     onFocus : function(){
133         Roo.form.TriggerField.superclass.onFocus.call(this);
134         if(!this.mimicing){
135             this.wrap.addClass('x-trigger-wrap-focus');
136             this.mimicing = true;
137             Roo.get(Roo.isIE ? document.body : document).on("mousedown", this.mimicBlur, this);
138             if(this.monitorTab){
139                 this.el.on("keydown", this.checkTab, this);
140             }
141         }
142     },
143
144     // private
145     checkTab : function(e){
146         if(e.getKey() == e.TAB){
147             this.triggerBlur();
148         }
149     },
150
151     // private
152     onBlur : function(){
153         // do nothing
154     },
155
156     // private
157     mimicBlur : function(e, t){
158         if(!this.wrap.contains(t) && this.validateBlur()){
159             this.triggerBlur();
160         }
161     },
162
163     // private
164     triggerBlur : function(){
165         this.mimicing = false;
166         Roo.get(Roo.isIE ? document.body : document).un("mousedown", this.mimicBlur);
167         if(this.monitorTab){
168             this.el.un("keydown", this.checkTab, this);
169         }
170         this.wrap.removeClass('x-trigger-wrap-focus');
171         Roo.form.TriggerField.superclass.onBlur.call(this);
172     },
173
174     // private
175     // This should be overriden by any subclass that needs to check whether or not the field can be blurred.
176     validateBlur : function(e, t){
177         return true;
178     },
179
180     // private
181     onDisable : function(){
182         Roo.form.TriggerField.superclass.onDisable.call(this);
183         if(this.wrap){
184             this.wrap.addClass('x-item-disabled');
185         }
186     },
187
188     // private
189     onEnable : function(){
190         Roo.form.TriggerField.superclass.onEnable.call(this);
191         if(this.wrap){
192             this.wrap.removeClass('x-item-disabled');
193         }
194     },
195
196     // private
197     onShow : function(){
198         var ae = this.getActionEl();
199         
200         if(ae){
201             ae.dom.style.display = '';
202             ae.dom.style.visibility = 'visible';
203         }
204     },
205
206     // private
207     
208     onHide : function(){
209         var ae = this.getActionEl();
210         ae.dom.style.display = 'none';
211     },
212
213     /**
214      * The function that should handle the trigger's click event.  This method does nothing by default until overridden
215      * by an implementing function.
216      * @method
217      * @param {EventObject} e
218      */
219     onTriggerClick : Roo.emptyFn
220 });
221
222 // TwinTriggerField is not a public class to be used directly.  It is meant as an abstract base class
223 // to be extended by an implementing class.  For an example of implementing this class, see the custom
224 // SearchField implementation here: http://extjs.com/deploy/ext/examples/form/custom.html
225 Roo.form.TwinTriggerField = Roo.extend(Roo.form.TriggerField, {
226     initComponent : function(){
227         Roo.form.TwinTriggerField.superclass.initComponent.call(this);
228
229         this.triggerConfig = {
230             tag:'span', cls:'x-form-twin-triggers', cn:[
231             {tag: "img", src: Roo.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
232             {tag: "img", src: Roo.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
233         ]};
234     },
235
236     getTrigger : function(index){
237         return this.triggers[index];
238     },
239
240     initTrigger : function(){
241         var ts = this.trigger.select('.x-form-trigger', true);
242         this.wrap.setStyle('overflow', 'hidden');
243         var triggerField = this;
244         ts.each(function(t, all, index){
245             t.hide = function(){
246                 var w = triggerField.wrap.getWidth();
247                 this.dom.style.display = 'none';
248                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
249             };
250             t.show = function(){
251                 var w = triggerField.wrap.getWidth();
252                 this.dom.style.display = '';
253                 triggerField.el.setWidth(w-triggerField.trigger.getWidth());
254             };
255             var triggerIndex = 'Trigger'+(index+1);
256
257             if(this['hide'+triggerIndex]){
258                 t.dom.style.display = 'none';
259             }
260             t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});
261             t.addClassOnOver('x-form-trigger-over');
262             t.addClassOnClick('x-form-trigger-click');
263         }, this);
264         this.triggers = ts.elements;
265     },
266
267     onTrigger1Click : Roo.emptyFn,
268     onTrigger2Click : Roo.emptyFn
269 });