4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-form-field-Trigger'>/**
19 </span> * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
20 * The trigger has no default action, so you must assign a function to implement the trigger click handler by overriding
21 * {@link #onTriggerClick}. You can create a Trigger field directly, as it renders exactly like a combobox for which you
22 * can provide a custom implementation.
27 * Ext.define('Ext.ux.CustomTrigger', {
28 * extend: 'Ext.form.field.Trigger',
29 * alias: 'widget.customtrigger',
31 * // override onTriggerClick
32 * onTriggerClick: function() {
33 * Ext.Msg.alert('Status', 'You clicked my trigger!');
37 * Ext.create('Ext.form.FormPanel', {
38 * title: 'Form with TriggerField',
41 * renderTo: Ext.getBody(),
43 * xtype: 'customtrigger',
44 * fieldLabel: 'Sample Trigger',
45 * emptyText: 'click the trigger',
49 * However, in general you will most likely want to use Trigger as the base class for a reusable component.
50 * {@link Ext.form.field.Date} and {@link Ext.form.field.ComboBox} are perfect examples of this.
52 Ext.define('Ext.form.field.Trigger', {
53 extend:'Ext.form.field.Text',
54 alias: ['widget.triggerfield', 'widget.trigger'],
55 requires: ['Ext.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
56 alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
58 // note: {id} here is really {inputId}, but {cmpId} is available
60 '<input id="{id}" type="{type}" ',
61 '<tpl if="name">name="{name}" </tpl>',
62 '<tpl if="size">size="{size}" </tpl>',
63 '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
64 'class="{fieldCls} {typeCls}" autocomplete="off" />',
65 '<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
67 '<div class="{clearCls}" role="presentation"></div>',
75 <span id='Ext-form-field-Trigger-cfg-triggerCls'> /**
76 </span> * @cfg {String} triggerCls
77 * An additional CSS class used to style the trigger button. The trigger will always get the {@link #triggerBaseCls}
78 * by default and triggerCls will be **appended** if specified.
81 <span id='Ext-form-field-Trigger-cfg-triggerBaseCls'> /**
82 </span> * @cfg {String} [triggerBaseCls='x-form-trigger']
83 * The base CSS class that is always added to the trigger button. The {@link #triggerCls} will be appended in
84 * addition to this class.
86 triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
88 <span id='Ext-form-field-Trigger-cfg-triggerWrapCls'> /**
89 </span> * @cfg {String} [triggerWrapCls='x-form-trigger-wrap']
90 * The CSS class that is added to the div wrapping the trigger button(s).
92 triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
94 <span id='Ext-form-field-Trigger-cfg-hideTrigger'> /**
95 </span> * @cfg {Boolean} hideTrigger
96 * true to hide the trigger element and display only the base text field
100 <span id='Ext-form-field-Trigger-cfg-editable'> /**
101 </span> * @cfg {Boolean} editable
102 * false to prevent the user from typing text directly into the field; the field can only have its value set via an
103 * action invoked by the trigger.
107 <span id='Ext-form-field-Trigger-cfg-readOnly'> /**
108 </span> * @cfg {Boolean} readOnly
109 * true to prevent the user from changing the field, and hides the trigger. Supercedes the editable and hideTrigger
110 * options if the value is true.
114 <span id='Ext-form-field-Trigger-cfg-selectOnFocus'> /**
115 </span> * @cfg {Boolean} [selectOnFocus=false]
116 * true to select any existing text in the field immediately on focus. Only applies when
117 * {@link #editable editable} = true
120 <span id='Ext-form-field-Trigger-cfg-repeatTriggerClick'> /**
121 </span> * @cfg {Boolean} repeatTriggerClick
122 * true to attach a {@link Ext.util.ClickRepeater click repeater} to the trigger.
124 repeatTriggerClick: false,
127 <span id='Ext-form-field-Trigger-method-autoSize'> /**
131 autoSize: Ext.emptyFn,
137 triggerIndexRe: /trigger-index-(\d+)/,
139 componentLayout: 'triggerfield',
141 initComponent: function() {
142 this.wrapFocusCls = this.triggerWrapCls + '-focus';
143 this.callParent(arguments);
147 onRender: function(ct, position) {
150 triggerBaseCls = me.triggerBaseCls,
151 triggerWrapCls = me.triggerWrapCls,
155 // triggerCls is a synonym for trigger1Cls, so copy it.
156 // TODO this trigger<n>Cls API design doesn't feel clean, especially where it butts up against the
157 // single triggerCls config. Should rethink this, perhaps something more structured like a list of
158 // trigger config objects that hold cls, handler, etc.
159 if (!me.trigger1Cls) {
160 me.trigger1Cls = me.triggerCls;
163 // Create as many trigger elements as we have trigger<n>Cls configs, but always at least one
164 for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) {
165 triggerConfigs.push({
166 cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
170 triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
172 <span id='Ext-form-field-Trigger-property-triggerWrap'> /**
173 </span> * @property {Ext.Element} triggerWrap
174 * A reference to the div element wrapping the trigger button(s). Only set after the field has been rendered.
176 me.addChildEls('triggerWrap');
178 Ext.applyIf(me.subTplData, {
179 triggerWrapCls: triggerWrapCls,
180 triggerEl: Ext.DomHelper.markup(triggerConfigs),
181 clearCls: me.clearCls
184 me.callParent(arguments);
186 <span id='Ext-form-field-Trigger-property-triggerEl'> /**
187 </span> * @property {Ext.CompositeElement} triggerEl
188 * A composite of all the trigger button elements. Only set after the field has been rendered.
190 me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
192 me.doc = Ext.getDoc();
196 onEnable: function() {
198 this.triggerWrap.unmask();
201 onDisable: function() {
203 this.triggerWrap.mask();
206 afterRender: function() {
208 this.updateEditState();
209 this.triggerEl.unselectable();
212 updateEditState: function() {
214 inputEl = me.inputEl,
215 triggerWrap = me.triggerWrap,
216 noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
222 inputEl.addCls(noeditCls);
227 inputEl.removeCls(noeditCls);
230 inputEl.addCls(noeditCls);
233 displayed = !me.hideTrigger;
236 triggerWrap.setDisplayed(displayed);
237 inputEl.dom.readOnly = readOnly;
238 me.doComponentLayout();
242 <span id='Ext-form-field-Trigger-method-getTriggerWidth'> /**
243 </span> * Get the total width of the trigger button area. Only useful after the field has been rendered.
244 * @return {Number} The trigger width
246 getTriggerWidth: function() {
248 triggerWrap = me.triggerWrap,
249 totalTriggerWidth = 0;
250 if (triggerWrap && !me.hideTrigger && !me.readOnly) {
251 me.triggerEl.each(function(trigger) {
252 totalTriggerWidth += trigger.getWidth();
254 totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
256 return totalTriggerWidth;
259 setHideTrigger: function(hideTrigger) {
260 if (hideTrigger != this.hideTrigger) {
261 this.hideTrigger = hideTrigger;
262 this.updateEditState();
266 <span id='Ext-form-field-Trigger-method-setEditable'> /**
267 </span> * Sets the editable state of this field. This method is the runtime equivalent of setting the 'editable' config
268 * option at config time.
269 * @param {Boolean} editable True to allow the user to directly edit the field text. If false is passed, the user
270 * will only be able to modify the field using the trigger. Will also add a click event to the text field which
271 * will call the trigger.
273 setEditable: function(editable) {
274 if (editable != this.editable) {
275 this.editable = editable;
276 this.updateEditState();
280 <span id='Ext-form-field-Trigger-method-setReadOnly'> /**
281 </span> * Sets the read-only state of this field. This method is the runtime equivalent of setting the 'readOnly' config
282 * option at config time.
283 * @param {Boolean} readOnly True to prevent the user changing the field and explicitly hide the trigger. Setting
284 * this to true will superceed settings editable and hideTrigger. Setting this to false will defer back to editable
287 setReadOnly: function(readOnly) {
288 if (readOnly != this.readOnly) {
289 this.readOnly = readOnly;
290 this.updateEditState();
295 initTrigger: function() {
297 triggerWrap = me.triggerWrap,
298 triggerEl = me.triggerEl;
300 if (me.repeatTriggerClick) {
301 me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
302 preventDefault: true,
303 handler: function(cr, e) {
304 me.onTriggerWrapClick(e);
308 me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
311 triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
312 triggerEl.each(function(el, c, i) {
313 el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
315 triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
316 triggerEl.each(function(el, c, i) {
317 el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
322 onDestroy: function() {
324 Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
330 onFocus: function() {
334 me.bodyEl.addCls(me.wrapFocusCls);
336 me.mon(me.doc, 'mousedown', me.mimicBlur, me, {
340 me.on('specialkey', me.checkTab, me);
346 checkTab: function(me, e) {
347 if (!this.ignoreMonitorTab && e.getKey() == e.TAB) {
356 mimicBlur: function(e) {
357 if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) {
363 triggerBlur: function() {
366 me.mun(me.doc, 'mousedown', me.mimicBlur, me);
367 if (me.monitorTab && me.inputEl) {
368 me.un('specialkey', me.checkTab, me);
370 Ext.form.field.Trigger.superclass.onBlur.call(me);
372 me.bodyEl.removeCls(me.wrapFocusCls);
376 beforeBlur: Ext.emptyFn,
379 // This should be overridden by any subclass that needs to check whether or not the field can be blurred.
380 validateBlur: function(e) {
385 // process clicks upon triggers.
386 // determine which trigger index, and dispatch to the appropriate click handler
387 onTriggerWrapClick: function(e) {
389 t = e && e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
390 match = t && t.className.match(me.triggerIndexRe),
394 if (match && !me.readOnly) {
395 idx = parseInt(match[1], 10);
396 triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
397 if (triggerClickMethod) {
398 triggerClickMethod.call(me, e);
403 <span id='Ext-form-field-Trigger-method-onTriggerClick'> /**
404 </span> * @method onTriggerClick
406 * The function that should handle the trigger's click event. This method does nothing by default until overridden
407 * by an implementing function. See Ext.form.field.ComboBox and Ext.form.field.Date for sample implementations.
408 * @param {Ext.EventObject} e
410 onTriggerClick: Ext.emptyFn
412 <span id='Ext-form-field-Trigger-cfg-grow'> /**
413 </span> * @cfg {Boolean} grow @hide
415 <span id='Ext-form-field-Trigger-cfg-growMin'> /**
416 </span> * @cfg {Number} growMin @hide
418 <span id='Ext-form-field-Trigger-cfg-growMax'> /**
419 </span> * @cfg {Number} growMax @hide