Last active
October 16, 2016 10:26
-
-
Save ExtAnimal/db5994292aaade756ef8d6c4384063bd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Text Field {@link Ext.field.Text#triggers trigger} widget. | |
*/ | |
Ext.define('Ext.field.trigger.Trigger', { | |
extend: 'Ext.Widget', | |
xtype: 'trigger', | |
alias: 'trigger.trigger', | |
requires: [ | |
'Ext.util.ClickRepeater' | |
], | |
mixins: [ | |
'Ext.mixin.Factoryable' | |
], | |
factoryConfig: { | |
defaultType: 'trigger', | |
aliasPrefix: 'trigger.' | |
}, | |
isTrigger: true, | |
/** | |
* @cfg {Boolean} [preventMouseDown=true] | |
* @private | |
* If true, preventDefault() will be called on the mousedown event. This prevents | |
* a click on the trigger from blurring the field, which is desirable in most cases. | |
* File field sets this to false, because preventing the default behavior of touchstart | |
* prevents the browser's file dialog from opening. | |
*/ | |
preventMouseDown: true, | |
/** | |
* @cfg {Boolean} [focusOnMouseDown=false] If `true`, the field will be focused upon | |
* mousedown on the trigger. This should be used only for main Picker field triggers | |
* that expand and collapse the picker; additional triggers should not focus the field. | |
* @private | |
*/ | |
focusOnMousedown: false, | |
config: { | |
/** | |
* @cfg {Ext.field.Text} | |
* The text field that created this trigger | |
* @private | |
*/ | |
field: null, | |
/** | |
* @cfg {String} [group] | |
* The name of an optional group trigger that this trigger belongs to. If no trigger | |
* Exists by that name one will automatically be created. A group trigger is a | |
* special trigger that contains other triggers. Those triggers' elements are | |
* appended to the group trigger's element in the DOM. | |
* | |
* The {@link #weight} of grouped triggers is relative to other triggers in the group. | |
*/ | |
group: null, | |
/** | |
* @cfg {Function/String} [handler=undefined] | |
* Function to run when trigger is clicked or tapped. | |
* @controllable | |
*/ | |
handler: null, | |
/** | |
* @cfg {String} | |
* @inheritdoc Ext.Button#iconCls | |
*/ | |
iconCls: null, | |
/** | |
* @cfg {Boolean/Object} | |
* `true` to attach a {@link Ext.util.ClickRepeater tap repeater} to the trigger, | |
* or a config object for a tap repeater. | |
*/ | |
repeat: null, | |
/** | |
* @cfg {'left'/'right'} [side='right'] | |
* The side of the text field's input to render the trigger on. | |
*/ | |
side: null, | |
/** | |
* @cfg {Object} [scope] | |
* Execution context for the {@link #handler} function. | |
*/ | |
scope: null, | |
/** | |
* @cfg {String} | |
* The key used to identify this trigger in the text field's triggers config. | |
* @private | |
*/ | |
name: null, | |
/** | |
* The triggers contained in this trigger (only applicable for trigger groups) | |
* @private | |
*/ | |
triggers: null, | |
weight: null | |
}, | |
classCls: Ext.baseCSSPrefix + 'trigger', | |
interactiveCls: Ext.baseCSSPrefix + 'interactive', | |
groupedCls: Ext.baseCSSPrefix + 'grouped', | |
template: [{ | |
reference: 'iconElement', | |
classList: [ | |
Ext.baseCSSPrefix + 'icon-el', | |
Ext.baseCSSPrefix + 'font-icon' | |
] | |
}], | |
statics: { | |
/** | |
* Sorts an array of triggers in place by weight | |
* @param {Ext.field.Trigger[]} triggers | |
* @return {Ext.field.Trigger[]} | |
* @private | |
* @static | |
*/ | |
sort: function(triggers) { | |
Ext.Array.sort(triggers, this.weightComparator); | |
return triggers; | |
}, | |
/** | |
* Comparison function for sorting an array of triggers in ascending order | |
* @param {Ext.form.field.Trigger} triggerA | |
* @param {Ext.form.field.Trigger} triggerB | |
* @return {Number} | |
* @private | |
* @static | |
*/ | |
weightComparator: function(triggerA, triggerB) { | |
return (triggerA.getWeight() || 0) - (triggerB.getWeight() || 0); | |
} | |
}, | |
constructor: function(config) { | |
var me = this, | |
element, repeat; | |
me.callParent([config]); | |
element = me.element; | |
repeat = me.getRepeat(); | |
if (repeat) { | |
me.repeater = new Ext.util.ClickRepeater(Ext.apply({ | |
target: me, | |
preventDefault: true, | |
listeners: { | |
mousedown: me.onClickRepeaterTouchStart, | |
mouseup: me.onClickRepeaterTouchEnd, | |
click: me.onClick, | |
scope: me | |
} | |
}, repeat)); | |
} else { | |
element.on({ | |
click: me.onClick, | |
mousedown: me.onMouseDown, | |
scope: me | |
}); | |
} | |
}, | |
doDestroy: function() { | |
var triggers = this.getTriggers(), | |
i, ln; | |
if (triggers) { | |
for (i = 0, ln = triggers.length; i < ln; i++) { | |
triggers[i].destroy(); | |
} | |
} | |
this.setTriggers(null); | |
Ext.destroyMembers(this, 'repeater'); | |
this.callParent(); | |
}, | |
onClick: function(e) { | |
var me = this, | |
handler = me.getHandler(), | |
field = me.getField(); | |
// TODO: skip this if readonly? !editable? | |
if (handler) { | |
Ext.callback(handler, me.getScope(), [field, me, e], null, field); | |
} | |
}, | |
onMouseDown: function(e) { | |
var field = this.getField(); | |
// If it was a genuine mousedown or pointerdown, NOT a touch, then focus the input field. | |
// Usually, the field will be focused, but the mousedown on the trigger | |
// might be the user's first contact with the field. | |
// It's definitely NOT the user's first contact with our field if the field | |
// has the focus. | |
// It is also possible that there are multiple triggers on the field, and only one | |
// of them causes picker expand/collapse. When picker is about to be collapsed | |
// we need to focus the input; otherwise if the picker was focused the focus will go | |
// to the document body which is not what we want. However if the mousedown was on | |
// a trigger that does not cause collapse we should NOT focus the field. | |
if (field && e.pointerType !== 'touch' && (!field.containsFocus || this.focusOnMousedown)) { | |
field.focus(); | |
} | |
if (this.preventMouseDown) { | |
// Stop the mousedown from blurring our field | |
e.preventDefault(); | |
} | |
}, | |
onClickRepeaterTouchStart: function(clickRepeater, e) { | |
this.onMouseDown(e); | |
}, | |
onClickRepeaterTouchEnd: function(clickRepeater, e) { | |
var me = this, | |
field = me.field; | |
Ext.callback(me.endHandler, me.scope, [field, me, e], 0, field); | |
}, | |
updateHandler: function(handler) { | |
this.toggleCls(this.interactiveCls, !!handler); | |
}, | |
updateGroup: function(group) { | |
if (!this.isConfiguring) { | |
this.getField().syncTriggers(); | |
} | |
}, | |
updateIconCls: function(iconCls, oldIconCls) { | |
this.iconElement.replaceCls(oldIconCls, iconCls); | |
}, | |
updateSide: function() { | |
if (!this.isConfiguring) { | |
this.getField().syncTriggers(); | |
} | |
}, | |
updateTriggers: function(triggers) { | |
var me = this, | |
dom = me.element.dom, | |
iconElement = me.iconElement, | |
i, ln; | |
me.toggleCls(me.groupedCls, !!(triggers && triggers.length)); | |
if (triggers) { | |
// group triggers do not have icons of their own, so we can safely remove the iconElement | |
if (iconElement) { | |
iconElement.destroy(); | |
me.iconElement = null; | |
Ext.Array.remove(me.referenceList, 'iconElement'); | |
} | |
for (i = 0, ln = triggers.length; i < ln; i++) { | |
dom.appendChild(triggers[i].element.dom); | |
} | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment