PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.86
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.86
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 51.1.45 All 40 releases
king-addons / includes / widgets / Image_Accordion / script.js

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

355 lines 20.6 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 $(window).on("elementor/frontend/init", function () {
5 elementorFrontend.hooks.addAction(
6 "frontend/element_ready/king-addons-image-accordion.default",
7 function ($scope) {
8 elementorFrontend.elementsHandler.addHandler(
9 elementorModules.frontend.handlers.Base.extend({
10 onInit() {
11 const normalizeSafeUrl = (rawUrl) => {
12 if (!rawUrl || typeof rawUrl !== "string") return null;
13 try {
14 const url = new URL(rawUrl, window.location.href);
15 const allowedProtocols = ["http:", "https:", "mailto:", "tel:"];
16 if (allowedProtocols.includes(url.protocol)) {
17 return url.href;
18 }
19 } catch (e) {
20 // ignore
21 }
22 return null;
23 };
24
25 const $elem = this.$element,
26 $wrap = $elem.find(".king-addons-image-accordion"),
27 $wrapContainer = $elem.find(".king-addons-image-accordion-wrap"),
28 settings = JSON.parse(
29 $elem
30 .find(".king-addons-img-accordion-media-hover")
31 .attr("data-settings")
32 ),
33 lightboxAttr = $wrap.attr("lightbox"),
34 lightboxSettings = lightboxAttr ? JSON.parse(lightboxAttr) : "",
35 $accordionItems = $elem.find(".king-addons-image-accordion-item");
36
37 // Content stays at the open-item size for the whole animation.
38 // Clearing that size when the transition ends was an instant
39 // resize: the text wrapped and the block jumped.
40 const contentAxis = () =>
41 $wrap.css("flex-direction") === "column" ? "height" : "width";
42
43 const setOpenContentSize = () => {
44 const axis = contentAxis();
45 const margin = axis === "height" ? "margin-bottom" : "margin-right";
46 const count = $accordionItems.length;
47 let gaps = 0;
48
49 $accordionItems.each(function (index) {
50 if (index < count - 1) {
51 gaps += parseFloat($(this).css(margin)) || 0;
52 }
53 });
54
55 const total =
56 ($wrap[axis === "height" ? "innerHeight" : "innerWidth"]() || 0) - gaps;
57 const activeGrow = parseFloat(settings.activeItem.activeWidth) || 1;
58 let inactiveGrow = 1;
59
60 $accordionItems.each(function () {
61 if (!$(this).hasClass("king-addons-image-accordion-item-grow")) {
62 inactiveGrow = parseFloat(window.getComputedStyle(this).flexGrow) || 1;
63 return false;
64 }
65 });
66
67 const sum = activeGrow + inactiveGrow * Math.max(count - 1, 0);
68 if (total <= 0 || sum <= 0) {
69 return;
70 }
71
72 $wrap[0].style.setProperty(
73 "--king-acc-open-size",
74 Math.round((total * activeGrow) / sum) + "px"
75 );
76 };
77
78 setOpenContentSize();
79 const resizeEvent = "resize.kingAddonsImageAccordion" + ($elem.data("id") || "item");
80 $(window).off(resizeEvent).on(resizeEvent, setOpenContentSize);
81 this.onDestroy = () => {
82 $(window).off(resizeEvent);
83 };
84
85 // Adjust row/column layout if necessary
86 if ($wrapContainer.hasClass("king-addons-acc-no-column")) {
87 if (!$elem.hasClass("king-addons-image-accordion-row")) {
88 $elem
89 .removeClass("king-addons-image-accordion-column")
90 .addClass("king-addons-image-accordion-row");
91 $wrap.css("flex-direction", "row");
92 }
93 }
94
95 // Initialize lightbox if settings exist
96 if (lightboxSettings) {
97 $wrap.lightGallery(lightboxSettings);
98
99 // Adjust thumbnails in lightbox
100 $wrap.on("onAfterOpen.lg", function () {
101 const $lgOuter = $(".lg-outer");
102 if ($lgOuter.find(".lg-thumb-item").length) {
103 $lgOuter.find(".lg-thumb-item").each(function () {
104 const $img = $(this).find("img");
105 const imgSrc = $img.attr("src");
106 const extIndex = imgSrc.lastIndexOf(".");
107 const ext = imgSrc.slice(extIndex);
108 const cropIndex = imgSrc.lastIndexOf("-");
109 let cropSize = /\d{3,}x\d{3,}/.test(
110 imgSrc.substring(extIndex, cropIndex)
111 )
112 ? imgSrc.substring(extIndex, cropIndex)
113 : false;
114 let newImgSrc = imgSrc;
115
116 if (cropSize && cropSize.length >= 42) {
117 cropSize = "";
118 }
119
120 if (cropSize !== "") {
121 if (cropSize !== false) {
122 newImgSrc = imgSrc.replace(cropSize, "-150x150");
123 } else {
124 newImgSrc = [
125 imgSrc.slice(0, extIndex),
126 "-150x150",
127 ext
128 ].join("");
129 }
130 }
131
132 $img.attr("src", newImgSrc);
133
134 // Restore original if invalid crop size
135 if (cropSize === false || cropSize === "-450x450") {
136 $img.attr("src", imgSrc);
137 }
138 });
139 }
140 });
141
142 // Control certain lightbox behaviors
143 $wrap.on("onAferAppendSlide.lg onAfterSlide.lg", function () {
144 const $lightboxDownload = $("#lg-download"),
145 lightboxControls = $(
146 "#lg-actual-size, #lg-zoom-in, #lg-zoom-out, #lg-download"
147 ),
148 downloadHref = $lightboxDownload.attr("href");
149
150 if ($lightboxDownload.length) {
151 if (downloadHref.indexOf("wp-content") === -1) {
152 lightboxControls.addClass("king-addons-hidden-element");
153 } else {
154 lightboxControls.removeClass("king-addons-hidden-element");
155 }
156 }
157
158 // Hide autoplay if not enabled
159 if (!lightboxSettings.autoplay) {
160 $(".lg-autoplay-button").css({
161 width: "0",
162 height: "0",
163 overflow: "hidden"
164 });
165 }
166 });
167 }
168
169 // Make the entire accordion item clickable
170 $wrap.css("cursor", "pointer");
171
172 // Handle hover interactions for clickable links
173 function mediaHoverLink() {
174 // Avoid linking in the Elementor editor
175 if (!$("body").hasClass("elementor-editor-active")) {
176 $elem
177 .find(".king-addons-img-accordion-media-hover")
178 .on("click", function (event) {
179 const isTarget = event.target.className.includes(
180 "king-addons-img-accordion-media-hover"
181 );
182 const thisSettings = JSON.parse(
183 isTarget
184 ? $(this).attr("data-settings")
185 : $(this)
186 .closest(".king-addons-img-accordion-media-hover")
187 .attr("data-settings")
188 );
189 if (
190 !$(event.target).hasClass(
191 "king-addons-img-accordion-item-lightbox"
192 ) &&
193 !$(event.target).closest(
194 ".king-addons-img-accordion-item-lightbox"
195 ).length
196 ) {
197 const itemUrl = thisSettings.activeItem.overlayLink;
198 const safeUrl = normalizeSafeUrl(itemUrl);
199 if (safeUrl) {
200 if (
201 thisSettings.activeItem.overlayLinkTarget ===
202 "_blank"
203 ) {
204 const w = window.open(safeUrl, "_blank");
205 if (w && typeof w.focus === "function") {
206 w.focus();
207 }
208 } else {
209 window.location.href = safeUrl;
210 }
211 }
212 }
213 });
214 }
215 }
216
217 // Interaction type: "hover"
218 if (settings.activeItem.interaction === "hover") {
219 mediaHoverLink();
220
221 $accordionItems.on("mouseenter", function () {
222 if ($(this).hasClass("king-addons-image-accordion-item-grow")) {
223 return;
224 }
225 $accordionItems.removeClass(
226 "king-addons-image-accordion-item-grow"
227 );
228 $accordionItems
229 .find(".king-addons-animation-wrap")
230 .removeClass("king-addons-animation-wrap-active");
231
232 $(this).addClass("king-addons-image-accordion-item-grow");
233 $(this)
234 .find(".king-addons-animation-wrap")
235 .addClass("king-addons-animation-wrap-active");
236 });
237 $wrap.on("mouseleave", function () {
238 $accordionItems.removeClass(
239 "king-addons-image-accordion-item-grow"
240 );
241 $accordionItems
242 .find(".king-addons-animation-wrap")
243 .removeClass("king-addons-animation-wrap-active");
244 });
245
246 // Interaction type: "click"
247 } else if (settings.activeItem.interaction === "click") {
248 $elem
249 .find(".king-addons-img-accordion-media-hover")
250 .removeClass("king-addons-animation-wrap");
251
252 $accordionItems.on(
253 "click",
254 ".king-addons-img-accordion-media-hover",
255 function (event) {
256 const isTarget = event.target.className.includes(
257 "king-addons-img-accordion-media-hover"
258 );
259 const hasActiveClass = isTarget
260 ? event.target.className.includes(
261 "king-addons-animation-wrap-active"
262 )
263 : $(this)
264 .closest(".king-addons-img-accordion-media-hover")
265 .hasClass("king-addons-animation-wrap-active");
266
267 // If this item is already active, redirect if a link is set
268 if (
269 hasActiveClass &&
270 !$("body").hasClass("elementor-editor-active")
271 ) {
272 const thisSettings = JSON.parse(
273 isTarget
274 ? $(this).attr("data-settings")
275 : $(this)
276 .closest(".king-addons-img-accordion-media-hover")
277 .attr("data-settings")
278 );
279
280 if (
281 !$(event.target).hasClass(
282 "king-addons-img-accordion-item-lightbox"
283 ) &&
284 !$(event.target).closest(
285 ".king-addons-img-accordion-item-lightbox"
286 ).length
287 ) {
288 const itemUrl = thisSettings.activeItem.overlayLink;
289 const safeUrl = normalizeSafeUrl(itemUrl);
290 if (safeUrl) {
291 if (
292 thisSettings.activeItem.overlayLinkTarget ===
293 "_blank"
294 ) {
295 const w = window.open(safeUrl, "_blank");
296 if (w && typeof w.focus === "function") {
297 w.focus();
298 }
299 } else {
300 window.location.href = safeUrl;
301 }
302 }
303 }
304 } else {
305 // Activate this item
306 $elem
307 .find(".king-addons-img-accordion-media-hover")
308 .removeClass("king-addons-animation-wrap king-addons-animation-wrap-active");
309 $accordionItems.removeClass(
310 "king-addons-image-accordion-item-grow"
311 );
312
313 $(this)
314 .closest(".king-addons-image-accordion-item")
315 .addClass("king-addons-image-accordion-item-grow");
316 $(this)
317 .closest(".king-addons-img-accordion-media-hover")
318 .addClass("king-addons-animation-wrap-active");
319 }
320 }
321 );
322 } else {
323 // If interaction is neither hover nor click
324 $elem
325 .find(".king-addons-img-accordion-media-hover")
326 .removeClass("king-addons-animation-wrap");
327 }
328
329 // Set default active item
330 $accordionItems.each(function () {
331 if ($(this).index() === settings.activeItem.defaultActive - 1) {
332 setTimeout(() => {
333 const action =
334 settings.activeItem.interaction === "click"
335 ? "click"
336 : "mouseenter";
337 $(this)
338 .find(".king-addons-img-accordion-media-hover")
339 .trigger(action);
340 }, 400);
341 }
342 });
343
344 // Show the accordion after initialization
345 $wrapContainer.css("opacity", 1);
346 }
347 }),
348 {
349 $element: $scope
350 }
351 );
352 }
353 );
354 });
355 })(jQuery);