PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.83
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 / Site_Preloader / templates / admin-page.php

admin-page.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.83, at includes/extensions/Site_Preloader/templates/admin-page.php

434 lines 16.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Site Preloader Admin Page Template.
4 *
5 * Premium style inspired admin UI for Site Preloader settings.
6 *
7 * @package King_Addons
8 * @since 1.0.0
9 *
10 * @var array $settings Current settings.
11 * @var bool $is_pro Whether Pro version is active.
12 * @var array $presets Available presets.
13 * @var array $rules Current display rules.
14 * @var string $current_tab Current active tab.
15 */
16
17 if (!defined('ABSPATH')) {
18 exit;
19 }
20
21 $tabs = [
22 'dashboard' => __('Dashboard', 'king-addons'),
23 'settings' => __('Settings', 'king-addons'),
24 'templates' => __('Templates', 'king-addons'),
25 'rules' => __('Rules', 'king-addons'),
26 'advanced' => __('Advanced', 'king-addons'),
27 'import-export' => __('Import / Export', 'king-addons'),
28 ];
29
30 // Show success/error messages
31 $updated = isset($_GET['updated']) && $_GET['updated'] === 'true';
32 $imported = isset($_GET['imported']) && $_GET['imported'] === 'true';
33 $reset = isset($_GET['reset']) && $_GET['reset'] === 'true';
34 $error = isset($_GET['error']) ? sanitize_key($_GET['error']) : '';
35
36 // Theme mode is per-user
37 $theme_mode = get_user_meta(get_current_user_id(), 'king_addons_theme_mode', true);
38 $allowed_theme_modes = ['dark', 'light', 'auto'];
39 if (!in_array($theme_mode, $allowed_theme_modes, true)) {
40 $theme_mode = 'auto';
41 }
42 ?>
43
44 <script>
45 (function() {
46 const mode = '<?php echo esc_js($theme_mode); ?>';
47 const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
48 const isDark = mode === 'auto' ? !!(mql && mql.matches) : mode === 'dark';
49
50 function applyThemeClasses(nextIsDark) {
51 document.documentElement.classList.toggle('ka-v3-dark', nextIsDark);
52 if (document.body) {
53 document.body.classList.add('ka-admin-v3');
54 document.body.classList.toggle('ka-v3-dark', nextIsDark);
55 }
56 }
57
58 function ensureBodyReady(fn) {
59 if (document.body) {
60 fn();
61 return;
62 }
63 document.addEventListener('DOMContentLoaded', fn, { once: true });
64 }
65
66 // Apply to <html> immediately to avoid flash; apply to body when ready.
67 document.documentElement.classList.toggle('ka-v3-dark', isDark);
68 ensureBodyReady(function() {
69 applyThemeClasses(isDark);
70 });
71 })();
72
73 // Theme segmented control (dashboard-style)
74 (function() {
75 const ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';
76 const nonce = '<?php echo esc_js(wp_create_nonce('king_addons_dashboard_ui')); ?>';
77 const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
78 let mode = 'dark';
79 let mqlHandler = null;
80
81 function saveUISetting(key, value) {
82 const body = new URLSearchParams();
83 body.set('action', 'king_addons_save_dashboard_ui');
84 body.set('nonce', nonce);
85 body.set('key', key);
86 body.set('value', value);
87 fetch(ajaxUrl, {
88 method: 'POST',
89 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
90 body: body.toString()
91 });
92 }
93
94 function updateSegment(activeMode) {
95 const segment = document.getElementById('ka-v3-theme-segment');
96 if (!segment) {
97 return;
98 }
99 segment.setAttribute('data-active', activeMode);
100 segment.querySelectorAll('.ka-v3-segmented-btn').forEach((btn) => {
101 const theme = btn.getAttribute('data-theme');
102 btn.setAttribute('aria-pressed', theme === activeMode ? 'true' : 'false');
103 });
104 }
105
106 function ensureBodyReady(fn) {
107 if (document.body) {
108 fn();
109 return;
110 }
111 document.addEventListener('DOMContentLoaded', fn, { once: true });
112 }
113
114 function applyTheme(isDark) {
115 document.documentElement.classList.toggle('ka-v3-dark', isDark);
116 if (document.body) {
117 document.body.classList.add('ka-admin-v3');
118 document.body.classList.toggle('ka-v3-dark', isDark);
119 }
120 }
121
122 function setThemeMode(nextMode, save) {
123 mode = nextMode;
124 updateSegment(nextMode);
125
126 if (mqlHandler && mql) {
127 if (mql.removeEventListener) {
128 mql.removeEventListener('change', mqlHandler);
129 } else if (mql.removeListener) {
130 mql.removeListener(mqlHandler);
131 }
132 mqlHandler = null;
133 }
134
135 if (nextMode === 'auto') {
136 ensureBodyReady(function() {
137 applyTheme(!!(mql && mql.matches));
138 });
139 mqlHandler = (e) => {
140 if (mode !== 'auto') {
141 return;
142 }
143 applyTheme(!!e.matches);
144 };
145 if (mql) {
146 if (mql.addEventListener) {
147 mql.addEventListener('change', mqlHandler);
148 } else if (mql.addListener) {
149 mql.addListener(mqlHandler);
150 }
151 }
152 } else {
153 ensureBodyReady(function() {
154 applyTheme(nextMode === 'dark');
155 });
156 }
157
158 if (save) {
159 saveUISetting('theme_mode', nextMode);
160 }
161 }
162
163 window.kaV3ToggleDark = function() {
164 const isDark = document.body.classList.contains('ka-v3-dark');
165 setThemeMode(isDark ? 'light' : 'dark', true);
166 };
167
168 function initThemeSegment() {
169 const segment = document.getElementById('ka-v3-theme-segment');
170 if (!segment) {
171 return;
172 }
173
174 mode = (segment.getAttribute('data-active') || 'dark').toString();
175
176 // Use event delegation to avoid edge-cases where the element gets re-rendered.
177 document.addEventListener('click', function(e) {
178 const btn = e.target && e.target.closest ? e.target.closest('#ka-v3-theme-segment .ka-v3-segmented-btn') : null;
179 if (!btn) {
180 return;
181 }
182 e.preventDefault();
183 setThemeMode((btn.getAttribute('data-theme') || 'dark').toString(), true);
184 });
185
186 setThemeMode(mode, false);
187 }
188
189 if (document.readyState === 'loading') {
190 document.addEventListener('DOMContentLoaded', initThemeSegment, { once: true });
191 } else {
192 initThemeSegment();
193 }
194 })();
195
196 // Tab switching
197 function kaPreloaderSwitchTab(tabId) {
198 // Update URL
199 const url = new URL(window.location.href);
200 url.searchParams.set('tab', tabId);
201 window.history.replaceState({}, '', url);
202
203 // Switch tabs
204 document.querySelectorAll('.ka-tab').forEach(tab => {
205 tab.classList.toggle('active', tab.dataset.tab === tabId);
206 });
207 document.querySelectorAll('.ka-tab-content').forEach(content => {
208 content.classList.toggle('active', content.dataset.tab === tabId);
209 });
210 }
211
212 // Preview functions
213 function kaPreloaderOpenPreview() {
214 document.getElementById('ka-preloader-preview-modal').style.display = 'flex';
215 document.body.style.overflow = 'hidden';
216 kaPreloaderUpdatePreview();
217 }
218
219 function kaPreloaderClosePreview() {
220 document.getElementById('ka-preloader-preview-modal').style.display = 'none';
221 document.body.style.overflow = '';
222 }
223
224 function kaPreloaderUpdatePreview() {
225 const container = document.getElementById('ka-preloader-preview-container');
226 if (!container) {
227 return;
228 }
229
230 const form = document.getElementById('ka-preloader-settings-form');
231
232 function getVal(name, fallback) {
233 if (!form) {
234 return fallback;
235 }
236 const el = form.querySelector('[name="' + name + '"]');
237 if (!el) {
238 return fallback;
239 }
240 if (el.type === 'checkbox') {
241 return el.checked ? '1' : '';
242 }
243 return (el.value ?? fallback);
244 }
245
246 // Try to re-use existing preview HTML so animations always match PHP output.
247 const liveWrapper = document.getElementById('ka-live-preview-wrapper');
248 const dashWrapper = document.querySelector('#ka-dashboard-preview .ka-preloader-preview-wrapper');
249 const activeTemplateCard = document.querySelector('.ka-preloader-template-card.active .ka-preloader-template-card__animation');
250 const source = liveWrapper || dashWrapper || activeTemplateCard;
251
252 const accent = getVal('accent_color', '#0071e3') || '#0071e3';
253 const textColor = getVal('text_color', '#1d1d1f') || '#1d1d1f';
254 const spinnerSize = parseInt(getVal('spinner_size', '48'), 10) || 48;
255 const bgType = getVal('bg_type', 'solid') || 'solid';
256 const bgColor = getVal('bg_color', '#ffffff') || '#ffffff';
257 const bgStart = getVal('bg_gradient_start', '#ffffff') || '#ffffff';
258 const bgEnd = getVal('bg_gradient_end', '#f5f5f7') || '#f5f5f7';
259 const bgImage = getVal('bg_image', '') || '';
260 const overlayOpacity = Math.max(0, Math.min(1, parseFloat(getVal('overlay_opacity', '1')) || 1));
261
262 let overlayStyle = '';
263 if (bgType === 'gradient') {
264 overlayStyle = 'background: linear-gradient(135deg, ' + bgStart + ' 0%, ' + bgEnd + ' 100%);';
265 } else if (bgType === 'image' && bgImage) {
266 overlayStyle = 'background-image: url(' + bgImage + '); background-size: cover; background-position: center;';
267 } else {
268 overlayStyle = 'background: ' + bgColor + ';';
269 }
270 overlayStyle += ' opacity: ' + overlayOpacity + ';';
271
272 const contentHtml = source ? source.innerHTML : '';
273
274 container.innerHTML = '';
275 const preloader = document.createElement('div');
276 preloader.className = 'kng-site-preloader';
277 preloader.setAttribute('aria-label', 'Preloader Preview');
278 preloader.style.cssText = '--kng-preloader-accent: ' + accent + '; --kng-preloader-text: ' + textColor + '; --kng-preloader-bg: ' + bgColor + '; --kng-preloader-size: ' + spinnerSize + 'px;';
279 preloader.innerHTML = '' +
280 '<div class="kng-site-preloader__overlay" style="' + overlayStyle + '"></div>' +
281 '<div class="kng-site-preloader__content">' + contentHtml + '</div>';
282 container.appendChild(preloader);
283 }
284
285 // Template selection
286 function kaPreloaderSelectTemplate(templateId) {
287 // Update hidden input
288 const hiddenInput = document.getElementById('ka-selected-template');
289 if (hiddenInput) {
290 hiddenInput.value = templateId;
291 }
292
293 // Update active state
294 document.querySelectorAll('.ka-preloader-template-card').forEach(card => {
295 card.classList.toggle('active', card.dataset.template === templateId);
296 });
297 }
298 </script>
299
300 <div class="ka-admin-wrap ka-preloader-admin">
301 <!-- Header -->
302 <div class="ka-admin-header">
303 <div class="ka-admin-header-left">
304 <div class="ka-admin-header-icon orange">
305 <span class="dashicons dashicons-visibility"></span>
306 </div>
307 <div>
308 <h1 class="ka-admin-title"><?php esc_html_e('Site Preloader', 'king-addons'); ?></h1>
309 <p class="ka-admin-subtitle"><?php esc_html_e('Create beautiful loading animations for your website', 'king-addons'); ?></p>
310 </div>
311 </div>
312 <div class="ka-admin-header-actions">
313 <span class="ka-status <?php echo !empty($settings['enabled']) ? 'ka-status-enabled' : 'ka-status-disabled'; ?>">
314 <span class="ka-status-dot"></span>
315 <?php echo !empty($settings['enabled']) ? esc_html__('Enabled', 'king-addons') : esc_html__('Disabled', 'king-addons'); ?>
316 </span>
317 <div class="ka-v3-segmented" id="ka-v3-theme-segment" role="radiogroup" aria-label="<?php echo esc_attr(esc_html__('Theme', 'king-addons')); ?>" data-active="<?php echo esc_attr($theme_mode); ?>">
318 <span class="ka-v3-segmented-indicator" aria-hidden="true"></span>
319 <button type="button" class="ka-v3-segmented-btn" data-theme="light" aria-pressed="<?php echo $theme_mode === 'light' ? 'true' : 'false'; ?>">
320 <span class="ka-v3-segmented-icon" aria-hidden="true">☀︎</span>
321 <?php esc_html_e('Light', 'king-addons'); ?>
322 </button>
323 <button type="button" class="ka-v3-segmented-btn" data-theme="dark" aria-pressed="<?php echo $theme_mode === 'dark' ? 'true' : 'false'; ?>">
324 <span class="ka-v3-segmented-icon" aria-hidden="true"></span>
325 <?php esc_html_e('Dark', 'king-addons'); ?>
326 </button>
327 <button type="button" class="ka-v3-segmented-btn" data-theme="auto" aria-pressed="<?php echo $theme_mode === 'auto' ? 'true' : 'false'; ?>">
328 <span class="ka-v3-segmented-icon" aria-hidden="true"></span>
329 <?php esc_html_e('Auto', 'king-addons'); ?>
330 </button>
331 </div>
332 </div>
333 </div>
334
335 <!-- Success/Error Messages -->
336 <?php if ($updated): ?>
337 <div class="ka-notice ka-notice-success">
338 <span class="dashicons dashicons-yes-alt"></span>
339 <?php esc_html_e('Settings saved successfully!', 'king-addons'); ?>
340 </div>
341 <?php endif; ?>
342
343 <?php if ($imported): ?>
344 <div class="ka-notice ka-notice-success">
345 <span class="dashicons dashicons-yes-alt"></span>
346 <?php esc_html_e('Settings imported successfully!', 'king-addons'); ?>
347 </div>
348 <?php endif; ?>
349
350 <?php if ($reset): ?>
351 <div class="ka-notice ka-notice-success">
352 <span class="dashicons dashicons-yes-alt"></span>
353 <?php esc_html_e('Settings reset to defaults!', 'king-addons'); ?>
354 </div>
355 <?php endif; ?>
356
357 <?php if ($error): ?>
358 <div class="ka-notice ka-notice-error">
359 <span class="dashicons dashicons-warning"></span>
360 <?php
361 switch ($error) {
362 case 'no-file':
363 esc_html_e('Please select a file to import.', 'king-addons');
364 break;
365 case 'invalid-json':
366 esc_html_e('Invalid JSON file. Please check the file and try again.', 'king-addons');
367 break;
368 default:
369 esc_html_e('An error occurred. Please try again.', 'king-addons');
370 }
371 ?>
372 </div>
373 <?php endif; ?>
374
375 <!-- Tabs -->
376 <div class="ka-tabs">
377 <?php foreach ($tabs as $tab_id => $tab_label): ?>
378 <button type="button"
379 class="ka-tab <?php echo $current_tab === $tab_id ? 'active' : ''; ?>"
380 data-tab="<?php echo esc_attr($tab_id); ?>"
381 onclick="kaPreloaderSwitchTab('<?php echo esc_attr($tab_id); ?>')">
382 <?php echo esc_html($tab_label); ?>
383 </button>
384 <?php endforeach; ?>
385 </div>
386
387 <!-- Tab Content: Dashboard -->
388 <div class="ka-tab-content <?php echo $current_tab === 'dashboard' ? 'active' : ''; ?>" data-tab="dashboard">
389 <?php include __DIR__ . '/partials/tab-dashboard.php'; ?>
390 </div>
391
392 <!-- Tab Content: Settings -->
393 <div class="ka-tab-content <?php echo $current_tab === 'settings' ? 'active' : ''; ?>" data-tab="settings">
394 <?php include __DIR__ . '/partials/tab-settings.php'; ?>
395 </div>
396
397 <!-- Tab Content: Templates -->
398 <div class="ka-tab-content <?php echo $current_tab === 'templates' ? 'active' : ''; ?>" data-tab="templates">
399 <?php include __DIR__ . '/partials/tab-templates.php'; ?>
400 </div>
401
402 <!-- Tab Content: Rules -->
403 <div class="ka-tab-content <?php echo $current_tab === 'rules' ? 'active' : ''; ?>" data-tab="rules">
404 <?php include __DIR__ . '/partials/tab-rules.php'; ?>
405 </div>
406
407 <!-- Tab Content: Advanced -->
408 <div class="ka-tab-content <?php echo $current_tab === 'advanced' ? 'active' : ''; ?>" data-tab="advanced">
409 <?php include __DIR__ . '/partials/tab-advanced.php'; ?>
410 </div>
411
412 <!-- Tab Content: Import/Export -->
413 <div class="ka-tab-content <?php echo $current_tab === 'import-export' ? 'active' : ''; ?>" data-tab="import-export">
414 <?php include __DIR__ . '/partials/tab-import-export.php'; ?>
415 </div>
416 </div>
417
418 <!-- Live Preview Modal -->
419 <div id="ka-preloader-preview-modal" class="ka-preloader-preview-modal" style="display: none;">
420 <div class="ka-preloader-preview-modal__backdrop" onclick="kaPreloaderClosePreview()"></div>
421 <div class="ka-preloader-preview-modal__content">
422 <button type="button" class="ka-preloader-preview-modal__close" onclick="kaPreloaderClosePreview()">
423 <span class="dashicons dashicons-no-alt"></span>
424 </button>
425 <div class="ka-preloader-preview-modal__frame">
426 <div id="ka-preloader-preview-container"></div>
427 </div>
428 <div class="ka-preloader-preview-modal__info">
429 <span class="ka-preloader-preview-modal__label"><?php esc_html_e('Preview Mode', 'king-addons'); ?></span>
430 <span class="ka-preloader-preview-modal__hint"><?php esc_html_e('Click anywhere to close', 'king-addons'); ?></span>
431 </div>
432 </div>
433 </div>
434