blob: 040637f79101e2e50f1f9a413652dd1c73d0fb8b [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);
28 };
29 cl.add('button-group');
Akron24aa0052020-11-10 11:00:34 +010030 this._el = e;
Akrondefa5e82018-07-10 12:09:46 +020031 return this;
32 },
Akrond141a362018-07-10 18:12:13 +020033
Akrondefa5e82018-07-10 12:09:46 +020034 /**
35 * Return main element
36 */
37 element : function () {
Akron24aa0052020-11-10 11:00:34 +010038 return this._el;
Akrondefa5e82018-07-10 12:09:46 +020039 },
40
Akronf8af3b82021-07-21 20:24:00 +020041 /**
42 * Define element following newly added buttons.
43 */
44 anchor : function (anchor) {
45 if (anchor.parentNode == this._el) {
46 this._anchor = anchor;
47 return true;
48 };
49 return false;
50 },
Akrond141a362018-07-10 18:12:13 +020051
52 /**
hebasta40a85cf2020-07-15 18:10:08 +020053 * Upgrade this object to another object,
Akrond141a362018-07-10 18:12:13 +020054 * while private data stays intact.
hebasta40a85cf2020-07-15 18:10:08 +020055 *
Akrond141a362018-07-10 18:12:13 +020056 * @param {Object} An object with properties.
57 */
58 upgradeTo : function (props) {
59 for (var prop in props) {
60 this[prop] = props[prop];
61 };
62 return this;
63 },
64
Akronf8af3b82021-07-21 20:24:00 +020065 _insert : function (tag = 'span') {
66 const span = document.createElement(tag);
67 if (this._anchor) {
68 this._el.insertBefore(span, this._anchor);
69 return span;
70 }
71 return this._el.appendChild(span);
72 },
Akrond141a362018-07-10 18:12:13 +020073
Akrondefa5e82018-07-10 12:09:46 +020074 /**
75 * Add button in order
hebasta40a85cf2020-07-15 18:10:08 +020076 *
Akron52ed22d2018-07-11 17:05:19 +020077 * Returns the button element
Akrondefa5e82018-07-10 12:09:46 +020078 */
Akron792b1a42020-09-14 18:56:38 +020079 add : function (title, data, cb) {
Akronf8af3b82021-07-21 20:24:00 +020080 const b = this._insert('span');
Akrondefa5e82018-07-10 12:09:46 +020081 b.setAttribute('title',title);
Akron792b1a42020-09-14 18:56:38 +020082
83 if (data !== undefined) {
84 if (data['cls'] !== undefined) {
85 b.classList.add.apply(b.classList, data['cls']);
86 };
hebasta40a85cf2020-07-15 18:10:08 +020087
Akronba09ed22020-10-01 16:01:45 +020088 if (data['icon'] !== undefined) {
Akron792b1a42020-09-14 18:56:38 +020089 b.setAttribute('data-icon', data['icon']);
90 };
Akronba09ed22020-10-01 16:01:45 +020091
92 if (data['state'] !== undefined) {
93 b['state'] = data['state'];
94 }
hebasta40a85cf2020-07-15 18:10:08 +020095 };
96
Akronbec4a6a2018-07-10 14:45:15 +020097 b.addE('span').addT(title);
Akrondefa5e82018-07-10 12:09:46 +020098
Akronbf713fc2020-10-13 10:44:35 +020099 let that = this;
Akrondefa5e82018-07-10 12:09:46 +0200100 b.addEventListener('click', function (e) {
101
102 // Do not bubble
103 e.halt();
104
105 // Call callback
Akronbf713fc2020-10-13 10:44:35 +0200106 let obj = that._bind || this;
Akron52ed22d2018-07-11 17:05:19 +0200107 obj.button = b;
108 cb.apply(obj, e)
Akrondefa5e82018-07-10 12:09:46 +0200109 });
Akron52ed22d2018-07-11 17:05:19 +0200110
111 return b;
Akrondefa5e82018-07-10 12:09:46 +0200112 },
113
Akrond141a362018-07-10 18:12:13 +0200114
Akrondefa5e82018-07-10 12:09:46 +0200115 /**
Akron52ed22d2018-07-11 17:05:19 +0200116 * Add button that spawns a list in order.
hebasta40a85cf2020-07-15 18:10:08 +0200117 *
Akron52ed22d2018-07-11 17:05:19 +0200118 * Returns the list object.
119 */
Akron792b1a42020-09-14 18:56:38 +0200120 addList : function (title, data, itemClass = defaultItemClass) {
Akronbf713fc2020-10-13 10:44:35 +0200121 const list = treeMenuClass.create([], itemClass);
Akron792b1a42020-09-14 18:56:38 +0200122 this.add(title, data, function (e) {
Akron52ed22d2018-07-11 17:05:19 +0200123 list.show();
124 list.button(this.button);
125 list.focus();
126 });
Akron52ed22d2018-07-11 17:05:19 +0200127 return list;
128 },
Akron858cbc82019-12-05 16:53:13 +0100129
130 /**
131 * Add button that can toggle a state.
132 * The state has to be a state object.
133 */
Akron37ea1192021-07-28 10:40:14 +0200134 /*
135 * addToggle() should be removed in favor of add(toggleObj)
136 * or similar, so the API of buttongroups and lists is similar
137 * for use as action plugins.
138 */
Akron792b1a42020-09-14 18:56:38 +0200139 addToggle : function (title, data, state) {
Akronf8af3b82021-07-21 20:24:00 +0200140 const b = this._insert('span');
Akron858cbc82019-12-05 16:53:13 +0100141 b.setAttribute('title',title);
Akron792b1a42020-09-14 18:56:38 +0200142
143 if (data != undefined) {
144 if (data['cls'] !== undefined) {
Akronbf713fc2020-10-13 10:44:35 +0200145 b.classList.add.apply(
146 b.classList,
147 data['cls']
148 );
Akron792b1a42020-09-14 18:56:38 +0200149 };
Akron858cbc82019-12-05 16:53:13 +0100150 };
151
152 // Set check marker
Akronbf713fc2020-10-13 10:44:35 +0200153 const check = b.addE('span');
Akron858cbc82019-12-05 16:53:13 +0100154 check.classList.add("check", "button-icon");
155 check.addE('span');
156
157 // Associate this object to state
158 // Add setState method to object
159 check.setState = function (value) {
160 if (value) {
161 this.classList.add("checked");
162 } else {
163 this.classList.remove("checked");
164 }
165 };
166 state.associate(check);
167
168 b.addE('span').addT(title);
169
170 let that = this;
171 b.addEventListener('click', function (e) {
172
173 // Do not bubble
174 e.halt();
175
176 // Toggle state
Akron237abc42020-10-07 14:14:52 +0200177 state.roll();
Akron858cbc82019-12-05 16:53:13 +0100178 });
179
180 return b;
181 },
Akron52ed22d2018-07-11 17:05:19 +0200182
183 /**
hebasta40a85cf2020-07-15 18:10:08 +0200184 * Bind an object to all callbacks of the button group.
185 * To get the button element inside the callback,
Akron52ed22d2018-07-11 17:05:19 +0200186 * use this.button
Akrondefa5e82018-07-10 12:09:46 +0200187 */
188 bind : function (obj) {
189 if (obj !== undefined) {
190 this._bind = obj;
Akronb23e2712018-07-13 18:17:37 +0200191 return this;
Akrondefa5e82018-07-10 12:09:46 +0200192 };
193 return this._bind || this;
Akrond141a362018-07-10 18:12:13 +0200194 },
195
196
197 /**
198 * Remove all defined buttons
199 */
200 clear : function () {
Akron24aa0052020-11-10 11:00:34 +0100201 _removeChildren(this._el);
Akrond141a362018-07-10 18:12:13 +0200202 return this;
Akrondefa5e82018-07-10 12:09:46 +0200203 }
204 }
205});