PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.87
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.87
51.1.87 51.1.86 51.1.84 51.1.85 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 All 41 releases
king-addons / includes / widgets / Woo_Checkout_Steps / script.js

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

151 lines 4.6 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
49 const stepsList = wrapper.querySelector('.ka-woo-checkout-steps');
50 // Pro checkout steps are driven by Woo_Builder/script.js. Binding both
51 // handlers made Next skip a step and mixed panel labels.
52 if (stepsList && stepsList.classList.contains('ka-woo-checkout-steps--pro')) {
53 return;
54 }
55 wrapper.dataset[INIT_FLAG] = "1";
56 const steps = [...wrapper.querySelectorAll('.ka-woo-checkout-step')];
57 if (!steps.length || !stepsList) return;
58
59 const enableNav = wrapper.dataset.enableNav === 'true';
60 const autoScroll = wrapper.dataset.autoScroll === 'yes';
61 const scrollTop = stepsList.dataset.scrollTop === 'yes';
62 const prevText = stepsList.dataset.prevText || 'Previous';
63 const nextText = stepsList.dataset.nextText || 'Next';
64
65 const navPrev = wrapper.querySelector('.ka-woo-checkout-steps__prev');
66 const navNext = wrapper.querySelector('.ka-woo-checkout-steps__next');
67
68 const targets = steps.map((step) => {
69 const sel = step.dataset.target;
70 if (!sel) return null;
71 return document.querySelector(sel);
72 });
73
74 let current = 0;
75
76 const setActive = (index, fromNav = false) => {
77 if (index < 0 || index >= steps.length) return;
78 if (fromNav) {
79 // validate current before moving forward
80 if (index > current && !validateStep(targets[current])) {
81 return;
82 }
83 }
84 current = index;
85 steps.forEach((step, i) => {
86 step.classList.toggle('is-active', i === current);
87 step.classList.toggle('is-complete', i < current);
88 });
89 hideTargets(targets.filter(Boolean), targets[current] || null);
90 if (scrollTop && autoScroll && targets[current]) {
91 scrollToEl(targets[current]);
92 } else if (autoScroll) {
93 scrollToEl(wrapper);
94 }
95 if (enableNav) {
96 if (navPrev) navPrev.disabled = current === 0;
97 if (navNext) navNext.textContent = current === steps.length - 1 ? nextText : nextText;
98 }
99 };
100
101 steps.forEach((step, i) => {
102 step.addEventListener('click', () => setActive(i, true));
103 });
104
105 if (enableNav && navPrev && navNext) {
106 navPrev.addEventListener('click', () => setActive(current - 1, true));
107 navNext.addEventListener('click', () => setActive(current + 1, true));
108 }
109
110 // Init
111 hideTargets(targets.filter(Boolean), targets[0] || null);
112 setActive(0);
113 };
114
115 const initAll = () => {
116 document.querySelectorAll('.ka-woo-checkout-steps-wrapper').forEach(initSteps);
117 };
118
119 const initInScope = ($scope) => {
120 const root = $scope && $scope[0] ? $scope[0] : document;
121 root.querySelectorAll('.ka-woo-checkout-steps-wrapper').forEach(initSteps);
122 };
123
124 document.addEventListener("DOMContentLoaded", initAll);
125
126 // WooCommerce checkout fragments updates can re-render parts of checkout.
127 $(document.body).on("updated_checkout", function () {
128 // Allow re-init after WooCommerce updates.
129 document.querySelectorAll(".ka-woo-checkout-steps-wrapper").forEach((wrap) => {
130 if (wrap && wrap.dataset) {
131 delete wrap.dataset[INIT_FLAG];
132 }
133 });
134 initAll();
135 });
136
137 $(window).on("elementor/frontend/init", function () {
138 elementorFrontend.hooks.addAction(
139 "frontend/element_ready/woo_checkout_steps.default",
140 function ($scope) {
141 initInScope($scope);
142 }
143 );
144 });
145 })(jQuery);
146
147
148
149
150
151