PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.49
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.49
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 / Pros_Cons_Box / script.js

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

218 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 "use strict";
2
3 (function ($) {
4 const parseNumber = (value, fallback) => {
5 const number = parseInt(value, 10);
6 return Number.isFinite(number) ? number : fallback;
7 };
8
9 const getStorage = () => {
10 try {
11 return window.localStorage;
12 } catch (error) {
13 return null;
14 }
15 };
16
17 const initCollapse = (wrapper, dataset, isEditMode) => {
18 if (dataset.collapse !== "yes") {
19 return;
20 }
21
22 const collapseMode = dataset.collapseMode || "mobile";
23 const remember = dataset.collapseRemember === "yes";
24 const autoScroll = dataset.collapseScroll === "yes";
25 const widgetId = dataset.widgetId || "";
26 const storage = remember ? getStorage() : null;
27 const mq = window.matchMedia("(max-width: 767px)");
28
29 const shouldCollapse = () => {
30 if (collapseMode === "always") {
31 return true;
32 }
33 if (collapseMode === "mobile") {
34 return mq.matches;
35 }
36 return false;
37 };
38
39 const sections = wrapper.querySelectorAll(".king-addons-pros-cons__section[data-collapsible='yes']");
40
41 const getStorageKey = (sectionName) => {
42 if (!widgetId || !sectionName) {
43 return "";
44 }
45 return `kngProsCons:${widgetId}:${sectionName}`;
46 };
47
48 const applyState = (section, collapsed, animate) => {
49 const list = section.querySelector(".king-addons-pros-cons__list");
50 const toggle = section.querySelector(".king-addons-pros-cons__toggle");
51
52 section.classList.toggle("is-collapsed", collapsed);
53 toggle?.setAttribute("aria-expanded", collapsed ? "false" : "true");
54
55 if (!list) {
56 return;
57 }
58 list.setAttribute("aria-hidden", collapsed ? "true" : "false");
59
60 if (!animate) {
61 list.style.display = collapsed ? "none" : "";
62 return;
63 }
64
65 if (collapsed) {
66 $(list).stop(true, true).slideUp(180);
67 } else {
68 $(list)
69 .stop(true, true)
70 .slideDown(180, () => {
71 list.style.display = "";
72 });
73 }
74 };
75
76 const setInitialState = () => {
77 const collapse = shouldCollapse();
78 sections.forEach((section) => {
79 const name = section.dataset.section || "";
80 let collapsed = collapse;
81
82 if (storage) {
83 const key = getStorageKey(name);
84 if (key) {
85 const stored = storage.getItem(key);
86 if (stored === "collapsed") {
87 collapsed = true;
88 } else if (stored === "expanded") {
89 collapsed = false;
90 }
91 }
92 }
93
94 applyState(section, collapse ? collapsed : false, false);
95 });
96 };
97
98 setInitialState();
99
100 if (collapseMode === "mobile") {
101 if (mq.addEventListener) {
102 mq.addEventListener("change", setInitialState);
103 } else if (mq.addListener) {
104 mq.addListener(setInitialState);
105 }
106 }
107
108 wrapper.addEventListener("click", (event) => {
109 const toggle = event.target.closest(".king-addons-pros-cons__toggle");
110 if (!toggle) {
111 return;
112 }
113
114 const section = toggle.closest(".king-addons-pros-cons__section");
115 if (!section) {
116 return;
117 }
118
119 const isCollapsed = section.classList.contains("is-collapsed");
120 applyState(section, !isCollapsed, true);
121
122 if (storage) {
123 const name = section.dataset.section || "";
124 const key = getStorageKey(name);
125 if (key) {
126 storage.setItem(key, isCollapsed ? "expanded" : "collapsed");
127 }
128 }
129
130 if (isCollapsed && autoScroll && !isEditMode) {
131 section.scrollIntoView({ behavior: "smooth", block: "start" });
132 }
133 });
134 };
135
136 const initTooltips = (wrapper, dataset) => {
137 if (dataset.tooltip !== "yes") {
138 return;
139 }
140
141 const delay = parseNumber(dataset.tooltipDelay, 150);
142 const timers = new WeakMap();
143
144 const showTooltip = (item) => {
145 item.classList.add("is-tooltip-visible");
146 };
147
148 const hideTooltip = (item) => {
149 item.classList.remove("is-tooltip-visible");
150 };
151
152 const scheduleShow = (item) => {
153 const timer = setTimeout(() => showTooltip(item), delay);
154 timers.set(item, timer);
155 };
156
157 const clearTimer = (item) => {
158 const timer = timers.get(item);
159 if (timer) {
160 clearTimeout(timer);
161 timers.delete(item);
162 }
163 };
164
165 wrapper.querySelectorAll(".king-addons-pros-cons__item.has-tooltip").forEach((item) => {
166 item.addEventListener("mouseenter", () => scheduleShow(item));
167 item.addEventListener("mouseleave", () => {
168 clearTimer(item);
169 hideTooltip(item);
170 });
171 });
172
173 wrapper.querySelectorAll(".king-addons-pros-cons__tooltip-trigger").forEach((trigger) => {
174 const item = trigger.closest(".king-addons-pros-cons__item");
175 if (!item) {
176 return;
177 }
178
179 trigger.addEventListener("focus", () => scheduleShow(item));
180 trigger.addEventListener("blur", () => {
181 clearTimer(item);
182 hideTooltip(item);
183 });
184 });
185
186 wrapper.addEventListener("keydown", (event) => {
187 if (event.key !== "Escape") {
188 return;
189 }
190 wrapper.querySelectorAll(".king-addons-pros-cons__item.is-tooltip-visible").forEach((item) => {
191 hideTooltip(item);
192 });
193 });
194 };
195
196 const initProsCons = ($scope) => {
197 const wrapper = $scope[0]?.querySelector(".king-addons-pros-cons");
198 if (!wrapper) {
199 return;
200 }
201
202 const dataset = wrapper.dataset;
203 const isEditMode = elementorFrontend?.isEditMode ? elementorFrontend.isEditMode() : false;
204
205 initCollapse(wrapper, dataset, isEditMode);
206 initTooltips(wrapper, dataset);
207 };
208
209 $(window).on("elementor/frontend/init", function () {
210 elementorFrontend.hooks.addAction(
211 "frontend/element_ready/king-addons-pros-cons-box.default",
212 function ($scope) {
213 initProsCons($scope);
214 }
215 );
216 });
217 })(jQuery);
218