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

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

234 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Sticky Contact Bar - Frontend JavaScript
3 *
4 * Handles visibility triggers, scroll behavior, and action buttons.
5 *
6 * @package King_Addons
7 */
8 (() => {
9 'use strict';
10
11 /**
12 * Initialize a single sticky contact bar.
13 *
14 * @param {HTMLElement} bar The bar element.
15 */
16 const initBar = (bar) => {
17 if (!bar) {
18 return;
19 }
20
21 const trigger = bar.dataset.trigger || 'always';
22 const triggerScroll = parseInt(bar.dataset.triggerScroll || '0', 10);
23 const triggerDelay = parseInt(bar.dataset.triggerDelay || '0', 10);
24 const hideOnScrollDown = (bar.dataset.hideOnScrollDown || 'no') === 'yes';
25 const showOnScrollUp = (bar.dataset.showOnScrollUp || 'no') === 'yes';
26 const analyticsEnabled = (bar.dataset.analyticsEnabled || 'no') === 'yes';
27
28 let lastY = window.scrollY;
29 let isVisible = false;
30 let triggerMet = false;
31
32 /**
33 * Show the bar with animation.
34 */
35 const show = () => {
36 if (!isVisible) {
37 bar.classList.add('is-visible');
38 bar.classList.remove('is-hidden');
39 isVisible = true;
40 }
41 };
42
43 /**
44 * Hide the bar with animation.
45 */
46 const hide = () => {
47 bar.classList.remove('is-visible');
48 bar.classList.add('is-hidden');
49 isVisible = false;
50 };
51
52 /**
53 * Handle scroll-based trigger activation.
54 */
55 const handleTriggerScroll = () => {
56 const currentY = window.scrollY;
57
58 // Check if trigger threshold is met
59 if (currentY >= triggerScroll) {
60 triggerMet = true;
61 } else {
62 triggerMet = false;
63 }
64
65 // If trigger not met, always hide
66 if (!triggerMet) {
67 hide();
68 return;
69 }
70
71 // Handle direction-based visibility (Pro feature)
72 if (hideOnScrollDown || showOnScrollUp) {
73 const goingDown = currentY > lastY;
74 const delta = Math.abs(currentY - lastY);
75
76 // Only react to significant scroll (debounce small movements)
77 if (delta > 5) {
78 if (hideOnScrollDown && goingDown) {
79 hide();
80 } else if (showOnScrollUp && !goingDown) {
81 show();
82 }
83 }
84 } else {
85 // No direction logic, just show if trigger is met
86 show();
87 }
88
89 lastY = currentY;
90 };
91
92 /**
93 * Handle direction-based visibility for always/delay triggers.
94 */
95 const handleDirectionOnly = () => {
96 const currentY = window.scrollY;
97 const goingDown = currentY > lastY;
98 const delta = Math.abs(currentY - lastY);
99
100 // Only react to significant scroll
101 if (delta > 5) {
102 if (hideOnScrollDown && goingDown && isVisible) {
103 hide();
104 } else if (showOnScrollUp && !goingDown && !isVisible) {
105 show();
106 }
107 }
108
109 lastY = currentY;
110 };
111
112 /**
113 * Track click event for analytics.
114 *
115 * @param {string} type Button type.
116 * @param {string} label Button label.
117 */
118 const trackClick = (type, label) => {
119 if (!analyticsEnabled) {
120 return;
121 }
122
123 const eventData = {
124 event: 'ka_sticky_contact_click',
125 ka_button_type: type,
126 ka_button_label: label,
127 };
128
129 // Push to dataLayer (GTM)
130 if (typeof window.dataLayer !== 'undefined') {
131 window.dataLayer.push(eventData);
132 }
133
134 // Send to gtag if available
135 if (typeof window.gtag === 'function') {
136 window.gtag('event', 'sticky_contact_click', {
137 button_type: type,
138 button_label: label,
139 });
140 }
141 };
142
143 // Initialize based on trigger type
144 if (trigger === 'always') {
145 show();
146 triggerMet = true;
147
148 // If direction features enabled, listen for scroll
149 if (hideOnScrollDown || showOnScrollUp) {
150 window.addEventListener('scroll', handleDirectionOnly, { passive: true });
151 }
152 } else if (trigger === 'delay') {
153 setTimeout(() => {
154 show();
155 triggerMet = true;
156
157 // If direction features enabled, listen for scroll after delay
158 if (hideOnScrollDown || showOnScrollUp) {
159 window.addEventListener('scroll', handleDirectionOnly, { passive: true });
160 }
161 }, Math.max(triggerDelay, 0));
162 } else if (trigger === 'scroll') {
163 window.addEventListener('scroll', handleTriggerScroll, { passive: true });
164 // Check initial position
165 handleTriggerScroll();
166 }
167
168 // Handle button clicks
169 bar.addEventListener('click', (event) => {
170 const target = event.target.closest('.ka-sticky-contact-item');
171 if (!target) {
172 return;
173 }
174
175 const action = target.dataset.action;
176 const type = target.classList.contains('ka-type-phone') ? 'phone' :
177 target.classList.contains('ka-type-email') ? 'email' :
178 target.classList.contains('ka-type-whatsapp') ? 'whatsapp' :
179 target.classList.contains('ka-type-telegram') ? 'telegram' :
180 target.classList.contains('ka-type-messenger') ? 'messenger' :
181 target.classList.contains('ka-type-viber') ? 'viber' :
182 action || 'link';
183 const label = target.getAttribute('aria-label') || type;
184
185 // Track the click
186 trackClick(type, label);
187
188 // Handle special actions
189 if (!action) {
190 return;
191 }
192
193 event.preventDefault();
194
195 if (action === 'popup') {
196 const popupId = target.dataset.popupId;
197 if (popupId && window.KingAddonsPopup && typeof window.KingAddonsPopup.open === 'function') {
198 window.KingAddonsPopup.open(popupId);
199 }
200 return;
201 }
202
203 if (action === 'offcanvas') {
204 const offcanvasId = target.dataset.offcanvasId;
205 if (offcanvasId && window.KingAddonsOffcanvas && typeof window.KingAddonsOffcanvas.open === 'function') {
206 window.KingAddonsOffcanvas.open(offcanvasId);
207 }
208 return;
209 }
210
211 if (action === 'scroll') {
212 const selector = target.dataset.scrollTarget;
213 if (selector) {
214 const el = document.querySelector(selector);
215 if (el) {
216 el.scrollIntoView({ behavior: 'smooth' });
217 }
218 }
219 }
220 });
221 };
222
223 // Initialize on DOM ready
224 document.addEventListener('DOMContentLoaded', () => {
225 document.querySelectorAll('.ka-sticky-contact-bar').forEach(initBar);
226 });
227 })();
228
229
230
231
232
233
234