StorageLocationPicker.js (6728B)
1 Ext.define("PartKeepr.StorageLocationPicker", { 2 extend: "Ext.form.field.Picker", 3 alias: 'widget.StorageLocationPicker', 4 5 /** 6 * @cfg {Number} typeAheadDelay 7 * The length of time in milliseconds to wait until the typeahead function is called 8 */ 9 typeAheadDelay: 250, 10 11 /** 12 * @var {Ext.util.DelayedTask} typeAheadTask 13 * The internal task for the typeAhead delay 14 */ 15 typeAheadTask: null, 16 17 /** 18 * @var {PartKeepr.StorageLocationBundle.Entity.StorageLocation} selectedStorageLocation 19 * The selected storage location 20 */ 21 selectedStorageLocation: null, 22 23 textValue: "", 24 25 enableKeyEvents: true, 26 27 listeners: { 28 'specialkey': { 29 fn: 'keyHandler', 30 scope: 'this' 31 } 32 }, 33 34 initComponent: function () 35 { 36 this.store = Ext.create("Ext.data.Store", { 37 model: 'PartKeepr.StorageLocationBundle.Entity.StorageLocation', 38 autoLoad: true, 39 remoteFilter: true, 40 remoteSort: true, 41 sorters: [ 42 { 43 property: 'category.categoryPath', 44 direction: 'ASC' 45 }, { 46 property: 'name', 47 direction: 'ASC' 48 } 49 ], 50 groupField: 'categoryPath' 51 }); 52 53 this.on("keyup", Ext.bind(this.onFieldChange, this)); 54 this.on("blur", Ext.bind(this.onBlur, this)); 55 56 this.callParent(); 57 }, 58 onFieldChange: function (field, e) 59 { 60 var newValue = this.inputEl.getValue(); 61 62 if (!this.typeAheadTask) { 63 this.typeAheadTask = new Ext.util.DelayedTask(this.onTypeAhead, this, [newValue]); 64 } 65 66 this.typeAheadTask.delay(this.typeAheadDelay, false, false, [newValue]); 67 }, 68 /** 69 * Handles special keys used in this field. 70 * 71 * Enter: Starts the search 72 * Escape: Removes the search and clears the field contents 73 */ 74 keyHandler: function (field, e) 75 { 76 var picker = this.getPicker(); 77 var grid = picker.getGrid(); 78 79 switch (e.getKey()) { 80 case e.DOWN: 81 var currentSelection = grid.getSelectionModel().getSelection(); 82 83 if (currentSelection.length === 0) { 84 grid.getSelectionModel().select(0); 85 } else { 86 var index = grid.getStore().indexOf(currentSelection[0]) + 1; 87 88 if (index < grid.getStore().count()) { 89 grid.getSelectionModel().select(index); 90 grid.getView().focusRow(grid.getStore().getAt(index)); 91 } 92 } 93 break; 94 case e.UP: 95 var currentSelection = grid.getSelectionModel().getSelection(); 96 97 if (currentSelection.length === 0) { 98 grid.getSelectionModel().select(grid.getStore().count()); 99 } else { 100 var index = grid.getStore().indexOf(currentSelection[0]) - 1; 101 102 if (index >= 0) { 103 grid.getSelectionModel().select(index); 104 grid.getView().focusRow(grid.getStore().getAt(index)); 105 } 106 } 107 break; 108 case e.ENTER: 109 if (!this.isExpanded) { 110 this.expand(); 111 return; 112 } else { 113 this.applyGridSelection(grid); 114 } 115 break; 116 case e.TAB: 117 this.applyGridSelection(grid); 118 break; 119 } 120 }, 121 applyGridSelection: function (grid) 122 { 123 var currentSelection = grid.getSelectionModel().getSelection(); 124 125 if (currentSelection.length === 1) { 126 this.setValue(currentSelection[0]); 127 } 128 129 this.collapse(); 130 131 }, 132 getValue: function () 133 { 134 return this.selectedStorageLocation; 135 }, 136 onTypeAhead: function (newValue) 137 { 138 var picker = this.getPicker(); 139 140 if (picker.getTree().getStore().isLoading()) { 141 Ext.defer(this.onTypeAhead, 200, this, [newValue]); 142 return; 143 } 144 145 if (newValue !== this.textValue) { 146 picker.setCategoryFilter(picker.getTree().getRootNode().firstChild); 147 picker.getTree().getSelectionModel().select(picker.getTree().getRootNode().firstChild); 148 picker.setSearchValue(newValue); 149 picker.getGrid().getSelectionModel().deselectAll(); 150 this.expand(); 151 this.textValue = newValue; 152 } 153 }, 154 onBlur: function () 155 { 156 var picker = this.getPicker(); 157 158 if (picker.getGrid().getStore().count() === 1) { 159 this.setValue(picker.getGrid().getStore().getAt(0)); 160 } 161 162 this.validate(); 163 }, 164 setValue: function (value) 165 { 166 if (value === null || !(value instanceof PartKeepr.StorageLocationBundle.Entity.StorageLocation)) { 167 return; 168 } 169 this.selectedStorageLocation = value; 170 this.textValue = value.get("name"); 171 PartKeepr.StorageLocationPicker.superclass.setValue.call(this, value.get("name")); 172 this.validate(); 173 }, 174 getErrors: function (value) { 175 var errors = this.callParent(arguments); 176 177 if (!this.inputEl) { 178 return errors; 179 } 180 181 if (!(this.selectedStorageLocation instanceof PartKeepr.StorageLocationBundle.Entity.StorageLocation) || 182 this.inputEl.getValue() !== this.selectedStorageLocation.get("name")) { 183 errors.push(i18n("An existing storage location must be selected")); 184 } 185 186 return errors; 187 188 }, 189 /** 190 * Creates and returns the tree panel to be used as this field's picker. 191 */ 192 createPicker: function () 193 { 194 var me = this, 195 picker = new PartKeepr.StorageLocationNavigation({ 196 store: me.store, 197 floating: true, 198 minHeight: me.minPickerHeight, 199 maxHeight: me.maxPickerHeight, 200 manageHeight: false, 201 shadow: false, 202 height: 250, 203 verticalLayout: true, 204 dragAndDrop: false, 205 categoryEditActions: false, 206 itemEditActions: false, 207 editItemAsObject: true, 208 listeners: { 209 itemEdit: function (v) 210 { 211 this.setValue(v); 212 this.collapse(); 213 }, 214 scope: this 215 } 216 }); 217 218 return picker; 219 } 220 });