blob: 922ca1c99b8886065098b10678e54cb3a43ba5a5 [file] [log] [blame]
Akrone51eaa32020-11-10 09:35:53 +01001"use strict";
2
Akron52ed22d2018-07-11 17:05:19 +02003define(['buttongroup/menu','menu/item','util'], function (treeMenuClass, defaultItemClass) {
Akron52ed22d2018-07-11 17:05:19 +02004
Akrondefa5e82018-07-10 12:09:46 +02005 return {
6 /**
7 * Create button group
8 */
9 create : function (classes) {
10 return Object.create(this)._init(classes);
11 },
Akronf8af3b82021-07-21 20:24:00 +020012
13 /**
14 * Adopt existing button group element
15 */
16 adopt : function (element) {
17 const obj = Object.create(this);
18 obj._el = element;
19 return obj;
20 },
21
Akrondefa5e82018-07-10 12:09:46 +020022 // Initialize button group
23 _init : function (classes) {
Akronbf713fc2020-10-13 10:44:35 +020024 const e = document.createElement('div');
25 const cl = e.classList;
Akron4d926f12018-07-16 15:30:25 +020026 if (classes) {
Akrondefa5e82018-07-10 12:09:46 +020027 cl.add.apply(cl,classes);
Akron4510a3e2021-09-10 15:09:56 +020028 classes.forEach(i => {
29 switch (i) {
30 case "open-menu-below" : {
31 this._omBelow = true;
32 break;
33 }
34 case "open-menu-outside" : {
35 this._omOutside = true;
36 break;
37 }
38 case "open-menu-left" : {
39 this._omLeft = true;
40 }
41 }
42 })
Akrondefa5e82018-07-10 12:09:46 +020043 };
44 cl.add('button-group');
Akron24aa0052020-11-10 11:00:34 +010045 this._el = e;
Akrondefa5e82018-07-10 12:09:46 +020046 return this;
47 },
Akrond141a362018-07-10 18:12:13 +020048
Akrondefa5e82018-07-10 12:09:46 +020049 /**
50 * Return main element
51 */
52 element : function () {
Akron24aa0052020-11-10 11:00:34 +010053 return this._el;
Akrondefa5e82018-07-10 12:09:46 +020054 },
55
Akronf8af3b82021-07-21 20:24:00 +020056 /**
57 * Define element following newly added buttons.
58 */
59 anchor : function (anchor) {
Akronc8c8bf12021-09-24 11:30:45 +020060 if (anchor !== null && anchor.parentNode == this._el) {
Akronf8af3b82021-07-21 20:24:00 +020061 this._anchor = anchor;
62 return true;
63 };
64 return false;
65 },
Akrond141a362018-07-10 18:12:13 +020066
Akrond141a362018-07-10 18:12:13 +020067
Akronf8af3b82021-07-21 20:24:00 +020068 _insert : function (tag = 'span') {
69 const span = document.createElement(tag);
70 if (this._anchor) {
71 this._el.insertBefore(span, this._anchor);
72 return span;
73 }
74 return this._el.appendChild(span);
75 },
Akrond141a362018-07-10 18:12:13 +020076
Akrondefa5e82018-07-10 12:09:46 +020077 /**
78 * Add button in order
hebasta40a85cf2020-07-15 18:10:08 +020079 *
Akron52ed22d2018-07-11 17:05:19 +020080 * Returns the button element
Akrondefa5e82018-07-10 12:09:46 +020081 */
Akron792b1a42020-09-14 18:56:38 +020082 add : function (title, data, cb) {
Akronf8af3b82021-07-21 20:24:00 +020083 const b = this._insert('span');
Akron83a58bc2024-11-08 09:55:19 +010084 let desc = title;
Akron792b1a42020-09-14 18:56:38 +020085
Akronb0ae8412026-02-24 11:47:52 +010086 let that = this;
Akron792b1a42020-09-14 18:56:38 +020087 if (data !== undefined) {
88 if (data['cls'] !== undefined) {
89 b.classList.add.apply(b.classList, data['cls']);
90 };
hebasta40a85cf2020-07-15 18:10:08 +020091
Akronba09ed22020-10-01 16:01:45 +020092 if (data['icon'] !== undefined) {
Akron792b1a42020-09-14 18:56:38 +020093 b.setAttribute('data-icon', data['icon']);
94 };
Akronba09ed22020-10-01 16:01:45 +020095
96 if (data['state'] !== undefined) {
97 b['state'] = data['state'];
Akron83a58bc2024-11-08 09:55:19 +010098 };
99
Akron5881be12026-02-19 11:52:01 +0100100 if (data['active'] !== undefined) {
101 let active = data['active'];
Akronb0ae8412026-02-24 11:47:52 +0100102 b['active'] = active;
Akron5881be12026-02-19 11:52:01 +0100103
Akronb0ae8412026-02-24 11:47:52 +0100104 let check = _addCheck(b,active);
105 check.addEventListener('click', function (e) {
106 // Do not bubble
107 e.halt();
Akron5881be12026-02-19 11:52:01 +0100108 // Toggle state
Akronb0ae8412026-02-24 11:47:52 +0100109 active.roll();
110
111 let obj = that._bind || this;
112 obj.button = b;
113 b._activeClick = true;
114 cb.apply(obj, e);
115 b._activeClick = false;
116 });
Akron5881be12026-02-19 11:52:01 +0100117 };
118
119
Akron83a58bc2024-11-08 09:55:19 +0100120 if (data['desc'] !== undefined) {
121 desc = data['desc'];
122 };
hebasta40a85cf2020-07-15 18:10:08 +0200123 };
Akron83a58bc2024-11-08 09:55:19 +0100124
125 b.setAttribute('title', desc);
Akron9306b252026-02-18 15:29:41 +0100126 let innerSpan = b.addE('span');
127 innerSpan.addT(title);
128
129 b["changeTitle"] = function (title) {
Akronb0ae8412026-02-24 11:47:52 +0100130 innerSpan.textContent = title;
Akron9306b252026-02-18 15:29:41 +0100131 };
Akron5881be12026-02-19 11:52:01 +0100132
Akrondefa5e82018-07-10 12:09:46 +0200133 b.addEventListener('click', function (e) {
134
135 // Do not bubble
136 e.halt();
137
138 // Call callback
Akronbf713fc2020-10-13 10:44:35 +0200139 let obj = that._bind || this;
Akron52ed22d2018-07-11 17:05:19 +0200140 obj.button = b;
141 cb.apply(obj, e)
Akrondefa5e82018-07-10 12:09:46 +0200142 });
Akron52ed22d2018-07-11 17:05:19 +0200143
144 return b;
Akrondefa5e82018-07-10 12:09:46 +0200145 },
146
Akrond141a362018-07-10 18:12:13 +0200147
Akrondefa5e82018-07-10 12:09:46 +0200148 /**
Akron52ed22d2018-07-11 17:05:19 +0200149 * Add button that spawns a list in order.
hebasta40a85cf2020-07-15 18:10:08 +0200150 *
Akron52ed22d2018-07-11 17:05:19 +0200151 * Returns the list object.
152 */
Akron792b1a42020-09-14 18:56:38 +0200153 addList : function (title, data, itemClass = defaultItemClass) {
Akronbf713fc2020-10-13 10:44:35 +0200154 const list = treeMenuClass.create([], itemClass);
Akron4510a3e2021-09-10 15:09:56 +0200155
156 list.openAt(
157 this._omLeft ? true : false,
158 this._omBelow ? true : false,
159 this._omOutside ? true : false,
160 );
161
Akron644ad9f2021-07-26 16:12:59 +0200162 let b = this.add(title, data, function (e) {
Akron52ed22d2018-07-11 17:05:19 +0200163 list.show();
164 list.button(this.button);
165 list.focus();
166 });
Akron644ad9f2021-07-26 16:12:59 +0200167 b.list = list;
168 return b;
Akron52ed22d2018-07-11 17:05:19 +0200169 },
Akron858cbc82019-12-05 16:53:13 +0100170
171 /**
172 * Add button that can toggle a state.
173 * The state has to be a state object.
174 */
Akron37ea1192021-07-28 10:40:14 +0200175 /*
176 * addToggle() should be removed in favor of add(toggleObj)
177 * or similar, so the API of buttongroups and lists is similar
178 * for use as action plugins.
179 */
Akron792b1a42020-09-14 18:56:38 +0200180 addToggle : function (title, data, state) {
Akronf8af3b82021-07-21 20:24:00 +0200181 const b = this._insert('span');
Akron83a58bc2024-11-08 09:55:19 +0100182 let desc = title;
Akron792b1a42020-09-14 18:56:38 +0200183
184 if (data != undefined) {
185 if (data['cls'] !== undefined) {
Akronbf713fc2020-10-13 10:44:35 +0200186 b.classList.add.apply(
187 b.classList,
188 data['cls']
189 );
Akron792b1a42020-09-14 18:56:38 +0200190 };
Akron83a58bc2024-11-08 09:55:19 +0100191
192 if (data['icon'] !== undefined) {
193 b.setAttribute('data-icon', data['icon']);
194 };
195
196 if (data['desc'] !== undefined) {
197 desc = data['desc'];
198 };
Akron858cbc82019-12-05 16:53:13 +0100199 };
200
Akron83a58bc2024-11-08 09:55:19 +0100201 b.setAttribute('title',desc);
Akron858cbc82019-12-05 16:53:13 +0100202
Akron5881be12026-02-19 11:52:01 +0100203 _addCheck(b, state);
Akron858cbc82019-12-05 16:53:13 +0100204
205 b.addE('span').addT(title);
206
207 let that = this;
208 b.addEventListener('click', function (e) {
209
210 // Do not bubble
211 e.halt();
212
213 // Toggle state
Akron237abc42020-10-07 14:14:52 +0200214 state.roll();
Akron858cbc82019-12-05 16:53:13 +0100215 });
216
217 return b;
218 },
Akron52ed22d2018-07-11 17:05:19 +0200219
220 /**
hebasta40a85cf2020-07-15 18:10:08 +0200221 * Bind an object to all callbacks of the button group.
222 * To get the button element inside the callback,
Akron52ed22d2018-07-11 17:05:19 +0200223 * use this.button
Akrondefa5e82018-07-10 12:09:46 +0200224 */
225 bind : function (obj) {
226 if (obj !== undefined) {
227 this._bind = obj;
Akronb23e2712018-07-13 18:17:37 +0200228 return this;
Akrondefa5e82018-07-10 12:09:46 +0200229 };
230 return this._bind || this;
Akrond141a362018-07-10 18:12:13 +0200231 },
232
233
234 /**
235 * Remove all defined buttons
236 */
237 clear : function () {
Akron24aa0052020-11-10 11:00:34 +0100238 _removeChildren(this._el);
Akrond141a362018-07-10 18:12:13 +0200239 return this;
Akrondefa5e82018-07-10 12:09:46 +0200240 }
241 }
242});
Akron5881be12026-02-19 11:52:01 +0100243
244function _addCheck(b,state) {
245
246 // Set check marker
247 const check = b.addE('span');
248 check.classList.add("check", "button-icon");
249 check.addE('span');
250
251 // Associate this object to state
252 // Add setState method to object
253 check.setState = function (value) {
254 if (value) {
255 this.classList.add("checked");
256 } else {
257 this.classList.remove("checked");
258 }
259 };
260 state.associate(check);
261 return check;
262};