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/Countdown/script.js +158 -0 51.1.251.1.83 View file →
@@ -1,0 +1,158 @@
1 +"use strict";
2 +(($) => {
3 + $(window).on("elementor/frontend/init", () => {
4 + elementorFrontend.hooks.addAction("frontend/element_ready/king-addons-countdown.default", ($scope) => {
5 + elementorFrontend.elementsHandler.addHandler(
6 + elementorModules.frontend.handlers.Base.extend({
7 + onInit() {
8 + const $element = this.$element;
9 + const countDownWrap = $element
10 + .children(".elementor-widget-container")
11 + .children(".king-addons-countdown-wrap");
12 +
13 + let countDownInterval = null;
14 + const dataInterval = countDownWrap.data("interval");
15 + const dataShowAgain = countDownWrap.data("show-again");
16 + let endTime = new Date(dataInterval * 1000).getTime();
17 +
18 + // Handle evergreen type
19 + if (countDownWrap.data("type") === "evergreen") {
20 + const widgetID = $element.attr("data-id");
21 + let now = new Date();
22 + const settings =
23 + JSON.parse(localStorage.getItem("KingAddonsCountdownSettings")) || {};
24 +
25 + // If this widget is saved in localStorage and intervals match, reuse its endTime.
26 + if (
27 + settings[widgetID] &&
28 + dataInterval === settings[widgetID].interval
29 + ) {
30 + endTime = settings[widgetID].endTime;
31 + } else {
32 + endTime = now.setSeconds(now.getSeconds() + dataInterval);
33 + }
34 +
35 + // Check if show-again time has passed
36 + if (endTime + dataShowAgain < Date.now()) {
37 + now = new Date();
38 + endTime = now.setSeconds(now.getSeconds() + dataInterval);
39 + }
40 +
41 + // Save updated settings
42 + settings[widgetID] = { interval: dataInterval, endTime };
43 + localStorage.setItem(
44 + "KingAddonsCountdownSettings",
45 + JSON.stringify(settings)
46 + );
47 + }
48 +
49 + // Initialize and run the countdown
50 + initCountDown();
51 + countDownInterval = setInterval(initCountDown, 1000);
52 +
53 + function initCountDown() {
54 + const timeLeft = endTime - Date.now();
55 +
56 + let numbers = {
57 + days: Math.floor(timeLeft / (1000 * 60 * 60 * 24)),
58 + hours: Math.floor((timeLeft / (1000 * 60 * 60)) % 24),
59 + minutes: Math.floor((timeLeft / 1000 / 60) % 60),
60 + seconds: Math.floor((timeLeft / 1000) % 60),
61 + };
62 +
63 + // If time is already up
64 + if (timeLeft < 0) {
65 + numbers = { days: 0, hours: 0, minutes: 0, seconds: 0 };
66 + }
67 +
68 + // Update DOM
69 + $element.find(".king-addons-countdown-number").each(function () {
70 + let number = numbers[$(this).attr("data-item")] || 0;
71 +
72 + if (number.toString().length === 1) {
73 + number = `0${number}`;
74 + }
75 + $(this).text(number);
76 +
77 + // Update label singular/plural
78 + const labels = $(this).next();
79 + if (
80 + labels.length &&
81 + !$(this).hasClass("king-addons-countdown-seconds")
82 + ) {
83 + const labelText = labels.data("text");
84 + labels.text(number === "01" ? labelText.singular : labelText.plural);
85 + }
86 + });
87 +
88 + // When countdown expires
89 + if (timeLeft < 0) {
90 + clearInterval(countDownInterval);
91 + expiredActions();
92 + }
93 + }
94 +
95 + function expiredActions() {
96 + const dataActions = countDownWrap.data("actions");
97 + // Skip if in elementor editor
98 + if ($("body").hasClass("elementor-editor-active")) return;
99 +
100 + const normalizeSafeUrl = (rawUrl) => {
101 + if (!rawUrl || typeof rawUrl !== "string") return null;
102 + try {
103 + const url = new URL(rawUrl, window.location.href);
104 + if (url.protocol === "http:" || url.protocol === "https:") {
105 + return url.href;
106 + }
107 + } catch (e) {
108 + // ignore
109 + }
110 + return null;
111 + };
112 +
113 + // Hide the timer
114 + if (dataActions.hasOwnProperty("hide-timer")) {
115 + countDownWrap.hide();
116 + }
117 +
118 + // Hide a specific element
119 + if (dataActions.hasOwnProperty("hide-element")) {
120 + $(dataActions["hide-element"]).hide();
121 + }
122 +
123 + // Show a message
124 + if (dataActions.hasOwnProperty("message")) {
125 + const messageSelector = ".king-addons-countdown-message";
126 + if (
127 + !$element
128 + .children(".elementor-widget-container")
129 + .children(messageSelector).length
130 + ) {
131 + const $msg = $("<div />", {
132 + class: "king-addons-countdown-message",
133 + text: String(dataActions["message"] ?? ""),
134 + });
135 + countDownWrap.after($msg);
136 + }
137 + }
138 +
139 + // Redirect
140 + if (dataActions.hasOwnProperty("redirect")) {
141 + const destinationUrl = normalizeSafeUrl(dataActions["redirect"]);
142 + if (destinationUrl) {
143 + window.location.href = destinationUrl;
144 + }
145 + }
146 +
147 + // Load a template (show the next .elementor section)
148 + if (dataActions.hasOwnProperty("load-template")) {
149 + countDownWrap.next(".elementor").show();
150 + }
151 + }
152 + },
153 + }),
154 + { $element: $scope }
155 + );
156 + });
157 + });
158 +})(jQuery);