Files
asset-management-system/resources/assets/js/form-wizard.js
Arya Dwi Putra 5514f7de5b first commit
2025-12-01 06:41:22 +07:00

1024 lines
31 KiB
JavaScript

/**
*
* A lightweight wizard UI component that supports accessibility and HTML5 in JavaScript Vanilla.
*
* @link https://github.com/AdrianVillamayor/Wizard-JS
* @author Adrii[https://github.com/AdrianVillamayor]
*
* @class Wizard
*/
class Wizard1 {
constructor(args) {
let opts = {
"wz_class": "",
"wz_nav": ".wizard-nav",
"wz_ori": ".horizontal",
"wz_nav_style": "dots",
"wz_content": ".wizard-content",
"wz_buttons": ".wizard-buttons",
"wz_button": ".wizard-btn",
"wz_button_style": ".btn",
"wz_step": ".wizard-step",
"wz_form": ".wizard-form",
"wz_next": ".next",
"wz_prev": ".prev",
"wz_finish": ".finish",
"wz_highlight": ".highlight",
"nav": true,
"buttons": true,
"highlight": true,
"current_step": 0,
"steps": 0,
"highlight_time": 1000,
"navigation": "all",
"next": "Next",
"prev": "Prev",
"finish": "Submit",
"highlight_type": { "error": "error", "warning": "warning", "success": "success", "info": "info" },
"i18n": {
"empty_wz": "No item has been found with which to generate the Wizard.",
"empty_nav": "Nav does not exist or is empty.",
"empty_content": "Content does not exist or is empty.",
"empty_html": "Undefined or null content cannot be added.",
"empty_update": "Nothing to update.",
"no_nav": "Both the nav and the buttons are disabled, there is no navigation system.",
"form_validation": "One or more of the form fields are invalid.",
"diff_steps": "Discordance between the steps of nav and content.",
"random": "There has been a problem, check the configuration and use of the wizard.",
"already_definded": "This item is already defined",
"title": "Step"
}
};
this.prefabOpts(opts, args);
this.wz_class = this.options.wz_class;
this.wz_active = "active";
this.wz_ori = this.options.wz_ori;
this.wz_nav = this.options.wz_nav;
this.wz_nav_style = this.options.wz_nav_style;
this.wz_content = this.options.wz_content;
this.wz_buttons = this.options.wz_buttons;
this.wz_button = this.options.wz_button;
this.wz_button_style = this.options.wz_button_style;
this.wz_step = this.options.wz_step;
this.wz_form = this.options.wz_form;
this.wz_next = this.options.wz_next;
this.wz_prev = this.options.wz_prev;
this.wz_finish = this.options.wz_finish;
this.wz_highlight = this.options.wz_highlight;
this.buttons = this.options.buttons;
this.nav = this.options.nav;
this.highlight = this.options.highlight;
this.highlight_time = this.options.highlight_time;
this.highlight_type = this.options.highlight_type;
this.steps = this.options.steps;
this.current_step = this.options.current_step;
this.last_step = this.current_step;
this.navigation = this.options.navigation;
this.prev = this.options.prev;
this.next = this.options.next;
this.finish = this.options.finish;
this.form = false;
this.locked = false;
this.locked_step = null;
}
/**
* Initializes the wizard
*
* @customevent wz.ready - Indicates that wizard has loaded and is accessible.
* @property {object} target - wz_class
* @property {object} elem - DOM element
*
* @throws empty_wz - Not found any element to generate the Wizard with.
* @throws empty_nav - Nav does not exist or is empty.
* @throws empty_content - Content does not exist or is empty.
* @throws diff_steps - Discordance between the steps of nav and content.
* @throws random - There has been a problem check the configuration and use of the wizard.
*
* @return {void}
*/
init() {
try {
const wz_check = ($_.exists(document.querySelector(this.wz_class))) ? document.querySelector(this.wz_class) : $_.throwException(this.options.i18n.empty_wz);
if ($_.str2bool(wz_check.getAttribute("data-wizard")) && wz_check.getAttribute("data-wizard") === this.wz_active) {
console.warn(`${this.wz_class} : ${this.options.i18n.already_definded}`);
return false;
}
$_.cleanEvents(document.querySelector(this.wz_class), true);
const wz = ($_.exists(document.querySelector(this.wz_class))) ? document.querySelector(this.wz_class) : $_.throwException(this.options.i18n.empty_wz);
if ($_.str2bool(this.buttons) === false && $_.str2bool(this.nav) === false) {
console.warn(this.options.i18n.no_nav);
}
wz.classList.add((this.wz_ori).replace(".", ""));
if (wz.tagName === "FORM") {
this.form = true;
}
this.check2Prepare(wz)
switch (this.navigation) {
case "all":
case "nav":
this.setNavEvent()
this.setBtnEvent()
break;
case "buttons":
this.setBtnEvent();
break;
}
wz.style.display = ($_.hasClass(wz, "vertical")) ? "flex" : "block";
wz.setAttribute("data-wizard", this.wz_active)
document.dispatchEvent(new CustomEvent("wz.ready", {
detail: {
"target": this.wz_class,
"elem": document.querySelector(this.wz_class)
}
}));
} catch (error) {
throw error;
}
}
/**
* Check and update each section of the wizard.
*
* @customevent wz.update - Indicates that wizard has updaded and is accessible.
* @property {object} target - wz_class
* @property {object} elem - DOM element
*
* @throws empty_wz - Not found any element to generate the Wizard with.
*
* @return {void}
*/
update() {
const wz = ($_.exists(document.querySelector(this.wz_class))) ? document.querySelector(this.wz_class) : $_.throwException(this.options.i18n.empty_wz);
if (($_.str2bool(wz.getAttribute("data-wizard")) === false) && wz.getAttribute("data-wizard") != this.wz_active) {
$_.throwException(this.options.i18n.empty_wz);
}
this.check2Prepare(wz)
this.content_update = false;
document.querySelector(this.wz_class).dispatchEvent(new CustomEvent("wz.update", {
detail: {
"target": this.wz_class,
"elem": document.querySelector(this.wz_class)
}
}));
}
/**
* Restart the wizard
*
* @event wz.reset
*
* @return {void}
*/
reset() {
this.setCurrentStep(0);
const wz = document.querySelector(this.wz_class);
const nav = wz.querySelector(this.wz_nav);
const content = wz.querySelector(this.wz_content);
if ($_.str2bool(this.buttons) !== false) {
let buttons = wz.querySelector(this.wz_buttons);
let next = buttons.querySelector(this.wz_button + this.wz_next);
let prev = buttons.querySelector(this.wz_button + this.wz_prev);
let finish = buttons.querySelector(this.wz_button + this.wz_finish);
this.checkButtons(next, prev, finish)
}
let $wz_nav = nav.querySelectorAll(this.wz_step);
$_.removeClassList($wz_nav, "active");
let $wz_content = content.querySelectorAll(this.wz_step);
$_.removeClassList($wz_content, "active");
nav.querySelector(`${this.wz_step}[data-step="${this.getCurrentStep()}"]`).classList.add("active");
content.querySelector(`${this.wz_step}[data-step="${this.getCurrentStep()}"]`).classList.add("active");
wz.dispatchEvent(new Event("wz.reset"));
}
/**
* Locks the wizard in the active step
*
* @return {void}
*/
lock() {
this.locked = true;
this.locked_step = this.getCurrentStep();
}
/**
* Unlock wizard
*
* @event wz.unlock
*
* @return {void}
*/
unlock() {
this.locked = false;
this.locked_step = null;
document.querySelector(this.wz_class).dispatchEvent(new Event("wz.unlock"));
}
/**
* Generate the steps and define a standard for each step.
*
* @param {object} $wz_nav - Nav element
* @param {object} $wz_nav_steps - Steps elements inside Nav
* @param {object} $wz_content_steps - Steps elements inside Content
*
* @return {void}
*/
prefabSteps($wz_content_steps, $wz_nav, $wz_nav_steps) {
let active_index = this.getCurrentStep();
for (let i = 0; i < $wz_content_steps.length; i++) {
let $this = $wz_content_steps[i];
$this.setAttribute("data-step", i);
if ($_.str2bool(this.nav) !== false) {
$wz_nav_steps[i].setAttribute("data-step", i);
}
};
if ($_.str2bool(this.nav) !== false) {
$_.removeClassList($wz_nav_steps, "active");
$wz_nav_steps[active_index].classList.add("active");
$wz_nav.classList.add(this.wz_nav_style);
}
$_.removeClassList($wz_content_steps, "active");
$wz_content_steps[active_index].classList.add("active");
// if (this.form) this.update2Form();
this.setButtons();
}
/**
* Adds the form tag and converts the wizard into a <form>
*
* @return {void}
*/
update2Form() {
let wz = document.querySelector(this.wz_class);
let wz_content = wz.querySelector(this.wz_content);
if (wz_content.tagName !== "FORM") {
let wz_content_class = wz_content.getAttribute("class");
let wz_content_content = wz_content.innerHTML
wz_content.remove();
const $form = document.createElement("form");
$form.setAttribute("method", "POST");
$form.setAttribute("class", wz_content_class + " " + (this.wz_form).replace(".", ""));
$form.innerHTML = wz_content_content;
wz.appendChild($form)
}
}
/**
* Checks and validates each input/select/textarea of the active step.
* If the step has no inputs, the checks will be ignored.
*
* @throws random - There has been a problem check the configuration and use of the wizard.
*
* @return {boolean} - If everything is OK, it returns false
*/
checkForm() {
let wz = document.querySelector(this.wz_class);
let wz_content = wz.querySelector(this.wz_content);
let steps = wz_content.querySelectorAll(this.wz_step);
let target = steps[this.getCurrentStep()];
let validation = false;
let inputs = target.querySelectorAll("input,textarea,select");
if (inputs.length > 0) {
validation = this.formValidator(wz_content, inputs);
}
return validation;
}
/**
* Generating, styling and shaping the Nav
*
* @param {object} $wz - Wizard element
*
* @return {void}
*/
setNav($wz) {
let wz_nav = $wz.querySelector(this.wz_nav);
if ($_.exists(wz_nav) !== false && $_.str2bool(this.nav) !== false) {
wz_nav.remove()
wz_nav = $wz.querySelector(this.wz_nav);
}
if ($_.exists(wz_nav) === false && $_.str2bool(this.nav) !== false) {
let wz_content = $wz.querySelector(this.wz_content);
let steps = wz_content.querySelectorAll(this.wz_step);
const nav = document.createElement("ASIDE");
nav.classList.add((this.wz_nav).replace(".", ""));
const wz_content_steps = wz_content.querySelectorAll(this.wz_step);
const steps_length = wz_content_steps.length;
for (let i = 0; i < steps_length; i++) {
const nav_step = document.createElement("DIV");
let title = (steps[i].hasAttribute("data-title")) ? steps[i].getAttribute("data-title") : `${this.options.i18n.title} ${i}`;
nav_step.classList.add((this.wz_step).replace(".", ""));
if (this.navigation === "buttons") nav_step.classList.add("nav-buttons");
const dot = document.createElement("SPAN");
dot.classList.add('dot');
nav_step.appendChild(dot);
const span = document.createElement("SPAN");
span.innerHTML = title;
nav_step.appendChild(span);
nav.appendChild(nav_step);
}
$wz.prepend(nav);
}
}
/**
* Generating, styling and shaping Buttons
*
* @return {void}
*/
setButtons() {
let wz = document.querySelector(this.wz_class);
let wz_btns = wz.querySelector(this.wz_buttons);;
if ($_.exists(wz_btns) !== false && $_.str2bool(this.buttons) !== false) {
wz_btns.remove()
wz_btns = wz.querySelector(this.wz_buttons);;
}
if ($_.exists(wz_btns) === false && $_.str2bool(this.buttons) !== false) {
const buttons = document.createElement("ASIDE");
buttons.classList.add((this.wz_buttons).replace(".", ""));
let btn_style = (this.wz_button_style).replaceAll(".", "");
btn_style = btn_style.split(" ");
const prev = document.createElement("BUTTON");
prev.innerHTML = this.prev;
prev.classList.add((this.wz_button).replace(".", ""));
prev.classList.add(...btn_style);
prev.classList.add((this.wz_prev).replace(".", ""));
if (this.navigation === "nav") prev.style.display = "none";
buttons.appendChild(prev);
const next = document.createElement("BUTTON");
next.innerHTML = this.next;
next.classList.add((this.wz_button).replace(".", ""));
next.classList.add(...btn_style);
next.classList.add((this.wz_next).replace(".", ""));
if (this.navigation === "nav") next.style.display = "none";
buttons.appendChild(next);
const finish = document.createElement("BUTTON");
finish.innerHTML = this.finish;
finish.classList.add((this.wz_button).replace(".", ""));
finish.classList.add(...btn_style);
finish.classList.add((this.wz_finish).replace(".", ""));
buttons.appendChild(finish);
this.checkButtons(next, prev, finish)
wz.appendChild(buttons);
}
}
/**
* Generating, styling and shaping Buttons
*
* @param {object} next - Next button element
* @param {object} prev - Prev button element
* @param {object} finish - Finish button element
*
* @return {void}
*/
checkButtons(next, prev, finish) {
let current_step = this.getCurrentStep();
let n_steps = this.steps - 1;
if (current_step == 0) {
prev.setAttribute("disabled", true);
} else {
prev.removeAttribute("disabled");
}
if (current_step == n_steps) {
next.setAttribute("disabled", true);
finish.style.display = "block";
} else {
finish.style.display = "none";
next.removeAttribute("disabled");
}
}
/**
* Common function for wizard checks and prefab.
*
* @param {object} wz - Wizard element
*
* @return {void}
*/
check2Prepare(wz) {
this.setNav(wz);
const wz_content = ($_.exists(wz.querySelector(this.wz_content))) ? wz.querySelector(this.wz_content) : $_.throwException(this.options.i18n.empty_content);
const wz_content_steps = wz_content.querySelectorAll(this.wz_step);
const wz_content_steps_length = (wz_content_steps.length > 0) ? wz_content_steps.length : $_.throwException(this.options.i18n.empty_content);
let wz_nav = undefined;
let wz_nav_steps = undefined;
if ($_.str2bool(this.nav) !== false) {
wz_nav = ($_.exists(wz.querySelector(this.wz_nav))) ? wz.querySelector(this.wz_nav) : $_.throwException(this.options.i18n.empty_nav);
wz_nav_steps = wz_nav.querySelectorAll(this.wz_step);
const wz_nav_steps_length = (wz_nav_steps.length > 0) ? wz_nav_steps.length : $_.throwException(this.options.i18n.empty_nav);
if (wz_nav_steps_length != wz_content_steps_length) {
$_.throwException(this.options.i18n.diff_steps);
}
}
this.steps = wz_content_steps_length;
this.prefabSteps(wz_content_steps, wz_nav, wz_nav_steps);
}
/**
* Click event handler for Buttons and Nav.
*
* @param {object} e - Event
*
* @event wz.btn.prev - In case the wizard goes backwards, the wz.btn.prev event will be fired.
* @event wz.btn.next - In case the wizard advances, the nextWizard event will be fired.
* @event wz.nav.forward - In case of moving forward with the navbar, the forwardNavWizard event will be fired.
* @event wz.nav.backward - In case of moving backward with the navbar, the backwardNavWizard event will be fired.
* @event wz.lock - In case it is blocked, it will fire the wz.lock event.
*
* @customevent wz.error - If the form is not correctly filled in, the wz.error event will be fired.
* @property {string} id - Eror id
* @property {string} msg - Error message
* @property {object} target - Contains all the elements that have given error
*
* @return {void}
*/
onClick(e) {
const $this = e
const wz = document.querySelector(this.wz_class);
if (this.locked && this.locked_step === this.getCurrentStep()) {
wz.dispatchEvent(new Event("wz.lock"));
return false;
}
const parent = $_.getParent($this, this.wz_class);
const nav = parent.querySelector(this.wz_nav);
const content = parent.querySelector(this.wz_content);
const is_btn = ($_.hasClass($this, this.wz_button));
const is_nav = ($_.hasClass($this, this.wz_step));
let step = ($_.str2bool($this.getAttribute("data-step")) !== false) ? parseInt($this.getAttribute("data-step")) : this.getCurrentStep();
if (is_btn) {
if ($_.hasClass($this, this.wz_prev)) {
step = step - 1;
wz.dispatchEvent(new Event("wz.btn.prev"));
} else if ($_.hasClass($this, this.wz_next)) {
step = step + 1;
wz.dispatchEvent(new Event("wz.btn.next"));
}
}
let step_action = step > this.getCurrentStep()
if (is_nav) {
if (step_action) {
wz.dispatchEvent(new Event("wz.nav.forward"));
} else if (step < this.getCurrentStep()) {
wz.dispatchEvent(new Event("wz.nav.backward"));
}
}
if (this.form && this.navigation != "buttons") {
if (step_action) {
if ((step !== this.getCurrentStep() + 1)) {
if (step >= this.last_step) {
step = this.last_step;
} else {
step = this.getCurrentStep() + 1;
}
}
}
}
if (this.form) {
const check_form = this.checkForm()
if (check_form.error === true) {
if (step_action) {
wz.dispatchEvent(new CustomEvent("wz.error", {
detail: {
"id": "form_validaton",
"msg": this.options.i18n.form_validation,
"target": check_form.target
}
}));
}
this.last_step = this.getCurrentStep();
if (this.getCurrentStep() < step) {
return false;
}
}
}
if ($_.str2bool(step)) {
this.setCurrentStep(step)
}
if ($_.str2bool(this.buttons) !== false) {
const buttons = parent.querySelector(this.wz_buttons);
const next = buttons.querySelector(this.wz_button + this.wz_next);;
const prev = buttons.querySelector(this.wz_button + this.wz_prev);
const finish = buttons.querySelector(this.wz_button + this.wz_finish);
this.checkButtons(next, prev, finish)
}
if ($_.str2bool(this.nav) !== false) {
const $wz_nav = nav.querySelectorAll(this.wz_step);
$_.removeClassList($wz_nav, "active");
nav.querySelector(`${this.wz_step}[data-step="${this.getCurrentStep()}"]`).classList.add("active");
}
const $wz_content = content.querySelectorAll(this.wz_step);
$_.removeClassList($wz_content, "active");
content.querySelector(`${this.wz_step}[data-step="${this.getCurrentStep()}"]`).classList.add("active");
}
/**
* Notifies that the wizard has been completed.
*
* @param {object} e - Event
*
* @event wz.form.submit - If the wizard is a form it will fire submitWizard
* @event wz.end - If the wizard is not a form it will fire endWizard
*
* @return {void}
*/
onClickFinish(e) {
if (this.form) {
const check_form = this.checkForm()
if (check_form.error !== true) {
document.querySelector(this.wz_class).dispatchEvent(new Event("wz.form.submit"));
}
} else {
document.querySelector(this.wz_class).dispatchEvent(new Event("wz.end"));
}
}
/**
* Set the active step
*
* @param {int} step - The active step
*
* @return {void}
*/
setCurrentStep(step) {
this.current_step = this.setStep(step);
}
/**
* Return the active step
*
* @return {int} The active step
*/
getCurrentStep() {
return this.current_step;
}
/**
* Check and match the steps of the wizard.
*
* @param {int} step - Step
*
* @return {int} Step
*/
setStep(step) {
let parent = document.querySelector(this.wz_class);
let content = parent.querySelector(this.wz_content);
let check_content = content.querySelector(`${this.wz_step}[data-step="${step}"]`);
if ($_.exists(check_content) === false) {
let content_length = (content.querySelectorAll(this.wz_step).length) - 1;
let diff = $_.closetNubmer(content_length, step)
step = diff;
}
this.last_step = (step > this.last_step) ? step : this.last_step;
return parseInt(step);
}
/**
* Set Nav events
*
* @return {void}
*/
setNavEvent() {
let _self = this;
let el = document.querySelector(this.wz_class);
$_.delegate(el, "click", `${this.wz_nav} ${this.wz_step}`, function (event) {
event.preventDefault()
_self.onClick(this)
});
}
/**
* Set Button events
*
* @return {void}
*/
setBtnEvent() {
let _self = this;
let el = document.querySelector(this.wz_class);
$_.delegate(el, "click", `${this.wz_buttons} ${this.wz_button}`, function clickFunction(event) {
event.preventDefault()
if ($_.hasClass(event.target, _self.wz_finish)) {
_self.onClickFinish(this)
} else {
_self.onClick(this)
}
});
}
/**
* Set options of wizard
*
* @param {object} options - List of options to build the wizard
*
* @return {void}
*/
set_options(options) {
this.options = options;
}
/**
* Check and match the options of the wizard with args definieds
*
* @param {object} options - List of options to build the wizard
* @param {object} args - List of arguments modifying the base options
*
* @return {void}
*/
prefabOpts(options, args) {
Object.entries(args).forEach(([key, value]) => {
if (typeof value === 'object') {
Object.entries(value).forEach(([key_1, value_1]) => {
options[key][key_1] = value_1;
});
} else {
options[key] = value;
}
});
this.set_options(options);
}
/**
* Checks the fields of the active step, in case there is an error it generates a highlight.
* Returns an array with all the fields that have given error.
*
* @param {object} wz_content - Active wizard content
* @param {object} formData - All inputs, textarea and select of the active content
*
* @return {object}
* @property {bool} error - There is an error or not
* @property {array} target - Contains all the elements that have given error
*/
formValidator(wz_content, formData) {
let error = false;
let target = [];
for (let e of formData) {
if ($_.hasClass(e, "required") || $_.exists(e.getAttribute("required"))) {
let check = false
switch (e.tagName) {
case "INPUT":
check = $_.dispatchInput(wz_content, e);
break;
case "SELECT":
case "TEXTAREA":
check = $_.isEmpty(e.value);
break;
}
if (check === false) {
error = true;
target.push(e);
if ($_.str2bool(this.highlight) === true) {
$_.highlight(e, this.wz_highlight, this.highlight_type['error'], this.highlight_time);
}
}
}
}
return {
"error": error,
"target": target
};
}
};
const $_ = {
hasClass: function (e, className) {
className = className.replace(".", "");
return new RegExp('(\\s|^)' + className + '(\\s|$)').test(e.className);
},
getParent: function (elem, selector) {
let parent = undefined;
while (elem.parentNode.tagName !== "BODY" && parent === undefined) {
elem = elem.parentNode;
if (elem.matches(selector)) {
parent = elem;
}
}
return parent;
},
delegate: function (el, evt, sel, handler) {
el.addEventListener(evt, function (event) {
let t = event.target;
while (t && t !== this) {
if (t.matches(sel)) {
handler.call(t, event);
}
t = t.parentNode;
}
});
},
removeClassList: function (e, className) {
for (let element of e) {
element.classList.remove(className);
};
},
objToString: function (obj, delimiter = ";") {
let str = '';
for (const p in obj) {
if (obj.hasOwnProperty(p)) {
str += p + ':' + obj[p] + delimiter;
}
}
return str;
},
isHidden: function (el) {
const style = window.getComputedStyle(el);
return (style.display === 'none')
},
str2bool: function (value) {
const str = String(value);
switch (str.toLowerCase()) {
case 'false':
case 'no':
case 'n':
case '':
case 'null':
case 'undefined':
return false;
default:
return true;
}
},
exists: function (element) {
return (typeof (element) != 'undefined' && element != null);
},
throwException: function (message) {
let err;
try {
throw new Error('wz.error');
} catch (e) {
err = e;
}
if (!err) return;
let aux = err.stack.split("\n");
aux.splice(0, 2); //removing the line that we force to generate the error (var err = new Error();) from the message
aux = aux.join('\n"');
throw message + ' \n' + aux;
},
closetNubmer: function (length, step) {
let counts = [];
for (let index = 0; index <= length; index++) {
counts.push(index)
}
let closet = counts.reduce(function (prev, curr) {
return (Math.abs(curr - step) < Math.abs(prev - step) ? curr : prev);
});
return closet;
},
highlight: function (e, highlight_class, highlight_type, highlight_time) {
let target = highlight_class.replace(".", "");
let classHigh = `${target}-${highlight_type}`;
e.classList.add(classHigh)
setTimeout(function () {
document.querySelectorAll(`[class*="${target}"]`)
.forEach((el) => {
for (let i = el.classList.length - 1; i >= 0; i--) {
let className = el.classList[i];
if (className.startsWith(`${target}`)) {
el.classList.remove(className);
}
}
});
}, highlight_time);
},
dispatchInput: function (wz_content, e) {
let type = e.getAttribute("type");
let check = false;
switch (type) {
case "email":
check = $_.isEmail(e.value);
break;
case "url":
check = $_.isValidURL(e.value);
break;
case "checkbox":
let name = e.getAttribute("name");
if (name.includes("[]")) {
checkbox_check = wz_content.querySelectorAll(`input[type="checkbox"][name="${e.getAttribute("name")}"]:checked`);
check = (checkbox_check.length > 0);
} else {
check = e.checked;
}
break;
case "radio":
let radio_check = wz_content.querySelectorAll(`input[type="radio"][name="${e.getAttribute("name")}"]:checked`);
check = (radio_check.length > 0);
break;
default:
check = $_.isEmpty(e.value);
break;
}
return check
},
isEmpty: function (val) {
val = val.trim();
return (val != undefined && val != null && val.length > 0);
},
isEmail: function (email) {
const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return regex.test(email);
},
isValidURL: function (str) {
let url;
try {
url = new URL(str);
} catch (_) {
return false;
}
return url.protocol === "http:" || url.protocol === "https:";
},
cleanEvents: function (el, withChildren = false) {
if ($_.exists(el)) {
if (withChildren) {
el.parentNode.replaceChild(el.cloneNode(true), el);
} else {
const newEl = el.cloneNode(false);
while (el.hasChildNodes()) newEl.appendChild(el.firstChild);
el.parentNode.replaceChild(newEl, el);
}
}
}
}