]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | /**\r |
2 | * This component provides a grid holding selected items from a second store of potential\r | |
3 | * members. The `store` of this component represents the selected items. The "search store"\r | |
4 | * represents the potentially selected items.\r | |
5 | *\r | |
6 | * While this component is a grid and so you can configure `columns`, it is best to leave\r | |
7 | * that to this class in its `initComponent` method. That allows this class to create the\r | |
8 | * extra column that allows the user to remove rows. Instead use `{@link #fieldName}` and\r | |
9 | * `{@link #fieldTitle}` to configure the primary column's `dataIndex` and column `text`,\r | |
10 | * respectively.\r | |
11 | *\r | |
12 | * @since 5.0.0\r | |
13 | */\r | |
14 | Ext.define('Ext.view.MultiSelector', {\r | |
15 | extend: 'Ext.grid.Panel',\r | |
16 | \r | |
17 | xtype: 'multiselector',\r | |
18 | \r | |
19 | config: {\r | |
20 | /**\r | |
21 | * @cfg {Object} search\r | |
22 | * This object configures the search popup component. By default this contains the\r | |
23 | * `xtype` for a `Ext.view.MultiSelectorSearch` component and specifies `autoLoad`\r | |
24 | * for its `store`.\r | |
25 | */\r | |
26 | search: {\r | |
27 | xtype: 'multiselector-search',\r | |
28 | width: 200,\r | |
29 | height: 200,\r | |
30 | store: {\r | |
31 | autoLoad: true\r | |
32 | }\r | |
33 | }\r | |
34 | },\r | |
35 | \r | |
36 | /**\r | |
37 | * @cfg {String} [fieldName="name"]\r | |
38 | * The name of the data field to display in the primary column of the grid.\r | |
39 | * @since 5.0.0\r | |
40 | */\r | |
41 | fieldName: 'name',\r | |
42 | \r | |
43 | /**\r | |
44 | * @cfg {String} [fieldTitle]\r | |
45 | * The text to display in the column header for the primary column of the grid.\r | |
46 | * @since 5.0.0\r | |
47 | */\r | |
48 | fieldTitle: null,\r | |
49 | \r | |
50 | /**\r | |
51 | * @cfg {String} removeRowText\r | |
52 | * The text to display in the "remove this row" column. By default this is a Unicode\r | |
53 | * "X" looking glyph.\r | |
54 | * @since 5.0.0\r | |
55 | */\r | |
56 | removeRowText: '\u2716',\r | |
57 | \r | |
58 | /**\r | |
59 | * @cfg {String} removeRowTip\r | |
60 | * The tooltip to display when the user hovers over the remove cell.\r | |
61 | * @since 5.0.0\r | |
62 | */\r | |
63 | removeRowTip: 'Remove this item',\r | |
64 | \r | |
65 | emptyText: 'Nothing selected',\r | |
66 | \r | |
67 | /**\r | |
68 | * @cfg {String} addToolText\r | |
69 | * The tooltip to display when the user hovers over the "+" tool in the panel header.\r | |
70 | * @since 5.0.0\r | |
71 | */\r | |
72 | addToolText: 'Search for items to add',\r | |
73 | \r | |
74 | initComponent: function () {\r | |
75 | var me = this,\r | |
76 | emptyText = me.emptyText,\r | |
77 | store = me.getStore(),\r | |
78 | search = me.getSearch(),\r | |
79 | fieldTitle = me.fieldTitle,\r | |
80 | searchStore, model;\r | |
81 | \r | |
82 | //<debug>\r | |
83 | if (!search) {\r | |
84 | Ext.raise('The search configuration is required for the multi selector');\r | |
85 | }\r | |
86 | //</debug>\r | |
87 | \r | |
88 | searchStore = search.store;\r | |
89 | if (searchStore.isStore) {\r | |
90 | model = searchStore.getModel();\r | |
91 | } else {\r | |
92 | model = searchStore.model;\r | |
93 | }\r | |
94 | \r | |
95 | if (!store) {\r | |
96 | me.store = {\r | |
97 | model: model\r | |
98 | };\r | |
99 | }\r | |
100 | \r | |
101 | if (emptyText && !me.viewConfig) {\r | |
102 | me.viewConfig = {\r | |
103 | deferEmptyText: false,\r | |
104 | emptyText: emptyText\r | |
105 | };\r | |
106 | }\r | |
107 | \r | |
108 | if (!me.columns) {\r | |
109 | me.hideHeaders = !fieldTitle;\r | |
110 | me.columns = [\r | |
111 | { text: fieldTitle, dataIndex: me.fieldName, flex: 1 },\r | |
112 | me.makeRemoveRowColumn()\r | |
113 | ];\r | |
114 | }\r | |
115 | \r | |
116 | me.callParent();\r | |
117 | },\r | |
118 | \r | |
119 | addTools: function () {\r | |
120 | this.addTool({\r | |
121 | type: 'plus',\r | |
122 | tooltip: this.addToolText,\r | |
123 | callback: 'onShowSearch',\r | |
124 | scope: this\r | |
125 | });\r | |
126 | },\r | |
127 | \r | |
128 | convertSearchRecord: Ext.identityFn,\r | |
129 | \r | |
130 | convertSelectionRecord: Ext.identityFn,\r | |
131 | \r | |
132 | makeRemoveRowColumn: function () {\r | |
133 | var me = this;\r | |
134 | \r | |
135 | return {\r | |
136 | width: 22,\r | |
137 | menuDisabled: true,\r | |
138 | tdCls: Ext.baseCSSPrefix + 'multiselector-remove',\r | |
139 | processEvent: me.processRowEvent.bind(me),\r | |
140 | renderer: me.renderRemoveRow,\r | |
141 | updater: Ext.emptyFn,\r | |
142 | scope: me\r | |
143 | };\r | |
144 | },\r | |
145 | \r | |
146 | processRowEvent: function (type, view, cell, recordIndex, cellIndex, e, record, row) {\r | |
147 | if (e.type !== 'click') {\r | |
148 | return;\r | |
149 | }\r | |
150 | \r | |
151 | if (Ext.fly(cell).hasCls(Ext.baseCSSPrefix + 'multiselector-remove')) {\r | |
152 | this.store.remove(record);\r | |
153 | if (this.searchPopup) {\r | |
154 | this.searchPopup.deselectRecords(record);\r | |
155 | }\r | |
156 | }\r | |
157 | },\r | |
158 | \r | |
159 | renderRemoveRow: function () {\r | |
160 | return '<span data-qtip="'+ this.removeRowTip + '" role="button">' +\r | |
161 | this.removeRowText + '</span>';\r | |
162 | },\r | |
163 | \r | |
164 | beforeDestroy: function() {\r | |
165 | Ext.un({\r | |
166 | mousedown: 'onDismissSearch',\r | |
167 | scope: this\r | |
168 | });\r | |
169 | this.callParent();\r | |
170 | },\r | |
171 | \r | |
172 | privates: {\r | |
173 | onDismissSearch: function (e) {\r | |
174 | var searchPopup = this.searchPopup;\r | |
175 | \r | |
176 | if (searchPopup && !(searchPopup.owns(e.getTarget()) || this.owns(e.getTarget()))) {\r | |
177 | Ext.un({\r | |
178 | mousedown: 'onDismissSearch',\r | |
179 | scope: this\r | |
180 | });\r | |
181 | searchPopup.hide();\r | |
182 | }\r | |
183 | },\r | |
184 | \r | |
185 | onShowSearch: function (panel, tool) {\r | |
186 | var me = this,\r | |
187 | searchPopup = me.searchPopup,\r | |
188 | store = me.getStore();\r | |
189 | \r | |
190 | if (!searchPopup) {\r | |
191 | searchPopup = Ext.merge({\r | |
192 | owner: me,\r | |
193 | field: me.fieldName,\r | |
194 | floating: true\r | |
195 | }, me.getSearch());\r | |
196 | me.searchPopup = searchPopup = me.add(searchPopup);\r | |
197 | \r | |
198 | // If we were configured with records prior to the UI requesting the popup,\r | |
199 | // ensure that the records are selected in the popup.\r | |
200 | if (store.getCount()) {\r | |
201 | searchPopup.selectRecords(store.getRange());\r | |
202 | }\r | |
203 | }\r | |
204 | \r | |
205 | searchPopup.showBy(me, 'tl-tr?');\r | |
206 | Ext.on({\r | |
207 | mousedown: 'onDismissSearch',\r | |
208 | scope: me\r | |
209 | });\r | |
210 | }\r | |
211 | }\r | |
212 | });\r |