PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.83
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 51.1.46 All 39 releases
← All changes | includes/widgets/Content_Ticker/script.js +279 -0 51.1.251.1.83 View file →
@@ -1,0 +1,279 @@
1 +"use strict";
2 +(function ($) {
3 + $(window).on("elementor/frontend/init", function () {
4 + elementorFrontend.hooks.addAction(
5 + "frontend/element_ready/king-addons-content-ticker.default",
6 + function ($scope) {
7 + // Register a new handler extending Elementor’s Base handler
8 + elementorFrontend.elementsHandler.addHandler(
9 + elementorModules.frontend.handlers.Base.extend({
10 + onInit() {
11 + const $element = this.$element;
12 +
13 + const $contentTickerSlider = $element.find(".king-addons-ticker-slider"),
14 + $contentTickerMarquee = $element.find(".king-addons-ticker-marquee"),
15 + marqueeData = $contentTickerMarquee.data("options"),
16 + sliderClass = $element.attr("class"),
17 + dataSlideEffect = $contentTickerSlider.attr("data-slide-effect");
18 +
19 + // Helper to capture a single digit at the end of a matched pattern
20 + const getClassNumber = (regex, fallback) => {
21 + const match = sliderClass.match(regex);
22 + return match ? parseInt(match[1], 10) : fallback;
23 + };
24 +
25 + // Determine how many columns to use in different breakpoints
26 + const sliderColumnsDesktop = getClassNumber(/king-addons-ticker-slider-columns-(\d)/, 2);
27 + const sliderColumnsWideScreen = getClassNumber(/columns--widescreen(\d)/, sliderColumnsDesktop);
28 + const sliderColumnsLaptop = getClassNumber(/columns--laptop(\d)/, sliderColumnsDesktop);
29 + const sliderColumnsTablet = getClassNumber(/columns--tablet(\d)/, 2);
30 + const sliderColumnsTabletExtra = getClassNumber(/columns--tablet_extra(\d)/, sliderColumnsTablet);
31 + const sliderColumnsMobile = getClassNumber(/columns--mobile(\d)/, 1);
32 + // Mobile extra should fall back to mobile, not tablet.
33 + const sliderColumnsMobileExtra = getClassNumber(/columns--mobile_extra(\d)/, sliderColumnsMobile);
34 +
35 + // Slides to scroll logic if the slider effect is "hr-slide"
36 + const sliderSlidesToScroll =
37 + dataSlideEffect === "hr-slide"
38 + ? getClassNumber(/king-addons-ticker-slides-to-scroll-(\d)/, 1)
39 + : 1;
40 +
41 + // Check if slide effect is typing or fade
42 + const isTypingOrFade = dataSlideEffect === "typing" || dataSlideEffect === "fade";
43 +
44 + // Short helper to decide slidesToShow and slidesToScroll
45 + const getSlidesToShow = columns => (isTypingOrFade ? 1 : columns);
46 + const getSlidesToScroll = columns => (sliderSlidesToScroll > columns ? 1 : sliderSlidesToScroll);
47 +
48 + const isMeasurable = ($el) => {
49 + if (!$el || !$el.length) {
50 + return false;
51 + }
52 + // :visible can be true even with width 0 depending on CSS.
53 + return $el.is(":visible") && $el.outerWidth() > 0;
54 + };
55 +
56 + // Slick settings with breakpoints
57 + const normalizeBool = (value) => {
58 + return value === true || value === 1 || value === "1" || value === "true" || value === "yes";
59 + };
60 +
61 + const slickOptionsFromAttr = (() => {
62 + const raw = $contentTickerSlider.attr("data-slick-options");
63 + if (!raw) {
64 + return {};
65 + }
66 +
67 + try {
68 + const parsed = JSON.parse(raw);
69 + if (parsed && typeof parsed === "object") {
70 + // Normalize Elementor switcher values.
71 + if ("pauseOnHover" in parsed) {
72 + parsed.pauseOnHover = normalizeBool(parsed.pauseOnHover);
73 + }
74 + if ("autoplay" in parsed) {
75 + parsed.autoplay = normalizeBool(parsed.autoplay);
76 + }
77 + if ("infinite" in parsed) {
78 + parsed.infinite = normalizeBool(parsed.infinite);
79 + }
80 + if ("rtl" in parsed) {
81 + parsed.rtl = normalizeBool(parsed.rtl);
82 + }
83 + if ("arrows" in parsed) {
84 + parsed.arrows = normalizeBool(parsed.arrows);
85 + }
86 + if ("vertical" in parsed) {
87 + parsed.vertical = normalizeBool(parsed.vertical);
88 + }
89 +
90 + if ("autoplaySpeed" in parsed) {
91 + parsed.autoplaySpeed = parseInt(parsed.autoplaySpeed, 10) || 0;
92 + }
93 + if ("speed" in parsed) {
94 + parsed.speed = parseInt(parsed.speed, 10) || 0;
95 + }
96 +
97 + return parsed;
98 + }
99 + } catch (e) {
100 + // Ignore invalid JSON.
101 + }
102 + return {};
103 + })();
104 +
105 + const initOrRefreshSlick = () => {
106 + if (!$contentTickerSlider.length) {
107 + return;
108 + }
109 +
110 + // If initialized while hidden, Slick can calculate wrong widths.
111 + // Re-init only when element has a measurable width.
112 + if (!isMeasurable($contentTickerSlider)) {
113 + return;
114 + }
115 +
116 + // Prevent duplicate initialization when Elementor re-renders.
117 + if ($contentTickerSlider.hasClass("slick-initialized")) {
118 + try {
119 + $contentTickerSlider.slick("setPosition");
120 + } catch (e) {
121 + // ignore
122 + }
123 + return;
124 + }
125 +
126 + $contentTickerSlider.slick({
127 + ...slickOptionsFromAttr,
128 + appendArrows: $element.find(".king-addons-ticker-slider-controls"),
129 + // Base (>= 2400px) uses widescreen columns when provided.
130 + slidesToShow: getSlidesToShow(sliderColumnsWideScreen),
131 + slidesToScroll: getSlidesToScroll(sliderColumnsWideScreen),
132 + fade: isTypingOrFade,
133 + responsive: [
134 + {
135 + breakpoint: 2399,
136 + settings: {
137 + slidesToShow: getSlidesToShow(sliderColumnsDesktop),
138 + slidesToScroll: getSlidesToScroll(sliderColumnsDesktop),
139 + fade: isTypingOrFade,
140 + },
141 + },
142 + {
143 + breakpoint: 1221,
144 + settings: {
145 + slidesToShow: getSlidesToShow(sliderColumnsLaptop),
146 + slidesToScroll: getSlidesToScroll(sliderColumnsLaptop),
147 + fade: isTypingOrFade,
148 + },
149 + },
150 + {
151 + breakpoint: 1200,
152 + settings: {
153 + slidesToShow: getSlidesToShow(sliderColumnsTabletExtra),
154 + slidesToScroll: getSlidesToScroll(sliderColumnsTabletExtra),
155 + fade: isTypingOrFade,
156 + },
157 + },
158 + {
159 + breakpoint: 1024,
160 + settings: {
161 + slidesToShow: getSlidesToShow(sliderColumnsTablet),
162 + slidesToScroll: getSlidesToScroll(sliderColumnsTablet),
163 + fade: isTypingOrFade,
164 + },
165 + },
166 + {
167 + breakpoint: 880,
168 + settings: {
169 + slidesToShow: getSlidesToShow(sliderColumnsMobileExtra),
170 + slidesToScroll: getSlidesToScroll(sliderColumnsMobileExtra),
171 + fade: isTypingOrFade,
172 + },
173 + },
174 + {
175 + breakpoint: 768,
176 + settings: {
177 + slidesToShow: getSlidesToShow(sliderColumnsMobile),
178 + slidesToScroll: getSlidesToScroll(sliderColumnsMobile),
179 + fade: isTypingOrFade,
180 + },
181 + },
182 + ],
183 + });
184 +
185 + // Force a layout pass right after init.
186 + try {
187 + $contentTickerSlider.slick("setPosition");
188 + } catch (e) {
189 + // ignore
190 + }
191 + };
192 +
193 + const retryInit = (attempt = 0) => {
194 + if (attempt > 40) {
195 + return;
196 + }
197 + initOrRefreshSlick();
198 + if (!$contentTickerSlider.hasClass("slick-initialized")) {
199 + setTimeout(() => retryInit(attempt + 1), 50);
200 + }
201 + };
202 +
203 + // If slider is already initialized (e.g. rendered by cached HTML), ensure it positions correctly.
204 + if ($contentTickerSlider.hasClass("slick-initialized")) {
205 + try {
206 + $contentTickerSlider.slick("setPosition");
207 + } catch (e) {
208 + // ignore
209 + }
210 + } else {
211 + // Try immediately, then retry while the widget becomes visible.
212 + retryInit(0);
213 + }
214 +
215 + // Refresh on image load (common cause of wrong widths on frontend).
216 + $contentTickerSlider.find("img").one("load", function () {
217 + if ($contentTickerSlider.hasClass("slick-initialized")) {
218 + try {
219 + $contentTickerSlider.slick("setPosition");
220 + } catch (e) {
221 + // ignore
222 + }
223 + } else {
224 + retryInit(0);
225 + }
226 + }).each(function () {
227 + if (this.complete) {
228 + $(this).trigger("load");
229 + }
230 + });
231 +
232 + // Also refresh on global events.
233 + $(window).on("load resize orientationchange", function () {
234 + if ($contentTickerSlider.hasClass("slick-initialized")) {
235 + try {
236 + $contentTickerSlider.slick("setPosition");
237 + } catch (e) {
238 + // ignore
239 + }
240 + } else {
241 + retryInit(0);
242 + }
243 + });
244 +
245 + document.addEventListener("visibilitychange", function () {
246 + if (!document.hidden) {
247 + if ($contentTickerSlider.hasClass("slick-initialized")) {
248 + try {
249 + $contentTickerSlider.slick("setPosition");
250 + } catch (e) {
251 + // ignore
252 + }
253 + } else {
254 + retryInit(0);
255 + }
256 + }
257 + });
258 +
259 + // Initialize marquee
260 + if ($contentTickerMarquee.length && marqueeData) {
261 + $contentTickerMarquee.marquee(marqueeData);
262 + }
263 +
264 + // If marquee is hidden, remove the hidden class
265 + if ($element.find(".king-addons-marquee-hidden").length) {
266 + $element
267 + .find(".king-addons-ticker-marquee")
268 + .removeClass("king-addons-marquee-hidden");
269 + }
270 + },
271 + }),
272 + {
273 + $element: $scope,
274 + }
275 + );
276 + }
277 + );
278 + });
279 +})(jQuery);