123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- * Note that this control will most likely remain as an example, and not as a core Ext form
- * control. However, the API will be changing in a future release and so should not yet be
- * treated as a final, stable API at this time.
- */
- /**
- * @class Ext.ux.form.ItemSelector
- * @extends Ext.form.field.Base
- * A control that allows selection of between two Ext.ux.form.MultiSelect controls.
- *
- * @history
- * 2008-06-19 bpm Original code contributed by Toby Stuart (with contributions from Robert Williams)
- *
- * @constructor
- * Create a new ItemSelector
- * @param {Object} config Configuration options
- * @xtype itemselector
- */
- Ext.define('Ext.ux.form.ItemSelector', {
- extend: 'Ext.ux.form.MultiSelect',
- alias: ['widget.itemselectorfield', 'widget.itemselector'],
- alternateClassName: ['Ext.ux.ItemSelector'],
- requires: ['Ext.ux.layout.component.form.ItemSelector', 'Ext.button.Button'],
-
- hideNavIcons:false,
- /**
- * @cfg {Array} buttons Defines the set of buttons that should be displayed in between the ItemSelector
- * fields. Defaults to <tt>['top', 'up', 'add', 'remove', 'down', 'bottom']</tt>. These names are used
- * to build the button CSS class names, and to look up the button text labels in {@link #buttonsText}.
- * This can be overridden with a custom Array to change which buttons are displayed or their order.
- */
- buttons: ['top', 'up', 'add', 'remove', 'down', 'bottom'],
- buttonsText: {
- top: "Move to Top",
- up: "Move Up",
- add: "Add to Selected",
- remove: "Remove from Selected",
- down: "Move Down",
- bottom: "Move to Bottom"
- },
- /**
- * @cfg {Array} multiselects An optional array of {@link Ext.ux.form.MultiSelect} config objects, containing
- * additional configuration to be applied to the internal MultiSelect fields.
- */
- multiselects: [],
- componentLayout: 'itemselectorfield',
- fieldBodyCls: Ext.baseCSSPrefix + 'form-itemselector-body',
- bindStore: function(store, initial) {
- var me = this,
- toField = me.toField,
- fromField = me.fromField,
- models;
- me.callParent(arguments);
- if (toField) {
- // Clear both field stores
- toField.store.removeAll();
- fromField.store.removeAll();
- // Clone the contents of the main store into the fromField
- models = [];
- me.store.each(function(model) {
- models.push(model.copy(model.getId()));
- });
- fromField.store.add(models);
- }
- },
- onRender: function(ct, position) {
- var me = this,
- baseCSSPrefix = Ext.baseCSSPrefix,
- ddGroup = 'ItemSelectorDD-' + Ext.id(),
- commonConfig = {
- displayField: me.displayField,
- valueField: me.valueField,
- dragGroup: ddGroup,
- dropGroup: ddGroup,
- flex: 1,
- hideLabel: true
- },
- fromConfig = Ext.apply({
- listTitle: 'Available',
- store: Ext.create('Ext.data.Store', {model: me.store.model}), //blank store to begin
- listeners: {
- boundList: {
- itemdblclick: me.onItemDblClick,
- scope: me
- }
- }
- }, me.multiselects[0], commonConfig),
- toConfig = Ext.apply({
- listTitle: 'Selected',
- store: Ext.create('Ext.data.Store', {model: me.store.model}), //blank store to begin
- listeners: {
- boundList: {
- itemdblclick: me.onItemDblClick,
- scope: me
- },
- change: me.onToFieldChange,
- scope: me
- }
- }, me.multiselects[1], commonConfig),
- fromField = Ext.widget('multiselect', fromConfig),
- toField = Ext.widget('multiselect', toConfig),
- innerCt,
- buttons = [];
- // Skip MultiSelect's onRender as we don't want its content
- Ext.ux.form.MultiSelect.superclass.onRender.call(me, ct, position);
- me.fromField = fromField;
- me.toField = toField;
- if (!me.hideNavIcons) {
- Ext.Array.forEach(me.buttons, function(name) {
- buttons.push({
- xtype: 'button',
- tooltip: me.buttonsText[name],
- handler: me['on' + Ext.String.capitalize(name) + 'BtnClick'],
- cls: baseCSSPrefix + 'form-itemselector-btn',
- iconCls: baseCSSPrefix + 'form-itemselector-' + name,
- scope: me
- });
- //div separator to force vertical stacking
- buttons.push({xtype: 'component', height: 3, width: 1, style: 'font-size:0;line-height:0'});
- });
- }
- innerCt = me.innerCt = Ext.widget('container', {
- renderTo: me.bodyEl,
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- items: [
- me.fromField,
- {
- xtype: 'container',
- margins: '0 4',
- items: buttons
- },
- me.toField
- ]
- });
- // Must set upward link after first render
- innerCt.ownerCt = me;
- // Rebind the store so it gets cloned to the fromField
- me.bindStore(me.store);
- // Set the initial value
- me.setRawValue(me.rawValue);
- },
-
- onToFieldChange: function() {
- this.checkChange();
- },
-
- getSelections: function(list){
- var store = list.getStore(),
- selections = list.getSelectionModel().getSelection(),
- i = 0,
- len = selections.length;
-
- return Ext.Array.sort(selections, function(a, b){
- a = store.indexOf(a);
- b = store.indexOf(b);
-
- if (a < b) {
- return -1;
- } else if (a > b) {
- return 1;
- }
- return 0;
- });
- },
- onTopBtnClick : function() {
- var list = this.toField.boundList,
- store = list.getStore(),
- selected = this.getSelections(list),
- i = selected.length - 1,
- selection;
-
-
- store.suspendEvents();
- for (; i > -1; --i) {
- selection = selected[i];
- store.remove(selected);
- store.insert(0, selected);
- }
- store.resumeEvents();
- list.refresh();
- },
- onBottomBtnClick : function() {
- var list = this.toField.boundList,
- store = list.getStore(),
- selected = this.getSelections(list),
- i = 0,
- len = selected.length,
- selection;
-
- store.suspendEvents();
- for (; i < len; ++i) {
- selection = selected[i];
- store.remove(selection);
- store.add(selection);
- }
- store.resumeEvents();
- list.refresh();
- },
- onUpBtnClick : function() {
- var list = this.toField.boundList,
- store = list.getStore(),
- selected = this.getSelections(list),
- i = 0,
- len = selected.length,
- selection,
- index;
-
- store.suspendEvents();
- for (; i < len; ++i) {
- selection = selected[i];
- index = Math.max(0, store.indexOf(selection) - 1);
- store.remove(selection);
- store.insert(index, selection);
- }
- store.resumeEvents();
- list.refresh();
- },
- onDownBtnClick : function() {
- var list = this.toField.boundList,
- store = list.getStore(),
- selected = this.getSelections(list),
- i = 0,
- len = selected.length,
- max = store.getCount(),
- selection,
- index;
-
- store.suspendEvents();
- for (; i < len; ++i) {
- selection = selected[i];
- index = Math.min(max, store.indexOf(selection) + 1);
- store.remove(selection);
- store.insert(index, selection);
- }
- store.resumeEvents();
- list.refresh();
- },
- onAddBtnClick : function() {
- var me = this,
- fromList = me.fromField.boundList,
- selected = this.getSelections(fromList);
-
- fromList.getStore().remove(selected);
- this.toField.boundList.getStore().add(selected);
- },
- onRemoveBtnClick : function() {
- var me = this,
- toList = me.toField.boundList,
- selected = this.getSelections(toList);
-
- toList.getStore().remove(selected);
- this.fromField.boundList.getStore().add(selected);
- },
- onItemDblClick : function(view) {
- var me = this;
- if (view == me.toField.boundList){
- me.onRemoveBtnClick();
- }
- else if (view == me.fromField.boundList) {
- me.onAddBtnClick();
- }
- },
- setRawValue: function(value) {
- var me = this,
- Array = Ext.Array,
- toStore, fromStore, models;
- value = Array.from(value);
- me.rawValue = value;
- if (me.toField) {
- toStore = me.toField.boundList.getStore();
- fromStore = me.fromField.boundList.getStore();
- // Move any selected values back to the fromField
- fromStore.add(toStore.getRange());
- toStore.removeAll();
- // Move the new values over to the toField
- models = [];
- Ext.Array.forEach(value, function(val) {
- var undef,
- model = fromStore.findRecord(me.valueField, val, undef, undef, true, true);
- if (model) {
- models.push(model);
- }
- });
- fromStore.remove(models);
- toStore.add(models);
- }
- return value;
- },
- getRawValue: function() {
- var me = this,
- toField = me.toField,
- rawValue = me.rawValue;
- if (toField) {
- rawValue = Ext.Array.map(toField.boundList.getStore().getRange(), function(model) {
- return model.get(me.valueField);
- });
- }
- me.rawValue = rawValue;
- return rawValue;
- },
- /**
- * @private Cascade readOnly/disabled state to the sub-fields and buttons
- */
- updateReadOnly: function() {
- var me = this,
- readOnly = me.readOnly || me.disabled;
- if (me.rendered) {
- me.toField.setReadOnly(readOnly);
- me.fromField.setReadOnly(readOnly);
- Ext.Array.forEach(me.innerCt.query('button'), function(button) {
- button.setDisabled(readOnly);
- });
- }
- },
- onDestroy: function() {
- Ext.destroyMembers(this, 'innerCt');
- this.callParent();
- }
- });
|