bootstrap5-toggle 4.3.6 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,422 +1,495 @@
1
- /* Copyright Notice
2
- * bootstrap5-toggle v4.3.6
3
- * https://palcarazm.github.io/bootstrap5-toggle/
4
- * @author 2011-2014 Min Hur (https://github.com/minhur)
5
- * @author 2018-2019 Brent Ely (https://github.com/gitbrent)
6
- * @author 2022 Pablo Alcaraz Martínez (https://github.com/palcarazm)
7
- * @funding GitHub Sponsors
8
- * @see https://github.com/sponsors/palcarazm
9
- * @license MIT
10
- * @see https://github.com/palcarazm/bootstrap5-toggle/blob/master/LICENSE
11
- */
12
-
13
-
14
- "use strict";
15
-
16
- (function () {
17
- /**
18
- * `Toggle` is instantiated for each toggle-button
19
- */
20
- class Toggle {
21
- constructor(element, options) {
22
- const DEFAULTS = {
23
- on: "On",
24
- onstyle: "primary",
25
- onvalue: null,
26
- off: "Off",
27
- offstyle: "secondary",
28
- offvalue: null,
29
- size: "",
30
- style: "",
31
- width: null,
32
- height: null,
33
- tabindex: 0,
34
- tristate: false,
35
- name: null,
36
- };
37
- options = options || {};
38
-
39
- // A: Capture ref to HMTL element
40
- this.element = element;
41
-
42
- // B: Set options
43
- this.options = {
44
- on: this.element.getAttribute("data-on") || options.on || DEFAULTS.on,
45
- onstyle:
46
- this.element.getAttribute("data-onstyle") ||
47
- options.onstyle ||
48
- DEFAULTS.onstyle,
49
- onvalue:
50
- this.element.getAttribute("value") ||
51
- this.element.getAttribute("data-onvalue") ||
52
- options.onvalue ||
53
- DEFAULTS.onvalue,
54
- off:
55
- this.element.getAttribute("data-off") || options.off || DEFAULTS.off,
56
- offstyle:
57
- this.element.getAttribute("data-offstyle") ||
58
- options.offstyle ||
59
- DEFAULTS.offstyle,
60
- offvalue:
61
- this.element.getAttribute("data-offvalue") ||
62
- options.offvalue ||
63
- DEFAULTS.offvalue,
64
- size:
65
- this.element.getAttribute("data-size") ||
66
- options.size ||
67
- DEFAULTS.size,
68
- style:
69
- this.element.getAttribute("data-style") ||
70
- options.style ||
71
- DEFAULTS.style,
72
- width:
73
- this.element.getAttribute("data-width") ||
74
- options.width ||
75
- DEFAULTS.width,
76
- height:
77
- this.element.getAttribute("data-height") ||
78
- options.height ||
79
- DEFAULTS.height,
80
- tabindex:
81
- this.element.getAttribute("tabindex") ||
82
- options.tabindex ||
83
- DEFAULTS.tabindex,
84
- tristate:
85
- this.element.hasAttribute("tristate") ||
86
- options.tristate ||
87
- DEFAULTS.tristate,
88
- name:
89
- this.element.getAttribute("name") || options.name || DEFAULTS.name,
90
- };
91
-
92
- // LAST: Render Toggle
93
- this.render();
94
- }
95
- render() {
96
- function calcH(el) {
97
- const styles = window.getComputedStyle(el);
98
- const height = el.offsetHeight;
99
- const borderTopWidth = parseFloat(styles.borderTopWidth);
100
- const borderBottomWidth = parseFloat(styles.borderBottomWidth);
101
- const paddingTop = parseFloat(styles.paddingTop);
102
- const paddingBottom = parseFloat(styles.paddingBottom);
103
-
104
- return (
105
- height -
106
- borderBottomWidth -
107
- borderTopWidth -
108
- paddingTop -
109
- paddingBottom
110
- );
111
- }
112
- // 0: Parse size
113
- let size;
114
- switch (this.options.size) {
115
- case "large":
116
- case "lg":
117
- size = "btn-lg";
118
- break;
119
- case "small":
120
- case "sm":
121
- size = "btn-sm";
122
- break;
123
- case "mini":
124
- case "xs":
125
- size = "btn-xs";
126
- break;
127
- default:
128
- size = "";
129
- break;
130
- }
131
-
132
- // 1: On
133
- let ecmasToggleOn = document.createElement("label");
134
- ecmasToggleOn.setAttribute(
135
- "class",
136
- "btn btn-" + this.options.onstyle + " " + size
137
- );
138
- if (this.element.id) ecmasToggleOn.setAttribute("for", this.element.id);
139
- ecmasToggleOn.innerHTML = this.options.on;
140
-
141
- // 2: Off
142
- let ecmasToggleOff = document.createElement("label");
143
- ecmasToggleOff.setAttribute(
144
- "class",
145
- "btn btn-" + this.options.offstyle + " " + size
146
- );
147
- if (this.element.id) ecmasToggleOff.setAttribute("for", this.element.id);
148
- ecmasToggleOff.innerHTML = this.options.off;
149
-
150
- // 3: Handle
151
- let ecmasToggleHandle = document.createElement("span");
152
- ecmasToggleHandle.setAttribute("class", "toggle-handle btn " + size);
153
-
154
- // 4: Toggle Group
155
- let ecmasToggleGroup = document.createElement("div");
156
- ecmasToggleGroup.setAttribute("class", "toggle-group");
157
- ecmasToggleGroup.appendChild(ecmasToggleOn);
158
- ecmasToggleGroup.appendChild(ecmasToggleOff);
159
- ecmasToggleGroup.appendChild(ecmasToggleHandle);
160
-
161
- // 5: Toggle
162
- let ecmasToggle = document.createElement("div");
163
- ecmasToggle.setAttribute("class", "toggle btn");
164
- ecmasToggle.classList.add(
165
- this.element.checked
166
- ? "btn-" + this.options.onstyle
167
- : "btn-" + this.options.offstyle
168
- );
169
- ecmasToggle.setAttribute("tabindex", this.options.tabindex);
170
- if (!this.element.checked) ecmasToggle.classList.add("off");
171
- if (this.options.size) ecmasToggle.classList.add(size);
172
- if (this.options.style) {
173
- this.options.style.split(" ").forEach((style) => {
174
- ecmasToggle.classList.add(style);
175
- });
176
- }
177
- if (this.element.disabled || this.element.readOnly) {
178
- ecmasToggle.classList.add("disabled");
179
- ecmasToggle.setAttribute("disabled", "disabled");
180
- }
181
-
182
- // 6: Set form values
183
- if (this.options.onvalue)
184
- this.element.setAttribute("value", this.options.onvalue);
185
- let invElement = null;
186
- if (this.options.offvalue) {
187
- invElement = this.element.cloneNode();
188
- invElement.setAttribute("value", this.options.offvalue);
189
- invElement.setAttribute("data-toggle", "invert-toggle");
190
- invElement.removeAttribute("id");
191
- invElement.checked = !this.element.checked;
192
- }
193
-
194
- // 7: Replace HTML checkbox with Toggle-Button
195
- this.element.parentElement.insertBefore(ecmasToggle, this.element);
196
- ecmasToggle.appendChild(this.element);
197
- if (invElement) ecmasToggle.appendChild(invElement);
198
- ecmasToggle.appendChild(ecmasToggleGroup);
199
-
200
- // 8: Set button W/H, lineHeight
201
- {
202
- // A: Set style W/H
203
- // NOTE: `offsetWidth` returns *rounded* integer values, so use `getBoundingClientRect` instead.
204
- ecmasToggle.style.width =
205
- (this.options.width ||
206
- Math.max(
207
- ecmasToggleOn.getBoundingClientRect().width,
208
- ecmasToggleOff.getBoundingClientRect().width
209
- ) +
210
- ecmasToggleHandle.getBoundingClientRect().width / 2) + "px";
211
- ecmasToggle.style.height =
212
- (this.options.height ||
213
- Math.max(
214
- ecmasToggleOn.getBoundingClientRect().height,
215
- ecmasToggleOff.getBoundingClientRect().height
216
- )) + "px";
217
-
218
- // B: Apply on/off class
219
- ecmasToggleOn.classList.add("toggle-on");
220
- ecmasToggleOff.classList.add("toggle-off");
221
-
222
- // C: Finally, set lineHeight if needed
223
- if (this.options.height) {
224
- ecmasToggleOn.style.lineHeight = calcH(ecmasToggleOn) + "px";
225
- ecmasToggleOff.style.lineHeight = calcH(ecmasToggleOff) + "px";
226
- }
227
- }
228
-
229
- // 9: Add listeners
230
- ecmasToggle.addEventListener("touchstart", (e) => {
231
- this.#toggleActionPerformed(e);
232
- });
233
- ecmasToggle.addEventListener("click", (e) => {
234
- this.#toggleActionPerformed(e);
235
- });
236
- ecmasToggle.addEventListener("keypress", (e) => {
237
- if (e.key == " ") {
238
- this.#toggleActionPerformed(e);
239
- }
240
- });
241
-
242
- // 10: Set elements to bootstrap object
243
- this.ecmasToggle = ecmasToggle;
244
- this.invElement = invElement;
245
-
246
- // 11: Keep reference to this instance for subsequent calls via `getElementById().bootstrapToggle()`
247
- this.element.bsToggle = this;
248
- }
249
-
250
- /**
251
- * Trigger actions
252
- * @param {Event} e event
253
- */
254
- #toggleActionPerformed(e) {
255
- if (this.options.tristate) {
256
- if (this.ecmasToggle.classList.contains("indeterminate")) {
257
- this.determinate(true);
258
- this.toggle();
259
- } else {
260
- this.indeterminate();
261
- }
262
- } else {
263
- this.toggle();
264
- }
265
- e.preventDefault();
266
- }
267
-
268
- toggle(silent = false) {
269
- if (this.element.checked) this.off(silent);
270
- else this.on(silent);
271
- }
272
-
273
- on(silent = false) {
274
- if (this.element.disabled || this.element.readOnly) return false;
275
- this.ecmasToggle.classList.remove("btn-" + this.options.offstyle);
276
- this.ecmasToggle.classList.add("btn-" + this.options.onstyle);
277
- this.ecmasToggle.classList.remove("off");
278
- this.element.checked = true;
279
- if (this.invElement) this.invElement.checked = false;
280
- if (!silent) this.trigger();
281
- }
282
-
283
- off(silent = false) {
284
- if (this.element.disabled || this.element.readOnly) return false;
285
- this.ecmasToggle.classList.remove("btn-" + this.options.onstyle);
286
- this.ecmasToggle.classList.add("btn-" + this.options.offstyle);
287
- this.ecmasToggle.classList.add("off");
288
- this.element.checked = false;
289
- if (this.invElement) this.invElement.checked = true;
290
- if (!silent) this.trigger();
291
- }
292
-
293
- indeterminate(silent = false) {
294
- if (
295
- !this.options.tristate ||
296
- this.element.disabled ||
297
- this.element.readOnly
298
- )
299
- return false;
300
- this.ecmasToggle.classList.add("indeterminate");
301
- this.element.indeterminate = true;
302
- this.element.removeAttribute("name");
303
- if (this.invElement) this.invElement.indeterminate = true;
304
- if (this.invElement) this.invElement.removeAttribute("name");
305
- if (!silent) this.trigger();
306
- }
307
-
308
- determinate(silent = false) {
309
- if (
310
- !this.options.tristate ||
311
- this.element.disabled ||
312
- this.element.readOnly
313
- )
314
- return false;
315
- this.ecmasToggle.classList.remove("indeterminate");
316
- this.element.indeterminate = false;
317
- if (this.options.name)
318
- this.element.setAttribute("name", this.options.name);
319
- if (this.invElement) this.invElement.indeterminate = false;
320
- if (this.invElement && this.options.name)
321
- this.invElement.setAttribute("name", this.options.name);
322
- if (!silent) this.trigger();
323
- }
324
-
325
- enable() {
326
- this.ecmasToggle.classList.remove("disabled");
327
- this.ecmasToggle.removeAttribute("disabled");
328
- this.element.removeAttribute("disabled");
329
- this.element.removeAttribute("readonly");
330
- if (this.invElement) {
331
- this.invElement.removeAttribute("disabled");
332
- this.invElement.removeAttribute("readonly");
333
- }
334
- }
335
-
336
- disable() {
337
- this.ecmasToggle.classList.add("disabled");
338
- this.ecmasToggle.setAttribute("disabled", "");
339
- this.element.setAttribute("disabled", "");
340
- this.element.removeAttribute("readonly");
341
- if (this.invElement) {
342
- this.invElement.setAttribute("disabled", "");
343
- this.invElement.removeAttribute("readonly");
344
- }
345
- }
346
-
347
- readonly() {
348
- this.ecmasToggle.classList.add("disabled");
349
- this.ecmasToggle.setAttribute("disabled", "");
350
- this.element.removeAttribute("disabled");
351
- this.element.setAttribute("readonly", "");
352
- if (this.invElement) {
353
- this.invElement.removeAttribute("disabled");
354
- this.invElement.setAttribute("readonly", "");
355
- }
356
- }
357
-
358
- update(silent) {
359
- if (this.element.disabled) this.disable();
360
- else if (this.element.readOnly) this.readonly();
361
- else this.enable();
362
- if (this.element.checked) this.on(silent);
363
- else this.off(silent);
364
- }
365
-
366
- trigger(silent) {
367
- if (!silent)
368
- this.element.dispatchEvent(new Event("change", { bubbles: true }));
369
- }
370
-
371
- destroy() {
372
- // A: Remove button-group from UI, replace checkbox element
373
- this.ecmasToggle.parentNode.insertBefore(this.element, this.ecmasToggle);
374
- this.ecmasToggle.parentNode.removeChild(this.ecmasToggle);
375
-
376
- // B: Delete internal refs
377
- delete this.element.bsToggle;
378
- delete this.ecmasToggle;
379
- }
380
- }
381
-
382
- /**
383
- * Add `bootstrapToggle` prototype function to HTML Elements
384
- * Enables execution when used with HTML - ex: `document.getElementById('toggle').bootstrapToggle('on')`
385
- */
386
- Element.prototype.bootstrapToggle = function (options, silent) {
387
- let _bsToggle = this.bsToggle || new Toggle(this, options);
388
-
389
- // Execute method calls
390
- if (options && typeof options === "string") {
391
- if (options.toLowerCase() == "toggle") _bsToggle.toggle(silent);
392
- else if (options.toLowerCase() == "on") _bsToggle.on(silent);
393
- else if (options.toLowerCase() == "off") _bsToggle.off(silent);
394
- else if (options.toLowerCase() == "indeterminate")
395
- _bsToggle.indeterminate(silent);
396
- else if (options.toLowerCase() == "determinate")
397
- _bsToggle.determinate(silent);
398
- else if (options.toLowerCase() == "enable") _bsToggle.enable();
399
- else if (options.toLowerCase() == "disable") _bsToggle.disable();
400
- else if (options.toLowerCase() == "readonly") _bsToggle.readonly();
401
- else if (options.toLowerCase() == "destroy") _bsToggle.destroy();
402
- }
403
- };
404
-
405
- /**
406
- * Replace all `input[type=checkbox][data-toggle="toggle"]` inputs with "Bootstrap-Toggle"
407
- * Executes once page elements have rendered enabling script to be placed in `<head>`
408
- */
409
- if (typeof window !== "undefined")
410
- window.onload = function () {
411
- document
412
- .querySelectorAll('input[type=checkbox][data-toggle="toggle"]')
413
- .forEach(function (ele) {
414
- ele.bootstrapToggle();
415
- });
416
- };
417
-
418
- // Export library if possible
419
- if (typeof module !== "undefined" && module.exports) {
420
- module.exports = Toggle;
421
- }
422
- })();
1
+ /* Copyright Notice
2
+ * bootstrap5-toggle v5.0.0-alpha
3
+ * https://palcarazm.github.io/bootstrap5-toggle/
4
+ * @author 2011-2014 Min Hur (https://github.com/minhur)
5
+ * @author 2018-2019 Brent Ely (https://github.com/gitbrent)
6
+ * @author 2022 Pablo Alcaraz Martínez (https://github.com/palcarazm)
7
+ * @funding GitHub Sponsors
8
+ * @see https://github.com/sponsors/palcarazm
9
+ * @license MIT
10
+ * @see https://github.com/palcarazm/bootstrap5-toggle/blob/master/LICENSE
11
+ */
12
+
13
+
14
+ "use strict";
15
+
16
+ (function () {
17
+ /**
18
+ * `Toggle` is instantiated for each toggle-button
19
+ */
20
+ class Toggle {
21
+ constructor(element, options) {
22
+ const DEPRECATION = {
23
+ value:
24
+ "BOOTSTRAP TOGGLE DEPRECATION CHECK -- a0Jhux0QySypjjs4tLtEo8xT2kx0AbYaq9K6mgNjWSs0HF0L8T8J0M0o3Kr7zkm7 --",
25
+ ATTRIBUTE: "attribute",
26
+ OPTION: "option",
27
+ log: function (type, oldlabel, newlabel) {
28
+ console.warn(
29
+ `Bootstrap Toggle deprecation warning: Using ${oldlabel} ${type} is deprected. Use ${newlabel} instead.`
30
+ );
31
+ },
32
+ };
33
+ const DEFAULTS = {
34
+ onlabel: "On",
35
+ onstyle: "primary",
36
+ onvalue: null,
37
+ ontitle: null,
38
+ offlabel: "Off",
39
+ offstyle: "secondary",
40
+ offvalue: null,
41
+ offtitle: null,
42
+ size: "",
43
+ style: "",
44
+ width: null,
45
+ height: null,
46
+ tabindex: 0,
47
+ tristate: false,
48
+ name: null,
49
+ };
50
+ options = options || {};
51
+
52
+ // A: Capture ref to HMTL element
53
+ this.element = element;
54
+
55
+ // B: Set options
56
+ this.options = {
57
+ onlabel:
58
+ this.element.getAttribute("data-onlabel") ||
59
+ options.onlabel ||
60
+ DEPRECATION.value ||
61
+ DEFAULTS.onlabel,
62
+ onstyle:
63
+ this.element.getAttribute("data-onstyle") ||
64
+ options.onstyle ||
65
+ DEFAULTS.onstyle,
66
+ onvalue:
67
+ this.element.getAttribute("value") ||
68
+ this.element.getAttribute("data-onvalue") ||
69
+ options.onvalue ||
70
+ DEFAULTS.onvalue,
71
+ ontitle:
72
+ this.element.getAttribute("data-ontitle") ||
73
+ options.ontitle ||
74
+ this.element.getAttribute("title") ||
75
+ DEFAULTS.ontitle,
76
+ offlabel:
77
+ this.element.getAttribute("data-offlabel") ||
78
+ options.offlabel ||
79
+ DEPRECATION.value ||
80
+ DEFAULTS.offlabel,
81
+ offstyle:
82
+ this.element.getAttribute("data-offstyle") ||
83
+ options.offstyle ||
84
+ DEFAULTS.offstyle,
85
+ offvalue:
86
+ this.element.getAttribute("data-offvalue") ||
87
+ options.offvalue ||
88
+ DEFAULTS.offvalue,
89
+ offtitle:
90
+ this.element.getAttribute("data-offtitle") ||
91
+ options.offtitle ||
92
+ this.element.getAttribute("title") ||
93
+ DEFAULTS.offtitle,
94
+ size:
95
+ this.element.getAttribute("data-size") ||
96
+ options.size ||
97
+ DEFAULTS.size,
98
+ style:
99
+ this.element.getAttribute("data-style") ||
100
+ options.style ||
101
+ DEFAULTS.style,
102
+ width:
103
+ this.element.getAttribute("data-width") ||
104
+ options.width ||
105
+ DEFAULTS.width,
106
+ height:
107
+ this.element.getAttribute("data-height") ||
108
+ options.height ||
109
+ DEFAULTS.height,
110
+ tabindex:
111
+ this.element.getAttribute("tabindex") ||
112
+ options.tabindex ||
113
+ DEFAULTS.tabindex,
114
+ tristate:
115
+ this.element.hasAttribute("tristate") ||
116
+ options.tristate ||
117
+ DEFAULTS.tristate,
118
+ name:
119
+ this.element.getAttribute("name") || options.name || DEFAULTS.name,
120
+ };
121
+
122
+ // C: Check deprecations
123
+ if (this.options.onlabel === DEPRECATION.value) {
124
+ if (this.element.getAttribute("data-on")) {
125
+ DEPRECATION.log(DEPRECATION.ATTRIBUTE, "data-on", "data-onlabel");
126
+ this.options.onlabel = this.element.getAttribute("data-on");
127
+ } else if (options.on) {
128
+ DEPRECATION.log(DEPRECATION.OPTION, "on", "onlabel");
129
+ this.options.onlabel = options.on;
130
+ } else {
131
+ this.options.onlabel = DEFAULTS.onlabel;
132
+ }
133
+ }
134
+ if (this.options.offlabel === DEPRECATION.value) {
135
+ if (this.element.getAttribute("data-off")) {
136
+ DEPRECATION.log(DEPRECATION.ATTRIBUTE, "data-off", "data-offlabel");
137
+ this.options.offlabel = this.element.getAttribute("data-off");
138
+ } else if (options.off) {
139
+ DEPRECATION.log(DEPRECATION.OPTION, "off", "offlabel");
140
+ this.options.offlabel = options.off;
141
+ } else {
142
+ this.options.offlabel = DEFAULTS.offlabel;
143
+ }
144
+ }
145
+
146
+ // LAST: Render Toggle
147
+ this.render();
148
+ }
149
+ render() {
150
+ function calcH(el) {
151
+ const styles = window.getComputedStyle(el);
152
+ const height = el.offsetHeight;
153
+ const borderTopWidth = parseFloat(styles.borderTopWidth);
154
+ const borderBottomWidth = parseFloat(styles.borderBottomWidth);
155
+ const paddingTop = parseFloat(styles.paddingTop);
156
+ const paddingBottom = parseFloat(styles.paddingBottom);
157
+
158
+ return (
159
+ height -
160
+ borderBottomWidth -
161
+ borderTopWidth -
162
+ paddingTop -
163
+ paddingBottom
164
+ );
165
+ }
166
+ // 0: Parse size
167
+ let size;
168
+ switch (this.options.size) {
169
+ case "large":
170
+ case "lg":
171
+ size = "btn-lg";
172
+ break;
173
+ case "small":
174
+ case "sm":
175
+ size = "btn-sm";
176
+ break;
177
+ case "mini":
178
+ case "xs":
179
+ size = "btn-xs";
180
+ break;
181
+ default:
182
+ size = "";
183
+ break;
184
+ }
185
+
186
+ // 1: On
187
+ let ecmasToggleOn = document.createElement("span");
188
+ ecmasToggleOn.setAttribute(
189
+ "class",
190
+ "btn btn-" + this.options.onstyle + " " + size
191
+ );
192
+ ecmasToggleOn.innerHTML = this.options.onlabel;
193
+ if (this.options.ontitle) {
194
+ ecmasToggleOn.setAttribute("title", this.options.ontitle);
195
+ }
196
+
197
+ // 2: Off
198
+ let ecmasToggleOff = document.createElement("span");
199
+ ecmasToggleOff.setAttribute(
200
+ "class",
201
+ "btn btn-" + this.options.offstyle + " " + size
202
+ );
203
+ ecmasToggleOff.innerHTML = this.options.offlabel;
204
+ if (this.options.offtitle) {
205
+ ecmasToggleOff.setAttribute("title", this.options.offtitle);
206
+ }
207
+
208
+ // 3: Handle
209
+ let ecmasToggleHandle = document.createElement("span");
210
+ ecmasToggleHandle.setAttribute("class", "toggle-handle btn " + size);
211
+
212
+ // 4: Toggle Group
213
+ let ecmasToggleGroup = document.createElement("div");
214
+ ecmasToggleGroup.setAttribute("class", "toggle-group");
215
+ ecmasToggleGroup.appendChild(ecmasToggleOn);
216
+ ecmasToggleGroup.appendChild(ecmasToggleOff);
217
+ ecmasToggleGroup.appendChild(ecmasToggleHandle);
218
+
219
+ // 5: Toggle
220
+ let ecmasToggle = document.createElement("div");
221
+ ecmasToggle.setAttribute("class", "toggle btn");
222
+ ecmasToggle.classList.add(
223
+ this.element.checked
224
+ ? "btn-" + this.options.onstyle
225
+ : "btn-" + this.options.offstyle
226
+ );
227
+ ecmasToggle.setAttribute("tabindex", this.options.tabindex);
228
+ if (!this.element.checked) ecmasToggle.classList.add("off");
229
+ if (this.options.size) ecmasToggle.classList.add(size);
230
+ if (this.options.style) {
231
+ this.options.style.split(" ").forEach((style) => {
232
+ ecmasToggle.classList.add(style);
233
+ });
234
+ }
235
+ if (this.element.disabled || this.element.readOnly) {
236
+ ecmasToggle.classList.add("disabled");
237
+ ecmasToggle.setAttribute("disabled", "disabled");
238
+ }
239
+
240
+ // 6: Set form values
241
+ if (this.options.onvalue)
242
+ this.element.setAttribute("value", this.options.onvalue);
243
+ let invElement = null;
244
+ if (this.options.offvalue) {
245
+ invElement = this.element.cloneNode();
246
+ invElement.setAttribute("value", this.options.offvalue);
247
+ invElement.setAttribute("data-toggle", "invert-toggle");
248
+ invElement.removeAttribute("id");
249
+ invElement.checked = !this.element.checked;
250
+ }
251
+
252
+ // 7: Replace HTML checkbox with Toggle-Button
253
+ this.element.parentElement.insertBefore(ecmasToggle, this.element);
254
+ ecmasToggle.appendChild(this.element);
255
+ if (invElement) ecmasToggle.appendChild(invElement);
256
+ ecmasToggle.appendChild(ecmasToggleGroup);
257
+
258
+ // 8: Set button W/H, lineHeight
259
+ {
260
+ // A: Set style W/H
261
+ // NOTE: `offsetWidth` returns *rounded* integer values, so use `getBoundingClientRect` instead.
262
+ ecmasToggle.style.width =
263
+ (this.options.width ||
264
+ Math.max(
265
+ ecmasToggleOn.getBoundingClientRect().width,
266
+ ecmasToggleOff.getBoundingClientRect().width
267
+ ) +
268
+ ecmasToggleHandle.getBoundingClientRect().width / 2) + "px";
269
+ ecmasToggle.style.height =
270
+ (this.options.height ||
271
+ Math.max(
272
+ ecmasToggleOn.getBoundingClientRect().height,
273
+ ecmasToggleOff.getBoundingClientRect().height
274
+ )) + "px";
275
+
276
+ // B: Apply on/off class
277
+ ecmasToggleOn.classList.add("toggle-on");
278
+ ecmasToggleOff.classList.add("toggle-off");
279
+
280
+ // C: Finally, set lineHeight if needed
281
+ if (this.options.height) {
282
+ ecmasToggleOn.style.lineHeight = calcH(ecmasToggleOn) + "px";
283
+ ecmasToggleOff.style.lineHeight = calcH(ecmasToggleOff) + "px";
284
+ }
285
+ }
286
+
287
+ // 9: Add listeners
288
+ ecmasToggle.addEventListener("touchstart", (e) => {
289
+ this.#toggleActionPerformed(e);
290
+ });
291
+ ecmasToggle.addEventListener("click", (e) => {
292
+ this.#toggleActionPerformed(e);
293
+ });
294
+ ecmasToggle.addEventListener("keypress", (e) => {
295
+ if (e.key == " ") {
296
+ this.#toggleActionPerformed(e);
297
+ }
298
+ });
299
+
300
+ if (this.element.id) {
301
+ document
302
+ .querySelectorAll('label[for="' + this.element.id + '"]')
303
+ .forEach((label) => {
304
+ label.addEventListener("touchstart", (_e) => {
305
+ this.toggle();
306
+ ecmasToggle.focus();
307
+ });
308
+ label.addEventListener("click", (_e) => {
309
+ this.toggle();
310
+ ecmasToggle.focus();
311
+ });
312
+ });
313
+ }
314
+
315
+ // 10: Set elements to bootstrap object
316
+ this.ecmasToggle = ecmasToggle;
317
+ this.invElement = invElement;
318
+
319
+ // 11: Keep reference to this instance for subsequent calls via `getElementById().bootstrapToggle()`
320
+ this.element.bsToggle = this;
321
+ }
322
+
323
+ /**
324
+ * Trigger actions
325
+ * @param {Event} e event
326
+ */
327
+ #toggleActionPerformed(e) {
328
+ if (this.options.tristate) {
329
+ if (this.ecmasToggle.classList.contains("indeterminate")) {
330
+ this.determinate(true);
331
+ this.toggle();
332
+ } else {
333
+ this.indeterminate();
334
+ }
335
+ } else {
336
+ this.toggle();
337
+ }
338
+ e.preventDefault();
339
+ }
340
+
341
+ toggle(silent = false) {
342
+ if (this.element.checked) this.off(silent);
343
+ else this.on(silent);
344
+ }
345
+
346
+ on(silent = false) {
347
+ if (this.element.disabled || this.element.readOnly) return false;
348
+ this.ecmasToggle.classList.remove("btn-" + this.options.offstyle);
349
+ this.ecmasToggle.classList.add("btn-" + this.options.onstyle);
350
+ this.ecmasToggle.classList.remove("off");
351
+ this.element.checked = true;
352
+ if (this.invElement) this.invElement.checked = false;
353
+ if (!silent) this.trigger();
354
+ }
355
+
356
+ off(silent = false) {
357
+ if (this.element.disabled || this.element.readOnly) return false;
358
+ this.ecmasToggle.classList.remove("btn-" + this.options.onstyle);
359
+ this.ecmasToggle.classList.add("btn-" + this.options.offstyle);
360
+ this.ecmasToggle.classList.add("off");
361
+ this.element.checked = false;
362
+ if (this.invElement) this.invElement.checked = true;
363
+ if (!silent) this.trigger();
364
+ }
365
+
366
+ indeterminate(silent = false) {
367
+ if (
368
+ !this.options.tristate ||
369
+ this.element.disabled ||
370
+ this.element.readOnly
371
+ )
372
+ return false;
373
+ this.ecmasToggle.classList.add("indeterminate");
374
+ this.element.indeterminate = true;
375
+ this.element.removeAttribute("name");
376
+ if (this.invElement) this.invElement.indeterminate = true;
377
+ if (this.invElement) this.invElement.removeAttribute("name");
378
+ if (!silent) this.trigger();
379
+ }
380
+
381
+ determinate(silent = false) {
382
+ if (
383
+ !this.options.tristate ||
384
+ this.element.disabled ||
385
+ this.element.readOnly
386
+ )
387
+ return false;
388
+ this.ecmasToggle.classList.remove("indeterminate");
389
+ this.element.indeterminate = false;
390
+ if (this.options.name)
391
+ this.element.setAttribute("name", this.options.name);
392
+ if (this.invElement) this.invElement.indeterminate = false;
393
+ if (this.invElement && this.options.name)
394
+ this.invElement.setAttribute("name", this.options.name);
395
+ if (!silent) this.trigger();
396
+ }
397
+
398
+ enable() {
399
+ this.ecmasToggle.classList.remove("disabled");
400
+ this.ecmasToggle.removeAttribute("disabled");
401
+ this.element.removeAttribute("disabled");
402
+ this.element.removeAttribute("readonly");
403
+ if (this.invElement) {
404
+ this.invElement.removeAttribute("disabled");
405
+ this.invElement.removeAttribute("readonly");
406
+ }
407
+ }
408
+
409
+ disable() {
410
+ this.ecmasToggle.classList.add("disabled");
411
+ this.ecmasToggle.setAttribute("disabled", "");
412
+ this.element.setAttribute("disabled", "");
413
+ this.element.removeAttribute("readonly");
414
+ if (this.invElement) {
415
+ this.invElement.setAttribute("disabled", "");
416
+ this.invElement.removeAttribute("readonly");
417
+ }
418
+ }
419
+
420
+ readonly() {
421
+ this.ecmasToggle.classList.add("disabled");
422
+ this.ecmasToggle.setAttribute("disabled", "");
423
+ this.element.removeAttribute("disabled");
424
+ this.element.setAttribute("readonly", "");
425
+ if (this.invElement) {
426
+ this.invElement.removeAttribute("disabled");
427
+ this.invElement.setAttribute("readonly", "");
428
+ }
429
+ }
430
+
431
+ update(silent) {
432
+ if (this.element.disabled) this.disable();
433
+ else if (this.element.readOnly) this.readonly();
434
+ else this.enable();
435
+ if (this.element.checked) this.on(silent);
436
+ else this.off(silent);
437
+ }
438
+
439
+ trigger(silent) {
440
+ if (!silent)
441
+ this.element.dispatchEvent(new Event("change", { bubbles: true }));
442
+ }
443
+
444
+ destroy() {
445
+ // A: Remove button-group from UI, replace checkbox element
446
+ this.ecmasToggle.parentNode.insertBefore(this.element, this.ecmasToggle);
447
+ this.ecmasToggle.parentNode.removeChild(this.ecmasToggle);
448
+
449
+ // B: Delete internal refs
450
+ delete this.element.bsToggle;
451
+ delete this.ecmasToggle;
452
+ }
453
+ }
454
+
455
+ /**
456
+ * Add `bootstrapToggle` prototype function to HTML Elements
457
+ * Enables execution when used with HTML - ex: `document.getElementById('toggle').bootstrapToggle('on')`
458
+ */
459
+ Element.prototype.bootstrapToggle = function (options, silent) {
460
+ let _bsToggle = this.bsToggle || new Toggle(this, options);
461
+
462
+ // Execute method calls
463
+ if (options && typeof options === "string") {
464
+ if (options.toLowerCase() == "toggle") _bsToggle.toggle(silent);
465
+ else if (options.toLowerCase() == "on") _bsToggle.on(silent);
466
+ else if (options.toLowerCase() == "off") _bsToggle.off(silent);
467
+ else if (options.toLowerCase() == "indeterminate")
468
+ _bsToggle.indeterminate(silent);
469
+ else if (options.toLowerCase() == "determinate")
470
+ _bsToggle.determinate(silent);
471
+ else if (options.toLowerCase() == "enable") _bsToggle.enable();
472
+ else if (options.toLowerCase() == "disable") _bsToggle.disable();
473
+ else if (options.toLowerCase() == "readonly") _bsToggle.readonly();
474
+ else if (options.toLowerCase() == "destroy") _bsToggle.destroy();
475
+ }
476
+ };
477
+
478
+ /**
479
+ * Replace all `input[type=checkbox][data-toggle="toggle"]` inputs with "Bootstrap-Toggle"
480
+ * Executes once page elements have rendered enabling script to be placed in `<head>`
481
+ */
482
+ if (typeof window !== "undefined")
483
+ window.onload = function () {
484
+ document
485
+ .querySelectorAll('input[type=checkbox][data-toggle="toggle"]')
486
+ .forEach(function (ele) {
487
+ ele.bootstrapToggle();
488
+ });
489
+ };
490
+
491
+ // Export library if possible
492
+ if (typeof module !== "undefined" && module.exports) {
493
+ module.exports = Toggle;
494
+ }
495
+ })();