PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.37
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.37
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 / admin / js / elementor-editor.js

elementor-editor.js in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.37, at includes/admin/js/elementor-editor.js

489 lines 20.5 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 function createProTooltip() {
5 const tooltip = document.createElement('div');
6 tooltip.className = 'king-addons-pro-tooltip';
7 tooltip.innerHTML = `
8 <p>This is available in <strong><a href="https://kingaddons.com/pricing/?utm_source=kng-module-upgrade-pro&utm_medium=plugin&utm_campaign=kng" target="_blank">King Addons PRO</a></strong> version</p>
9 `;
10 return tooltip;
11 }
12
13 function appendProTooltip(controlElement) {
14 // Only append if a tooltip doesn't already exist
15 if (!controlElement.querySelector('.king-addons-pro-tooltip')) {
16 controlElement.appendChild(createProTooltip());
17 }
18 }
19
20 // Function for handling custom menu and submenu
21 function setupMegaMenuItemsHandling() {
22 // Carefully apply styles to submenu elements
23 function markSubmenuItems() {
24 $('.elementor-control-submenu_items .elementor-repeater-fields').addClass('king-addons-submenu-item');
25
26 $('.elementor-control-item_type select').each(function() {
27 if ($(this).val() === 'submenu') {
28 $(this).closest('.elementor-repeater-fields').addClass('king-addons-parent-submenu-item');
29 }
30 });
31 }
32
33 // Process menu item type change events
34 $(document).on('change', '.elementor-control-item_type select', function() {
35 var $select = $(this);
36 var selectedValue = $select.val();
37
38 // If submenu type is selected
39 if (selectedValue === 'submenu') {
40 // Find item container
41 var $itemContainer = $select.closest('.elementor-repeater-fields');
42
43 // Mark element as parent for submenu
44 $itemContainer.addClass('king-addons-parent-submenu-item');
45 } else {
46 $select.closest('.elementor-repeater-fields').removeClass('king-addons-parent-submenu-item');
47 }
48
49 // Apply styles to all submenu items after change
50 markSubmenuItems();
51 });
52
53 // Immediately style submenu items on page load
54 markSubmenuItems();
55
56 // Apply styles when loading panel
57 if (window.elementor) {
58 elementor.hooks.addAction('panel/open_editor/widget', function(panel, model, view) {
59 if (model.attributes.widgetType === 'king-mega-menu' || model.attributes.widgetType === 'king-mega-menu-pro') {
60 // Apply styles and classes on first opening
61 markSubmenuItems();
62
63 // Check for submenu items every 500ms for the first few seconds
64 // to catch items that might be added dynamically
65 for (let i = 1; i <= 10; i++) {
66 setTimeout(markSubmenuItems, i * 500);
67 }
68
69 // Track element addition via MutationObserver more safely
70 try {
71 const observer = new MutationObserver(function(mutations) {
72 mutations.forEach(function(mutation) {
73 if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
74 // If new nodes are added, apply styles
75 if ($(mutation.target).closest('.elementor-control-submenu_items').length > 0) {
76 // If change is in submenu
77 markSubmenuItems();
78 }
79 }
80 });
81 });
82
83 // Start observing the entire editor, but with a narrower focus on changes
84 observer.observe(panel.$el[0], {
85 childList: true,
86 subtree: true,
87 attributes: false
88 });
89
90 // Stop observing when panel is closed
91 elementor.hooks.addAction('panel/close_editor', function() {
92 observer.disconnect();
93 });
94 } catch (error) {
95 console.error('Error when setting up observer:', error);
96 }
97 }
98 });
99
100 // Hook after adding a new element to Elementor repeater
101 $(document).on('DOMNodeInserted', '.elementor-repeater-row-item-title', function(e) {
102 // Apply styles after any item is inserted
103 setTimeout(markSubmenuItems, 150);
104 });
105 }
106
107 // Add styles for visual distinction of submenu elements
108 try {
109 const style = document.createElement('style');
110 style.textContent = `
111 .king-addons-parent-submenu-item {
112 border-left: 3px solid #4054b2 !important;
113 background-color: rgba(64, 84, 178, 0.05) !important;
114 }
115 .king-addons-submenu-item {
116 border-left: 3px solid #6d7882 !important;
117 margin-left: 15px !important;
118 width: calc(100% - 15px) !important;
119 }
120
121 /* Custom styles for bug report section */
122 .king-addons-help-wrapper {
123 width: 100%;
124 max-width: 100%;
125 box-sizing: border-box;
126 }
127
128 .king-addons-bug-report {
129 background: #ffffff;
130 border: 1px solid #ddd;
131 border-radius: 5px;
132 padding: 15px;
133 margin-top: 8px;
134 line-height: 1.4;
135 width: 100%;
136 box-sizing: border-box;
137 }
138
139 .king-addons-bug-report-title {
140 font-weight: 600;
141 font-size: 14px;
142 color: #333;
143 margin-bottom: 8px;
144 }
145
146 .king-addons-bug-report-text {
147 font-size: 12px;
148 color: #666;
149 margin-bottom: 10px;
150 }
151
152 .king-addons-bug-report-email-section {
153 display: flex;
154 align-items: center;
155 gap: 8px;
156 }
157
158 .king-addons-bug-report-email-field {
159 flex: 1;
160 background: #f8f9fa;
161 border: 1px solid #ddd;
162 border-radius: 4px;
163 padding: 6px 10px;
164 font-family: monospace;
165 font-size: 11px;
166 color: #333;
167 user-select: all;
168 }
169
170 .king-addons-bug-report-copy-btn {
171 padding: 6px 12px;
172 background: #666666;
173 color: white;
174 border: none;
175 border-radius: 4px;
176 cursor: pointer;
177 font-size: 11px;
178 font-weight: 500;
179 transition: background 0.2s;
180 }
181
182 .king-addons-bug-report-copy-btn:hover {
183 background: #2d3a80;
184 }
185
186 .king-addons-bug-report-copy-btn.copied {
187 background: #28a745;
188 }
189
190 /* Promo block styles */
191 .king-addons-promo-block {
192 background: linear-gradient(135deg, #93117e 0%, #d946ef 100%);
193 border-radius: 6px;
194 padding: 16px;
195 margin-top: 12px;
196 margin-bottom: 0;
197 color: white;
198 position: relative;
199 overflow: hidden;
200 width: 100%;
201 box-sizing: border-box;
202 }
203
204 .king-addons-promo-block::before {
205 content: '';
206 position: absolute;
207 top: 0;
208 right: 0;
209 bottom: 0;
210 left: 0;
211 background: rgba(255, 255, 255, 0.05);
212 border-radius: 6px;
213 pointer-events: none;
214 }
215
216 .king-addons-promo-title {
217 font-weight: 600;
218 font-size: 13px;
219 margin-bottom: 6px;
220 line-height: 1.3;
221 position: relative;
222 z-index: 1;
223 }
224
225 .king-addons-promo-text {
226 font-size: 11px;
227 line-height: 1.4;
228 margin-bottom: 8px;
229 opacity: 0.9;
230 position: relative;
231 z-index: 1;
232 }
233
234 .king-addons-promo-highlight {
235 font-weight: 600;
236 color: #fbbf24;
237 }
238
239 .king-addons-promo-small {
240 font-size: 10px;
241 opacity: 0.8;
242 margin-bottom: 10px;
243 position: relative;
244 z-index: 1;
245 }
246
247 .king-addons-promo-buttons {
248 display: flex;
249 gap: 8px;
250 position: relative;
251 z-index: 1;
252 flex-wrap: wrap;
253 }
254
255 .king-addons-promo-btn {
256 padding: 6px 12px;
257 border: none;
258 border-radius: 4px;
259 font-size: 11px;
260 font-weight: 600;
261 cursor: pointer;
262 transition: all 0.2s;
263 text-decoration: none;
264 display: inline-block;
265 white-space: nowrap;
266 }
267
268 .king-addons-promo-btn-primary {
269 background: #ffffff;
270 color: #93117e;
271 }
272
273 .king-addons-promo-btn-primary:hover {
274 background: #f3f4f6;
275 transform: translateY(-1px);
276 }
277
278 .king-addons-promo-btn-secondary {
279 background: rgba(255, 255, 255, 0.2);
280 color: white;
281 }
282
283 .king-addons-promo-btn-secondary:hover {
284 background: rgba(255, 255, 255, 0.3);
285 color: rgb(255 255 255 / 80%);
286 }
287
288 /* Dark mode styles using system preference */
289 @media (prefers-color-scheme: dark) {
290 .king-addons-bug-report {
291 background: #2c2c2c;
292 border-color: #444;
293 }
294
295 .king-addons-bug-report-title {
296 color: #ffffff;
297 }
298
299 .king-addons-bug-report-text {
300 color: #b0b0b0;
301 }
302
303 .king-addons-bug-report-email-field {
304 background: #383838;
305 border-color: #555;
306 color: #ffffff;
307 }
308 }
309 `;
310 document.head.appendChild(style);
311 } catch (styleError) {
312 console.error('Error when adding styles:', styleError);
313 }
314 }
315
316 $(window).on('elementor:init', function() {
317 console.log('elementor:init event fired for mega menu editor');
318 const panelEl = document.getElementById('elementor-panel');
319
320 // Watch for newly-added .king-addons-pro-control elements
321 const observer = new MutationObserver(function(mutations) {
322 mutations.forEach((mutation) => {
323 if (mutation.type === 'childList') {
324 mutation.addedNodes.forEach((node) => {
325 if (node.nodeType === Node.ELEMENT_NODE) {
326 // Find .king-addons-pro-control .elementor-control-content in newly added nodes
327 const proControls = node.querySelectorAll('.king-addons-pro-control .elementor-control-content');
328 proControls.forEach(appendProTooltip);
329 }
330 });
331 }
332 });
333 });
334
335 // Start observing if the elementor panel is found
336 if (panelEl) {
337 observer.observe(panelEl, {
338 childList: true,
339 subtree: true
340 });
341 }
342
343 // Initial pass for any controls already in the DOM
344 const initialProControls = document.querySelectorAll('.king-addons-pro-control .elementor-control-content');
345 initialProControls.forEach(appendProTooltip);
346
347 // Initialize custom menu handling
348 setupMegaMenuItemsHandling();
349
350 // Replace default "Need Help" link with King Addons bug report section
351 (function replaceHelpLink() {
352 const EMAIL = 'contact@kingaddons.com';
353
354 // Function to copy text to clipboard
355 function copyToClipboard(text) {
356 return new Promise((resolve, reject) => {
357 if (navigator.clipboard && window.isSecureContext) {
358 navigator.clipboard.writeText(text)
359 .then(() => resolve(true))
360 .catch(err => reject(err));
361 } else {
362 // Fallback for older browsers
363 const textArea = document.createElement('textarea');
364 textArea.value = text;
365 textArea.style.position = 'fixed';
366 textArea.style.left = '-999999px';
367 textArea.style.top = '-999999px';
368 document.body.appendChild(textArea);
369 textArea.focus();
370 textArea.select();
371
372 try {
373 document.execCommand('copy');
374 document.body.removeChild(textArea);
375 resolve(true);
376 } catch (err) {
377 document.body.removeChild(textArea);
378 reject(err);
379 }
380 }
381 });
382 }
383
384 function createBugReportSection() {
385 // Create new bug report section
386 const bugReportSection = document.createElement('div');
387 bugReportSection.className = 'king-addons-bug-report';
388 bugReportSection.innerHTML = `
389 <div class="king-addons-bug-report-title">Questions, bugs, feedback, or ideas?</div>
390 <div class="king-addons-bug-report-text">Reach out to us at ${EMAIL} we love hearing from our users!</div>
391 <div class="king-addons-bug-report-email-section">
392 <span class="king-addons-bug-report-email-field">${EMAIL}</span>
393 <button class="king-addons-bug-report-copy-btn">Copy</button>
394 </div>
395 `;
396
397 // Add copy functionality
398 const copyBtn = bugReportSection.querySelector('.king-addons-bug-report-copy-btn');
399
400 // Copy email address function
401 copyBtn.addEventListener('click', () => {
402 copyToClipboard(EMAIL).then(() => {
403 copyBtn.textContent = 'Copied!';
404 copyBtn.classList.add('copied');
405 setTimeout(() => {
406 copyBtn.textContent = 'Copy';
407 copyBtn.classList.remove('copied');
408 }, 2000);
409 }).catch(err => {
410 console.error('Error copying email:', err);
411 alert('Failed to copy email address.');
412 });
413 });
414
415 return bugReportSection;
416 }
417
418 function createPromoBlock() {
419 // Check if PRO is active
420 if (typeof kingAddonsEditor !== 'undefined' && kingAddonsEditor.isPro) {
421 return null; // Don't show promo for PRO users
422 }
423
424 const promoBlock = document.createElement('div');
425 promoBlock.className = 'king-addons-promo-block';
426 promoBlock.innerHTML = `
427 <div class="king-addons-promo-title">Unlock <span class="king-addons-promo-highlight">650+</span> premium templates and <span class="king-addons-promo-highlight">200+</span> advanced features for only <span class="king-addons-promo-highlight">$4.99</span>/month.</div>
428 <div class="king-addons-promo-text">Upgrade now and boost your website's performance!</div>
429 <div class="king-addons-promo-small">Trusted by 20,000+ users</div>
430 <div class="king-addons-promo-buttons">
431 <a href="https://kingaddons.com/pricing/?utm_source=kng-module-elementor-panel-upgrade&utm_medium=plugin&utm_campaign=kng" target="_blank" class="king-addons-promo-btn king-addons-promo-btn-primary">Upgrade Now</a>
432 <a href="https://kingaddons.com/pricing/?utm_source=kng-module-elementor-panel-lm&utm_medium=plugin&utm_campaign=kng" target="_blank" class="king-addons-promo-btn king-addons-promo-btn-secondary">Learn More</a>
433 </div>
434 `;
435 return promoBlock;
436 }
437
438 function replaceBugReportInPanel() {
439 const helpSection = document.querySelector('#elementor-panel__editor__help');
440 if (helpSection) {
441 // Clear existing content and create wrapper
442 helpSection.innerHTML = '';
443
444 // Create wrapper div
445 const wrapper = document.createElement('div');
446 wrapper.className = 'king-addons-help-wrapper';
447
448 // Add promo block only if not PRO user
449 const promoBlock = createPromoBlock();
450 if (promoBlock) {
451 wrapper.appendChild(promoBlock);
452 }
453
454 // Always add bug report section
455 wrapper.appendChild(createBugReportSection());
456
457 // Add wrapper to help section
458 helpSection.appendChild(wrapper);
459 }
460 }
461
462 // Hook into Elementor panel events to replace help section for King Addons widgets
463 if (window.elementor) {
464 elementor.hooks.addAction('panel/open_editor/widget', function(panel, model, view) {
465 const widgetType = model.attributes.widgetType;
466
467 // Check if it's a King Addons widget
468 if (widgetType && widgetType.startsWith('king-addons-')) {
469 // Wait a bit for the panel to fully load, then replace the help section
470 setTimeout(() => {
471 replaceBugReportInPanel();
472 }, 100);
473 }
474 });
475 }
476
477 // Initial replacement if we're already on a King Addons widget
478 setTimeout(() => {
479 if (window.elementor && elementor.panel && elementor.panel.currentView) {
480 const currentModel = elementor.panel.currentView.model;
481 if (currentModel && currentModel.attributes.widgetType && currentModel.attributes.widgetType.startsWith('king-addons-')) {
482 replaceBugReportInPanel();
483 }
484 }
485 }, 500);
486 })();
487 });
488
489 }(jQuery));