bootstrap5-toggle 5.1.3 → 5.2.0-rc1

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,5 +1,5 @@
1
1
  /* Copyright Notice
2
- * bootstrap5-toggle v5.1.3
2
+ * bootstrap5-toggle v5.2.0-rc1
3
3
  * https://palcarazm.github.io/bootstrap5-toggle/
4
4
  * @author 2011-2014 Min Hur (https://github.com/minhur)
5
5
  * @author 2018-2019 Brent Ely (https://github.com/gitbrent)
@@ -10,527 +10,993 @@
10
10
  * @see https://github.com/palcarazm/bootstrap5-toggle/blob/master/LICENSE
11
11
  */
12
12
 
13
+ (function (factory) {
14
+ typeof define === 'function' && define.amd ? define(factory) :
15
+ factory();
16
+ })((function () { 'use strict';
13
17
 
14
- "use strict";
15
- function sanitize(text) {
16
- if (!text) return text; // handle null or undefined
17
- var map = {
18
- "&": "&",
19
- "<": "&lt;",
20
- ">": "&gt;",
21
- '"': "&quot;",
22
- "'": "&#39;",
23
- "/": "&#x2F;",
24
- };
25
- return text.replace(/[&<>"'/]/g, function (m) {
26
- return map[m];
27
- });
28
- }
29
-
30
- (function () {
31
- /**
32
- * `Toggle` is instantiated for each toggle-button
33
- */
34
- class Toggle {
35
- constructor(element, options) {
36
- const DEPRECATION = {
37
- value:
38
- "BOOTSTRAP TOGGLE DEPRECATION CHECK -- a0Jhux0QySypjjs4tLtEo8xT2kx0AbYaq9K6mgNjWSs0HF0L8T8J0M0o3Kr7zkm7 --",
39
- ATTRIBUTE: "attribute",
40
- OPTION: "option",
41
- log: function (type, oldlabel, newlabel) {
42
- console.warn(
43
- `Bootstrap Toggle deprecation warning: Using ${oldlabel} ${type} is deprecated. Use ${newlabel} instead.`
44
- );
45
- },
46
- };
47
- const DEFAULTS = {
48
- onlabel: "On",
49
- onstyle: "primary",
50
- onvalue: null,
51
- ontitle: null,
52
- offlabel: "Off",
53
- offstyle: "secondary",
54
- offvalue: null,
55
- offtitle: null,
56
- size: "",
57
- style: "",
58
- width: null,
59
- height: null,
60
- tabindex: 0,
61
- tristate: false,
62
- name: null,
63
- };
64
- options = options || {};
65
-
66
- // A: Capture ref to HMTL element
67
- this.element = element;
68
-
69
- // B: Set options
70
- this.options = {
71
- onlabel:
72
- this.element.getAttribute("data-onlabel") ||
73
- options.onlabel ||
74
- DEPRECATION.value ||
75
- DEFAULTS.onlabel,
76
- onstyle:
77
- sanitize(this.element.getAttribute("data-onstyle")) ||
78
- options.onstyle ||
79
- DEFAULTS.onstyle,
80
- onvalue:
81
- sanitize(this.element.getAttribute("value")) ||
82
- sanitize(this.element.getAttribute("data-onvalue")) ||
83
- options.onvalue ||
84
- DEFAULTS.onvalue,
85
- ontitle:
86
- sanitize(this.element.getAttribute("data-ontitle")) ||
87
- options.ontitle ||
88
- sanitize(this.element.getAttribute("title")) ||
89
- DEFAULTS.ontitle,
90
- offlabel:
91
- this.element.getAttribute("data-offlabel") ||
92
- options.offlabel ||
93
- DEPRECATION.value ||
94
- DEFAULTS.offlabel,
95
- offstyle:
96
- sanitize(this.element.getAttribute("data-offstyle")) ||
97
- options.offstyle ||
98
- DEFAULTS.offstyle,
99
- offvalue:
100
- sanitize(this.element.getAttribute("data-offvalue")) ||
101
- options.offvalue ||
102
- DEFAULTS.offvalue,
103
- offtitle:
104
- sanitize(this.element.getAttribute("data-offtitle")) ||
105
- options.offtitle ||
106
- sanitize(this.element.getAttribute("title")) ||
107
- DEFAULTS.offtitle,
108
- size:
109
- sanitize(this.element.getAttribute("data-size")) ||
110
- options.size ||
111
- DEFAULTS.size,
112
- style:
113
- sanitize(this.element.getAttribute("data-style")) ||
114
- options.style ||
115
- DEFAULTS.style,
116
- width:
117
- sanitize(this.element.getAttribute("data-width")) ||
118
- options.width ||
119
- DEFAULTS.width,
120
- height:
121
- sanitize(this.element.getAttribute("data-height")) ||
122
- options.height ||
123
- DEFAULTS.height,
124
- tabindex:
125
- sanitize(this.element.getAttribute("tabindex")) ||
126
- options.tabindex ||
127
- DEFAULTS.tabindex,
128
- tristate:
129
- this.element.hasAttribute("tristate") ||
130
- options.tristate ||
131
- DEFAULTS.tristate,
132
- name:
133
- sanitize(this.element.getAttribute("name")) ||
134
- options.name ||
135
- DEFAULTS.name,
136
- };
137
-
138
- // C: Check deprecations
139
- if (this.options.onlabel === DEPRECATION.value) {
140
- if (sanitize(this.element.getAttribute("data-on"))) {
141
- DEPRECATION.log(DEPRECATION.ATTRIBUTE, "data-on", "data-onlabel");
142
- this.options.onlabel = this.element.getAttribute("data-on");
143
- } else if (options.on) {
144
- DEPRECATION.log(DEPRECATION.OPTION, "on", "onlabel");
145
- this.options.onlabel = options.on;
146
- } else {
147
- this.options.onlabel = DEFAULTS.onlabel;
148
- }
149
- }
150
- if (this.options.offlabel === DEPRECATION.value) {
151
- if (sanitize(this.element.getAttribute("data-off"))) {
152
- DEPRECATION.log(DEPRECATION.ATTRIBUTE, "data-off", "data-offlabel");
153
- this.options.offlabel = this.element.getAttribute("data-off");
154
- } else if (options.off) {
155
- DEPRECATION.log(DEPRECATION.OPTION, "off", "offlabel");
156
- this.options.offlabel = options.off;
157
- } else {
158
- this.options.offlabel = DEFAULTS.offlabel;
159
- }
160
- }
161
-
162
- // LAST: Render Toggle
163
- this.render();
164
- }
165
- render() {
166
- function calcH(el) {
167
- const styles = window.getComputedStyle(el);
168
- const height = el.offsetHeight;
169
- const borderTopWidth = parseFloat(styles.borderTopWidth);
170
- const borderBottomWidth = parseFloat(styles.borderBottomWidth);
171
- const paddingTop = parseFloat(styles.paddingTop);
172
- const paddingBottom = parseFloat(styles.paddingBottom);
173
-
174
- return (
175
- height -
176
- borderBottomWidth -
177
- borderTopWidth -
178
- paddingTop -
179
- paddingBottom
180
- );
181
- }
182
- // 0: Parse size
183
- let size;
184
- switch (this.options.size) {
185
- case "large":
186
- case "lg":
187
- size = "btn-lg";
188
- break;
189
- case "small":
190
- case "sm":
191
- size = "btn-sm";
192
- break;
193
- case "mini":
194
- case "xs":
195
- size = "btn-xs";
196
- break;
197
- default:
198
- size = "";
199
- break;
200
- }
201
-
202
- // 1: On
203
- let ecmasToggleOn = document.createElement("span");
204
- ecmasToggleOn.setAttribute(
205
- "class",
206
- "btn btn-" + this.options.onstyle + " " + size
207
- );
208
- ecmasToggleOn.innerHTML = this.options.onlabel;
209
- if (this.options.ontitle) {
210
- ecmasToggleOn.setAttribute("title", this.options.ontitle);
211
- }
212
-
213
- // 2: Off
214
- let ecmasToggleOff = document.createElement("span");
215
- ecmasToggleOff.setAttribute(
216
- "class",
217
- "btn btn-" + this.options.offstyle + " " + size
218
- );
219
- ecmasToggleOff.innerHTML = this.options.offlabel;
220
- if (this.options.offtitle) {
221
- ecmasToggleOff.setAttribute("title", this.options.offtitle);
222
- }
223
-
224
- // 3: Handle
225
- let ecmasToggleHandle = document.createElement("span");
226
- ecmasToggleHandle.setAttribute("class", "toggle-handle btn " + size);
227
-
228
- // 4: Toggle Group
229
- let ecmasToggleGroup = document.createElement("div");
230
- ecmasToggleGroup.setAttribute("class", "toggle-group");
231
- ecmasToggleGroup.appendChild(ecmasToggleOn);
232
- ecmasToggleGroup.appendChild(ecmasToggleOff);
233
- ecmasToggleGroup.appendChild(ecmasToggleHandle);
234
-
235
- // 5: Render Toggle
236
- let ecmasToggle = document.createElement("div");
237
- ecmasToggle.setAttribute("class", "toggle btn");
238
- ecmasToggle.classList.add(
239
- this.element.checked
240
- ? "btn-" + this.options.onstyle
241
- : "btn-" + this.options.offstyle
242
- );
243
- ecmasToggle.setAttribute("tabindex", this.options.tabindex);
244
- if (!this.element.checked) ecmasToggle.classList.add("off");
245
- if (this.options.size) ecmasToggle.classList.add(size);
246
- if (this.options.style) {
247
- this.options.style.split(" ").forEach((style) => {
248
- ecmasToggle.classList.add(style);
249
- });
250
- }
251
- if (this.element.disabled || this.element.readOnly) {
252
- ecmasToggle.classList.add("disabled");
253
- ecmasToggle.setAttribute("disabled", "disabled");
254
- }
255
-
256
- // 6: Set form values
257
- if (this.options.onvalue)
258
- this.element.setAttribute("value", this.options.onvalue);
259
- let invElement = null;
260
- if (this.options.offvalue) {
261
- invElement = this.element.cloneNode();
262
- invElement.setAttribute("value", this.options.offvalue);
263
- invElement.setAttribute("data-toggle", "invert-toggle");
264
- invElement.removeAttribute("id");
265
- invElement.checked = !this.element.checked;
266
- }
267
-
268
- // 7: Replace HTML checkbox with Toggle-Button
269
- this.element.parentElement.insertBefore(ecmasToggle, this.element);
270
- ecmasToggle.appendChild(this.element);
271
- if (invElement) ecmasToggle.appendChild(invElement);
272
- ecmasToggle.appendChild(ecmasToggleGroup);
273
-
274
- // 8: Set button W/H, lineHeight
275
- {
276
- // A: Set style W/H
277
- // NOTE: `offsetWidth` returns *rounded* integer values, so use `getBoundingClientRect` instead.
278
- if (this.options.width) {
279
- ecmasToggle.style.width = `${this.options.width}px`;
280
- } else {
281
- ecmasToggle.style["min-width"] = "100px"; // First approach for better calculation
282
- ecmasToggle.style["min-width"] = `${
283
- Math.max(
284
- ecmasToggleOn.getBoundingClientRect().width,
285
- ecmasToggleOff.getBoundingClientRect().width
286
- ) +
287
- ecmasToggleHandle.getBoundingClientRect().width / 2
288
- }px`;
289
- }
290
-
291
- if (this.options.height) {
292
- ecmasToggle.style.height = `${this.options.height}px`;
293
- } else {
294
- ecmasToggle.style["min-height"] = "36px"; // First approach for better calculation
295
- ecmasToggle.style["min-height"] = `${Math.max(
296
- ecmasToggleOn.getBoundingClientRect().height,
297
- ecmasToggleOff.getBoundingClientRect().height
298
- )}px`;
299
- }
300
-
301
- // B: Apply on/off class
302
- ecmasToggleOn.classList.add("toggle-on");
303
- ecmasToggleOff.classList.add("toggle-off");
304
-
305
- // C: Finally, set lineHeight if needed
306
- if (this.options.height) {
307
- ecmasToggleOn.style.lineHeight = calcH(ecmasToggleOn) + "px";
308
- ecmasToggleOff.style.lineHeight = calcH(ecmasToggleOff) + "px";
309
- }
310
- }
311
-
312
- // 9: Add listeners
313
- ecmasToggle.addEventListener(
314
- "pointerdown",
315
- (e) => {
316
- this.#toggleActionPerformed(e);
317
- },
318
- { passive: true }
319
- );
320
- ecmasToggle.addEventListener(
321
- "keypress",
322
- (e) => {
323
- if (e.key == " ") {
324
- this.#toggleActionPerformed(e);
325
- }
326
- },
327
- { passive: true }
328
- );
329
-
330
- if (this.element.id) {
331
- document
332
- .querySelectorAll('label[for="' + this.element.id + '"]')
333
- .forEach((label) => {
334
- label.addEventListener(
335
- "pointerdown",
336
- (e) => {
337
- e.preventDefault();
338
- this.toggle();
339
- ecmasToggle.focus();
340
- },
341
- { passive: true }
342
- );
343
- });
344
- }
345
-
346
- // 10: Set elements to bootstrap object
347
- this.ecmasToggle = ecmasToggle;
348
- this.invElement = invElement;
349
-
350
- // 11: Handle indeterminate state
351
- if(this.options.tristate && this.element.indeterminate) {
352
- this.indeterminate(true);
353
- }
354
-
355
- // 12: Keep reference to this instance for subsequent calls via `getElementById().bootstrapToggle()`
356
- this.element.bsToggle = this;
357
- }
358
-
359
- /**
360
- * Trigger actions
361
- * @param {Event} e event
362
- */
363
- #toggleActionPerformed(e) {
364
- if (this.options.tristate) {
365
- if (this.ecmasToggle.classList.contains("indeterminate")) {
366
- this.determinate(true);
367
- this.toggle();
368
- } else {
369
- this.indeterminate();
370
- }
371
- } else {
372
- this.toggle();
373
- }
374
- }
375
-
376
- toggle(silent = false) {
377
- if (this.element.checked) this.off(silent);
378
- else this.on(silent);
379
- }
380
-
381
- on(silent = false) {
382
- if (this.element.disabled || this.element.readOnly) return false;
383
- this.ecmasToggle.classList.remove("btn-" + this.options.offstyle);
384
- this.ecmasToggle.classList.add("btn-" + this.options.onstyle);
385
- this.ecmasToggle.classList.remove("off");
386
- this.element.checked = true;
387
- if (this.invElement) this.invElement.checked = false;
388
- if (!silent) this.trigger();
389
- }
390
-
391
- off(silent = false) {
392
- if (this.element.disabled || this.element.readOnly) return false;
393
- this.ecmasToggle.classList.remove("btn-" + this.options.onstyle);
394
- this.ecmasToggle.classList.add("btn-" + this.options.offstyle);
395
- this.ecmasToggle.classList.add("off");
396
- this.element.checked = false;
397
- if (this.invElement) this.invElement.checked = true;
398
- if (!silent) this.trigger();
399
- }
400
-
401
- indeterminate(silent = false) {
402
- if (
403
- !this.options.tristate ||
404
- this.element.disabled ||
405
- this.element.readOnly
406
- )
407
- return false;
408
- this.ecmasToggle.classList.add("indeterminate");
409
- this.element.indeterminate = true;
410
- this.element.removeAttribute("name");
411
- if (this.invElement) this.invElement.indeterminate = true;
412
- if (this.invElement) this.invElement.removeAttribute("name");
413
- if (!silent) this.trigger();
414
- }
415
-
416
- determinate(silent = false) {
417
- if (
418
- !this.options.tristate ||
419
- this.element.disabled ||
420
- this.element.readOnly
421
- )
422
- return false;
423
- this.ecmasToggle.classList.remove("indeterminate");
424
- this.element.indeterminate = false;
425
- if (this.options.name)
426
- this.element.setAttribute("name", this.options.name);
427
- if (this.invElement) this.invElement.indeterminate = false;
428
- if (this.invElement && this.options.name)
429
- this.invElement.setAttribute("name", this.options.name);
430
- if (!silent) this.trigger();
431
- }
432
-
433
- enable() {
434
- this.ecmasToggle.classList.remove("disabled");
435
- this.ecmasToggle.removeAttribute("disabled");
436
- this.element.removeAttribute("disabled");
437
- this.element.removeAttribute("readonly");
438
- if (this.invElement) {
439
- this.invElement.removeAttribute("disabled");
440
- this.invElement.removeAttribute("readonly");
441
- }
442
- }
443
-
444
- disable() {
445
- this.ecmasToggle.classList.add("disabled");
446
- this.ecmasToggle.setAttribute("disabled", "");
447
- this.element.setAttribute("disabled", "");
448
- this.element.removeAttribute("readonly");
449
- if (this.invElement) {
450
- this.invElement.setAttribute("disabled", "");
451
- this.invElement.removeAttribute("readonly");
452
- }
453
- }
454
-
455
- readonly() {
456
- this.ecmasToggle.classList.add("disabled");
457
- this.ecmasToggle.setAttribute("disabled", "");
458
- this.element.removeAttribute("disabled");
459
- this.element.setAttribute("readonly", "");
460
- if (this.invElement) {
461
- this.invElement.removeAttribute("disabled");
462
- this.invElement.setAttribute("readonly", "");
463
- }
464
- }
465
-
466
- update(silent) {
467
- if (this.element.disabled) this.disable();
468
- else if (this.element.readOnly) this.readonly();
469
- else this.enable();
470
- if (this.element.checked) this.on(silent);
471
- else this.off(silent);
472
- }
473
-
474
- trigger(silent) {
475
- if (!silent)
476
- this.element.dispatchEvent(new Event("change", { bubbles: true }));
477
- }
478
-
479
- destroy() {
480
- // A: Remove button-group from UI, replace checkbox element
481
- this.ecmasToggle.parentNode.insertBefore(this.element, this.ecmasToggle);
482
- this.ecmasToggle.parentNode.removeChild(this.ecmasToggle);
483
-
484
- // B: Delete internal refs
485
- delete this.element.bsToggle;
486
- delete this.ecmasToggle;
487
- }
488
-
489
- rerender() {
490
- this.destroy();
491
- this.element.bootstrapToggle();
492
- }
493
- }
494
-
495
- /**
496
- * Add `bootstrapToggle` prototype function to HTML Elements
497
- * Enables execution when used with HTML - ex: `document.getElementById('toggle').bootstrapToggle('on')`
498
- */
499
- Element.prototype.bootstrapToggle = function (options, silent) {
500
- let _bsToggle = this.bsToggle || new Toggle(this, options);
501
-
502
- // Execute method calls
503
- if (options && typeof options === "string") {
504
- if (options.toLowerCase() == "toggle") _bsToggle.toggle(silent);
505
- else if (options.toLowerCase() == "on") _bsToggle.on(silent);
506
- else if (options.toLowerCase() == "off") _bsToggle.off(silent);
507
- else if (options.toLowerCase() == "indeterminate")
508
- _bsToggle.indeterminate(silent);
509
- else if (options.toLowerCase() == "determinate")
510
- _bsToggle.determinate(silent);
511
- else if (options.toLowerCase() == "enable") _bsToggle.enable();
512
- else if (options.toLowerCase() == "disable") _bsToggle.disable();
513
- else if (options.toLowerCase() == "readonly") _bsToggle.readonly();
514
- else if (options.toLowerCase() == "destroy") _bsToggle.destroy();
515
- else if (options.toLowerCase() == "rerender") _bsToggle.rerender();
516
- }
517
- };
518
-
519
- /**
520
- * Replace all `input[type=checkbox][data-toggle="toggle"]` inputs with "Bootstrap-Toggle"
521
- * Executes once page elements have rendered enabling script to be placed in `<head>`
522
- */
523
- if (typeof window !== "undefined")
524
- window.onload = function () {
525
- document
526
- .querySelectorAll('input[type=checkbox][data-toggle="toggle"]')
527
- .forEach(function (ele) {
528
- ele.bootstrapToggle();
529
- });
530
- };
531
-
532
- // Export library if possible
533
- if (typeof module !== "undefined" && module.exports) {
534
- module.exports = Toggle;
535
- }
536
- })();
18
+ var ToggleStateValue;
19
+ (function (ToggleStateValue) {
20
+ ToggleStateValue["ON"] = "on";
21
+ ToggleStateValue["OFF"] = "off";
22
+ ToggleStateValue["INDETERMINATE"] = "indeterminate";
23
+ })(ToggleStateValue || (ToggleStateValue = {}));
24
+ var ToggleStateStatus;
25
+ (function (ToggleStateStatus) {
26
+ ToggleStateStatus["ENABLED"] = "enabled";
27
+ ToggleStateStatus["DISABLED"] = "disabled";
28
+ ToggleStateStatus["READONLY"] = "readonly";
29
+ })(ToggleStateStatus || (ToggleStateStatus = {}));
30
+ var ToggleActionType;
31
+ (function (ToggleActionType) {
32
+ ToggleActionType["NEXT"] = "next";
33
+ ToggleActionType["ON"] = "on";
34
+ ToggleActionType["OFF"] = "off";
35
+ ToggleActionType["TOGGLE"] = "toggle";
36
+ ToggleActionType["DETERMINATE"] = "determinate";
37
+ ToggleActionType["INDETERMINATE"] = "indeterminate";
38
+ ToggleActionType["READONLY"] = "readonly";
39
+ ToggleActionType["DISABLE"] = "disable";
40
+ ToggleActionType["ENABLE"] = "enable";
41
+ })(ToggleActionType || (ToggleActionType = {}));
42
+
43
+ var DOMBuilder = /** @class */ (function () {
44
+ /**
45
+ * Initializes a new instance of the DOMBuilder class.
46
+ * @param checkbox HTMLInputElement element representing the toggle.
47
+ * @param options ToggleOptions object containing options for the toggle.
48
+ * @param state ToggleState object containing the initial state of the toggle.
49
+ */
50
+ function DOMBuilder(checkbox, options, state) {
51
+ this.onStyle = "btn-".concat(options.onstyle);
52
+ this.offStyle = "btn-".concat(options.offstyle);
53
+ this.name = options.name;
54
+ this.checkbox = checkbox;
55
+ if (options.onvalue)
56
+ this.checkbox.value = options.onvalue;
57
+ this.invCheckbox = options.offvalue
58
+ ? this.createInvCheckbox(options.offvalue)
59
+ : null;
60
+ this.sizeClass = DOMBuilder.sizeResolver(options.size);
61
+ this.toggleOn = this.createToggleSpan(options.onlabel, this.onStyle, options.ontitle);
62
+ this.toggleOff = this.createToggleSpan(options.offlabel, this.offStyle, options.offtitle);
63
+ this.toggleHandle = this.createToggleHandle();
64
+ this.toggleGroup = this.createToggleGroup();
65
+ this.toggle = document.createElement("div");
66
+ this.renderToggle(options);
67
+ this.render(state);
68
+ }
69
+ /**
70
+ * Resolves the size class for the toggle based on the provided size.
71
+ * If size is not provided or is invalid, returns an empty string.
72
+ * @param size ToggleSize value representing the size of the toggle.
73
+ * @returns string representing the size class for the toggle.
74
+ */
75
+ DOMBuilder.sizeResolver = function (size) {
76
+ var _a;
77
+ var sizeMap = {
78
+ large: "btn-lg",
79
+ lg: "btn-lg",
80
+ small: "btn-sm",
81
+ sm: "btn-sm",
82
+ mini: "btn-xs",
83
+ xs: "btn-xs",
84
+ };
85
+ return (_a = sizeMap[size]) !== null && _a !== void 0 ? _a : "";
86
+ };
87
+ /**
88
+ * Creates an inverted checkbox element that is used in the toggle.
89
+ * This checkbox is used to create the toggle's "off" state.
90
+ * @param offValue The value of the checkbox when the toggle is in the "off" state.
91
+ * @returns An HTMLInputElement representing the inverted checkbox element.
92
+ */
93
+ DOMBuilder.prototype.createInvCheckbox = function (offValue) {
94
+ var invCheckbox = this.checkbox.cloneNode(true);
95
+ invCheckbox.value = offValue;
96
+ invCheckbox.setAttribute("data-toggle", "invert-toggle");
97
+ invCheckbox.removeAttribute("id");
98
+ return invCheckbox;
99
+ };
100
+ /**
101
+ * Renders the toggle element and its children.
102
+ * Sets the class attribute of the toggle with the provided style and size class.
103
+ * Sets the tabindex attribute of the toggle with the provided tabindex.
104
+ * Inserts the toggle element before the original checkbox element.
105
+ * Appends the checkbox, inverted checkbox (if exists) and toggle group elements to the toggle element.
106
+ * Handles the toggle size by setting the width and height attributes of the toggle element.
107
+ * @param options - ToggleOptions object containing the style, width, height and tabindex for the toggle.
108
+ */
109
+ DOMBuilder.prototype.renderToggle = function (_a) {
110
+ var _b;
111
+ var style = _a.style, width = _a.width, height = _a.height, tabindex = _a.tabindex;
112
+ this.toggle.setAttribute("class", "toggle btn ".concat(this.sizeClass, " ").concat(style));
113
+ this.toggle.setAttribute("data-toggle", "toggle");
114
+ this.toggle.tabIndex = tabindex;
115
+ this.toggle.role = "button";
116
+ (_b = this.checkbox.parentElement) === null || _b === void 0 ? void 0 : _b.insertBefore(this.toggle, this.checkbox);
117
+ this.toggle.appendChild(this.checkbox);
118
+ if (this.invCheckbox)
119
+ this.toggle.appendChild(this.invCheckbox);
120
+ this.toggle.appendChild(this.toggleGroup);
121
+ this.handleToggleSize(width, height);
122
+ };
123
+ /**
124
+ * Creates a div element representing the toggle group.
125
+ * The toggle group contains the on, off, and handle elements of the toggle.
126
+ * @returns An HTMLElement representing the toggle group element.
127
+ */
128
+ DOMBuilder.prototype.createToggleGroup = function () {
129
+ var toggleGroup = document.createElement("div");
130
+ toggleGroup.setAttribute("class", "toggle-group");
131
+ toggleGroup.appendChild(this.toggleOn);
132
+ toggleGroup.appendChild(this.toggleOff);
133
+ toggleGroup.appendChild(this.toggleHandle);
134
+ return toggleGroup;
135
+ };
136
+ /**
137
+ * Creates a span element representing a toggle option (on/off).
138
+ * The span element is given a class attribute with the provided style and size class.
139
+ * The innerHTML of the span element is set to the provided label.
140
+ * If a title is provided, the span element is given a title attribute with the provided title.
141
+ * @param label The text to be displayed in the toggle option.
142
+ * @param style The style of the toggle option (primary, secondary, etc.).
143
+ * @param title The title of the toggle option.
144
+ * @returns An HTMLElement representing the toggle option element.
145
+ */
146
+ DOMBuilder.prototype.createToggleSpan = function (label, style, title) {
147
+ var toggleSpan = document.createElement("span");
148
+ toggleSpan.setAttribute("class", "btn ".concat(this.sizeClass, " ").concat(style));
149
+ toggleSpan.innerHTML = label;
150
+ if (title)
151
+ toggleSpan.setAttribute("title", title);
152
+ return toggleSpan;
153
+ };
154
+ /**
155
+ * Creates a span element representing the toggle handle.
156
+ * The span element is given a class attribute with the provided size class.
157
+ * @returns An HTMLElement representing the toggle handle element.
158
+ */
159
+ DOMBuilder.prototype.createToggleHandle = function () {
160
+ var toggleHandle = document.createElement("span");
161
+ toggleHandle.setAttribute("class", "toggle-handle btn ".concat(this.sizeClass));
162
+ return toggleHandle;
163
+ };
164
+ /**
165
+ * Sets the width and height of the toggle element.
166
+ * If a width or height is not provided, the toggle element will be given a minimum width and height
167
+ * that is calculated based on the size of the toggle on and off options.
168
+ * @param width The width of the toggle element.
169
+ * @param height The height of the toggle element.
170
+ */
171
+ DOMBuilder.prototype.handleToggleSize = function (width, height) {
172
+ function calcH(toggleSpan) {
173
+ var styles = window.getComputedStyle(toggleSpan);
174
+ var height = toggleSpan.offsetHeight;
175
+ var borderTopWidth = parseFloat(styles.borderTopWidth);
176
+ var borderBottomWidth = parseFloat(styles.borderBottomWidth);
177
+ var paddingTop = parseFloat(styles.paddingTop);
178
+ var paddingBottom = parseFloat(styles.paddingBottom);
179
+ return (height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom);
180
+ }
181
+ if (width) {
182
+ this.toggle.style.width = width;
183
+ }
184
+ else {
185
+ this.toggle.style.minWidth = "100px"; // First approach for better calculation
186
+ this.toggle.style.minWidth = "".concat(Math.max(this.toggleOn.getBoundingClientRect().width, this.toggleOff.getBoundingClientRect().width) +
187
+ this.toggleHandle.getBoundingClientRect().width / 2, "px");
188
+ }
189
+ if (height) {
190
+ this.toggle.style.height = height;
191
+ }
192
+ else {
193
+ this.toggle.style.minHeight = "36px"; // First approach for better calculation
194
+ this.toggle.style.minHeight = "".concat(Math.max(this.toggleOn.getBoundingClientRect().height, this.toggleOff.getBoundingClientRect().height), "px");
195
+ }
196
+ // B: Apply on/off class
197
+ this.toggleOn.classList.add("toggle-on");
198
+ this.toggleOff.classList.add("toggle-off");
199
+ // C: Finally, set lineHeight if needed
200
+ if (height) {
201
+ this.toggleOn.style.lineHeight = calcH(this.toggleOn) + "px";
202
+ this.toggleOff.style.lineHeight = calcH(this.toggleOff) + "px";
203
+ }
204
+ };
205
+ /**
206
+ * Renders the toggle element based on the provided state.
207
+ * @param {ToggleState} state The state of the toggle element.
208
+ */
209
+ DOMBuilder.prototype.render = function (state) {
210
+ this.toggle.classList.remove(this.onStyle, this.offStyle, "off", "indeterminate");
211
+ switch (state.value) {
212
+ case ToggleStateValue.ON:
213
+ this.toggle.classList.add(this.onStyle);
214
+ break;
215
+ case ToggleStateValue.OFF:
216
+ this.toggle.classList.add(this.offStyle, "off");
217
+ break;
218
+ case ToggleStateValue.INDETERMINATE:
219
+ this.toggle.classList.add("indeterminate");
220
+ if (state.checked) {
221
+ this.toggle.classList.add(this.onStyle);
222
+ }
223
+ else {
224
+ this.toggle.classList.add(this.offStyle, "off");
225
+ }
226
+ break;
227
+ }
228
+ this.checkbox.checked = state.checked;
229
+ if (this.invCheckbox)
230
+ this.invCheckbox.checked = !state.checked;
231
+ this.toggle.classList.add(state.checked ? this.onStyle : this.offStyle);
232
+ switch (state.status) {
233
+ case ToggleStateStatus.ENABLED:
234
+ this.toggle.classList.remove("disabled");
235
+ this.toggle.removeAttribute("disabled");
236
+ this.checkbox.disabled = false;
237
+ this.checkbox.readOnly = false;
238
+ if (this.invCheckbox) {
239
+ this.invCheckbox.disabled = false;
240
+ this.invCheckbox.readOnly = false;
241
+ }
242
+ break;
243
+ case ToggleStateStatus.DISABLED:
244
+ this.toggle.classList.add("disabled");
245
+ this.toggle.setAttribute("disabled", "");
246
+ this.checkbox.disabled = true;
247
+ this.checkbox.readOnly = false;
248
+ if (this.invCheckbox) {
249
+ this.invCheckbox.disabled = true;
250
+ this.invCheckbox.readOnly = false;
251
+ }
252
+ break;
253
+ case ToggleStateStatus.READONLY:
254
+ this.toggle.classList.add("disabled");
255
+ this.toggle.setAttribute("disabled", "");
256
+ this.checkbox.disabled = false;
257
+ this.checkbox.readOnly = true;
258
+ if (this.invCheckbox) {
259
+ this.invCheckbox.disabled = false;
260
+ this.invCheckbox.readOnly = true;
261
+ }
262
+ break;
263
+ }
264
+ if (state.indeterminate) {
265
+ this.checkbox.indeterminate = true;
266
+ this.checkbox.removeAttribute("name");
267
+ if (this.invCheckbox)
268
+ this.invCheckbox.indeterminate = true;
269
+ if (this.invCheckbox)
270
+ this.invCheckbox.removeAttribute("name");
271
+ }
272
+ else {
273
+ this.checkbox.indeterminate = false;
274
+ if (this.name)
275
+ this.checkbox.name = this.name;
276
+ if (this.invCheckbox)
277
+ this.invCheckbox.indeterminate = false;
278
+ if (this.invCheckbox && this.name)
279
+ this.invCheckbox.name = this.name;
280
+ }
281
+ };
282
+ Object.defineProperty(DOMBuilder.prototype, "root", {
283
+ /**
284
+ * Returns the root element of the toggle, which is the container of all toggle elements.
285
+ * @returns {HTMLElement} The root element of the toggle.
286
+ */
287
+ get: function () {
288
+ return this.toggle;
289
+ },
290
+ enumerable: false,
291
+ configurable: true
292
+ });
293
+ /**
294
+ * Destroys the toggle by removing the toggle element from the DOM and
295
+ *inserting the original checkbox element back into its original position.
296
+ */
297
+ DOMBuilder.prototype.destroy = function () {
298
+ var _a, _b;
299
+ (_a = this.toggle.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(this.checkbox, this.toggle);
300
+ (_b = this.toggle.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(this.toggle);
301
+ };
302
+ return DOMBuilder;
303
+ }());
304
+
305
+ function sanitize(text) {
306
+ if (!text)
307
+ return text;
308
+ var map = {
309
+ "&": "&amp;",
310
+ "<": "&lt;",
311
+ ">": "&gt;",
312
+ '"': "&quot;",
313
+ "'": "&#39;",
314
+ "/": "&#x2F;"
315
+ };
316
+ return text.replace(/[&<>"'/]/g, function (m) { return map[m]; });
317
+ }
318
+
319
+ /**
320
+ * OptionResolver is responsible for reading HTML attributes and user options
321
+ * to build a complete ToggleOptions object.
322
+ * It also handles deprecated options.
323
+ */
324
+ var OptionResolver = /** @class */ (function () {
325
+ function OptionResolver() {
326
+ }
327
+ /**
328
+ * Resolves all toggle options from the element and user options
329
+ * @param element HTMLInputElement representing the toggle
330
+ * @param userOptions Options provided by the user
331
+ * @returns Complete ToggleOptions object
332
+ */
333
+ OptionResolver.resolve = function (element, userOptions) {
334
+ if (userOptions === void 0) { userOptions = {}; }
335
+ var options = {
336
+ onlabel: this.getAttrOrDeprecation(element, "data-onlabel", userOptions.onlabel, false),
337
+ offlabel: this.getAttrOrDeprecation(element, "data-offlabel", userOptions.offlabel, false),
338
+ onstyle: this.getAttrOrDefault(element, "data-onstyle", userOptions.onstyle, OptionResolver.DEFAULT.onstyle),
339
+ offstyle: this.getAttrOrDefault(element, "data-offstyle", userOptions.offstyle, OptionResolver.DEFAULT.offstyle),
340
+ onvalue: this.getAttrOrDefault(element, "data-onvalue", userOptions.onvalue, OptionResolver.DEFAULT.onvalue),
341
+ offvalue: this.getAttrOrDefault(element, "data-offvalue", userOptions.offvalue, OptionResolver.DEFAULT.offvalue),
342
+ ontitle: this.getAttrOrDefault(element, "data-ontitle", userOptions.ontitle, OptionResolver.getAttr(element, "title") ||
343
+ OptionResolver.DEFAULT.ontitle),
344
+ offtitle: this.getAttrOrDefault(element, "data-offtitle", userOptions.offtitle, OptionResolver.getAttr(element, "title") ||
345
+ OptionResolver.DEFAULT.offtitle),
346
+ size: this.getAttrOrDefault(element, "data-size", userOptions.size, this.DEFAULT.size),
347
+ style: this.getAttrOrDefault(element, "data-style", userOptions.style, this.DEFAULT.style),
348
+ width: this.getAttrOrDefault(element, "data-width", userOptions.width, this.DEFAULT.width),
349
+ height: this.getAttrOrDefault(element, "data-height", userOptions.height, this.DEFAULT.height),
350
+ tabindex: Number(this.getAttrOrDefault(element, "tabindex", userOptions.tabindex, this.DEFAULT.tabindex)),
351
+ tristate: element.hasAttribute("tristate") ||
352
+ userOptions.tristate ||
353
+ OptionResolver.DEFAULT.tristate,
354
+ name: this.getAttrOrDefault(element, "name", userOptions.name, this.DEFAULT.name),
355
+ };
356
+ if (options.width && parseFloat(options.width))
357
+ options.width = "".concat(options.width, "px");
358
+ if (options.height && parseFloat(options.height))
359
+ options.height = "".concat(options.height, "px");
360
+ DeprecationConfig.handle(options, element, userOptions);
361
+ return options;
362
+ };
363
+ /** Default values for all toggle options */
364
+ OptionResolver.DEFAULT = {
365
+ onlabel: "On",
366
+ onstyle: "primary",
367
+ onvalue: null,
368
+ ontitle: null,
369
+ offlabel: "Off",
370
+ offstyle: "secondary",
371
+ offvalue: null,
372
+ offtitle: null,
373
+ size: "",
374
+ style: "",
375
+ width: null,
376
+ height: null,
377
+ tabindex: 0,
378
+ tristate: false,
379
+ name: null,
380
+ };
381
+ /**
382
+ * Gets a sanitized attribute value from an HTML element
383
+ * @param element HTMLInputElement to read
384
+ * @param attrName Attribute name
385
+ * @param sanitized Flag to indicate if the attribute value needs to be sanitized (default: {@code true})
386
+ * @returns Sanitized attribute value or null
387
+ */
388
+ OptionResolver.getAttr = function (element, attrName, sanitized) {
389
+ if (sanitized === void 0) { sanitized = true; }
390
+ return sanitized ? sanitize(element.getAttribute(attrName)) : element.getAttribute(attrName);
391
+ };
392
+ /**
393
+ * Returns the value of an attribute, user-provided value, or default value
394
+ * @param element HTMLInputElement to read
395
+ * @param attrName Attribute name
396
+ * @param userValue Value provided by the user
397
+ * @param defaultValue Default value if neither attribute nor user value exists
398
+ * @param sanitized Flag to indicate if the attribute value needs to be sanitized (default: {@code true})
399
+ * @returns Final attribute value
400
+ */
401
+ OptionResolver.getAttrOrDefault = function (element, attrName, userValue, defaultValue, sanitized) {
402
+ if (sanitized === void 0) { sanitized = true; }
403
+ return OptionResolver.getAttr(element, attrName, sanitized) || userValue || defaultValue;
404
+ };
405
+ /**
406
+ * Returns the value of an attribute, user-provided value, or marks as deprecated
407
+ * @param element HTMLInputElement to read
408
+ * @param attrName Attribute name
409
+ * @param userValue Value provided by the user
410
+ * @param sanitized Flag to indicate if the attribute value needs to be sanitized (default: {@code true})
411
+ * @returns Final attribute value or DeprecationConfig.value if not found
412
+ */
413
+ OptionResolver.getAttrOrDeprecation = function (element, attrName, userValue, sanitized) {
414
+ if (sanitized === void 0) { sanitized = true; }
415
+ return OptionResolver.getAttr(element, attrName, sanitized) ||
416
+ userValue ||
417
+ DeprecationConfig.value;
418
+ };
419
+ return OptionResolver;
420
+ }());
421
+ /** Types of deprecation source */
422
+ var OptionType;
423
+ (function (OptionType) {
424
+ OptionType["ATTRIBUTE"] = "attribute";
425
+ OptionType["OPTION"] = "option";
426
+ })(OptionType || (OptionType = {}));
427
+ /**
428
+ * Handles deprecated attributes and options for Bootstrap Toggle.
429
+ */
430
+ var DeprecationConfig = /** @class */ (function () {
431
+ function DeprecationConfig() {
432
+ }
433
+ /**
434
+ * Processes deprecated options and attributes and logs warnings
435
+ * @param options ToggleOptions object to update
436
+ * @param element HTMLInputElement to read deprecated attributes from
437
+ * @param userOptions UserOptions provided by the user
438
+ */
439
+ DeprecationConfig.handle = function (options, element, userOptions) {
440
+ var _this = this;
441
+ this.deprecatedOptions.forEach(function (_a) {
442
+ var currentOpt = _a.currentOpt, deprecatedAttr = _a.deprecatedAttr, deprecatedOpt = _a.deprecatedOpt;
443
+ if (options[currentOpt] === DeprecationConfig.value) {
444
+ var deprecatedAttrSanitized = sanitize(element.getAttribute(deprecatedAttr));
445
+ if (deprecatedAttrSanitized) {
446
+ _this.log(OptionType.ATTRIBUTE, deprecatedAttr, "data-".concat(currentOpt));
447
+ options[currentOpt] = deprecatedAttrSanitized;
448
+ }
449
+ else if (userOptions[deprecatedOpt]) {
450
+ _this.log(OptionType.OPTION, deprecatedOpt, currentOpt);
451
+ options[currentOpt] = userOptions[deprecatedOpt];
452
+ }
453
+ else {
454
+ options[currentOpt] = OptionResolver.DEFAULT[currentOpt];
455
+ }
456
+ }
457
+ });
458
+ };
459
+ /**
460
+ * Logs a deprecation warning to the console
461
+ * @param type Source of the deprecated option (ATTRIBUTE | OPTION)
462
+ * @param oldLabel Deprecated attribute or option name
463
+ * @param newLabel Recommended replacement option name
464
+ */
465
+ DeprecationConfig.log = function (type, oldLabel, newLabel) {
466
+ console.warn("Bootstrap Toggle deprecation warning: Using ".concat(oldLabel, " ").concat(type, " is deprecated. Use ").concat(newLabel, " instead."));
467
+ };
468
+ /** Unique string used to detect deprecated placeholders */
469
+ DeprecationConfig.value = "BOOTSTRAP TOGGLE DEPRECATION CHECK -- a0Jhux0QySypjjs4tLtEo8xT2kx0AbYaq9K6mgNjWSs0HF0L8T8J0M0o3Kr7zkm7 --";
470
+ /** Mapping of current option, deprecated attribute, and deprecated user option */
471
+ DeprecationConfig.deprecatedOptions = [
472
+ {
473
+ currentOpt: "onlabel",
474
+ deprecatedAttr: "data-on",
475
+ deprecatedOpt: "on",
476
+ },
477
+ {
478
+ currentOpt: "offlabel",
479
+ deprecatedAttr: "data-off",
480
+ deprecatedOpt: "off",
481
+ },
482
+ ];
483
+ return DeprecationConfig;
484
+ }());
485
+
486
+ var __assign = (undefined && undefined.__assign) || function () {
487
+ __assign = Object.assign || function(t) {
488
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
489
+ s = arguments[i];
490
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
491
+ t[p] = s[p];
492
+ }
493
+ return t;
494
+ };
495
+ return __assign.apply(this, arguments);
496
+ };
497
+ var StateReducer = /** @class */ (function () {
498
+ /**
499
+ * Constructor for the StateReducer class.
500
+ * @param element The HTMLInputElement which represents the toggle.
501
+ * @param isTristate A boolean indicating whether the toggle is tristate.
502
+ * Initializes the toggle state with the given element and tristate value.
503
+ */
504
+ function StateReducer(element, isTristate) {
505
+ this.isTristate = isTristate;
506
+ this.state = this.getElementState(element);
507
+ }
508
+ /**
509
+ * Retrieves the current state of the toggle based on the HTMLInputElement.
510
+ * The state is determined by the following:
511
+ * - The checked property of the input element
512
+ * - The disabled property of the input element
513
+ * - The readonly property of the input element
514
+ * - The indeterminate property of the input element if the toggle is tristate
515
+ * @returns An object containing the state of the toggle.
516
+ */
517
+ StateReducer.prototype.getElementState = function (element) {
518
+ var checked = element.checked;
519
+ var status = element.disabled ? ToggleStateStatus.DISABLED : element.readOnly ? ToggleStateStatus.READONLY : ToggleStateStatus.ENABLED;
520
+ var indeterminate = this.isTristate && element.indeterminate;
521
+ return {
522
+ value: indeterminate
523
+ ? ToggleStateValue.INDETERMINATE
524
+ : checked
525
+ ? ToggleStateValue.ON
526
+ : ToggleStateValue.OFF,
527
+ checked: checked,
528
+ status: status,
529
+ indeterminate: indeterminate,
530
+ };
531
+ };
532
+ /**
533
+ * Get the current toggle state.
534
+ * @returns An immutable copy of the current toggle state.
535
+ */
536
+ StateReducer.prototype.get = function () {
537
+ return Object.freeze(__assign({}, this.state));
538
+ };
539
+ /**
540
+ * Synchronizes the internal state of the toggle with the provided HTMLInputElement.
541
+ * This method is useful when you need to update the internal state of the toggle
542
+ * manually, such as when the toggle is updated programmatically.
543
+ * @param element The HTMLInputElement to synchronize the toggle state with.
544
+ */
545
+ StateReducer.prototype.sync = function (element) {
546
+ this.state = this.getElementState(element);
547
+ };
548
+ /**
549
+ * Apply a toggle action to the toggle state.
550
+ * @param action The toggle action to apply.
551
+ * @returns A boolean indicating whether the action was successful.
552
+ * If the toggle is disabled, any action execpect {@code ToggleActionType.ENABLE} will return {@code false}.
553
+ * If the toggle is currently in the target state of the action, the action will return {@code false}.
554
+ * If the toggle is in the indeterminate state and the action is {@code ToggleActionType.DETERMINATE},
555
+ * the toggle will be set to the checked state.
556
+ * If the action is {@code ToggleActionType.TOGGLE} :
557
+ * - For a tristate toggle, the toggle will do ON -> INDETERMINATE -> OFF -> INDETERMINATE -> ON.
558
+ * - For a non-tristate toggle, the toggle will do ON -> OFF -> ON.
559
+ */
560
+ StateReducer.prototype.do = function (action) {
561
+ switch (action) {
562
+ case ToggleActionType.ON:
563
+ if (this.state.status != ToggleStateStatus.ENABLED)
564
+ return false;
565
+ if (this.state.value === ToggleStateValue.ON)
566
+ return false;
567
+ this.state = __assign(__assign({}, this.state), { value: ToggleStateValue.ON, checked: true, indeterminate: false });
568
+ return true;
569
+ case ToggleActionType.OFF:
570
+ if (this.state.status != ToggleStateStatus.ENABLED)
571
+ return false;
572
+ if (this.state.value === ToggleStateValue.OFF)
573
+ return false;
574
+ this.state = __assign(__assign({}, this.state), { value: ToggleStateValue.OFF, checked: false, indeterminate: false });
575
+ return true;
576
+ case ToggleActionType.TOGGLE:
577
+ if (this.state.status != ToggleStateStatus.ENABLED)
578
+ return false;
579
+ if (this.state.value === ToggleStateValue.ON)
580
+ return this.do(ToggleActionType.OFF);
581
+ if (this.state.value === ToggleStateValue.OFF)
582
+ return this.do(ToggleActionType.ON);
583
+ return false;
584
+ case ToggleActionType.INDETERMINATE:
585
+ if (this.state.status != ToggleStateStatus.ENABLED)
586
+ return false;
587
+ if (this.state.value === ToggleStateValue.INDETERMINATE)
588
+ return false;
589
+ this.state = __assign(__assign({}, this.state), { value: ToggleStateValue.INDETERMINATE, indeterminate: true });
590
+ return true;
591
+ case ToggleActionType.DETERMINATE:
592
+ if (this.state.status != ToggleStateStatus.ENABLED)
593
+ return false;
594
+ if (this.state.value != ToggleStateValue.INDETERMINATE)
595
+ return false;
596
+ this.state = __assign(__assign({}, this.state), { value: this.state.checked
597
+ ? ToggleStateValue.ON
598
+ : ToggleStateValue.OFF, indeterminate: false });
599
+ return true;
600
+ case ToggleActionType.NEXT:
601
+ if (this.state.status != ToggleStateStatus.ENABLED)
602
+ return false;
603
+ if (this.isTristate) {
604
+ if (this.state.value === ToggleStateValue.ON ||
605
+ this.state.value === ToggleStateValue.OFF)
606
+ return this.do(ToggleActionType.INDETERMINATE);
607
+ if (this.state.value === ToggleStateValue.INDETERMINATE &&
608
+ this.state.checked)
609
+ return this.do(ToggleActionType.OFF);
610
+ if (this.state.value === ToggleStateValue.INDETERMINATE &&
611
+ !this.state.checked)
612
+ return this.do(ToggleActionType.ON);
613
+ }
614
+ else {
615
+ if (this.state.value === ToggleStateValue.ON)
616
+ return this.do(ToggleActionType.OFF);
617
+ if (this.state.value === ToggleStateValue.OFF)
618
+ return this.do(ToggleActionType.ON);
619
+ }
620
+ return false;
621
+ case ToggleActionType.DISABLE:
622
+ if (this.state.status === ToggleStateStatus.DISABLED)
623
+ return false;
624
+ this.state = __assign(__assign({}, this.state), { status: ToggleStateStatus.DISABLED });
625
+ return true;
626
+ case ToggleActionType.ENABLE:
627
+ if (this.state.status === ToggleStateStatus.ENABLED)
628
+ return false;
629
+ this.state = __assign(__assign({}, this.state), { status: ToggleStateStatus.ENABLED });
630
+ return true;
631
+ case ToggleActionType.READONLY:
632
+ if (this.state.status != ToggleStateStatus.ENABLED)
633
+ return false;
634
+ this.state = __assign(__assign({}, this.state), { status: ToggleStateStatus.READONLY });
635
+ return true;
636
+ }
637
+ };
638
+ return StateReducer;
639
+ }());
640
+
641
+ var Toggle = /** @class */ (function () {
642
+ /**
643
+ * Initializes a new instance of the BootstrapToggle class.
644
+ * @param element The HTMLInputElement element which represents the toggle.
645
+ * @param options The options for the toggle.
646
+ * @returns The constructed BootstrapToggle instance.
647
+ */
648
+ function Toggle(element, options) {
649
+ var _this = this;
650
+ this.eventsBound = false;
651
+ this.handlePointerEvent = function (e) {
652
+ _this.apply(ToggleActionType.NEXT);
653
+ };
654
+ this.handlerKeyboardEvent = function (e) {
655
+ if (e.key == " ") {
656
+ _this.apply(ToggleActionType.NEXT);
657
+ }
658
+ };
659
+ this.handlerLabelEvent = function (e) {
660
+ e.preventDefault();
661
+ _this.apply(ToggleActionType.NEXT);
662
+ _this.domBuilder.root.focus();
663
+ };
664
+ this.element = element;
665
+ this.options = OptionResolver.resolve(element, options);
666
+ this.stateReducer = new StateReducer(element, this.options.tristate);
667
+ this.domBuilder = new DOMBuilder(element, this.options, this.stateReducer.get());
668
+ this.bindEventListeners();
669
+ this.element.bsToggle = this;
670
+ }
671
+ /**
672
+ * Binds event listeners to the toggle element.
673
+ * This method is called by the constructor and is responsible for
674
+ * binding the following event listeners:
675
+ * - Pointer events (click, touchstart, touchend)
676
+ * - Keyboard events (keydown, keyup)
677
+ * - Label events (click)
678
+ * If the event listeners are already bound (i.e. this.eventsBound is true),
679
+ * this method does nothing.
680
+ * @returns void
681
+ */
682
+ Toggle.prototype.bindEventListeners = function () {
683
+ if (this.eventsBound)
684
+ return;
685
+ this.bindPointerEventListener();
686
+ this.bindKeyboardEventListener();
687
+ this.bindLabelEventListener();
688
+ this.eventsBound = true;
689
+ };
690
+ /**
691
+ * Unbinds all event listeners from the toggle element.
692
+ * This method is called by the destructor and is responsible for
693
+ * unbinding the following event listeners:
694
+ * - Pointer events (click, touchstart, touchend)
695
+ * - Keyboard events (keydown, keyup)
696
+ * - Label events (click)
697
+ * If the event listeners are not bound (i.e. this.eventsBound is false),
698
+ * this method does nothing.
699
+ * @returns void
700
+ */
701
+ Toggle.prototype.unbindEventListeners = function () {
702
+ if (!this.eventsBound)
703
+ return;
704
+ this.unbindPointerEventListener();
705
+ this.unbindKeyboardEventListener();
706
+ this.unbindLabelEventListener();
707
+ this.eventsBound = false;
708
+ };
709
+ /**
710
+ * Binds a pointerdown event listener to the root element of the toggle.
711
+ * The event listener is responsible for handling pointer events (e.g. mouse clicks, touch events)
712
+ * and triggering the toggle's state change when a pointer event occurs.
713
+ * The event listener is bound with the passive option, which means that it will not block
714
+ * other event listeners from being triggered.
715
+ */
716
+ Toggle.prototype.bindPointerEventListener = function () {
717
+ this.domBuilder.root.addEventListener("pointerdown", this.handlePointerEvent, { passive: true });
718
+ };
719
+ /**
720
+ * Unbinds the pointerdown event listener from the root element of the toggle.
721
+ * This method is responsible for unbinding the pointerdown event listener that was
722
+ * previously bound by the bindPointerEventListener method.
723
+ * If the event listener is not bound (i.e. this.eventsBound is false), this method does nothing.
724
+ * @returns void
725
+ */
726
+ Toggle.prototype.unbindPointerEventListener = function () {
727
+ this.domBuilder.root.removeEventListener("pointerdown", this.handlePointerEvent);
728
+ };
729
+ /**
730
+ * Binds a keypress event listener to the root element of the toggle.
731
+ * The event listener is responsible for handling keypress events
732
+ * and triggering the toggle's state change when a keypress event occurs.
733
+ * The event listener is bound with the passive option, which means that it will not block
734
+ * other event listeners from being triggered.
735
+ */
736
+ Toggle.prototype.bindKeyboardEventListener = function () {
737
+ this.domBuilder.root.addEventListener("keypress", this.handlerKeyboardEvent, { passive: true });
738
+ };
739
+ /**
740
+ * Unbinds the keypress event listener from the root element of the toggle.
741
+ * This method is responsible for unbinding the keypress event listener that was
742
+ * previously bound by the bindKeyboardEventListener method.
743
+ * If the event listener is not bound (i.e. this.eventsBound is false), this method does nothing.
744
+ * @returns void
745
+ */
746
+ Toggle.prototype.unbindKeyboardEventListener = function () {
747
+ this.domBuilder.root.removeEventListener("keypress", this.handlerKeyboardEvent);
748
+ };
749
+ /**
750
+ * Binds a click event listener to all labels that are associated with the toggle's input element.
751
+ * The event listener is responsible for handling click events and triggering the toggle's state change when a click event occurs.
752
+ * The event listener is bound with the passive option set to false, which means that it will block other event listeners from being triggered until it has finished its execution.
753
+ * This method is called by the constructor and is responsible for binding the event listener to the toggle's labels.
754
+ * If the toggle's input element does not have an id (i.e. this.element.id is null or undefined), this method does nothing.
755
+ * @returns void
756
+ */
757
+ Toggle.prototype.bindLabelEventListener = function () {
758
+ var _this = this;
759
+ if (this.element.id) {
760
+ document
761
+ .querySelectorAll('label[for="' + this.element.id + '"]')
762
+ .forEach(function (label) {
763
+ label.addEventListener("click", _this.handlerLabelEvent, {
764
+ passive: false,
765
+ });
766
+ });
767
+ }
768
+ };
769
+ /**
770
+ * Unbinds the click event listener from all labels that are associated with the toggle's input element.
771
+ * This method is responsible for unbinding the event listener that was previously bound by the bindLabelEventListener method.
772
+ * If the toggle's input element does not have an id (i.e. this.element.id is null or undefined), this method does nothing.
773
+ * @returns void
774
+ */
775
+ Toggle.prototype.unbindLabelEventListener = function () {
776
+ var _this = this;
777
+ if (this.element.id) {
778
+ document
779
+ .querySelectorAll('label[for="' + this.element.id + '"]')
780
+ .forEach(function (label) {
781
+ label.removeEventListener("click", _this.handlerLabelEvent);
782
+ });
783
+ }
784
+ };
785
+ /**
786
+ * Applies a toggle action to the toggle state and renders the toggle element.
787
+ * If the action is successful, this method will render the toggle element with the new state.
788
+ * If the silent parameter is false, this method will also trigger the change event.
789
+ * @param action The toggle action to apply.
790
+ * @param silent A boolean indicating whether to trigger the change event after applying the action.
791
+ */
792
+ Toggle.prototype.apply = function (action, silent) {
793
+ if (silent === void 0) { silent = false; }
794
+ if (this.stateReducer.do(action)) {
795
+ this.domBuilder.render(this.stateReducer.get());
796
+ if (!silent)
797
+ this.trigger();
798
+ }
799
+ };
800
+ /**
801
+ * Toggles the state of the toggle.
802
+ * If the toggle is currently in the on state, it will be set to the off state.
803
+ * If the toggle is currently in the off state, it will be set to the on state.
804
+ * If the toggle is currently in the indeterminate state, it will be set to the on state.
805
+ * If the silent parameter is false, this method will also trigger the change event.
806
+ * @param silent A boolean indicating whether to trigger the change event after applying the action.
807
+ */
808
+ Toggle.prototype.toggle = function (silent) {
809
+ if (silent === void 0) { silent = false; }
810
+ this.apply(ToggleActionType.TOGGLE, silent);
811
+ };
812
+ /**
813
+ * Sets the toggle state to on.
814
+ * If the silent parameter is false, this method will also trigger the change event.
815
+ * @param silent A boolean indicating whether to trigger the change event after applying the action.
816
+ */
817
+ Toggle.prototype.on = function (silent) {
818
+ if (silent === void 0) { silent = false; }
819
+ this.apply(ToggleActionType.ON, silent);
820
+ };
821
+ /**
822
+ * Sets the toggle state to off.
823
+ * If the silent parameter is false, this method will also trigger the change event.
824
+ * @param silent A boolean indicating whether to trigger the change event after applying the action.
825
+ */
826
+ Toggle.prototype.off = function (silent) {
827
+ if (silent === void 0) { silent = false; }
828
+ this.apply(ToggleActionType.OFF, silent);
829
+ };
830
+ /**
831
+ * Sets the toggle state to indeterminate.
832
+ * If the silent parameter is false, this method will also trigger the change event.
833
+ * @param {boolean} silent A boolean indicating whether to trigger the change event after applying the action.
834
+ */
835
+ Toggle.prototype.indeterminate = function (silent) {
836
+ if (silent === void 0) { silent = false; }
837
+ this.apply(ToggleActionType.INDETERMINATE, silent);
838
+ };
839
+ /**
840
+ * Sets the toggle state to determinate.
841
+ * If the silent parameter is false, this method will also trigger the change event.
842
+ * @param {boolean} silent A boolean indicating whether to trigger the change event after applying the action.
843
+ */
844
+ Toggle.prototype.determinate = function (silent) {
845
+ if (silent === void 0) { silent = false; }
846
+ this.apply(ToggleActionType.DETERMINATE, silent);
847
+ };
848
+ /**
849
+ * Enables the toggle.
850
+ * If the toggle is currently disabled, this method will set the toggle state to enabled.
851
+ * If the silent parameter is false, this method will also trigger the change event.
852
+ * @returns void
853
+ */
854
+ Toggle.prototype.enable = function () {
855
+ this.apply(ToggleActionType.ENABLE);
856
+ };
857
+ /**
858
+ * Disables the toggle.
859
+ * If the toggle is currently enabled, this method will set the toggle state to disabled.
860
+ * If the silent parameter is false, this method will also trigger the change event.
861
+ */
862
+ Toggle.prototype.disable = function () {
863
+ this.apply(ToggleActionType.DISABLE);
864
+ };
865
+ /**
866
+ * Sets the toggle state to readonly.
867
+ * If the toggle is currently disabled or enabled, this method will set the toggle state to readonly.
868
+ * If the silent parameter is false, this method will also trigger the change event.
869
+ * @returns void
870
+ */
871
+ Toggle.prototype.readonly = function () {
872
+ this.apply(ToggleActionType.READONLY);
873
+ };
874
+ /**
875
+ * Synchronizes the toggle state with the input element and renders the toggle.
876
+ * If the silent parameter is false, this method will also trigger the change event.
877
+ * @param {boolean} silent A boolean indicating whether to trigger the change event after synchronizing the toggle state.
878
+ */
879
+ Toggle.prototype.update = function (silent) {
880
+ this.stateReducer.sync(this.element);
881
+ this.domBuilder.render(this.stateReducer.get());
882
+ if (!silent)
883
+ this.trigger();
884
+ };
885
+ /**
886
+ * Triggers the change event on the toggle's input element.
887
+ * @param {boolean} silent A boolean indicating whether to trigger the change event.
888
+ * If the silent parameter is false, this method will trigger the change event.
889
+ */
890
+ Toggle.prototype.trigger = function (silent) {
891
+ if (silent === void 0) { silent = false; }
892
+ if (!silent)
893
+ this.element.dispatchEvent(new Event("change", { bubbles: true }));
894
+ };
895
+ /**
896
+ * Destroys the toggle element and unbinds all event listeners.
897
+ *This method is useful when you need to remove the toggle element from the DOM.
898
+ *After calling this method, the toggle element will be removed from the DOM and all event listeners will be unbound.
899
+ */
900
+ Toggle.prototype.destroy = function () {
901
+ this.unbindEventListeners();
902
+ this.domBuilder.destroy();
903
+ delete this.element.bsToggle;
904
+ };
905
+ /**
906
+ * Destroys the toggle element and reinitializes it with the same options.
907
+ *This method is useful when you need to reinitialize the toggle element with the same options.
908
+ */
909
+ Toggle.prototype.rerender = function () {
910
+ this.destroy();
911
+ this.element.bootstrapToggle();
912
+ };
913
+ return Toggle;
914
+ }());
915
+
916
+ var ToggleMethods;
917
+ (function (ToggleMethods) {
918
+ ToggleMethods["on"] = "on";
919
+ ToggleMethods["ON"] = "ON";
920
+ ToggleMethods["off"] = "off";
921
+ ToggleMethods["OFF"] = "OFF";
922
+ ToggleMethods["toggle"] = "toggle";
923
+ ToggleMethods["TOGGLE"] = "TOGGLE";
924
+ ToggleMethods["determinate"] = "determinate";
925
+ ToggleMethods["DETERMINATE"] = "DETERMINATE";
926
+ ToggleMethods["indeterminate"] = "indeterminate";
927
+ ToggleMethods["INDETERMINATE"] = "INDETERMINATE";
928
+ ToggleMethods["enable"] = "enable";
929
+ ToggleMethods["ENABLE"] = "ENABLE";
930
+ ToggleMethods["disable"] = "disable";
931
+ ToggleMethods["DISABLE"] = "DISABLE";
932
+ ToggleMethods["readonly"] = "readonly";
933
+ ToggleMethods["READONLY"] = "READONLY";
934
+ ToggleMethods["destroy"] = "destroy";
935
+ ToggleMethods["DESTROY"] = "DESTROY";
936
+ ToggleMethods["rerender"] = "rerender";
937
+ ToggleMethods["RENDERER"] = "RENDERER";
938
+ })(ToggleMethods || (ToggleMethods = {}));
939
+
940
+ (function () {
941
+ /**
942
+ * Add `bootstrapToggle` prototype function to HTML Elements
943
+ * Enables execution when used with HTML - ex: `document.getElementById('toggle').bootstrapToggle('on')`
944
+ */
945
+ HTMLInputElement.prototype.bootstrapToggle = function (options, silent) {
946
+ var _bsToggle = this.bsToggle || new Toggle(this, (options && typeof options !== "string") ? options : {});
947
+ // Execute method calls
948
+ if (options && typeof options === "string") {
949
+ switch (options) {
950
+ case ToggleMethods.TOGGLE:
951
+ case ToggleMethods.toggle:
952
+ return _bsToggle.toggle(silent);
953
+ case ToggleMethods.ON:
954
+ case ToggleMethods.on:
955
+ return _bsToggle.on(silent);
956
+ case ToggleMethods.OFF:
957
+ case ToggleMethods.off:
958
+ return _bsToggle.off(silent);
959
+ case ToggleMethods.INDETERMINATE:
960
+ case ToggleMethods.indeterminate:
961
+ return _bsToggle.indeterminate(silent);
962
+ case ToggleMethods.DETERMINATE:
963
+ case ToggleMethods.determinate:
964
+ return _bsToggle.determinate(silent);
965
+ case ToggleMethods.ENABLE:
966
+ case ToggleMethods.enable:
967
+ return _bsToggle.enable();
968
+ case ToggleMethods.DISABLE:
969
+ case ToggleMethods.disable:
970
+ return _bsToggle.disable();
971
+ case ToggleMethods.READONLY:
972
+ case ToggleMethods.readonly:
973
+ return _bsToggle.readonly();
974
+ case ToggleMethods.DESTROY:
975
+ case ToggleMethods.destroy:
976
+ return _bsToggle.destroy();
977
+ case ToggleMethods.RENDERER:
978
+ case ToggleMethods.rerender:
979
+ return _bsToggle.rerender();
980
+ }
981
+ }
982
+ };
983
+ /**
984
+ * Replace all `input[type=checkbox][data-toggle="toggle"]` inputs with "Bootstrap-Toggle"
985
+ * Executes once page elements have rendered enabling script to be placed in `<head>`
986
+ */
987
+ if (typeof window !== "undefined")
988
+ window.onload = function () {
989
+ document
990
+ .querySelectorAll('input[type=checkbox][data-toggle="toggle"]')
991
+ .forEach(function (ele) {
992
+ ele.bootstrapToggle();
993
+ });
994
+ };
995
+ // Export library if possible
996
+ if (typeof module !== "undefined" && module.exports) {
997
+ module.exports = Toggle;
998
+ }
999
+ })();
1000
+
1001
+ }));
1002
+ //# sourceMappingURL=bootstrap5-toggle.ecmas.js.map