/* * Document : helpers.js * Author : pixelcave * Description: Various helpers for plugin inits or helper functionality * */ // Helper variables let jqSparklineResize = false; let jqSparklineTimeout; // Helpers export default class Helpers { /* * Run helpers * */ static run(helpers, options = {}) { let helperList = { // Bootstrap "bs-tooltip": () => this.bsTooltip(), "bs-popover": () => this.bsPopover(), // Dashmix "dm-toggle-class": () => this.dmToggleClass(), "dm-year-copy": () => this.dmYearCopy(), "dm-ripple": () => this.dmRipple(), "dm-print": () => this.dmPrint(), "dm-table-tools-sections": () => this.dmTableToolsSections(), "dm-table-tools-checkable": () => this.dmTableToolsCheckable(), // JavaScript "js-ckeditor5": () => this.jsCkeditor5(), "js-simplemde": () => this.jsSimpleMDE(), "js-highlightjs": () => this.jsHighlightjs(), "js-flatpickr": () => this.jsFlatpickr(), // jQuery "jq-appear": () => this.jqAppear(), "jq-magnific-popup": () => this.jqMagnific(), "jq-slick": () => this.jqSlick(), "jq-datepicker": () => this.jqDatepicker(), "jq-masked-inputs": () => this.jqMaskedInputs(), "jq-select2": () => this.jqSelect2(), "jq-notify": (options) => this.jqNotify(options), "jq-easy-pie-chart": () => this.jqEasyPieChart(), "jq-maxlength": () => this.jqMaxlength(), "jq-rangeslider": () => this.jqRangeslider(), "jq-pw-strength": () => this.jqPwStrength(), "jq-sparkline": () => this.jqSparkline(), "jq-validation": () => this.jqValidation(), }; if (helpers instanceof Array) { for (let index in helpers) { if (helperList[helpers[index]]) { helperList[helpers[index]](options); } } } else { if (helperList[helpers]) { helperList[helpers](options); } } } /* ******************************************************************************************** * * Init helpers for Bootstrap plugins * ********************************************************************************************* */ /* * Bootstrap Tooltip, for more examples you can check out https://getbootstrap.com/docs/5.3/components/tooltips/ * * Helpers.run('bs-tooltip'); * * Example usage: * * or * * */ static bsTooltip() { let elements = [].slice.call( document.querySelectorAll( '[data-bs-toggle="tooltip"]:not(.js-bs-tooltip-enabled), .js-bs-tooltip:not(.js-bs-tooltip-enabled)' ) ); window.helperBsTooltips = elements.map((el) => { // Add .js-bs-tooltip-enabled class to tag it as activated el.classList.add("js-bs-tooltip-enabled"); // Init Bootstrap Tooltip return new bootstrap.Tooltip(el, { container: el.dataset.bsContainer || "#page-container", animation: el.dataset.bsAnimation && el.dataset.bsAnimation.toLowerCase() == "true" ? true : false, }); }); } /* * Bootstrap Popover, for more examples you can check out https://getbootstrap.com/docs/5.3/components/popovers/ * * Helpers.run('bs-popover'); * * Example usage: * * or * * */ static bsPopover() { let elements = [].slice.call( document.querySelectorAll( '[data-bs-toggle="popover"]:not(.js-bs-popover-enabled), .js-bs-popover:not(.js-bs-popover-enabled)' ) ); window.helperBsPopovers = elements.map((el) => { // Add .js-bs-popover-enabled class to tag it as activated el.classList.add("js-bs-popover-enabled"); // Init Bootstrap Popover return new bootstrap.Popover(el, { container: el.dataset.bsContainer || "#page-container", animation: el.dataset.bsAnimation && el.dataset.bsAnimation.toLowerCase() == "true" ? true : false, trigger: el.dataset.bsTrigger || "hover focus", }); }); } /* ******************************************************************************************** * * JS helpers to add custom functionality * ********************************************************************************************* */ /* * Toggle class on element click * * Helpers.run('dm-toggle-class'); * * Example usage (on button click, "exampleClass" class is toggled on the element with id "elementID"): * * * * or * * * */ static dmToggleClass() { let elements = document.querySelectorAll( '[data-toggle="class-toggle"]:not(.js-class-toggle-enabled), .js-class-toggle:not(.js-class-toggle-enabled)' ); elements.forEach((el) => { el.addEventListener("click", () => { // Add .js-class-toggle-enabled class to tag it as activated el.classList.add("js-class-toggle-enabled"); // Get all classes let cssClasses = el.dataset.class ? el.dataset.class.split(" ") : false; // Toggle class on target elements document.querySelectorAll(el.dataset.target).forEach((targetEl) => { if (cssClasses) { cssClasses.forEach((cls) => { targetEl.classList.toggle(cls); }); } }); }); }); } /* * Add the correct copyright year to an element * * Helpers.run('dm-year-copy'); * * Example usage (it will get populated with current year if empty or will append it to specified year if needed): * * or * 2018 * */ static dmYearCopy() { let elements = document.querySelectorAll( '[data-toggle="year-copy"]:not(.js-year-copy-enabled)' ); elements.forEach((el) => { let date = new Date(); let currentYear = date.getFullYear(); let baseYear = el.textContent || currentYear; // Add .js-year-copy-enabled class to tag it as activated el.classList.add("js-year-copy-enabled"); // Set the correct year el.textContent = parseInt(baseYear) >= currentYear ? currentYear : baseYear + "-" + currentYear.toString().substr(2, 2); }); } /* * Ripple effect fuctionality * * Helpers.run('dm-ripple'); * * Example usage: * * * */ static dmRipple() { let elements = document.querySelectorAll( '[data-toggle="click-ripple"]:not(.js-click-ripple-enabled)' ); elements.forEach((el) => { // Add .js-click-ripple-enabled class to tag it as activated and init it el.classList.add("js-click-ripple-enabled"); // Add custom CSS styles el.style.overflow = "hidden"; el.style.position = "relative"; el.style.zIndex = 1; // On click create and render the ripple el.addEventListener("click", (e) => { let cssClass = "click-ripple"; let ripple = el.querySelector("." + cssClass); let d, x, y; // If the ripple element exists in this element, remove .animate class from ripple element.. if (ripple) { ripple.classList.remove("animate"); } else { // ..else add it let elChild = document.createElement("span"); elChild.classList.add(cssClass); el.insertBefore(elChild, el.firstChild); } // Get the ripple element ripple = el.querySelector("." + cssClass); // If the ripple element doesn't have dimensions, set them accordingly if ( getComputedStyle(ripple).height === "0px" || getComputedStyle(ripple).width === "0px" ) { d = Math.max(el.offsetWidth, el.offsetHeight); ripple.style.height = d + "px"; ripple.style.width = d + "px"; } // Get coordinates for our ripple element x = e.pageX - (el.getBoundingClientRect().left + window.scrollX) - parseFloat(getComputedStyle(ripple).width.replace("px", "")) / 2; y = e.pageY - (el.getBoundingClientRect().top + window.scrollY) - parseFloat(getComputedStyle(ripple).height.replace("px", "")) / 2; // Position the ripple element and add the class .animate to it ripple.style.top = y + "px"; ripple.style.left = x + "px"; ripple.classList.add("animate"); }); }); } /* * Print Page functionality * * Helpers.run('dm-print'); * */ static dmPrint() { // Store all #page-container classes let lPage = document.getElementById("page-container"); let pageCls = lPage.className; console.log(pageCls); // Remove all classes from #page-container lPage.classList = ""; // Print the page window.print(); // Restore all #page-container classes lPage.classList = pageCls; } /* * Table sections functionality * * Helpers.run('dm-table-tools-sections'); * * Example usage: * * Please check out the Table Helpers page for complete markup examples * */ static dmTableToolsSections() { let tables = document.querySelectorAll( ".js-table-sections:not(.js-table-sections-enabled)" ); tables.forEach((table) => { // Add .js-table-sections-enabled class to tag it as activated table.classList.add("js-table-sections-enabled"); // When a row is clicked in tbody.js-table-sections-header table.querySelectorAll(".js-table-sections-header > tr").forEach((tr) => { tr.addEventListener("click", (e) => { if ( e.target.type !== "checkbox" && e.target.type !== "button" && e.target.tagName.toLowerCase() !== "a" && e.target.parentNode.nodeName.toLowerCase() !== "a" && e.target.parentNode.nodeName.toLowerCase() !== "button" && e.target.parentNode.nodeName.toLowerCase() !== "label" && !e.target.parentNode.classList.contains("custom-control") ) { let tbody = tr.parentNode; let tbodyAll = table.querySelectorAll("tbody"); if (!tbody.classList.contains("show")) { if (tbodyAll) { tbodyAll.forEach((tbodyEl) => { tbodyEl.classList.remove("show"); tbodyEl.classList.remove("table-active"); }); } } tbody.classList.toggle("show"); tbody.classList.toggle("table-active"); } }); }); }); } /* * Checkable table functionality * * Helpers.run('dm-table-tools-checkable'); * * Example usage: * * Please check out the Table Helpers page for complete markup examples * */ static dmTableToolsCheckable() { let tables = document.querySelectorAll( ".js-table-checkable:not(.js-table-checkable-enabled)" ); tables.forEach((table) => { // Add .js-table-checkable-enabled class to tag it as activated table.classList.add("js-table-checkable-enabled"); // When a checkbox is clicked in thead table .querySelector("thead input[type=checkbox]") .addEventListener("click", (e) => { // Check or uncheck all checkboxes in tbody table .querySelectorAll("tbody input[type=checkbox]") .forEach((checkbox) => { checkbox.checked = e.currentTarget.checked; // Update Row classes this.tableToolscheckRow(checkbox, e.currentTarget.checked); }); }); // When a checkbox is clicked in tbody table .querySelectorAll("tbody input[type=checkbox], tbody input + label") .forEach((checkbox) => { checkbox.addEventListener("click", (e) => { let checkboxHead = table.querySelector( "thead input[type=checkbox]" ); // Adjust checkbox in thead if (!checkbox.checked) { checkboxHead.checked = false; } else { if ( table.querySelectorAll("tbody input[type=checkbox]:checked") .length === table.querySelectorAll("tbody input[type=checkbox]").length ) { checkboxHead.checked = true; } } // Update Row classes this.tableToolscheckRow(checkbox, checkbox.checked); }); }); // When a row is clicked in tbody table.querySelectorAll("tbody > tr").forEach((tr) => { tr.addEventListener("click", (e) => { if ( e.target.type !== "checkbox" && e.target.type !== "button" && e.target.tagName.toLowerCase() !== "a" && e.target.parentNode.nodeName.toLowerCase() !== "a" && e.target.parentNode.nodeName.toLowerCase() !== "button" && e.target.parentNode.nodeName.toLowerCase() !== "label" && !e.target.parentNode.classList.contains("custom-control") ) { let checkboxHead = table.querySelector( "thead input[type=checkbox]" ); let checkbox = e.currentTarget.querySelector( "input[type=checkbox]" ); // Update row's checkbox status checkbox.checked = !checkbox.checked; // Update Row classes this.tableToolscheckRow(checkbox, checkbox.checked); // Adjust checkbox in thead if (!checkbox.checked) { checkboxHead.checked = false; } else { if ( table.querySelectorAll("tbody input[type=checkbox]:checked") .length === table.querySelectorAll("tbody input[type=checkbox]").length ) { checkboxHead.checked = true; } } } }); }); }); } // Checkable table functionality helper - Checks or unchecks table row static tableToolscheckRow(checkbox, checkedStatus) { if (checkedStatus) { checkbox.closest("tr").classList.add("table-active"); } else { checkbox.closest("tr").classList.remove("table-active"); } } /* ******************************************************************************************** * * Init helpers for pure JS libraries * ******************************************************************************************** */ /* * CKEditor 5 init, for more examples you can check out http://ckeditor.com/ * * Helpers.run('js-ckeditor5'); * * Example usage: * *
Hello classic CKEditor 5!
* ..or.. *
Hello inline CKEditor 5!
* */ static jsCkeditor5() { let ckeditor5Inline = document.querySelector("#js-ckeditor5-inline"); let ckeditor5Full = document.querySelector("#js-ckeditor5-classic"); // Init inline text editor if (ckeditor5Inline) { InlineEditor.create(document.querySelector("#js-ckeditor5-inline")) .then((editor) => { window.editor = editor; }) .catch((error) => { console.error( "There was a problem initializing the inline editor.", error ); }); } // Init full text editor if (ckeditor5Full) { ClassicEditor.create(document.querySelector("#js-ckeditor5-classic")) .then((editor) => { window.editor = editor; }) .catch((error) => { console.error( "There was a problem initializing the classic editor.", error ); }); } } /* * SimpleMDE init, for more examples you can check out https://github.com/NextStepWebs/simplemde-markdown-editor * * Helpers.run('js-simplemde'); * * Example usage: * * * */ static jsSimpleMDE() { let elements = document.querySelectorAll(".js-simplemde"); elements.forEach((el) => { // Init editor new SimpleMDE({ element: el, autoDownloadFontAwesome: false }); }); // Fix: Change SimpleMDE's Font Awesome 4 Icons with Font Awesome 6 if (elements) { document .querySelector(".editor-toolbar > a.fa-header") .classList.replace("fa-header", "fa-heading"); document .querySelector(".editor-toolbar > a.fa-picture-o") .classList.replace("fa-picture-o", "fa-image"); } } /* * Highlight.js, for more examples you can check out https://highlightjs.org/usage/ * * Helpers.run('js-highlightjs'); * * Example usage: * * Please check out the Syntax Highlighting page in Components for complete markup examples * */ static jsHighlightjs() { // Init Highlight.js if (!hljs.isHighlighted) { hljs.initHighlighting(); } } /* * Flatpickr init, for more examples you can check out https://github.com/flatpickr/flatpickr * * Helpers.run('js-flatpickr'); * * Example usage: * * * */ static jsFlatpickr() { let elements = document.querySelectorAll( ".js-flatpickr:not(.js-flatpickr-enabled)" ); elements.forEach((el) => { // Add .js-flatpickr-enabled class to tag it as activated el.classList.add("js-flatpickr-enabled"); // Init it flatpickr(el); }); } /* ******************************************************************************************** * * Init helpers for jQuery plugins * ******************************************************************************************** */ /* * jQuery Appear, for more examples you can check out https://github.com/bas2k/jquery.appear * * Helpers.run('jq-appear'); * * Example usage (the following div will appear on scrolling, remember to add the invisible class): * * * */ static jqAppear() { // Add a specific class on elements (when they become visible on scrolling) jQuery('[data-toggle="appear"]:not(.js-appear-enabled)').each( (index, element) => { let windowW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; let el = jQuery(element); let elCssClass = el.data("class") || "animated fadeIn"; let elOffset = el.data("offset") || 0; let elTimeout = windowW < 992 ? 0 : el.data("timeout") ? el.data("timeout") : 0; // Add .js-appear-enabled class to tag it as activated and init it el.addClass("js-appear-enabled").appear( () => { setTimeout(() => { el.removeClass("invisible").addClass(elCssClass); }, elTimeout); }, { accY: elOffset } ); } ); } /* * Magnific Popup functionality, for more examples you can check out http://dimsemenov.com/plugins/magnific-popup/ * * Helpers.run('jq-magnific-popup'); * * Example usage: * * Please check out the Gallery page in Components for complete markup examples * */ static jqMagnific() { // Gallery init jQuery(".js-gallery:not(.js-gallery-enabled)").each((index, element) => { // Add .js-gallery-enabled class to tag it as activated and init it jQuery(element) .addClass("js-gallery-enabled") .magnificPopup({ delegate: "a.img-lightbox", type: "image", gallery: { enabled: true, }, }); }); } /* * Slick init, for more examples you can check out http://kenwheeler.github.io/slick/ * * Helpers.run('jq-slick'); * * Example usage: * *
*
Slide #1
*
Slide #2
*
Slide #3
*
* */ static jqSlick() { // Get each slider element (with .js-slider class) jQuery(".js-slider:not(.js-slider-enabled)").each((index, element) => { let el = jQuery(element); // Add .js-slider-enabled class to tag it as activated and init it el.addClass("js-slider-enabled").slick({ arrows: el.data("arrows") || false, dots: el.data("dots") || false, slidesToShow: el.data("slides-to-show") || 1, centerMode: el.data("center-mode") || false, autoplay: el.data("autoplay") || false, autoplaySpeed: el.data("autoplay-speed") || 3000, infinite: typeof el.data("infinite") === "undefined" ? true : el.data("infinite"), }); }); } /* * Bootstrap Datepicker init, for more examples you can check out https://github.com/eternicode/bootstrap-datepicker * * Helpers.run('jq-datepicker'); * * Example usage: * * * */ static jqDatepicker() { // Init datepicker (with .js-datepicker and .input-daterange class) jQuery(".js-datepicker:not(.js-datepicker-enabled)") .add(".input-daterange:not(.js-datepicker-enabled)") .each((index, element) => { let el = jQuery(element); // Add .js-datepicker-enabled class to tag it as activated and init it el.addClass("js-datepicker-enabled").datepicker({ weekStart: el.data("week-start") || 0, autoclose: el.data("autoclose") || false, todayHighlight: el.data("today-highlight") || false, startDate: el.data("start-date") || false, container: el.data("container") || "#page-container", orientation: "bottom", // Position issue when using BS5, set it to bottom until officially supported }); }); } /* * Masked Inputs, for more examples you can check out https://github.com/digitalBush/jquery.maskedinput * * Helpers.run('jq-masked-inputs'); * * Example usage: * * Please check out the Form plugins page for complete markup examples * */ static jqMaskedInputs() { // Init Masked Inputs // a - Represents an alpha character (A-Z,a-z) // 9 - Represents a numeric character (0-9) // * - Represents an alphanumeric character (A-Z,a-z,0-9) jQuery(".js-masked-date:not(.js-masked-enabled)").mask("99/99/9999"); jQuery(".js-masked-date-dash:not(.js-masked-enabled)").mask("99-99-9999"); jQuery(".js-masked-phone:not(.js-masked-enabled)").mask("(999) 999-9999"); jQuery(".js-masked-phone-ext:not(.js-masked-enabled)").mask( "(999) 999-9999? x99999" ); jQuery(".js-masked-taxid:not(.js-masked-enabled)").mask("99-9999999"); jQuery(".js-masked-ssn:not(.js-masked-enabled)").mask("999-99-9999"); jQuery(".js-masked-pkey:not(.js-masked-enabled)").mask("a*-999-a999"); jQuery(".js-masked-time:not(.js-masked-enabled)").mask("99:99"); jQuery(".js-masked-date") .add(".js-masked-date-dash") .add(".js-masked-phone") .add(".js-masked-phone-ext") .add(".js-masked-taxid") .add(".js-masked-ssn") .add(".js-masked-pkey") .add(".js-masked-time") .addClass("js-masked-enabled"); } /* * Select2, for more examples you can check out https://github.com/select2/select2 * * Helpers.run('jq-select2'); * * Example usage: * * * */ static jqSelect2() { // Init Select2 (with .js-select2 class) jQuery(".js-select2:not(.js-select2-enabled)").each((index, element) => { let el = jQuery(element); // Add .js-select2-enabled class to tag it as activated and init it el.addClass("js-select2-enabled").select2({ placeholder: el.data("placeholder") || false, dropdownParent: document.querySelector( el.data("container") || "#page-container" ), }); }); } /* * Bootstrap Notify, for more examples you can check out http://bootstrap-growl.remabledesigns.com/ * * Helpers.run('jq-notify'); * * Example usage: * * Please check out the Notifications page for examples * */ static jqNotify(options = {}) { if (jQuery.isEmptyObject(options)) { // Init notifications (with .js-notify class) jQuery(".js-notify:not(.js-notify-enabled)").each((index, element) => { // Add .js-notify-enabled class to tag it as activated and init it jQuery(element) .addClass("js-notify-enabled") .on("click.pixelcave.helpers", (e) => { let el = jQuery(e.currentTarget); // Create notification jQuery.notify( { icon: el.data("icon") || "", message: el.data("message"), url: el.data("url") || "", }, { element: "body", type: el.data("type") || "info", placement: { from: el.data("from") || "top", align: el.data("align") || "right", }, allow_dismiss: true, newest_on_top: true, showProgressbar: false, offset: 20, spacing: 10, z_index: 1033, delay: 5000, timer: 1000, animate: { enter: "animated fadeIn", exit: "animated fadeOutDown", }, template: ``, } ); }); }); } else { // Create notification jQuery.notify( { icon: options.icon || "", message: options.message, url: options.url || "", }, { element: options.element || "body", type: options.type || "info", placement: { from: options.from || "top", align: options.align || "right", }, allow_dismiss: options.allow_dismiss === false ? false : true, newest_on_top: options.newest_on_top === false ? false : true, showProgressbar: options.show_progress_bar ? true : false, offset: options.offset || 20, spacing: options.spacing || 10, z_index: options.z_index || 1033, delay: options.delay || 5000, timer: options.timer || 1000, animate: { enter: options.animate_enter || "animated fadeIn", exit: options.animate_exit || "animated fadeOutDown", }, template: ``, } ); } } /* * Easy Pie Chart, for more examples you can check out http://rendro.github.io/easy-pie-chart/ * * Helpers.run('jq-easy-pie-chart'); * * Example usage: * *
* ..Content.. *
* */ static jqEasyPieChart() { // Init Easy Pie Charts (with .js-pie-chart class) jQuery(".js-pie-chart:not(.js-pie-chart-enabled)").each( (index, element) => { let el = jQuery(element); // Add .js-pie-chart-enabled class to tag it as activated and init it el.addClass("js-pie-chart-enabled").easyPieChart({ barColor: el.data("bar-color") || "#777777", trackColor: el.data("track-color") || "#eeeeee", lineWidth: el.data("line-width") || 3, size: el.data("size") || "80", animate: el.data("animate") || 750, scaleColor: el.data("scale-color") || false, }); } ); } /* * Bootstrap Maxlength, for more examples you can check out https://github.com/mimo84/bootstrap-maxlength * * Helpers.run('jq-maxlength'); * * Example usage: * * * */ static jqMaxlength() { // Init Bootstrap Maxlength (with .js-maxlength class) jQuery(".js-maxlength:not(.js-maxlength-enabled)").each( (index, element) => { let el = jQuery(element); // Add .js-maxlength-enabled class to tag it as activated and init it el.addClass("js-maxlength-enabled").maxlength({ alwaysShow: el.data("always-show") ? true : false, threshold: el.data("threshold") || 10, warningClass: el.data("warning-class") || "badge bg-warning", limitReachedClass: el.data("limit-reached-class") || "badge bg-danger", placement: el.data("placement") || "bottom", preText: el.data("pre-text") || "", separator: el.data("separator") || "/", postText: el.data("post-text") || "", }); } ); } /* * Ion Range Slider, for more examples you can check out https://github.com/IonDen/ion.rangeSlider * * Helpers.run('jq-rangeslider'); * * Example usage: * * * */ static jqRangeslider() { // Init Ion Range Slider (with .js-rangeslider class) jQuery(".js-rangeslider:not(.js-rangeslider-enabled)").each( (index, element) => { let el = jQuery(element); // Add .js-rangeslider-enabled class to tag it as activated and init it jQuery(element) .addClass("js-rangeslider-enabled") .ionRangeSlider({ input_values_separator: ";", skin: el.data("skin") || "round", }); } ); } /* * Password Strength Meter, for more examples you can check out https://github.com/ablanco/jquery.pwstrength.bootstrap * * Helpers.run('jq-pw-strength'); * * Example usage: * *
* * *
*

*
* */ static jqPwStrength() { // Init Password Strength Meter (with .js-pw-strength class) jQuery(".js-pw-strength:not(.js-pw-strength-enabled)").each( (index, element) => { let el = jQuery(element); let container = el.parents(".js-pw-strength-container"); let progress = jQuery(".js-pw-strength-progress", container); let verdict = jQuery(".js-pw-strength-feedback", container); // Add .js-pw-strength-enabled class to tag it as activated and init it el.addClass("js-pw-strength-enabled").pwstrength({ ui: { container: container, viewports: { progress: progress, verdict: verdict, }, }, }); } ); } /* * jQuery Sparkline Charts, for more examples you can check out http://omnipotent.net/jquery.sparkline/#s-docs * * Helpers.run('jq-sparkline'); * * Example usage: * * * */ static jqSparkline() { let self = this; // Init jQuery Sparkline Charts (with .js-sparkline class) jQuery(".js-sparkline:not(.js-sparkline-enabled)").each( (index, element) => { let el = jQuery(element); let type = el.data("type"); let options = {}; // Sparkline types let types = { line: () => { options["type"] = type; options["lineWidth"] = el.data("line-width") || 2; options["lineColor"] = el.data("line-color") || "#0665d0"; options["fillColor"] = el.data("fill-color") || "#0665d0"; options["spotColor"] = el.data("spot-color") || "#495057"; options["minSpotColor"] = el.data("min-spot-color") || "#495057"; options["maxSpotColor"] = el.data("max-spot-color") || "#495057"; options["highlightSpotColor"] = el.data("highlight-spot-color") || "#495057"; options["highlightLineColor"] = el.data("highlight-line-color") || "#495057"; options["spotRadius"] = el.data("spot-radius") || 2; options["tooltipFormat"] = "{{prefix}}{{y}}{{suffix}}"; }, bar: () => { options["type"] = type; options["barWidth"] = el.data("bar-width") || 8; options["barSpacing"] = el.data("bar-spacing") || 6; options["barColor"] = el.data("bar-color") || "#0665d0"; options["tooltipFormat"] = "{{prefix}}{{value}}{{suffix}}"; }, pie: () => { options["type"] = type; options["sliceColors"] = [ "#fadb7d", "#faad7d", "#75b0eb", "#abe37d", ]; options["highlightLighten"] = el.data("highlight-lighten") || 1.1; options["tooltipFormat"] = "{{prefix}}{{value}}{{suffix}}"; }, tristate: () => { options["type"] = type; options["barWidth"] = el.data("bar-width") || 8; options["barSpacing"] = el.data("bar-spacing") || 6; options["posBarColor"] = el.data("pos-bar-color") || "#82b54b"; options["negBarColor"] = el.data("neg-bar-color") || "#e04f1a"; }, }; // If the correct type is set init the chart if (types[type]) { types[type](); // Extra options added only if specified if (type === "line") { if (el.data("chart-range-min") >= 0 || el.data("chart-range-min")) { options["chartRangeMin"] = el.data("chart-range-min"); } if (el.data("chart-range-max") >= 0 || el.data("chart-range-max")) { options["chartRangeMax"] = el.data("chart-range-max"); } } // Add common options used in all types options["width"] = el.data("width") || "120px"; options["height"] = el.data("height") || "80px"; options["tooltipPrefix"] = el.data("tooltip-prefix") ? el.data("tooltip-prefix") + " " : ""; options["tooltipSuffix"] = el.data("tooltip-suffix") ? " " + el.data("tooltip-suffix") : ""; // If we need a responsive width for the chart, then don't add .js-sparkline-enabled class and re-run the helper on window resize if (options["width"] === "100%") { if (!jqSparklineResize) { // Make sure that we bind the event only once jqSparklineResize = true; // On window resize, re-run the Sparkline helper jQuery(window).on( "resize.pixelcave.helpers.sparkline", function (e) { clearTimeout(jqSparklineTimeout); jqSparklineTimeout = setTimeout(() => { self.sparkline(); }, 500); } ); } } else { // It has a specific width (it doesn't need to re-init again on resize), so add .js-sparkline-enabled class to tag it as activated jQuery(element).addClass("js-sparkline-enabled"); } // Finally init it jQuery(element).sparkline(el.data("points") || [0], options); } else { console.log( "[jQuery Sparkline JS Helper] Please add a correct type (line, bar, pie or tristate) in all your elements with 'js-sparkline' class." ); } } ); } /* * jQuery Validation, for more examples you can check out https://github.com/jzaefferer/jquery-validation * * Helpers.run('jq-validation'); * * Example usage: * * By calling the helper, you set up the default options that will be used for jQuery Validation * */ static jqValidation() { // Set default options for jQuery Validation plugin jQuery.validator.setDefaults({ errorClass: "invalid-feedback animated fadeIn", errorElement: "div", errorPlacement: (error, el) => { jQuery(el).addClass("is-invalid"); jQuery(el).parents("div:not(.input-group)").first().append(error); }, highlight: (el) => { jQuery(el) .parents("div:not(.input-group)") .first() .find(".is-invalid") .removeClass("is-invalid") .addClass("is-invalid"); }, success: (el) => { jQuery(el) .parents("div:not(.input-group)") .first() .find(".is-invalid") .removeClass("is-invalid"); jQuery(el).remove(); }, }); // Add custom email validation rule which requires a dot after @ jQuery.validator.addMethod( "emailWithDot", function (value, element) { let reg = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i; return this.optional(element) || reg.test(value); }, "Please enter a valid email address" ); } }