Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Trigger.html
diff --git a/docs/source/Trigger.html b/docs/source/Trigger.html
new file mode 100644 (file)
index 0000000..c94ba30
--- /dev/null
@@ -0,0 +1,413 @@
+<!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-form.field.Trigger-method-constructor'><span id='Ext-form.field.Trigger'>/**
+</span></span> * @class Ext.form.field.Trigger
+ * @extends Ext.form.field.Text
+ * &lt;p&gt;Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
+ * The trigger has no default action, so you must assign a function to implement the trigger click handler by
+ * overriding {@link #onTriggerClick}. You can create a Trigger field directly, as it renders exactly like a combobox
+ * for which you can provide a custom implementation. 
+ * {@img Ext.form.field.Trigger/Ext.form.field.Trigger.png Ext.form.field.Trigger component}
+ * For example:&lt;/p&gt;
+ * &lt;pre&gt;&lt;code&gt;
+Ext.define('Ext.ux.CustomTrigger', {
+    extend: 'Ext.form.field.Trigger',
+    alias: 'widget.customtrigger',
+    
+    // override onTriggerClick
+    onTriggerClick: function() {
+        Ext.Msg.alert('Status', 'You clicked my trigger!');
+    }
+});
+
+Ext.create('Ext.form.FormPanel', {
+    title: 'Form with TriggerField',
+    bodyPadding: 5,
+    width: 350,
+    renderTo: Ext.getBody(),
+    items:[{
+        xtype: 'customtrigger',
+        fieldLabel: 'Sample Trigger',
+        emptyText: 'click the trigger',
+    }]
+});
+&lt;/code&gt;&lt;/pre&gt;
+ *
+ * &lt;p&gt;However, in general you will most likely want to use Trigger as the base class for a reusable component.
+ * {@link Ext.form.field.Date} and {@link Ext.form.field.ComboBox} are perfect examples of this.&lt;/p&gt;
+ *
+ * @constructor
+ * Create a new Trigger field.
+ * @param {Object} config Configuration options (valid {@Ext.form.field.Text} config options will also be applied
+ * to the base Text field)
+ * @xtype triggerfield
+ */
+Ext.define('Ext.form.field.Trigger', {
+    extend:'Ext.form.field.Text',
+    alias: ['widget.triggerfield', 'widget.trigger'],
+    requires: ['Ext.core.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
+    alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
+
+    fieldSubTpl: [
+        '&lt;input id=&quot;{id}&quot; type=&quot;{type}&quot; ',
+            '&lt;tpl if=&quot;name&quot;&gt;name=&quot;{name}&quot; &lt;/tpl&gt;',
+            '&lt;tpl if=&quot;size&quot;&gt;size=&quot;{size}&quot; &lt;/tpl&gt;',
+            '&lt;tpl if=&quot;tabIdx&quot;&gt;tabIndex=&quot;{tabIdx}&quot; &lt;/tpl&gt;',
+            'class=&quot;{fieldCls} {typeCls}&quot; autocomplete=&quot;off&quot; /&gt;',
+        '&lt;div class=&quot;{triggerWrapCls}&quot; role=&quot;presentation&quot;&gt;',
+            '{triggerEl}',
+            '&lt;div class=&quot;{clearCls}&quot; role=&quot;presentation&quot;&gt;&lt;/div&gt;',
+        '&lt;/div&gt;',
+        {
+            compiled: true,
+            disableFormats: true
+        }
+    ],
+
+<span id='Ext-form.field.Trigger-cfg-triggerCls'>    /**
+</span>     * @cfg {String} triggerCls
+     * An additional CSS class used to style the trigger button.  The trigger will always get the
+     * {@link #triggerBaseCls} by default and &lt;tt&gt;triggerCls&lt;/tt&gt; will be &lt;b&gt;appended&lt;/b&gt; if specified.
+     * Defaults to undefined.
+     */
+
+<span id='Ext-form.field.Trigger-cfg-triggerBaseCls'>    /**
+</span>     * @cfg {String} triggerBaseCls
+     * The base CSS class that is always added to the trigger button. The {@link #triggerCls} will be
+     * appended in addition to this class.
+     */
+    triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
+
+<span id='Ext-form.field.Trigger-cfg-triggerWrapCls'>    /**
+</span>     * @cfg {String} triggerWrapCls
+     * The CSS class that is added to the div wrapping the trigger button(s).
+     */
+    triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
+
+<span id='Ext-form.field.Trigger-cfg-hideTrigger'>    /**
+</span>     * @cfg {Boolean} hideTrigger &lt;tt&gt;true&lt;/tt&gt; to hide the trigger element and display only the base
+     * text field (defaults to &lt;tt&gt;false&lt;/tt&gt;)
+     */
+    hideTrigger: false,
+
+<span id='Ext-form.field.Trigger-cfg-editable'>    /**
+</span>     * @cfg {Boolean} editable &lt;tt&gt;false&lt;/tt&gt; to prevent the user from typing text directly into the field;
+     * the field can only have its value set via an action invoked by the trigger. (defaults to &lt;tt&gt;true&lt;/tt&gt;).
+     */
+    editable: true,
+
+<span id='Ext-form.field.Trigger-cfg-readOnly'>    /**
+</span>     * @cfg {Boolean} readOnly &lt;tt&gt;true&lt;/tt&gt; to prevent the user from changing the field, and
+     * hides the trigger.  Supercedes the editable and hideTrigger options if the value is true.
+     * (defaults to &lt;tt&gt;false&lt;/tt&gt;)
+     */
+    readOnly: false,
+
+<span id='Ext-form.field.Trigger-cfg-selectOnFocus'>    /**
+</span>     * @cfg {Boolean} selectOnFocus &lt;tt&gt;true&lt;/tt&gt; to select any existing text in the field immediately on focus.
+     * Only applies when &lt;tt&gt;{@link #editable editable} = true&lt;/tt&gt; (defaults to &lt;tt&gt;false&lt;/tt&gt;).
+     */
+
+<span id='Ext-form.field.Trigger-cfg-repeatTriggerClick'>    /**
+</span>     * @cfg {Boolean} repeatTriggerClick &lt;tt&gt;true&lt;/tt&gt; to attach a {@link Ext.util.ClickRepeater click repeater}
+     * to the trigger. Defaults to &lt;tt&gt;false&lt;/tt&gt;.
+     */
+    repeatTriggerClick: false,
+
+
+<span id='Ext-form.field.Trigger-method-autoSize'>    /**
+</span>     * @hide
+     * @method autoSize
+     */
+    autoSize: Ext.emptyFn,
+    // private
+    monitorTab: true,
+    // private
+    mimicing: false,
+    // private
+    triggerIndexRe: /trigger-index-(\d+)/,
+
+    componentLayout: 'triggerfield',
+
+    initComponent: function() {
+        this.wrapFocusCls = this.triggerWrapCls + '-focus';
+        this.callParent(arguments);
+    },
+
+    // private
+    onRender: function(ct, position) {
+        var me = this,
+            triggerCls,
+            triggerBaseCls = me.triggerBaseCls,
+            triggerWrapCls = me.triggerWrapCls,
+            triggerConfigs = [],
+            i;
+
+        // triggerCls is a synonym for trigger1Cls, so copy it.
+        // TODO this trigger&lt;n&gt;Cls API design doesn't feel clean, especially where it butts up against the
+        // single triggerCls config. Should rethink this, perhaps something more structured like a list of
+        // trigger config objects that hold cls, handler, etc.
+        if (!me.trigger1Cls) {
+            me.trigger1Cls = me.triggerCls;
+        }
+
+        // Create as many trigger elements as we have trigger&lt;n&gt;Cls configs, but always at least one
+        for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i &lt; 1; i++) {
+            triggerConfigs.push({
+                cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
+                role: 'button'
+            });
+        }
+        triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
+
+        Ext.applyIf(me.renderSelectors, {
+<span id='Ext-form.field.Trigger-property-triggerWrap'>            /**
+</span>             * @property triggerWrap
+             * @type Ext.core.Element
+             * A reference to the div element wrapping the trigger button(s). Only set after the field has been rendered.
+             */
+            triggerWrap: '.' + triggerWrapCls
+        });
+        Ext.applyIf(me.subTplData, {
+            triggerWrapCls: triggerWrapCls,
+            triggerEl: Ext.core.DomHelper.markup(triggerConfigs),
+            clearCls: me.clearCls
+        });
+
+        me.callParent(arguments);
+
+<span id='Ext-form.field.Trigger-property-triggerEl'>        /**
+</span>         * @property triggerEl
+         * @type Ext.CompositeElement
+         * A composite of all the trigger button elements. Only set after the field has been rendered.
+         */
+        me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
+
+        me.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
+        me.initTrigger();
+    },
+
+    onEnable: function() {
+        this.callParent();
+        this.triggerWrap.unmask();
+    },
+    
+    onDisable: function() {
+        this.callParent();
+        this.triggerWrap.mask();
+    },
+    
+    afterRender: function() {
+        this.callParent();
+        this.updateEditState();
+    },
+
+    updateEditState: function() {
+        var me = this,
+            inputEl = me.inputEl,
+            triggerWrap = me.triggerWrap,
+            noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
+            displayed,
+            readOnly;
+
+        if (me.rendered) {
+            if (me.readOnly) {
+                inputEl.addCls(noeditCls);
+                readOnly = true;
+                displayed = false;
+            } else {
+                if (me.editable) {
+                    inputEl.removeCls(noeditCls);
+                    readOnly = false;
+                } else {
+                    inputEl.addCls(noeditCls);
+                    readOnly = true;
+                }
+                displayed = !me.hideTrigger;
+            }
+
+            triggerWrap.setDisplayed(displayed);
+            inputEl.dom.readOnly = readOnly;
+            me.doComponentLayout();
+        }
+    },
+
+<span id='Ext-form.field.Trigger-method-getTriggerWidth'>    /**
+</span>     * Get the total width of the trigger button area. Only useful after the field has been rendered.
+     * @return {Number} The trigger width
+     */
+    getTriggerWidth: function() {
+        var me = this,
+            triggerWrap = me.triggerWrap,
+            totalTriggerWidth = 0;
+        if (triggerWrap &amp;&amp; !me.hideTrigger &amp;&amp; !me.readOnly) {
+            me.triggerEl.each(function(trigger) {
+                totalTriggerWidth += trigger.getWidth();
+            });
+            totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
+        }
+        return totalTriggerWidth;
+    },
+
+    setHideTrigger: function(hideTrigger) {
+        if (hideTrigger != this.hideTrigger) {
+            this.hideTrigger = hideTrigger;
+            this.updateEditState();
+        }
+    },
+
+<span id='Ext-form.field.Trigger-method-setEditable'>    /**
+</span>     * @param {Boolean} editable True to allow the user to directly edit the field text
+     * Allow or prevent the user from directly editing the field text.  If false is passed,
+     * the user will only be able to modify the field using the trigger.  Will also add
+     * a click event to the text field which will call the trigger. This method
+     * is the runtime equivalent of setting the 'editable' config option at config time.
+     */
+    setEditable: function(editable) {
+        if (editable != this.editable) {
+            this.editable = editable;
+            this.updateEditState();
+        }
+    },
+
+<span id='Ext-form.field.Trigger-method-setReadOnly'>    /**
+</span>     * @param {Boolean} readOnly True to prevent the user changing the field and explicitly
+     * hide the trigger.
+     * Setting this to true will superceed settings editable and hideTrigger.
+     * Setting this to false will defer back to editable and hideTrigger. This method
+     * is the runtime equivalent of setting the 'readOnly' config option at config time.
+     */
+    setReadOnly: function(readOnly) {
+        if (readOnly != this.readOnly) {
+            this.readOnly = readOnly;
+            this.updateEditState();
+        }
+    },
+
+    // private
+    initTrigger: function() {
+        var me = this,
+            triggerWrap = me.triggerWrap,
+            triggerEl = me.triggerEl;
+
+        if (me.repeatTriggerClick) {
+            me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
+                preventDefault: true,
+                handler: function(cr, e) {
+                    me.onTriggerWrapClick(e);
+                }
+            });
+        } else {
+            me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
+        }
+
+        triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
+        triggerEl.each(function(el, c, i) {
+            el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
+        });
+        triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
+        triggerEl.each(function(el, c, i) {
+            el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
+        });
+    },
+
+    // private
+    onDestroy: function() {
+        var me = this;
+        Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
+        delete me.doc;
+        me.callParent();
+    },
+
+    // private
+    onFocus: function() {
+        var me = this;
+        this.callParent();
+        if (!me.mimicing) {
+            me.bodyEl.addCls(me.wrapFocusCls);
+            me.mimicing = true;
+            me.mon(me.doc, 'mousedown', me.mimicBlur, me, {
+                delay: 10
+            });
+            if (me.monitorTab) {
+                me.on('specialkey', me.checkTab, me);
+            }
+        }
+    },
+
+    // private
+    checkTab: function(me, e) {
+        if (!this.ignoreMonitorTab &amp;&amp; e.getKey() == e.TAB) {
+            this.triggerBlur();
+        }
+    },
+
+    // private
+    onBlur: Ext.emptyFn,
+
+    // private
+    mimicBlur: function(e) {
+        if (!this.isDestroyed &amp;&amp; !this.bodyEl.contains(e.target) &amp;&amp; this.validateBlur(e)) {
+            this.triggerBlur();
+        }
+    },
+
+    // private
+    triggerBlur: function() {
+        var me = this;
+        me.mimicing = false;
+        me.mun(me.doc, 'mousedown', me.mimicBlur, me);
+        if (me.monitorTab &amp;&amp; me.inputEl) {
+            me.un('specialkey', me.checkTab, me);
+        }
+        Ext.form.field.Trigger.superclass.onBlur.call(me);
+        if (me.bodyEl) {
+            me.bodyEl.removeCls(me.wrapFocusCls);
+        }
+    },
+
+    beforeBlur: Ext.emptyFn,
+
+    // private
+    // This should be overridden by any subclass that needs to check whether or not the field can be blurred.
+    validateBlur: function(e) {
+        return true;
+    },
+
+    // private
+    // process clicks upon triggers.
+    // determine which trigger index, and dispatch to the appropriate click handler
+    onTriggerWrapClick: function(e) {
+        var me = this,
+            t = e &amp;&amp; e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
+            match = t &amp;&amp; t.className.match(me.triggerIndexRe),
+            idx,
+            triggerClickMethod;
+
+        if (match &amp;&amp; !me.readOnly) {
+            idx = parseInt(match[1], 10);
+            triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
+            if (triggerClickMethod) {
+                triggerClickMethod.call(me, e);
+            }
+        }
+    },
+
+<span id='Ext-form.field.Trigger-method-onTriggerClick'>    /**
+</span>     * The function that should handle the trigger's click event.  This method does nothing by default
+     * until overridden by an implementing function.  See Ext.form.field.ComboBox and Ext.form.field.Date for
+     * sample implementations.
+     * @method
+     * @param {Ext.EventObject} e
+     */
+    onTriggerClick: Ext.emptyFn
+
+<span id='Ext-form.field.Trigger-cfg-grow'>    /**
+</span>     * @cfg {Boolean} grow @hide
+     */
+<span id='Ext-form.field.Trigger-cfg-growMin'>    /**
+</span>     * @cfg {Number} growMin @hide
+     */
+<span id='Ext-form.field.Trigger-cfg-growMax'>    /**
+</span>     * @cfg {Number} growMax @hide
+     */
+});
+</pre></pre></body></html>
\ No newline at end of file