PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.83
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Woo_Checkout_Steps / script.js

script.js in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.83, at includes/widgets/Woo_Checkout_Steps/script.js

146 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Woo Checkout Steps widget behavior.
3 *
4 * Initializes step navigation and hides/shows checkout sections.
5 */
6 (function ($) {
7 "use strict";
8
9 const INIT_FLAG = "kaCheckoutStepsInit";
10
11 const scrollToEl = (el) => {
12 if (!el) return;
13 const rect = el.getBoundingClientRect();
14 const offset = window.pageYOffset + rect.top - 80;
15 window.scrollTo({ top: offset, behavior: 'smooth' });
16 };
17
18 const hideTargets = (allTargets, activeTarget) => {
19 allTargets.forEach((el) => {
20 if (!el) return;
21 if (el === activeTarget) {
22 el.classList.remove('ka-woo-checkout-step-hidden');
23 } else {
24 el.classList.add('ka-woo-checkout-step-hidden');
25 }
26 });
27 };
28
29 const validateStep = (target) => {
30 if (!target) return true;
31 const fields = target.querySelectorAll('input[required], select[required], textarea[required]');
32 let valid = true;
33 fields.forEach((field) => {
34 const value = field.value?.trim();
35 if (!value) {
36 valid = false;
37 field.classList.add('ka-woo-checkout-step-error');
38 } else {
39 field.classList.remove('ka-woo-checkout-step-error');
40 }
41 });
42 return valid;
43 };
44
45 const initSteps = (wrapper) => {
46 if (!wrapper || !wrapper.dataset) return;
47 if (wrapper.dataset[INIT_FLAG] === "1") return;
48 wrapper.dataset[INIT_FLAG] = "1";
49
50 const stepsList = wrapper.querySelector('.ka-woo-checkout-steps');
51 const steps = [...wrapper.querySelectorAll('.ka-woo-checkout-step')];
52 if (!steps.length || !stepsList) return;
53
54 const enableNav = wrapper.dataset.enableNav === 'true';
55 const autoScroll = wrapper.dataset.autoScroll === 'yes';
56 const scrollTop = stepsList.dataset.scrollTop === 'yes';
57 const prevText = stepsList.dataset.prevText || 'Previous';
58 const nextText = stepsList.dataset.nextText || 'Next';
59
60 const navPrev = wrapper.querySelector('.ka-woo-checkout-steps__prev');
61 const navNext = wrapper.querySelector('.ka-woo-checkout-steps__next');
62
63 const targets = steps.map((step) => {
64 const sel = step.dataset.target;
65 if (!sel) return null;
66 return document.querySelector(sel);
67 });
68
69 let current = 0;
70
71 const setActive = (index, fromNav = false) => {
72 if (index < 0 || index >= steps.length) return;
73 if (fromNav) {
74 // validate current before moving forward
75 if (index > current && !validateStep(targets[current])) {
76 return;
77 }
78 }
79 current = index;
80 steps.forEach((step, i) => {
81 step.classList.toggle('is-active', i === current);
82 step.classList.toggle('is-complete', i < current);
83 });
84 hideTargets(targets.filter(Boolean), targets[current] || null);
85 if (scrollTop && autoScroll && targets[current]) {
86 scrollToEl(targets[current]);
87 } else if (autoScroll) {
88 scrollToEl(wrapper);
89 }
90 if (enableNav) {
91 if (navPrev) navPrev.disabled = current === 0;
92 if (navNext) navNext.textContent = current === steps.length - 1 ? nextText : nextText;
93 }
94 };
95
96 steps.forEach((step, i) => {
97 step.addEventListener('click', () => setActive(i, true));
98 });
99
100 if (enableNav && navPrev && navNext) {
101 navPrev.addEventListener('click', () => setActive(current - 1, true));
102 navNext.addEventListener('click', () => setActive(current + 1, true));
103 }
104
105 // Init
106 hideTargets(targets.filter(Boolean), targets[0] || null);
107 setActive(0);
108 };
109
110 const initAll = () => {
111 document.querySelectorAll('.ka-woo-checkout-steps-wrapper').forEach(initSteps);
112 };
113
114 const initInScope = ($scope) => {
115 const root = $scope && $scope[0] ? $scope[0] : document;
116 root.querySelectorAll('.ka-woo-checkout-steps-wrapper').forEach(initSteps);
117 };
118
119 document.addEventListener("DOMContentLoaded", initAll);
120
121 // WooCommerce checkout fragments updates can re-render parts of checkout.
122 $(document.body).on("updated_checkout", function () {
123 // Allow re-init after WooCommerce updates.
124 document.querySelectorAll(".ka-woo-checkout-steps-wrapper").forEach((wrap) => {
125 if (wrap && wrap.dataset) {
126 delete wrap.dataset[INIT_FLAG];
127 }
128 });
129 initAll();
130 });
131
132 $(window).on("elementor/frontend/init", function () {
133 elementorFrontend.hooks.addAction(
134 "frontend/element_ready/woo_checkout_steps.default",
135 function ($scope) {
136 initInScope($scope);
137 }
138 );
139 });
140 })(jQuery);
141
142
143
144
145
146