/** * * 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