tweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloud
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
10 KiB
316 lines
10 KiB
/** |
|
* An internally used DataView for {@link Ext.form.field.ComboBox ComboBox}. |
|
*/ |
|
Ext.define('Ext.view.BoundList', { |
|
extend: 'Ext.view.View', |
|
alias: 'widget.boundlist', |
|
alternateClassName: 'Ext.BoundList', |
|
requires: [ |
|
'Ext.view.BoundListKeyNav', |
|
'Ext.layout.component.BoundList', |
|
'Ext.toolbar.Paging' |
|
], |
|
|
|
mixins: [ |
|
'Ext.mixin.Queryable' |
|
], |
|
|
|
/** |
|
* @cfg {Number} [pageSize=0] |
|
* If greater than `0`, a {@link Ext.toolbar.Paging} is displayed at the bottom of the list and store |
|
* queries will execute with page {@link Ext.data.operation.Read#start start} and |
|
* {@link Ext.data.operation.Read#limit limit} parameters. |
|
*/ |
|
pageSize: 0, |
|
|
|
/** |
|
* @cfg {String} [displayField=""] |
|
* The field from the store to show in the view. |
|
*/ |
|
|
|
/** |
|
* @property {Ext.toolbar.Paging} pagingToolbar |
|
* A reference to the PagingToolbar instance in this view. Only populated if {@link #pageSize} is greater |
|
* than zero and the BoundList has been rendered. |
|
*/ |
|
|
|
// private overrides |
|
baseCls: Ext.baseCSSPrefix + 'boundlist', |
|
itemCls: Ext.baseCSSPrefix + 'boundlist-item', |
|
listItemCls: '', |
|
shadow: false, |
|
trackOver: true, |
|
|
|
preserveScrollOnRefresh: true, |
|
enableInitialSelection: false, |
|
refreshSelmodelOnRefresh: true, |
|
|
|
componentLayout: 'boundlist', |
|
|
|
navigationModel: 'boundlist', |
|
|
|
scrollable: true, |
|
|
|
childEls: [ |
|
'listWrap', 'listEl' |
|
], |
|
|
|
renderTpl: [ |
|
'<div id="{id}-listWrap" data-ref="listWrap" role="presentation" class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '">', |
|
'<ul id="{id}-listEl" data-ref="listEl" class="' + Ext.baseCSSPrefix + 'list-plain">', |
|
'</ul>', |
|
'</div>', |
|
'{%', |
|
'var pagingToolbar=values.$comp.pagingToolbar;', |
|
'if (pagingToolbar) {', |
|
'Ext.DomHelper.generateMarkup(pagingToolbar.getRenderTree(), out);', |
|
'}', |
|
'%}', |
|
{ |
|
disableFormats: true |
|
} |
|
], |
|
|
|
/** |
|
* @cfg {String/Ext.XTemplate} tpl |
|
* A String or Ext.XTemplate instance to apply to inner template. |
|
* |
|
* {@link Ext.view.BoundList} is used for the dropdown list of |
|
* {@link Ext.form.field.ComboBox}. To customize the template you can set the tpl on |
|
* the combobox config object: |
|
* |
|
* Ext.create('Ext.form.field.ComboBox', { |
|
* fieldLabel : 'State', |
|
* queryMode : 'local', |
|
* displayField : 'text', |
|
* valueField : 'abbr', |
|
* store : Ext.create('StateStore', { |
|
* fields : ['abbr', 'text'], |
|
* data : [ |
|
* {"abbr":"AL", "name":"Alabama"}, |
|
* {"abbr":"AK", "name":"Alaska"}, |
|
* {"abbr":"AZ", "name":"Arizona"} |
|
* //... |
|
* ] |
|
* }), |
|
* // Template for the dropdown menu. |
|
* // Note the use of the "x-list-plain" and "x-boundlist-item" class, |
|
* // this is required to make the items selectable. |
|
* tpl: Ext.create('Ext.XTemplate', |
|
* '<ul class="x-list-plain"><tpl for=".">', |
|
* '<li role="option" class="x-boundlist-item">{abbr} - {name}</li>', |
|
* '</tpl></ul>' |
|
* ), |
|
* }); |
|
* |
|
* Defaults to: |
|
* |
|
* Ext.create('Ext.XTemplate', |
|
* '<ul><tpl for=".">', |
|
* '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>', |
|
* '</tpl></ul>' |
|
* ); |
|
* |
|
*/ |
|
|
|
// Override because on non-touch devices, the bound field |
|
// retains focus so that typing may narrow the list. |
|
// Only when the show is triggered by a touch does the BoundList |
|
// get explicitly focused so that the keyboard does not appear. |
|
focusOnToFront: false, |
|
|
|
initComponent: function() { |
|
var me = this, |
|
baseCls = me.baseCls, |
|
itemCls = me.itemCls; |
|
|
|
me.selectedItemCls = baseCls + '-selected'; |
|
if (me.trackOver) { |
|
me.overItemCls = baseCls + '-item-over'; |
|
} |
|
me.itemSelector = "." + itemCls; |
|
me.scrollerSelector = 'ul.' + Ext.baseCSSPrefix + 'list-plain'; |
|
|
|
if (me.floating) { |
|
me.addCls(baseCls + '-floating'); |
|
} |
|
|
|
if (!me.tpl) { |
|
// should be setting aria-posinset based on entire set of data |
|
// not filtered set |
|
me.tpl = new Ext.XTemplate( |
|
'<tpl for=".">', |
|
'<li role="option" unselectable="on" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>', |
|
'</tpl>' |
|
); |
|
} else if (!me.tpl.isTemplate) { |
|
me.tpl = new Ext.XTemplate(me.tpl); |
|
} |
|
|
|
if (me.pageSize) { |
|
me.pagingToolbar = me.createPagingToolbar(); |
|
} |
|
|
|
me.callParent(); |
|
}, |
|
|
|
getRefOwner: function() { |
|
return this.pickerField || this.callParent(); |
|
}, |
|
|
|
getRefItems: function() { |
|
var result = this.callParent(), |
|
toolbar = this.pagingToolbar; |
|
|
|
if (toolbar) { |
|
result.push(toolbar); |
|
} |
|
return result; |
|
}, |
|
|
|
createPagingToolbar: function() { |
|
return Ext.widget('pagingtoolbar', { |
|
id: this.id + '-paging-toolbar', |
|
pageSize: this.pageSize, |
|
store: this.dataSource, |
|
border: false, |
|
ownerCt: this, |
|
ownerLayout: this.getComponentLayout() |
|
}); |
|
}, |
|
|
|
getNodeContainer: function() { |
|
return this.listEl; |
|
}, |
|
|
|
refresh: function(){ |
|
var me = this, |
|
tpl = me.tpl; |
|
|
|
// Allow access to the context for XTemplate scriptlets |
|
tpl.field = me.pickerField; |
|
tpl.store = me.store; |
|
me.callParent(); |
|
tpl.field = tpl.store = null; |
|
|
|
// The view selectively removes item nodes, so the toolbar |
|
// will be preserves in the DOM |
|
}, |
|
|
|
bindStore : function(store, initial) { |
|
var toolbar = this.pagingToolbar; |
|
|
|
this.callParent(arguments); |
|
if (toolbar) { |
|
toolbar.bindStore(store, initial); |
|
} |
|
}, |
|
|
|
/** |
|
* A method that returns the inner template for displaying items in the list. |
|
* This method is useful to override when using a more complex display value, for example |
|
* inserting an icon along with the text. |
|
* |
|
* The XTemplate is created with a reference to the owning form field in the `field` property to provide access |
|
* to context. For example to highlight the currently typed value, the getInnerTpl may be configured into a |
|
* ComboBox as part of the {@link Ext.form.field.ComboBox#listConfig listConfig}: |
|
* |
|
* listConfig: { |
|
* getInnerTpl: function() { |
|
* return '{[values.name.replace(this.field.getRawValue(), "<b>" + this.field.getRawValue() + "</b>")]}'; |
|
* } |
|
* } |
|
* @param {String} displayField The {@link #displayField} for the BoundList. |
|
* @return {String} The inner template |
|
*/ |
|
getInnerTpl: function(displayField) { |
|
return '{' + displayField + '}'; |
|
}, |
|
|
|
onShow: function() { |
|
this.callParent(); |
|
|
|
// If the input field is not focused, then focus the picker. |
|
if (Ext.Element.getActiveElement() !== this.pickerField.inputEl.dom) { |
|
this.focus(); |
|
} |
|
}, |
|
|
|
onHide: function() { |
|
var inputEl = this.pickerField.inputEl.dom; |
|
|
|
// If we're hiding a focused picker, focus must move to the input field unless the instigating |
|
// browser event is a touch. In that case, the input only focuses when they touch it - |
|
// we want to avoid an appearing keyboard. |
|
if (Ext.Element.getActiveElement() !== inputEl && |
|
(!Ext.EventObject || Ext.EventObject.pointerType !== 'touch')) { |
|
inputEl.focus(); |
|
} |
|
// Call parent (hide the element) *after* focus has been moved out. |
|
// Maintainer: Component#onHide takes parameters. |
|
this.callParent(arguments); |
|
}, |
|
|
|
afterComponentLayout: function(width, height, oldWidth, oldHeight) { |
|
var picker = this.pickerField; |
|
|
|
this.callParent(arguments); |
|
|
|
// Bound list may change size, so realign on layout |
|
// **if the field is an Ext.form.field.Picker which has alignPicker!** |
|
if (picker && picker.alignPicker) { |
|
picker.alignPicker(); |
|
} |
|
}, |
|
|
|
// Clicking on an already selected item collapses the picker |
|
onItemClick: function(record) { |
|
// The selection change events won't fire when clicking on the selected element. Detect it here. |
|
var me = this, |
|
pickerField = me.pickerField, |
|
valueField = pickerField.valueField, |
|
selected = me.getSelectionModel().getSelection(); |
|
|
|
if (!pickerField.multiSelect && selected.length) { |
|
selected = selected[0]; |
|
// Not all pickerField's have a collapse API, i.e. Ext.ux.form.MultiSelect. |
|
if (selected && pickerField.isEqual(record.get(valueField), selected.get(valueField)) && pickerField.collapse) { |
|
pickerField.collapse(); |
|
} |
|
} |
|
}, |
|
|
|
onContainerClick: function(e) { |
|
// Ext.view.View template method |
|
// Do not continue to process the event as a container click if it is within the pagingToolbar |
|
if (this.pagingToolbar && this.pagingToolbar.rendered && e.within(this.pagingToolbar.el)) { |
|
return false; |
|
} |
|
}, |
|
|
|
onDestroy: function() { |
|
this.callParent(); |
|
Ext.destroyMembers(this, 'pagingToolbar', 'listWrap', 'listEl'); |
|
}, |
|
|
|
privates: { |
|
getTargetEl: function() { |
|
return this.listEl; |
|
}, |
|
|
|
getOverflowEl: function() { |
|
return this.listWrap; |
|
}, |
|
|
|
// Do the job of a container layout at this point even though we are not a Container. |
|
finishRenderChildren: function () { |
|
var toolbar = this.pagingToolbar; |
|
|
|
this.callParent(arguments); |
|
|
|
if (toolbar) { |
|
toolbar.finishRender(); |
|
} |
|
} |
|
} |
|
});
|
|
|