| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- /*
- This file is part of Ext JS 4
- Copyright (c) 2011 Sencha Inc
- Contact: http://www.sencha.com/contact
- GNU General Public License Usage
- This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
- If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
- */
- /*
- * 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,
- disabled: me.disabled
- },
- 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);
- });
- }
- },
-
- onDisable: function(){
- this.callParent();
- var fromField = this.fromField;
-
- // if we have one, we have both, they get created at the same time
- if (fromField) {
- fromField.disable();
- this.toField.disable();
- }
- },
-
- onEnable: function(){
- this.callParent();
- var fromField = this.fromField;
-
- // if we have one, we have both, they get created at the same time
- if (fromField) {
- fromField.enable();
- this.toField.enable();
- }
- },
- onDestroy: function() {
- Ext.destroyMembers(this, 'innerCt');
- this.callParent();
- }
- });
|