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 / Comparison_Matrix_Cards / 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/Comparison_Matrix_Cards/script.js

256 lines 8.1 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 debounce = (callback, wait) => {
5 let timeout;
6 return (...args) => {
7 window.clearTimeout(timeout);
8 timeout = window.setTimeout(() => callback(...args), wait);
9 };
10 };
11
12 const normalizeText = (value) => {
13 if (value === undefined || value === null) {
14 return "";
15 }
16 return value.toString().trim().toLowerCase();
17 };
18
19 const getValueKey = (row, compareMode) => {
20 const type = row.dataset.valueType || "";
21 const text = row.dataset.valueText || "";
22 if (type === "text") {
23 return compareMode === "normalized" ? normalizeText(text) : text;
24 }
25 return compareMode === "normalized" ? normalizeText(type) : type;
26 };
27
28 const computeDifferences = (widget) => {
29 const rows = Array.from(
30 widget.querySelectorAll(".king-addons-comparison-matrix-cards__feature")
31 );
32 if (!rows.length) {
33 return;
34 }
35
36 const compareMode = widget.dataset.highlightCompare || "normalized";
37 const groups = new Map();
38
39 rows.forEach((row) => {
40 const id = row.dataset.featureId || "";
41 if (!id) {
42 return;
43 }
44 if (!groups.has(id)) {
45 groups.set(id, []);
46 }
47 groups.get(id).push(row);
48 });
49
50 groups.forEach((groupRows) => {
51 const values = groupRows.map((row) => getValueKey(row, compareMode));
52 const uniqueValues = Array.from(new Set(values));
53 const identical = uniqueValues.length <= 1;
54
55 groupRows.forEach((row) => {
56 row.classList.toggle("is-identical", identical);
57 row.classList.toggle("is-different", !identical);
58 });
59
60 if (!identical) {
61 const counts = values.reduce((acc, value) => {
62 acc[value] = (acc[value] || 0) + 1;
63 return acc;
64 }, {});
65
66 groupRows.forEach((row, index) => {
67 const key = values[index];
68 row.classList.toggle("is-unique", counts[key] === 1);
69 });
70 } else {
71 groupRows.forEach((row) => row.classList.remove("is-unique"));
72 }
73 });
74 };
75
76 const applyHighlightState = (widget, active) => {
77 widget.classList.toggle("is-highlight-active", active);
78
79 const mode = widget.dataset.highlightMode || "dim";
80 const rows = widget.querySelectorAll(".king-addons-comparison-matrix-cards__feature");
81 const hide = mode === "hide" && active;
82
83 rows.forEach((row) => {
84 const shouldHide = hide && row.classList.contains("is-identical");
85 row.classList.toggle("is-highlight-hidden", shouldHide);
86 });
87 };
88
89 const updateGroupVisibility = (widget) => {
90 const cards = widget.querySelectorAll(".king-addons-comparison-matrix-cards__card");
91
92 cards.forEach((card) => {
93 const rows = Array.from(
94 card.querySelectorAll(".king-addons-comparison-matrix-cards__feature")
95 );
96 const visibility = new Map();
97
98 rows.forEach((row) => {
99 const group = row.dataset.featureGroup || "";
100 if (!group) {
101 return;
102 }
103 const hidden =
104 row.classList.contains("is-filter-hidden") ||
105 row.classList.contains("is-highlight-hidden");
106 if (!hidden) {
107 visibility.set(group, true);
108 }
109 });
110
111 const groupHeaders = card.querySelectorAll(
112 ".king-addons-comparison-matrix-cards__feature-group"
113 );
114 groupHeaders.forEach((header) => {
115 const group = header.dataset.featureGroup || "";
116 const isVisible = visibility.get(group) === true;
117 header.classList.toggle("is-hidden", !isVisible);
118 });
119 });
120 };
121
122 const applyFilter = (widget, value) => {
123 const query = normalizeText(value);
124 const includeTooltip = widget.dataset.searchTooltip === "yes";
125 const rows = Array.from(
126 widget.querySelectorAll(".king-addons-comparison-matrix-cards__feature")
127 );
128 const featureMap = new Map();
129
130 rows.forEach((row) => {
131 const id = row.dataset.featureId || "";
132 if (!id || featureMap.has(id)) {
133 return;
134 }
135 featureMap.set(id, {
136 label: row.dataset.featureLabel || "",
137 tooltip: row.dataset.featureTooltip || "",
138 });
139 });
140
141 const visibleIds = new Set();
142 featureMap.forEach((data, id) => {
143 if (!query) {
144 visibleIds.add(id);
145 return;
146 }
147 const label = normalizeText(data.label);
148 const tooltip = normalizeText(data.tooltip);
149 if (label.includes(query) || (includeTooltip && tooltip.includes(query))) {
150 visibleIds.add(id);
151 }
152 });
153
154 rows.forEach((row) => {
155 const id = row.dataset.featureId || "";
156 if (!id) {
157 row.classList.remove("is-filter-hidden");
158 return;
159 }
160 row.classList.toggle("is-filter-hidden", !visibleIds.has(id));
161 });
162
163 updateGroupVisibility(widget);
164 };
165
166 const initScroll = (widget) => {
167 const layout = widget.dataset.mobileLayout || "stack";
168 if (layout !== "scroll") {
169 return;
170 }
171
172 const grid = widget.querySelector(".king-addons-comparison-matrix-cards__grid");
173 if (!grid || grid.hasAttribute("tabindex")) {
174 return;
175 }
176
177 grid.setAttribute("tabindex", "0");
178 };
179
180 const initHighlight = (widget) => {
181 if (widget.dataset.highlightEnable !== "yes") {
182 return;
183 }
184
185 computeDifferences(widget);
186
187 const toggle = widget.querySelector(
188 ".king-addons-comparison-matrix-cards__highlight-input"
189 );
190 const defaultOn = widget.dataset.highlightDefault === "yes";
191
192 if (toggle) {
193 toggle.checked = defaultOn;
194 if (!toggle.dataset.kngBound) {
195 toggle.dataset.kngBound = "yes";
196 toggle.addEventListener("change", () => {
197 applyHighlightState(widget, toggle.checked);
198 updateGroupVisibility(widget);
199 });
200 }
201 }
202
203 applyHighlightState(widget, defaultOn);
204 updateGroupVisibility(widget);
205
206 if (!widget.dataset.kngResizeBound) {
207 widget.dataset.kngResizeBound = "yes";
208 const handleResize = debounce(() => {
209 computeDifferences(widget);
210 updateGroupVisibility(widget);
211 }, 150);
212 window.addEventListener("resize", handleResize);
213 }
214 };
215
216 const initSearch = (widget) => {
217 const input = widget.querySelector(
218 ".king-addons-comparison-matrix-cards__search-input"
219 );
220 if (!input) {
221 return;
222 }
223
224 if (!input.dataset.kngBound) {
225 input.dataset.kngBound = "yes";
226 input.addEventListener("input", () => {
227 applyFilter(widget, input.value);
228 });
229 }
230
231 if (input.value) {
232 applyFilter(widget, input.value);
233 }
234 };
235
236 const initComparisonMatrixCards = ($scope) => {
237 const widget = $scope[0]?.querySelector(".king-addons-comparison-matrix-cards");
238 if (!widget) {
239 return;
240 }
241
242 initScroll(widget);
243 initHighlight(widget);
244 initSearch(widget);
245 };
246
247 $(window).on("elementor/frontend/init", function () {
248 elementorFrontend.hooks.addAction(
249 "frontend/element_ready/king-addons-comparison-matrix-cards.default",
250 function ($scope) {
251 initComparisonMatrixCards($scope);
252 }
253 );
254 });
255 })(jQuery);
256