]> git.proxmox.com Git - extjs.git/blame - extjs/modern/modern/src/SegmentedButton.js
add extjs 6.0.1 sources
[extjs.git] / extjs / modern / modern / src / SegmentedButton.js
CommitLineData
6527f429
DM
1/**\r
2 * SegmentedButton is a container for a group of {@link Ext.Button}s. Generally a SegmentedButton would be\r
3 * a child of a {@link Ext.Toolbar} and would be used to switch between different views.\r
4 *\r
5 * ## Example usage:\r
6 *\r
7 * @example\r
8 * var segmentedButton = Ext.create('Ext.SegmentedButton', {\r
9 * allowMultiple: true,\r
10 * items: [\r
11 * {\r
12 * text: 'Option 1'\r
13 * },\r
14 * {\r
15 * text: 'Option 2',\r
16 * pressed: true\r
17 * },\r
18 * {\r
19 * text: 'Option 3'\r
20 * }\r
21 * ],\r
22 * listeners: {\r
23 * toggle: function(container, button, pressed){\r
24 * alert("User toggled the '" + button.getText() + "' button: " + (pressed ? 'on' : 'off'));\r
25 * }\r
26 * }\r
27 * });\r
28 * Ext.Viewport.add({ xtype: 'container', padding: 10, items: [segmentedButton] });\r
29 */\r
30Ext.define('Ext.SegmentedButton', {\r
31 extend: 'Ext.Container',\r
32 xtype : 'segmentedbutton',\r
33\r
34 alternateClassName: 'Ext.button.Segmented',\r
35\r
36 requires: [\r
37 'Ext.Button'\r
38 ],\r
39\r
40 isSegmentedButton: true,\r
41\r
42 config: {\r
43 /**\r
44 * @cfg\r
45 * @inheritdoc\r
46 */\r
47 baseCls: Ext.baseCSSPrefix + 'segmentedbutton',\r
48\r
49 /**\r
50 * @cfg {String} pressedCls\r
51 * CSS class when a button is in pressed state.\r
52 * @accessor\r
53 */\r
54 pressedCls: Ext.baseCSSPrefix + 'button-pressed',\r
55\r
56 /**\r
57 * @cfg {Boolean} allowMultiple\r
58 * Allow multiple pressed buttons.\r
59 * @accessor\r
60 */\r
61 allowMultiple: false,\r
62\r
63 /**\r
64 * @cfg {Boolean} allowDepress\r
65 * Allow toggling the pressed state of each button.\r
66 * Defaults to `true` when {@link #allowMultiple} is `true`.\r
67 * @accessor\r
68 */\r
69 allowDepress: false,\r
70\r
71 /**\r
72 * @cfg {Boolean} allowToggle Allow child buttons to be pressed when tapped on. Set to `false` to allow tapping but not toggling of the buttons.\r
73 * @accessor\r
74 */\r
75 allowToggle: true,\r
76\r
77 /**\r
78 * @cfg {Array} pressedButtons\r
79 * The pressed buttons for this segmented button.\r
80 *\r
81 * You can remove all pressed buttons by calling {@link #setPressedButtons} with an empty array.\r
82 * @accessor\r
83 */\r
84 pressedButtons: [],\r
85\r
86 /**\r
87 * @cfg\r
88 * @inheritdoc\r
89 */\r
90 layout: {\r
91 type : 'hbox',\r
92 align: 'stretch'\r
93 },\r
94\r
95 /**\r
96 * @cfg\r
97 * @inheritdoc\r
98 */\r
99 defaultType: 'button',\r
100\r
101 /**\r
102 * @cfg {String}\r
103 * Default {@link Ext.Component#ui ui} to use for buttons in this segmented button.\r
104 * Buttons can override this default by specifying their own UI\r
105 */\r
106 defaultUI: null\r
107 },\r
108\r
109 /**\r
110 * @event toggle\r
111 * Fires when any child button's pressed state has changed.\r
112 * @param {Ext.SegmentedButton} this\r
113 * @param {Ext.Button} button The toggled button.\r
114 * @param {Boolean} isPressed Boolean to indicate if the button was pressed or not.\r
115 */\r
116\r
117 initialize: function() {\r
118 var me = this;\r
119\r
120 me.callParent();\r
121\r
122 me.on({\r
123 delegate: '> button',\r
124 scope : me,\r
125 tap: 'onButtonRelease'\r
126 });\r
127\r
128 me.onAfter({\r
129 delegate: '> button',\r
130 scope : me,\r
131 hide: 'onButtonHiddenChange',\r
132 show: 'onButtonHiddenChange'\r
133 });\r
134 },\r
135\r
136 updateAllowMultiple: function(allowMultiple) {\r
137 if (!this.initialized && !this.getInitialConfig().hasOwnProperty('allowDepress') && allowMultiple) {\r
138 this.setAllowDepress(true);\r
139 }\r
140 },\r
141\r
142 /**\r
143 * We override `initItems` so we can check for the pressed config.\r
144 */\r
145 applyItems: function() {\r
146 var me = this,\r
147 pressedButtons = [],\r
148 ln, i, item, items;\r
149\r
150 //call the parent first so the items get converted into a MixedCollection\r
151 me.callParent(arguments);\r
152\r
153 items = this.getItems();\r
154 ln = items.length;\r
155\r
156 for (i = 0; i < ln; i++) {\r
157 item = items.items[i];\r
158 if (item.getInitialConfig('pressed')) {\r
159 pressedButtons.push(items.items[i]);\r
160 }\r
161 }\r
162\r
163 me.updateFirstAndLastCls(items);\r
164\r
165 me.setPressedButtons(pressedButtons);\r
166 },\r
167\r
168 /**\r
169 * Button sets a timeout of 10ms to remove the {@link #pressedCls} on the release event.\r
170 * We don't want this to happen, so lets return `false` and cancel the event.\r
171 * @private\r
172 */\r
173 onButtonRelease: function(button) {\r
174 if (!this.getAllowToggle()) {\r
175 return;\r
176 }\r
177 var me = this,\r
178 pressedButtons = me.getPressedButtons() || [],\r
179 buttons = [],\r
180 alreadyPressed;\r
181\r
182 if (!me.getDisabled() && !button.getDisabled()) {\r
183 //if we allow for multiple pressed buttons, use the existing pressed buttons\r
184 if (me.getAllowMultiple()) {\r
185 buttons = pressedButtons.concat(buttons);\r
186 }\r
187\r
188 alreadyPressed = (buttons.indexOf(button) !== -1) || (pressedButtons.indexOf(button) !== -1);\r
189\r
190 //if we allow for depressing buttons, and the new pressed button is currently pressed, remove it\r
191 if (alreadyPressed && me.getAllowDepress()) {\r
192 Ext.Array.remove(buttons, button);\r
193 } else if (!alreadyPressed || !me.getAllowDepress()) {\r
194 buttons.push(button);\r
195 }\r
196\r
197 me.setPressedButtons(buttons);\r
198 }\r
199 },\r
200\r
201 onItemAdd: function() {\r
202 this.callParent(arguments);\r
203 this.updateFirstAndLastCls(this.getItems());\r
204 },\r
205\r
206 onItemRemove: function() {\r
207 this.callParent(arguments);\r
208 this.updateFirstAndLastCls(this.getItems());\r
209 },\r
210\r
211 /**\r
212 * @private\r
213 */\r
214 onButtonHiddenChange: function() {\r
215 this.updateFirstAndLastCls(this.getItems());\r
216 },\r
217\r
218 /**\r
219 * @private\r
220 */\r
221 updateFirstAndLastCls: function(items) {\r
222 var ln = items.length,\r
223 basePrefix = Ext.baseCSSPrefix,\r
224 firstCls = basePrefix + 'first',\r
225 lastCls = basePrefix + 'last',\r
226 item, i;\r
227\r
228 //remove all existing classes\r
229 for (i = 0; i < ln; i++) {\r
230 item = items.items[i];\r
231 item.removeCls(firstCls);\r
232 item.removeCls(lastCls);\r
233 }\r
234\r
235 //add a first cls to the first non-hidden button\r
236 for (i = 0; i < ln; i++) {\r
237 item = items.items[i];\r
238 if (!item.isHidden()) {\r
239 item.addCls(firstCls);\r
240 break;\r
241 }\r
242 }\r
243\r
244 //add a last cls to the last non-hidden button\r
245 for (i = ln - 1; i >= 0; i--) {\r
246 item = items.items[i];\r
247 if (!item.isHidden()) {\r
248 item.addCls(lastCls);\r
249 break;\r
250 }\r
251 }\r
252 },\r
253\r
254 /**\r
255 * @private\r
256 */\r
257 applyPressedButtons: function(newButtons) {\r
258 var me = this,\r
259 array = [],\r
260 button, ln, i;\r
261\r
262 if (me.getAllowToggle()) {\r
263 if (Ext.isArray(newButtons)) {\r
264 ln = newButtons.length;\r
265 for (i = 0; i< ln; i++) {\r
266 button = me.getComponent(newButtons[i]);\r
267 if (button && array.indexOf(button) === -1) {\r
268 array.push(button);\r
269 }\r
270 }\r
271 } else {\r
272 button = me.getComponent(newButtons);\r
273 if (button && array.indexOf(button) === -1) {\r
274 array.push(button);\r
275 }\r
276 }\r
277 }\r
278\r
279 return array;\r
280 },\r
281\r
282 /**\r
283 * Updates the pressed buttons.\r
284 * @private\r
285 */\r
286 updatePressedButtons: function(newButtons, oldButtons) {\r
287 var me = this,\r
288 items = me.getItems(),\r
289 pressedCls = me.getPressedCls(),\r
290 events = [],\r
291 item, button, ln, i, e;\r
292\r
293 //loop through existing items and remove the pressed cls from them\r
294 ln = items.length;\r
295 if (oldButtons && oldButtons.length) {\r
296 for (i = 0; i < ln; i++) {\r
297 item = items.items[i];\r
298\r
299 if (oldButtons.indexOf(item) != -1 && newButtons.indexOf(item) == -1) {\r
300 item.removeCls([pressedCls, item.getPressedCls()]);\r
301 events.push({\r
302 item: item,\r
303 toggle: false\r
304 });\r
305 }\r
306 }\r
307 }\r
308\r
309 //loop through the new pressed buttons and add the pressed cls to them\r
310 ln = newButtons.length;\r
311 for (i = 0; i < ln; i++) {\r
312 button = newButtons[i];\r
313 if (!oldButtons || oldButtons.indexOf(button) == -1) {\r
314 button.addCls(pressedCls);\r
315 events.push({\r
316 item: button,\r
317 toggle: true\r
318 });\r
319 }\r
320 }\r
321\r
322 //loop through each of the events and fire them after a delay\r
323 ln = events.length;\r
324 if (ln && oldButtons !== undefined) {\r
325 Ext.defer(function() {\r
326 for (i = 0; i < ln; i++) {\r
327 e = events[i];\r
328 me.fireEvent('toggle', me, e.item, e.toggle);\r
329 }\r
330 }, 50);\r
331 }\r
332 },\r
333\r
334 setPressed: function(button, pressed) {\r
335 var pressedButtons = this.getPressedButtons().slice();\r
336 if (pressed) {\r
337 Ext.Array.include(pressedButtons, button);\r
338 } else {\r
339 Ext.Array.remove(pressedButtons, button);\r
340 }\r
341 this.setPressedButtons(pressedButtons);\r
342 },\r
343\r
344 /**\r
345 * Returns `true` if a specified {@link Ext.Button} is pressed.\r
346 * @param {Ext.Button} button The button to check if pressed.\r
347 * @return {Boolean} pressed\r
348 */\r
349 isPressed: function(button) {\r
350 var pressedButtons = this.getPressedButtons();\r
351 return pressedButtons.indexOf(button) !== -1;\r
352 },\r
353\r
354 /**\r
355 * @private\r
356 */\r
357 updateDisabled: function(disabled) {\r
358 var me = this;\r
359\r
360 me.items.each(function(item) {\r
361 item.setDisabled(disabled);\r
362 }, me);\r
363\r
364 me.callParent(arguments);\r
365 },\r
366\r
367 setValue: function(value) {\r
368 this.setPressedButtons([this.items.getAt(value)]);\r
369 },\r
370\r
371 getValue: function() {\r
372 var buttons = this.getPressedButtons(),\r
373 out = -1;\r
374\r
375 if (buttons.length) {\r
376 out = this.items.indexOf(buttons[0]);\r
377 }\r
378 return out;\r
379 },\r
380\r
381 updateDefaultUI: function(defaultUI) {\r
382 var items = this.items && this.items.items,\r
383 len = items.length,\r
384 i, item;\r
385\r
386 for (i = 0; i < len; i++) {\r
387 item = items[i];\r
388 if (item.getUi() == null) {\r
389 item.setUi(defaultUI);\r
390 }\r
391 }\r
392\r
393 },\r
394\r
395 doAdd: function(item, instanced) {\r
396 var defaultUI = this.getDefaultUI();\r
397\r
398 if (defaultUI && (item.getUi() == null)) {\r
399 item.setUi(defaultUI);\r
400 }\r
401 this.callParent([item, instanced]);\r
402 }\r
403});\r