init
This commit is contained in:
@@ -0,0 +1,504 @@
|
||||
/* Copyright Notice
|
||||
* bootstrap5-toggle v5.0.6
|
||||
* https://palcarazm.github.io/bootstrap5-toggle/
|
||||
* @author 2011-2014 Min Hur (https://github.com/minhur)
|
||||
* @author 2018-2019 Brent Ely (https://github.com/gitbrent)
|
||||
* @author 2022 Pablo Alcaraz Martínez (https://github.com/palcarazm)
|
||||
* @funding GitHub Sponsors
|
||||
* @see https://github.com/sponsors/palcarazm
|
||||
* @license MIT
|
||||
* @see https://github.com/palcarazm/bootstrap5-toggle/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
(function () {
|
||||
/**
|
||||
* `Toggle` is instantiated for each toggle-button
|
||||
*/
|
||||
class Toggle {
|
||||
constructor(element, options) {
|
||||
const DEPRECATION = {
|
||||
value:
|
||||
"BOOTSTRAP TOGGLE DEPRECATION CHECK -- a0Jhux0QySypjjs4tLtEo8xT2kx0AbYaq9K6mgNjWSs0HF0L8T8J0M0o3Kr7zkm7 --",
|
||||
ATTRIBUTE: "attribute",
|
||||
OPTION: "option",
|
||||
log: function (type, oldlabel, newlabel) {
|
||||
console.warn(
|
||||
`Bootstrap Toggle deprecation warning: Using ${oldlabel} ${type} is deprected. Use ${newlabel} instead.`
|
||||
);
|
||||
},
|
||||
};
|
||||
const DEFAULTS = {
|
||||
onlabel: "On",
|
||||
onstyle: "primary",
|
||||
onvalue: null,
|
||||
ontitle: null,
|
||||
offlabel: "Off",
|
||||
offstyle: "secondary",
|
||||
offvalue: null,
|
||||
offtitle: null,
|
||||
size: "",
|
||||
style: "",
|
||||
width: null,
|
||||
height: null,
|
||||
tabindex: 0,
|
||||
tristate: false,
|
||||
name: null,
|
||||
};
|
||||
options = options || {};
|
||||
|
||||
// A: Capture ref to HMTL element
|
||||
this.element = element;
|
||||
|
||||
// B: Set options
|
||||
this.options = {
|
||||
onlabel:
|
||||
this.element.getAttribute("data-onlabel") ||
|
||||
options.onlabel ||
|
||||
DEPRECATION.value ||
|
||||
DEFAULTS.onlabel,
|
||||
onstyle:
|
||||
this.element.getAttribute("data-onstyle") ||
|
||||
options.onstyle ||
|
||||
DEFAULTS.onstyle,
|
||||
onvalue:
|
||||
this.element.getAttribute("value") ||
|
||||
this.element.getAttribute("data-onvalue") ||
|
||||
options.onvalue ||
|
||||
DEFAULTS.onvalue,
|
||||
ontitle:
|
||||
this.element.getAttribute("data-ontitle") ||
|
||||
options.ontitle ||
|
||||
this.element.getAttribute("title") ||
|
||||
DEFAULTS.ontitle,
|
||||
offlabel:
|
||||
this.element.getAttribute("data-offlabel") ||
|
||||
options.offlabel ||
|
||||
DEPRECATION.value ||
|
||||
DEFAULTS.offlabel,
|
||||
offstyle:
|
||||
this.element.getAttribute("data-offstyle") ||
|
||||
options.offstyle ||
|
||||
DEFAULTS.offstyle,
|
||||
offvalue:
|
||||
this.element.getAttribute("data-offvalue") ||
|
||||
options.offvalue ||
|
||||
DEFAULTS.offvalue,
|
||||
offtitle:
|
||||
this.element.getAttribute("data-offtitle") ||
|
||||
options.offtitle ||
|
||||
this.element.getAttribute("title") ||
|
||||
DEFAULTS.offtitle,
|
||||
size:
|
||||
this.element.getAttribute("data-size") ||
|
||||
options.size ||
|
||||
DEFAULTS.size,
|
||||
style:
|
||||
this.element.getAttribute("data-style") ||
|
||||
options.style ||
|
||||
DEFAULTS.style,
|
||||
width:
|
||||
this.element.getAttribute("data-width") ||
|
||||
options.width ||
|
||||
DEFAULTS.width,
|
||||
height:
|
||||
this.element.getAttribute("data-height") ||
|
||||
options.height ||
|
||||
DEFAULTS.height,
|
||||
tabindex:
|
||||
this.element.getAttribute("tabindex") ||
|
||||
options.tabindex ||
|
||||
DEFAULTS.tabindex,
|
||||
tristate:
|
||||
this.element.hasAttribute("tristate") ||
|
||||
options.tristate ||
|
||||
DEFAULTS.tristate,
|
||||
name:
|
||||
this.element.getAttribute("name") || options.name || DEFAULTS.name,
|
||||
};
|
||||
|
||||
// C: Check deprecations
|
||||
if (this.options.onlabel === DEPRECATION.value) {
|
||||
if (this.element.getAttribute("data-on")) {
|
||||
DEPRECATION.log(DEPRECATION.ATTRIBUTE, "data-on", "data-onlabel");
|
||||
this.options.onlabel = this.element.getAttribute("data-on");
|
||||
} else if (options.on) {
|
||||
DEPRECATION.log(DEPRECATION.OPTION, "on", "onlabel");
|
||||
this.options.onlabel = options.on;
|
||||
} else {
|
||||
this.options.onlabel = DEFAULTS.onlabel;
|
||||
}
|
||||
}
|
||||
if (this.options.offlabel === DEPRECATION.value) {
|
||||
if (this.element.getAttribute("data-off")) {
|
||||
DEPRECATION.log(DEPRECATION.ATTRIBUTE, "data-off", "data-offlabel");
|
||||
this.options.offlabel = this.element.getAttribute("data-off");
|
||||
} else if (options.off) {
|
||||
DEPRECATION.log(DEPRECATION.OPTION, "off", "offlabel");
|
||||
this.options.offlabel = options.off;
|
||||
} else {
|
||||
this.options.offlabel = DEFAULTS.offlabel;
|
||||
}
|
||||
}
|
||||
|
||||
// LAST: Render Toggle
|
||||
this.render();
|
||||
}
|
||||
render() {
|
||||
function calcH(el) {
|
||||
const styles = window.getComputedStyle(el);
|
||||
const height = el.offsetHeight;
|
||||
const borderTopWidth = parseFloat(styles.borderTopWidth);
|
||||
const borderBottomWidth = parseFloat(styles.borderBottomWidth);
|
||||
const paddingTop = parseFloat(styles.paddingTop);
|
||||
const paddingBottom = parseFloat(styles.paddingBottom);
|
||||
|
||||
return (
|
||||
height -
|
||||
borderBottomWidth -
|
||||
borderTopWidth -
|
||||
paddingTop -
|
||||
paddingBottom
|
||||
);
|
||||
}
|
||||
// 0: Parse size
|
||||
let size;
|
||||
switch (this.options.size) {
|
||||
case "large":
|
||||
case "lg":
|
||||
size = "btn-lg";
|
||||
break;
|
||||
case "small":
|
||||
case "sm":
|
||||
size = "btn-sm";
|
||||
break;
|
||||
case "mini":
|
||||
case "xs":
|
||||
size = "btn-xs";
|
||||
break;
|
||||
default:
|
||||
size = "";
|
||||
break;
|
||||
}
|
||||
|
||||
// 1: On
|
||||
let ecmasToggleOn = document.createElement("span");
|
||||
ecmasToggleOn.setAttribute(
|
||||
"class",
|
||||
"btn btn-" + this.options.onstyle + " " + size
|
||||
);
|
||||
ecmasToggleOn.innerHTML = this.options.onlabel;
|
||||
if (this.options.ontitle) {
|
||||
ecmasToggleOn.setAttribute("title", this.options.ontitle);
|
||||
}
|
||||
|
||||
// 2: Off
|
||||
let ecmasToggleOff = document.createElement("span");
|
||||
ecmasToggleOff.setAttribute(
|
||||
"class",
|
||||
"btn btn-" + this.options.offstyle + " " + size
|
||||
);
|
||||
ecmasToggleOff.innerHTML = this.options.offlabel;
|
||||
if (this.options.offtitle) {
|
||||
ecmasToggleOff.setAttribute("title", this.options.offtitle);
|
||||
}
|
||||
|
||||
// 3: Handle
|
||||
let ecmasToggleHandle = document.createElement("span");
|
||||
ecmasToggleHandle.setAttribute("class", "toggle-handle btn " + size);
|
||||
|
||||
// 4: Toggle Group
|
||||
let ecmasToggleGroup = document.createElement("div");
|
||||
ecmasToggleGroup.setAttribute("class", "toggle-group");
|
||||
ecmasToggleGroup.appendChild(ecmasToggleOn);
|
||||
ecmasToggleGroup.appendChild(ecmasToggleOff);
|
||||
ecmasToggleGroup.appendChild(ecmasToggleHandle);
|
||||
|
||||
// 5: Toggle
|
||||
let ecmasToggle = document.createElement("div");
|
||||
ecmasToggle.setAttribute("class", "toggle btn");
|
||||
ecmasToggle.classList.add(
|
||||
this.element.checked
|
||||
? "btn-" + this.options.onstyle
|
||||
: "btn-" + this.options.offstyle
|
||||
);
|
||||
ecmasToggle.setAttribute("tabindex", this.options.tabindex);
|
||||
if (!this.element.checked) ecmasToggle.classList.add("off");
|
||||
if (this.options.size) ecmasToggle.classList.add(size);
|
||||
if (this.options.style) {
|
||||
this.options.style.split(" ").forEach((style) => {
|
||||
ecmasToggle.classList.add(style);
|
||||
});
|
||||
}
|
||||
if (this.element.disabled || this.element.readOnly) {
|
||||
ecmasToggle.classList.add("disabled");
|
||||
ecmasToggle.setAttribute("disabled", "disabled");
|
||||
}
|
||||
|
||||
// 6: Set form values
|
||||
if (this.options.onvalue)
|
||||
this.element.setAttribute("value", this.options.onvalue);
|
||||
let invElement = null;
|
||||
if (this.options.offvalue) {
|
||||
invElement = this.element.cloneNode();
|
||||
invElement.setAttribute("value", this.options.offvalue);
|
||||
invElement.setAttribute("data-toggle", "invert-toggle");
|
||||
invElement.removeAttribute("id");
|
||||
invElement.checked = !this.element.checked;
|
||||
}
|
||||
|
||||
// 7: Replace HTML checkbox with Toggle-Button
|
||||
this.element.parentElement.insertBefore(ecmasToggle, this.element);
|
||||
ecmasToggle.appendChild(this.element);
|
||||
if (invElement) ecmasToggle.appendChild(invElement);
|
||||
ecmasToggle.appendChild(ecmasToggleGroup);
|
||||
|
||||
// 8: Set button W/H, lineHeight
|
||||
{
|
||||
// A: Set style W/H
|
||||
// NOTE: `offsetWidth` returns *rounded* integer values, so use `getBoundingClientRect` instead.
|
||||
if (this.options.width) {
|
||||
ecmasToggle.style.width = `${this.options.width}px`;
|
||||
} else {
|
||||
ecmasToggle.style["min-width"] = "100px"; // First approach for better calculation
|
||||
ecmasToggle.style["min-width"] = `${
|
||||
Math.max(
|
||||
ecmasToggleOn.getBoundingClientRect().width,
|
||||
ecmasToggleOff.getBoundingClientRect().width
|
||||
) +
|
||||
ecmasToggleHandle.getBoundingClientRect().width / 2
|
||||
}px`;
|
||||
}
|
||||
|
||||
if (this.options.height) {
|
||||
ecmasToggle.style.height = `${this.options.height}px`;
|
||||
} else {
|
||||
ecmasToggle.style["min-height"] = "36px"; // First approach for better calculation
|
||||
ecmasToggle.style["min-height"] = `${Math.max(
|
||||
ecmasToggleOn.getBoundingClientRect().height,
|
||||
ecmasToggleOff.getBoundingClientRect().height
|
||||
)}px`;
|
||||
}
|
||||
|
||||
// B: Apply on/off class
|
||||
ecmasToggleOn.classList.add("toggle-on");
|
||||
ecmasToggleOff.classList.add("toggle-off");
|
||||
|
||||
// C: Finally, set lineHeight if needed
|
||||
if (this.options.height) {
|
||||
ecmasToggleOn.style.lineHeight = calcH(ecmasToggleOn) + "px";
|
||||
ecmasToggleOff.style.lineHeight = calcH(ecmasToggleOff) + "px";
|
||||
}
|
||||
}
|
||||
|
||||
// 9: Add listeners
|
||||
ecmasToggle.addEventListener("touchstart", (e) => {
|
||||
this.#toggleActionPerformed(e);
|
||||
});
|
||||
ecmasToggle.addEventListener("click", (e) => {
|
||||
this.#toggleActionPerformed(e);
|
||||
});
|
||||
ecmasToggle.addEventListener("keypress", (e) => {
|
||||
if (e.key == " ") {
|
||||
this.#toggleActionPerformed(e);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.element.id) {
|
||||
document
|
||||
.querySelectorAll('label[for="' + this.element.id + '"]')
|
||||
.forEach((label) => {
|
||||
label.addEventListener("touchstart", (_e) => {
|
||||
this.toggle();
|
||||
ecmasToggle.focus();
|
||||
});
|
||||
label.addEventListener("click", (_e) => {
|
||||
this.toggle();
|
||||
ecmasToggle.focus();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 10: Set elements to bootstrap object
|
||||
this.ecmasToggle = ecmasToggle;
|
||||
this.invElement = invElement;
|
||||
|
||||
// 11: Keep reference to this instance for subsequent calls via `getElementById().bootstrapToggle()`
|
||||
this.element.bsToggle = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger actions
|
||||
* @param {Event} e event
|
||||
*/
|
||||
#toggleActionPerformed(e) {
|
||||
if (this.options.tristate) {
|
||||
if (this.ecmasToggle.classList.contains("indeterminate")) {
|
||||
this.determinate(true);
|
||||
this.toggle();
|
||||
} else {
|
||||
this.indeterminate();
|
||||
}
|
||||
} else {
|
||||
this.toggle();
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
toggle(silent = false) {
|
||||
if (this.element.checked) this.off(silent);
|
||||
else this.on(silent);
|
||||
}
|
||||
|
||||
on(silent = false) {
|
||||
if (this.element.disabled || this.element.readOnly) return false;
|
||||
this.ecmasToggle.classList.remove("btn-" + this.options.offstyle);
|
||||
this.ecmasToggle.classList.add("btn-" + this.options.onstyle);
|
||||
this.ecmasToggle.classList.remove("off");
|
||||
this.element.checked = true;
|
||||
if (this.invElement) this.invElement.checked = false;
|
||||
if (!silent) this.trigger();
|
||||
}
|
||||
|
||||
off(silent = false) {
|
||||
if (this.element.disabled || this.element.readOnly) return false;
|
||||
this.ecmasToggle.classList.remove("btn-" + this.options.onstyle);
|
||||
this.ecmasToggle.classList.add("btn-" + this.options.offstyle);
|
||||
this.ecmasToggle.classList.add("off");
|
||||
this.element.checked = false;
|
||||
if (this.invElement) this.invElement.checked = true;
|
||||
if (!silent) this.trigger();
|
||||
}
|
||||
|
||||
indeterminate(silent = false) {
|
||||
if (
|
||||
!this.options.tristate ||
|
||||
this.element.disabled ||
|
||||
this.element.readOnly
|
||||
)
|
||||
return false;
|
||||
this.ecmasToggle.classList.add("indeterminate");
|
||||
this.element.indeterminate = true;
|
||||
this.element.removeAttribute("name");
|
||||
if (this.invElement) this.invElement.indeterminate = true;
|
||||
if (this.invElement) this.invElement.removeAttribute("name");
|
||||
if (!silent) this.trigger();
|
||||
}
|
||||
|
||||
determinate(silent = false) {
|
||||
if (
|
||||
!this.options.tristate ||
|
||||
this.element.disabled ||
|
||||
this.element.readOnly
|
||||
)
|
||||
return false;
|
||||
this.ecmasToggle.classList.remove("indeterminate");
|
||||
this.element.indeterminate = false;
|
||||
if (this.options.name)
|
||||
this.element.setAttribute("name", this.options.name);
|
||||
if (this.invElement) this.invElement.indeterminate = false;
|
||||
if (this.invElement && this.options.name)
|
||||
this.invElement.setAttribute("name", this.options.name);
|
||||
if (!silent) this.trigger();
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.ecmasToggle.classList.remove("disabled");
|
||||
this.ecmasToggle.removeAttribute("disabled");
|
||||
this.element.removeAttribute("disabled");
|
||||
this.element.removeAttribute("readonly");
|
||||
if (this.invElement) {
|
||||
this.invElement.removeAttribute("disabled");
|
||||
this.invElement.removeAttribute("readonly");
|
||||
}
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.ecmasToggle.classList.add("disabled");
|
||||
this.ecmasToggle.setAttribute("disabled", "");
|
||||
this.element.setAttribute("disabled", "");
|
||||
this.element.removeAttribute("readonly");
|
||||
if (this.invElement) {
|
||||
this.invElement.setAttribute("disabled", "");
|
||||
this.invElement.removeAttribute("readonly");
|
||||
}
|
||||
}
|
||||
|
||||
readonly() {
|
||||
this.ecmasToggle.classList.add("disabled");
|
||||
this.ecmasToggle.setAttribute("disabled", "");
|
||||
this.element.removeAttribute("disabled");
|
||||
this.element.setAttribute("readonly", "");
|
||||
if (this.invElement) {
|
||||
this.invElement.removeAttribute("disabled");
|
||||
this.invElement.setAttribute("readonly", "");
|
||||
}
|
||||
}
|
||||
|
||||
update(silent) {
|
||||
if (this.element.disabled) this.disable();
|
||||
else if (this.element.readOnly) this.readonly();
|
||||
else this.enable();
|
||||
if (this.element.checked) this.on(silent);
|
||||
else this.off(silent);
|
||||
}
|
||||
|
||||
trigger(silent) {
|
||||
if (!silent)
|
||||
this.element.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
// A: Remove button-group from UI, replace checkbox element
|
||||
this.ecmasToggle.parentNode.insertBefore(this.element, this.ecmasToggle);
|
||||
this.ecmasToggle.parentNode.removeChild(this.ecmasToggle);
|
||||
|
||||
// B: Delete internal refs
|
||||
delete this.element.bsToggle;
|
||||
delete this.ecmasToggle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add `bootstrapToggle` prototype function to HTML Elements
|
||||
* Enables execution when used with HTML - ex: `document.getElementById('toggle').bootstrapToggle('on')`
|
||||
*/
|
||||
Element.prototype.bootstrapToggle = function (options, silent) {
|
||||
let _bsToggle = this.bsToggle || new Toggle(this, options);
|
||||
|
||||
// Execute method calls
|
||||
if (options && typeof options === "string") {
|
||||
if (options.toLowerCase() == "toggle") _bsToggle.toggle(silent);
|
||||
else if (options.toLowerCase() == "on") _bsToggle.on(silent);
|
||||
else if (options.toLowerCase() == "off") _bsToggle.off(silent);
|
||||
else if (options.toLowerCase() == "indeterminate")
|
||||
_bsToggle.indeterminate(silent);
|
||||
else if (options.toLowerCase() == "determinate")
|
||||
_bsToggle.determinate(silent);
|
||||
else if (options.toLowerCase() == "enable") _bsToggle.enable();
|
||||
else if (options.toLowerCase() == "disable") _bsToggle.disable();
|
||||
else if (options.toLowerCase() == "readonly") _bsToggle.readonly();
|
||||
else if (options.toLowerCase() == "destroy") _bsToggle.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace all `input[type=checkbox][data-toggle="toggle"]` inputs with "Bootstrap-Toggle"
|
||||
* Executes once page elements have rendered enabling script to be placed in `<head>`
|
||||
*/
|
||||
if (typeof window !== "undefined")
|
||||
window.onload = function () {
|
||||
document
|
||||
.querySelectorAll('input[type=checkbox][data-toggle="toggle"]')
|
||||
.forEach(function (ele) {
|
||||
ele.bootstrapToggle();
|
||||
});
|
||||
};
|
||||
|
||||
// Export library if possible
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports = Toggle;
|
||||
}
|
||||
})();
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,464 @@
|
||||
/* Copyright Notice
|
||||
* bootstrap5-toggle v5.0.6
|
||||
* https://palcarazm.github.io/bootstrap5-toggle/
|
||||
* @author 2011-2014 Min Hur (https://github.com/minhur)
|
||||
* @author 2018-2019 Brent Ely (https://github.com/gitbrent)
|
||||
* @author 2022 Pablo Alcaraz Martínez (https://github.com/palcarazm)
|
||||
* @funding GitHub Sponsors
|
||||
* @see https://github.com/sponsors/palcarazm
|
||||
* @license MIT
|
||||
* @see https://github.com/palcarazm/bootstrap5-toggle/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
|
||||
+(function ($) {
|
||||
"use strict";
|
||||
|
||||
// TOGGLE PUBLIC CLASS DEFINITION
|
||||
// ==============================
|
||||
|
||||
let Toggle = function (element, options) {
|
||||
// A: Capture ref to HMTL element
|
||||
this.$element = $(element);
|
||||
|
||||
// B: Set options
|
||||
this.options = $.extend({}, this.defaults(), options);
|
||||
|
||||
// C: Check deprecations
|
||||
if (this.options.onlabel === Toggle.DEPRECATION.value) {
|
||||
if (this.$element.attr("data-on")) {
|
||||
Toggle.DEPRECATION.log(
|
||||
Toggle.DEPRECATION.ATTRIBUTE,
|
||||
"data-on",
|
||||
"data-onlabel"
|
||||
);
|
||||
this.options.onlabel = this.$element.attr("data-on");
|
||||
} else if (options.on) {
|
||||
Toggle.DEPRECATION.log(Toggle.DEPRECATION.OPTION, "on", "onlabel");
|
||||
this.options.onlabel = options.on;
|
||||
} else {
|
||||
this.options.onlabel = Toggle.DEFAULTS.onlabel;
|
||||
}
|
||||
}
|
||||
if (this.options.offlabel === Toggle.DEPRECATION.value) {
|
||||
if (this.$element.attr("data-off")) {
|
||||
Toggle.DEPRECATION.log(
|
||||
Toggle.DEPRECATION.ATTRIBUTE,
|
||||
"data-off",
|
||||
"data-offlabel"
|
||||
);
|
||||
this.options.offlabel = this.$element.attr("data-off");
|
||||
} else if (options.off) {
|
||||
Toggle.DEPRECATION.log(Toggle.DEPRECATION.OPTION, "off", "offlabel");
|
||||
this.options.offlabel = options.off;
|
||||
} else {
|
||||
this.options.offlabel = Toggle.DEFAULTS.offlabel;
|
||||
}
|
||||
}
|
||||
|
||||
// LAST: Render Toggle
|
||||
this.render();
|
||||
};
|
||||
|
||||
Toggle.DEPRECATION = {
|
||||
value:
|
||||
"BOOTSTRAP TOGGLE DEPRECATION CHECK -- a0Jhux0QySypjjs4tLtEo8xT2kx0AbYaq9K6mgNjWSs0HF0L8T8J0M0o3Kr7zkm7 --",
|
||||
ATTRIBUTE: "attribute",
|
||||
OPTION: "option",
|
||||
log: function (type, oldlabel, newlabel) {
|
||||
console.warn(
|
||||
`Bootstrap Toggle deprecation warning: Using ${oldlabel} ${type} is deprected. Use ${newlabel} instead.`
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
Toggle.DEFAULTS = {
|
||||
onlabel: "On",
|
||||
offlabel: "Off",
|
||||
onstyle: "primary",
|
||||
offstyle: "secondary",
|
||||
onvalue: null,
|
||||
offvalue: null,
|
||||
ontitle: null,
|
||||
offtitle: null,
|
||||
size: "normal",
|
||||
style: "",
|
||||
width: null,
|
||||
height: null,
|
||||
tabindex: 0,
|
||||
tristate: false,
|
||||
name: null,
|
||||
};
|
||||
|
||||
Toggle.prototype.defaults = function () {
|
||||
return {
|
||||
onlabel:
|
||||
this.$element.attr("data-onlabel") ||
|
||||
Toggle.DEPRECATION.value ||
|
||||
Toggle.DEFAULTS.onlabel,
|
||||
offlabel:
|
||||
this.$element.attr("data-offlabel") ||
|
||||
Toggle.DEPRECATION.value ||
|
||||
Toggle.DEFAULTS.offlabel,
|
||||
onstyle: this.$element.attr("data-onstyle") || Toggle.DEFAULTS.onstyle,
|
||||
offstyle: this.$element.attr("data-offstyle") || Toggle.DEFAULTS.offstyle,
|
||||
onvalue:
|
||||
this.$element.attr("value") ||
|
||||
this.$element.attr("data-onvalue") ||
|
||||
Toggle.DEFAULTS.onvalue,
|
||||
offvalue: this.$element.attr("data-offvalue") || Toggle.DEFAULTS.offvalue,
|
||||
ontitle:
|
||||
this.$element.attr("data-ontitle") ||
|
||||
this.$element.attr("title") ||
|
||||
Toggle.DEFAULTS.ontitle,
|
||||
offtitle:
|
||||
this.$element.attr("data-offtitle") ||
|
||||
this.$element.attr("title") ||
|
||||
Toggle.DEFAULTS.offtitle,
|
||||
size: this.$element.attr("data-size") || Toggle.DEFAULTS.size,
|
||||
style: this.$element.attr("data-style") || Toggle.DEFAULTS.style,
|
||||
width: this.$element.attr("data-width") || Toggle.DEFAULTS.width,
|
||||
height: this.$element.attr("data-height") || Toggle.DEFAULTS.height,
|
||||
tabindex: this.$element.attr("tabindex") || Toggle.DEFAULTS.tabindex,
|
||||
tristate: this.$element.is("[tristate]") || Toggle.DEFAULTS.tristate,
|
||||
name: this.$element.attr("name") || Toggle.DEFAULTS.name,
|
||||
};
|
||||
};
|
||||
|
||||
Toggle.prototype.render = function () {
|
||||
// 0: Parse size
|
||||
let size;
|
||||
switch (this.options.size) {
|
||||
case "large":
|
||||
case "lg":
|
||||
size = "btn-lg";
|
||||
break;
|
||||
case "small":
|
||||
case "sm":
|
||||
size = "btn-sm";
|
||||
break;
|
||||
case "mini":
|
||||
case "xs":
|
||||
size = "btn-xs";
|
||||
break;
|
||||
default:
|
||||
size = "";
|
||||
break;
|
||||
}
|
||||
|
||||
// 1: On
|
||||
let $toggleOn = $('<span class="btn">')
|
||||
.html(this.options.onlabel)
|
||||
.addClass("btn-" + this.options.onstyle + " " + size);
|
||||
if (this.options.ontitle) {
|
||||
$toggleOn.attr("title", this.options.ontitle);
|
||||
}
|
||||
|
||||
// 2: Off
|
||||
let $toggleOff = $('<span class="btn">')
|
||||
.html(this.options.offlabel)
|
||||
.addClass("btn-" + this.options.offstyle + " " + size);
|
||||
if (this.options.offtitle) {
|
||||
$toggleOff.attr("title", this.options.offtitle);
|
||||
}
|
||||
|
||||
// 3: Handle
|
||||
let $toggleHandle = $('<span class="toggle-handle btn">').addClass(size);
|
||||
|
||||
// 4: Toggle Group
|
||||
let $toggleGroup = $('<div class="toggle-group">').append(
|
||||
$toggleOn,
|
||||
$toggleOff,
|
||||
$toggleHandle
|
||||
);
|
||||
|
||||
// 5: Toggle
|
||||
let $toggle = $(
|
||||
'<div class="toggle btn" data-toggle="toggle" role="button">'
|
||||
)
|
||||
.addClass(
|
||||
this.$element.prop("checked")
|
||||
? "btn-" + this.options.onstyle
|
||||
: "btn-" + this.options.offstyle + " off"
|
||||
)
|
||||
.addClass(size)
|
||||
.addClass(this.options.style)
|
||||
.attr("tabindex", this.options.tabindex);
|
||||
if (this.$element.prop("disabled") || this.$element.prop("readonly")) {
|
||||
$toggle.addClass("disabled");
|
||||
$toggle.attr("disabled", "disabled");
|
||||
}
|
||||
|
||||
// 6: Set form values
|
||||
if (this.options.onvalue) this.$element.val(this.options.onvalue);
|
||||
let $invElement = null;
|
||||
if (this.options.offvalue) {
|
||||
$invElement = this.$element.clone();
|
||||
$invElement.val(this.options.offvalue);
|
||||
$invElement.attr("data-toggle", "invert-toggle");
|
||||
$invElement.removeAttr("id");
|
||||
$invElement.prop("checked", !this.$element.prop("checked"));
|
||||
}
|
||||
|
||||
// 7: Replace HTML checkbox with Toggle-Button
|
||||
this.$element.wrap($toggle);
|
||||
$.extend(this, {
|
||||
$toggle: this.$element.parent(),
|
||||
$toggleOn: $toggleOn,
|
||||
$toggleOff: $toggleOff,
|
||||
$toggleGroup: $toggleGroup,
|
||||
$invElement: $invElement,
|
||||
});
|
||||
this.$toggle.append($invElement, $toggleGroup);
|
||||
|
||||
// 8: Set button W/H, lineHeight
|
||||
{
|
||||
// A: Set style W/H
|
||||
if (this.options.width) {
|
||||
this.$toggle.css("width", this.options.width);
|
||||
} else {
|
||||
this.$toggle.css("min-width", "100px"); // First approach for better calculation
|
||||
this.$toggle.css(
|
||||
"min-width",
|
||||
`${
|
||||
Math.max($toggleOn.outerWidth(), $toggleOff.outerWidth()) +
|
||||
$toggleHandle.outerWidth() / 2
|
||||
}px`
|
||||
);
|
||||
}
|
||||
|
||||
if (this.options.height) {
|
||||
this.$toggle.css("height", this.options.height);
|
||||
} else {
|
||||
this.$toggle.css("min-height", "36px"); // First approach for better calculation
|
||||
this.$toggle.css(
|
||||
"min-height",
|
||||
`${Math.max($toggleOn.outerHeight(), $toggleOff.outerHeight())}px`
|
||||
);
|
||||
}
|
||||
|
||||
// B: Apply on/off class
|
||||
$toggleOn.addClass("toggle-on");
|
||||
$toggleOff.addClass("toggle-off");
|
||||
|
||||
// C: Finally, set lineHeight if needed
|
||||
if (this.options.height) {
|
||||
$toggleOn.css("line-height", $toggleOn.height() + "px");
|
||||
$toggleOff.css("line-height", $toggleOff.height() + "px");
|
||||
}
|
||||
}
|
||||
|
||||
// 9: Add listeners
|
||||
this.$toggle.on("touchstart", (e) => {
|
||||
toggleActionPerformed(e, this);
|
||||
});
|
||||
this.$toggle.on("click", (e) => {
|
||||
toggleActionPerformed(e, this);
|
||||
});
|
||||
this.$toggle.on("keypress", (e) => {
|
||||
if (e.key == " ") {
|
||||
toggleActionPerformed(e, this);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.$element.prop("id")) {
|
||||
$('label[for="' + this.$element.prop("id") + '"]').on(
|
||||
"touchstart click",
|
||||
(_e) => {
|
||||
this.toggle();
|
||||
this.$toggle.focus();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// 10: Set elements to bootstrap object (NOT NEEDED)
|
||||
// 11: Keep reference to this instance for subsequent calls via `getElementById().bootstrapToggle()` (NOT NEEDED)
|
||||
};
|
||||
|
||||
/**
|
||||
* Trigger actions
|
||||
* @param {Event} e event
|
||||
* @param {Toggle} target Toggle
|
||||
*/
|
||||
function toggleActionPerformed(e, target) {
|
||||
if (target.options.tristate) {
|
||||
if (target.$toggle.hasClass("indeterminate")) {
|
||||
target.determinate(true);
|
||||
target.toggle();
|
||||
} else {
|
||||
target.indeterminate();
|
||||
}
|
||||
} else {
|
||||
target.toggle();
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
Toggle.prototype.toggle = function (silent = false) {
|
||||
if (this.$element.prop("checked")) this.off(silent);
|
||||
else this.on(silent);
|
||||
};
|
||||
|
||||
Toggle.prototype.on = function (silent = false) {
|
||||
if (this.$element.prop("disabled") || this.$element.prop("readonly"))
|
||||
return false;
|
||||
this.$toggle
|
||||
.removeClass("btn-" + this.options.offstyle + " off")
|
||||
.addClass("btn-" + this.options.onstyle);
|
||||
this.$element.prop("checked", true);
|
||||
if (this.$invElement) this.$invElement.prop("checked", false);
|
||||
if (!silent) this.trigger();
|
||||
};
|
||||
|
||||
Toggle.prototype.off = function (silent = false) {
|
||||
if (this.$element.prop("disabled") || this.$element.prop("readonly"))
|
||||
return false;
|
||||
this.$toggle
|
||||
.removeClass("btn-" + this.options.onstyle)
|
||||
.addClass("btn-" + this.options.offstyle + " off");
|
||||
this.$element.prop("checked", false);
|
||||
if (this.$invElement) this.$invElement.prop("checked", true);
|
||||
if (!silent) this.trigger();
|
||||
};
|
||||
|
||||
Toggle.prototype.indeterminate = function (silent = false) {
|
||||
if (
|
||||
!this.options.tristate ||
|
||||
this.$element.prop("disabled") ||
|
||||
this.$element.prop("readonly")
|
||||
)
|
||||
return false;
|
||||
this.$toggle.addClass("indeterminate");
|
||||
this.$element.prop("indeterminate", true);
|
||||
this.$element.removeAttr("name");
|
||||
if (this.$invElement) this.$invElement.prop("indeterminate", true);
|
||||
if (this.$invElement) this.$invElement.removeAttr("name");
|
||||
if (!silent) this.trigger();
|
||||
};
|
||||
|
||||
Toggle.prototype.determinate = function (silent = false) {
|
||||
if (
|
||||
!this.options.tristate ||
|
||||
this.$element.prop("disabled") ||
|
||||
this.$element.prop("readonly")
|
||||
)
|
||||
return false;
|
||||
this.$toggle.removeClass("indeterminate");
|
||||
this.$element.prop("indeterminate", false);
|
||||
if (this.options.name) this.$element.attr("name", this.options.name);
|
||||
if (this.$invElement) this.$invElement.prop("indeterminate", false);
|
||||
if (this.$invElement && this.options.name)
|
||||
this.$invElement.attr("name", this.options.name);
|
||||
if (!silent) this.trigger();
|
||||
};
|
||||
|
||||
Toggle.prototype.enable = function () {
|
||||
this.$toggle.removeClass("disabled");
|
||||
this.$toggle.removeAttr("disabled");
|
||||
this.$element.prop("disabled", false);
|
||||
this.$element.prop("readonly", false);
|
||||
if (this.$invElement) {
|
||||
this.$invElement.prop("disabled", false);
|
||||
this.$invElement.prop("readonly", false);
|
||||
}
|
||||
};
|
||||
|
||||
Toggle.prototype.disable = function () {
|
||||
this.$toggle.addClass("disabled");
|
||||
this.$toggle.attr("disabled", "disabled");
|
||||
this.$element.prop("disabled", true);
|
||||
this.$element.prop("readonly", false);
|
||||
if (this.$invElement) {
|
||||
this.$invElement.prop("disabled", true);
|
||||
this.$invElement.prop("readonly", false);
|
||||
}
|
||||
};
|
||||
|
||||
Toggle.prototype.readonly = function () {
|
||||
this.$toggle.addClass("disabled");
|
||||
this.$toggle.attr("disabled", "disabled");
|
||||
this.$element.prop("disabled", false);
|
||||
this.$element.prop("readonly", true);
|
||||
if (this.$invElement) {
|
||||
this.$invElement.prop("disabled", false);
|
||||
this.$invElement.prop("readonly", true);
|
||||
}
|
||||
};
|
||||
|
||||
Toggle.prototype.update = function (silent) {
|
||||
if (this.$element.prop("disabled")) this.disable();
|
||||
else if (this.$element.prop("readonly")) this.readonly();
|
||||
else this.enable();
|
||||
if (this.$element.prop("checked")) this.on(silent);
|
||||
else this.off(silent);
|
||||
};
|
||||
|
||||
Toggle.prototype.trigger = function (silent) {
|
||||
this.$element.off("change.bs.toggle");
|
||||
if (!silent) this.$element.change();
|
||||
this.$element.on(
|
||||
"change.bs.toggle",
|
||||
$.proxy(function () {
|
||||
this.update();
|
||||
}, this)
|
||||
);
|
||||
};
|
||||
|
||||
Toggle.prototype.destroy = function () {
|
||||
// A: Remove button-group from UI, replace checkbox element
|
||||
this.$element.off("change.bs.toggle");
|
||||
this.$toggleGroup.remove();
|
||||
if (this.$invElement) this.$invElement.remove();
|
||||
|
||||
// B: Delete internal refs
|
||||
this.$element.removeData("bs.toggle");
|
||||
this.$element.unwrap();
|
||||
};
|
||||
|
||||
// TOGGLE PLUGIN DEFINITION
|
||||
// ========================
|
||||
|
||||
function Plugin(option) {
|
||||
let optArg = Array.prototype.slice.call(arguments, 1)[0];
|
||||
|
||||
return this.each(function () {
|
||||
let $this = $(this);
|
||||
let data = $this.data("bs.toggle");
|
||||
let options = typeof option == "object" && option;
|
||||
|
||||
if (!data) {
|
||||
data = new Toggle(this, options);
|
||||
$this.data("bs.toggle", data);
|
||||
}
|
||||
if (
|
||||
typeof option === "string" &&
|
||||
data[option] &&
|
||||
typeof optArg === "boolean"
|
||||
)
|
||||
data[option](optArg);
|
||||
else if (typeof option === "string" && data[option]) data[option]();
|
||||
//else if (option && !data[option]) console.log('bootstrap-toggle: error: method `'+ option +'` does not exist!');
|
||||
});
|
||||
}
|
||||
|
||||
let old = $.fn.bootstrapToggle;
|
||||
|
||||
$.fn.bootstrapToggle = Plugin;
|
||||
$.fn.bootstrapToggle.Constructor = Toggle;
|
||||
|
||||
// TOGGLE NO CONFLICT
|
||||
// ==================
|
||||
|
||||
$.fn.toggle.noConflict = function () {
|
||||
$.fn.bootstrapToggle = old;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace all `input[type=checkbox][data-toggle="toggle"]` inputs with "Bootstrap-Toggle"
|
||||
* Executes once page elements have rendered enabling script to be placed in `<head>`
|
||||
*/
|
||||
$(function () {
|
||||
$("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle();
|
||||
});
|
||||
})(jQuery);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user