| 1 |
/** |
| 2 |
* Site Preloader Admin Script. |
| 3 |
* |
| 4 |
* Handles admin UI interactions, live preview, color pickers, media uploaders, and AJAX operations. |
| 5 |
* Premium style inspired smooth interactions. |
| 6 |
* |
| 7 |
* @package King_Addons |
| 8 |
* @since 1.0.0 |
| 9 |
*/ |
| 10 |
|
| 11 |
(function ($) { |
| 12 |
'use strict'; |
| 13 |
|
| 14 |
/** |
| 15 |
* Admin Controller |
| 16 |
*/ |
| 17 |
const KngPreloaderAdmin = { |
| 18 |
|
| 19 |
/** |
| 20 |
* Cached elements |
| 21 |
*/ |
| 22 |
elements: { |
| 23 |
form: null, |
| 24 |
preview: null, |
| 25 |
previewFrame: null, |
| 26 |
previewContent: null, |
| 27 |
colorPickers: null, |
| 28 |
mediaButtons: null, |
| 29 |
tabLinks: null, |
| 30 |
rulesList: null |
| 31 |
}, |
| 32 |
|
| 33 |
/** |
| 34 |
* Current settings state |
| 35 |
*/ |
| 36 |
settings: {}, |
| 37 |
|
| 38 |
/** |
| 39 |
* Initialize admin |
| 40 |
*/ |
| 41 |
init: function () { |
| 42 |
this.cacheElements(); |
| 43 |
this.initColorPickers(); |
| 44 |
this.initMediaUploaders(); |
| 45 |
this.initTabs(); |
| 46 |
this.initPresetSelection(); |
| 47 |
this.initLivePreview(); |
| 48 |
this.initRulesManager(); |
| 49 |
this.initImportExport(); |
| 50 |
this.initDarkModeToggle(); |
| 51 |
this.initFormSubmit(); |
| 52 |
this.initPreviewModal(); |
| 53 |
}, |
| 54 |
|
| 55 |
/** |
| 56 |
* Cache DOM elements |
| 57 |
*/ |
| 58 |
cacheElements: function () { |
| 59 |
this.elements.form = $('#ka-preloader-settings-form'); |
| 60 |
if (!this.elements.form.length) { |
| 61 |
this.elements.form = $('#kng-preloader-settings-form'); |
| 62 |
} |
| 63 |
this.elements.preview = $('.ka-preloader-live-preview'); |
| 64 |
this.elements.previewFrame = $('.ka-preloader-preview-frame'); |
| 65 |
this.elements.previewContent = $('.ka-preloader-preview-content'); |
| 66 |
this.elements.colorPickers = $('.ka-preloader-color-input, .ka-color-picker, .ka-preloader-wp-color-picker'); |
| 67 |
this.elements.mediaButtons = $('.ka-preloader-media-button'); |
| 68 |
this.elements.tabLinks = $('.ka-preloader-tab-link'); |
| 69 |
this.elements.rulesList = $('.ka-preloader-rules-list'); |
| 70 |
}, |
| 71 |
|
| 72 |
/** |
| 73 |
* Initialize color pickers |
| 74 |
*/ |
| 75 |
initColorPickers: function () { |
| 76 |
// Legacy custom preview inputs (if any exist) |
| 77 |
$('.ka-preloader-color-input').each(function () { |
| 78 |
const $input = $(this); |
| 79 |
const $preview = $input.siblings('.ka-preloader-color-preview'); |
| 80 |
|
| 81 |
$input.off('input.kngPreloader change.kngPreloader'); |
| 82 |
$input.on('input.kngPreloader change.kngPreloader', function () { |
| 83 |
const color = $(this).val(); |
| 84 |
$preview.css('background-color', color); |
| 85 |
KngPreloaderAdmin.updatePreview(); |
| 86 |
}); |
| 87 |
|
| 88 |
$preview.css('background-color', $input.val()); |
| 89 |
}); |
| 90 |
|
| 91 |
// Alpha-enabled WordPress color picker |
| 92 |
if ($.fn.wpColorPicker) { |
| 93 |
const $pickers = $('.ka-color-picker, .ka-preloader-wp-color-picker'); |
| 94 |
$pickers.each(function () { |
| 95 |
const $input = $(this); |
| 96 |
if ($input.hasClass('wp-color-picker')) { |
| 97 |
return; |
| 98 |
} |
| 99 |
|
| 100 |
$input.wpColorPicker({ |
| 101 |
defaultColor: $input.data('default-color'), |
| 102 |
change: function () { |
| 103 |
KngPreloaderAdmin.updatePreview(); |
| 104 |
}, |
| 105 |
clear: function () { |
| 106 |
KngPreloaderAdmin.updatePreview(); |
| 107 |
} |
| 108 |
}); |
| 109 |
}); |
| 110 |
} |
| 111 |
}, |
| 112 |
|
| 113 |
/** |
| 114 |
* Initialize media uploaders |
| 115 |
*/ |
| 116 |
initMediaUploaders: function () { |
| 117 |
this.elements.mediaButtons.on('click', function (e) { |
| 118 |
e.preventDefault(); |
| 119 |
|
| 120 |
const $button = $(this); |
| 121 |
const $container = $button.closest('.ka-preloader-media-field'); |
| 122 |
const $input = $container.find('input[type="hidden"]'); |
| 123 |
const $preview = $container.find('.ka-preloader-media-preview'); |
| 124 |
const $removeBtn = $container.find('.ka-preloader-media-remove'); |
| 125 |
|
| 126 |
// Create media frame |
| 127 |
const frame = wp.media({ |
| 128 |
title: $button.data('title') || 'Select Image', |
| 129 |
button: { |
| 130 |
text: $button.data('button-text') || 'Use Image' |
| 131 |
}, |
| 132 |
multiple: false |
| 133 |
}); |
| 134 |
|
| 135 |
// Handle selection |
| 136 |
frame.on('select', function () { |
| 137 |
const attachment = frame.state().get('selection').first().toJSON(); |
| 138 |
|
| 139 |
$input.val(attachment.id); |
| 140 |
|
| 141 |
let imgUrl = attachment.url; |
| 142 |
if (attachment.sizes && attachment.sizes.thumbnail) { |
| 143 |
imgUrl = attachment.sizes.thumbnail.url; |
| 144 |
} |
| 145 |
|
| 146 |
$preview.html('<img src="' + imgUrl + '" alt="" />').show(); |
| 147 |
$removeBtn.show(); |
| 148 |
$button.text('Change Image'); |
| 149 |
|
| 150 |
KngPreloaderAdmin.updatePreview(); |
| 151 |
}); |
| 152 |
|
| 153 |
frame.open(); |
| 154 |
}); |
| 155 |
|
| 156 |
// Handle remove button |
| 157 |
$('.ka-preloader-media-remove').on('click', function (e) { |
| 158 |
e.preventDefault(); |
| 159 |
|
| 160 |
const $button = $(this); |
| 161 |
const $container = $button.closest('.ka-preloader-media-field'); |
| 162 |
const $input = $container.find('input[type="hidden"]'); |
| 163 |
const $preview = $container.find('.ka-preloader-media-preview'); |
| 164 |
const $uploadBtn = $container.find('.ka-preloader-media-button'); |
| 165 |
|
| 166 |
$input.val(''); |
| 167 |
$preview.empty().hide(); |
| 168 |
$button.hide(); |
| 169 |
$uploadBtn.text('Upload Image'); |
| 170 |
|
| 171 |
KngPreloaderAdmin.updatePreview(); |
| 172 |
}); |
| 173 |
}, |
| 174 |
|
| 175 |
/** |
| 176 |
* Initialize tabs |
| 177 |
*/ |
| 178 |
initTabs: function () { |
| 179 |
this.elements.tabLinks.on('click', function (e) { |
| 180 |
e.preventDefault(); |
| 181 |
|
| 182 |
const $link = $(this); |
| 183 |
const tab = $link.data('tab'); |
| 184 |
|
| 185 |
// Update URL without reload |
| 186 |
const url = new URL(window.location); |
| 187 |
url.searchParams.set('tab', tab); |
| 188 |
window.history.replaceState({}, '', url); |
| 189 |
|
| 190 |
// Update active states |
| 191 |
KngPreloaderAdmin.elements.tabLinks.removeClass('active'); |
| 192 |
$link.addClass('active'); |
| 193 |
|
| 194 |
// Show target panel |
| 195 |
$('.ka-preloader-tab-panel').removeClass('active'); |
| 196 |
$('#ka-preloader-tab-' + tab).addClass('active'); |
| 197 |
}); |
| 198 |
}, |
| 199 |
|
| 200 |
/** |
| 201 |
* Initialize preset selection |
| 202 |
*/ |
| 203 |
initPresetSelection: function () { |
| 204 |
$(document).on('click', '.ka-preloader-preset-card', function () { |
| 205 |
const $card = $(this); |
| 206 |
const presetId = $card.data('preset'); |
| 207 |
|
| 208 |
// Update active state |
| 209 |
$('.ka-preloader-preset-card').removeClass('active'); |
| 210 |
$card.addClass('active'); |
| 211 |
|
| 212 |
// Update hidden input |
| 213 |
$('input[name="template"], input[name="preset"]').val(presetId); |
| 214 |
|
| 215 |
// Update preview |
| 216 |
KngPreloaderAdmin.updatePreview(); |
| 217 |
}); |
| 218 |
}, |
| 219 |
|
| 220 |
/** |
| 221 |
* Initialize live preview |
| 222 |
*/ |
| 223 |
initLivePreview: function () { |
| 224 |
// Collect all form inputs |
| 225 |
const $formInputs = this.elements.form.length ? this.elements.form.find('input, select, textarea') : $('input, select, textarea'); |
| 226 |
|
| 227 |
// Update preview on input change |
| 228 |
$formInputs.on('input change', function () { |
| 229 |
KngPreloaderAdmin.debounce(KngPreloaderAdmin.updatePreview, 150)(); |
| 230 |
}); |
| 231 |
|
| 232 |
// Initial preview render |
| 233 |
this.updatePreview(); |
| 234 |
}, |
| 235 |
|
| 236 |
/** |
| 237 |
* Update live preview |
| 238 |
*/ |
| 239 |
updatePreview: function () { |
| 240 |
if (!this.elements.previewContent.length) { |
| 241 |
return; |
| 242 |
} |
| 243 |
|
| 244 |
// Collect current settings |
| 245 |
const settings = this.collectFormSettings(); |
| 246 |
|
| 247 |
const bgColor = settings.bg_color || settings.background_color || 'rgba(0,0,0,0)'; |
| 248 |
const presetId = settings.template || settings.preset || 'spinner-circle'; |
| 249 |
const sizePx = (settings.spinner_size || settings.animation_size || 48) + 'px'; |
| 250 |
|
| 251 |
// Update preview CSS variables |
| 252 |
const $frame = this.elements.previewFrame; |
| 253 |
$frame.css({ |
| 254 |
'--kng-preloader-accent': settings.accent_color || '#0071e3', |
| 255 |
'--kng-preloader-bg': bgColor, |
| 256 |
'--kng-preloader-text': settings.text_color || '#1d1d1f', |
| 257 |
'--kng-preloader-size': sizePx |
| 258 |
}); |
| 259 |
|
| 260 |
// Update background overlay |
| 261 |
const $overlay = this.elements.previewContent.find('.ka-preloader-preview-overlay'); |
| 262 |
if ($overlay.length) { |
| 263 |
$overlay.css('background-color', bgColor); |
| 264 |
} |
| 265 |
|
| 266 |
// Update preset animation |
| 267 |
this.updatePresetAnimation(presetId); |
| 268 |
|
| 269 |
// Update text |
| 270 |
const $text = this.elements.previewContent.find('.ka-preloader-preview-text'); |
| 271 |
if (settings.text_content) { |
| 272 |
$text.text(settings.text_content).show(); |
| 273 |
} else { |
| 274 |
$text.hide(); |
| 275 |
} |
| 276 |
}, |
| 277 |
|
| 278 |
/** |
| 279 |
* Update preset animation in preview |
| 280 |
*/ |
| 281 |
updatePresetAnimation: function (presetId) { |
| 282 |
const $animation = this.elements.previewContent.find('.ka-preloader-preview-animation'); |
| 283 |
if (!$animation.length) { |
| 284 |
return; |
| 285 |
} |
| 286 |
|
| 287 |
// Generate preset HTML |
| 288 |
const presetHtml = this.getPresetHtml(presetId); |
| 289 |
$animation.html(presetHtml); |
| 290 |
}, |
| 291 |
|
| 292 |
/** |
| 293 |
* Get preset HTML |
| 294 |
*/ |
| 295 |
getPresetHtml: function (presetId) { |
| 296 |
const presets = { |
| 297 |
'spinner-circle': '<div class="kng-preloader-spinner-circle"></div>', |
| 298 |
'dual-ring': '<div class="kng-preloader-dual-ring"></div>', |
| 299 |
'dots-bounce': '<div class="kng-preloader-dots-bounce"><span></span><span></span><span></span></div>', |
| 300 |
'bar-loader': '<div class="kng-preloader-bar-loader"><div class="kng-preloader-bar-loader__bar"></div></div>', |
| 301 |
'pulse-logo': '<div class="kng-preloader-pulse-logo"><div class="kng-preloader-pulse-logo__circle"></div></div>', |
| 302 |
'minimal-line': '<div class="kng-preloader-minimal-line"><div class="kng-preloader-minimal-line__track"><div class="kng-preloader-minimal-line__bar"></div></div></div>', |
| 303 |
'gradient-spinner': '<div class="kng-preloader-gradient-spinner"></div>', |
| 304 |
'fade-text': '<div class="kng-preloader-fade-text"><span style="animation-delay: 0s">L</span><span style="animation-delay: 0.1s">o</span><span style="animation-delay: 0.2s">a</span><span style="animation-delay: 0.3s">d</span><span style="animation-delay: 0.4s">i</span><span style="animation-delay: 0.5s">n</span><span style="animation-delay: 0.6s">g</span></div>', |
| 305 |
'cube-grid': '<div class="kng-preloader-cube-grid">' + '<div class="kng-preloader-cube-grid__cube"></div>'.repeat(9) + '</div>', |
| 306 |
'wave-bars': '<div class="kng-preloader-wave-bars">' + '<div class="kng-preloader-wave-bars__bar"></div>'.repeat(5) + '</div>', |
| 307 |
'rotating-squares': '<div class="kng-preloader-rotating-squares"><div class="kng-preloader-rotating-squares__square"></div><div class="kng-preloader-rotating-squares__square"></div></div>', |
| 308 |
'morphing-circle': '<div class="kng-preloader-morphing-circle"></div>' |
| 309 |
}; |
| 310 |
|
| 311 |
return presets[presetId] || presets['spinner-circle']; |
| 312 |
}, |
| 313 |
|
| 314 |
/** |
| 315 |
* Collect form settings |
| 316 |
*/ |
| 317 |
collectFormSettings: function () { |
| 318 |
const settings = {}; |
| 319 |
|
| 320 |
this.elements.form.find('input, select, textarea').each(function () { |
| 321 |
const $field = $(this); |
| 322 |
const name = $field.attr('name'); |
| 323 |
|
| 324 |
if (!name) return; |
| 325 |
|
| 326 |
if ($field.is(':checkbox')) { |
| 327 |
settings[name] = $field.is(':checked') ? '1' : '0'; |
| 328 |
} else if ($field.is(':radio')) { |
| 329 |
if ($field.is(':checked')) { |
| 330 |
settings[name] = $field.val(); |
| 331 |
} |
| 332 |
} else { |
| 333 |
settings[name] = $field.val(); |
| 334 |
} |
| 335 |
}); |
| 336 |
|
| 337 |
return settings; |
| 338 |
}, |
| 339 |
|
| 340 |
/** |
| 341 |
* Initialize rules manager |
| 342 |
*/ |
| 343 |
initRulesManager: function () { |
| 344 |
// Add rule button - support both class and ID |
| 345 |
$(document).on('click', '#ka-add-rule-btn, .ka-preloader-add-rule', function (e) { |
| 346 |
e.preventDefault(); |
| 347 |
KngPreloaderAdmin.addNewRule(); |
| 348 |
}); |
| 349 |
|
| 350 |
// Remove rule button (both classes) - use deleteRule with AJAX |
| 351 |
$(document).on('click', '.ka-preloader-rule-remove, .ka-rule-delete-btn', function (e) { |
| 352 |
e.preventDefault(); |
| 353 |
e.stopPropagation(); |
| 354 |
|
| 355 |
if (!confirm(kngPreloaderAdmin.strings.confirmDelete || 'Are you sure you want to delete this rule?')) { |
| 356 |
return; |
| 357 |
} |
| 358 |
|
| 359 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 360 |
KngPreloaderAdmin.deleteRule($rule); |
| 361 |
}); |
| 362 |
|
| 363 |
// Edit rule button - toggle details |
| 364 |
$(document).on('click', '.ka-rule-edit-btn', function (e) { |
| 365 |
e.preventDefault(); |
| 366 |
e.stopPropagation(); |
| 367 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 368 |
const $details = $rule.find('.ka-preloader-rule-item__details'); |
| 369 |
$details.slideToggle(200); |
| 370 |
}); |
| 371 |
|
| 372 |
// Save rule button |
| 373 |
$(document).on('click', '.ka-rule-save-btn', function (e) { |
| 374 |
e.preventDefault(); |
| 375 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 376 |
KngPreloaderAdmin.saveRule($rule); |
| 377 |
}); |
| 378 |
|
| 379 |
// Cancel rule button |
| 380 |
$(document).on('click', '.ka-rule-cancel-btn', function (e) { |
| 381 |
e.preventDefault(); |
| 382 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 383 |
KngPreloaderAdmin.cancelRuleEdit($rule); |
| 384 |
}); |
| 385 |
|
| 386 |
// Action buttons (Show/Hide/Override) - both old and new class names |
| 387 |
$(document).on('click', '.ka-rule-action-btn, .ka-rule-action-btns .ka-btn', function (e) { |
| 388 |
e.preventDefault(); |
| 389 |
const $btn = $(this); |
| 390 |
const $rule = $btn.closest('.ka-preloader-rule-item'); |
| 391 |
const action = $btn.data('action'); |
| 392 |
|
| 393 |
// Update active state |
| 394 |
$btn.siblings().removeClass('active'); |
| 395 |
$btn.addClass('active'); |
| 396 |
|
| 397 |
// Store in hidden input if exists |
| 398 |
$rule.find('input.ka-rule-action').val(action); |
| 399 |
|
| 400 |
// Show/hide template row (only for override) |
| 401 |
const $templateRow = $rule.find('.ka-rule-template-row'); |
| 402 |
const $colorsToggleRow = $rule.find('.ka-rule-colors-toggle-row'); |
| 403 |
const $colorsRow = $rule.find('.ka-rule-colors-row'); |
| 404 |
|
| 405 |
if (action === 'override') { |
| 406 |
$templateRow.slideDown(200); |
| 407 |
$colorsToggleRow.slideDown(200); |
| 408 |
if ($rule.find('.ka-rule-override-colors').is(':checked')) { |
| 409 |
$colorsRow.slideDown(200); |
| 410 |
} |
| 411 |
} else { |
| 412 |
$templateRow.slideUp(200); |
| 413 |
$colorsToggleRow.slideUp(200); |
| 414 |
$colorsRow.slideUp(200); |
| 415 |
} |
| 416 |
|
| 417 |
// Update header badge |
| 418 |
const actionLabels = { 'show': 'Show', 'hide': 'Hide', 'override': 'Override' }; |
| 419 |
const actionIcons = { 'show': 'visibility', 'hide': 'hidden', 'override': 'admin-customizer' }; |
| 420 |
$rule.find('.ka-preloader-rule-item__summary .ka-rule-action') |
| 421 |
.removeClass('ka-rule-action--show ka-rule-action--hide ka-rule-action--override') |
| 422 |
.addClass('ka-rule-action--' + action) |
| 423 |
.html('<span class="dashicons dashicons-' + actionIcons[action] + '"></span> ' + actionLabels[action]); |
| 424 |
}); |
| 425 |
|
| 426 |
// Toggle rule expansion (header click) |
| 427 |
$(document).on('click', '.ka-preloader-rule-item__header', function (e) { |
| 428 |
// Don't toggle if clicking buttons |
| 429 |
if ($(e.target).closest('button, .ka-toggle, input').length) { |
| 430 |
return; |
| 431 |
} |
| 432 |
|
| 433 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 434 |
const $details = $rule.find('.ka-preloader-rule-item__details'); |
| 435 |
$details.slideToggle(200); |
| 436 |
}); |
| 437 |
|
| 438 |
// Toggle rule expansion (old class for JS-generated rules) |
| 439 |
$(document).on('click', '.ka-preloader-rule-header', function (e) { |
| 440 |
if ($(e.target).closest('button').length) { |
| 441 |
return; |
| 442 |
} |
| 443 |
|
| 444 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 445 |
$rule.toggleClass('expanded'); |
| 446 |
}); |
| 447 |
|
| 448 |
// Rule condition change - show/hide appropriate fields |
| 449 |
$(document).on('change', '.ka-rule-condition', function () { |
| 450 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 451 |
const condition = $(this).val(); |
| 452 |
|
| 453 |
KngPreloaderAdmin.updateConditionFields($rule, condition); |
| 454 |
}); |
| 455 |
|
| 456 |
// Also support old class names |
| 457 |
$(document).on('change', '.ka-preloader-rule-condition, .ka-rule-condition-type', function () { |
| 458 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 459 |
const condition = $(this).val(); |
| 460 |
|
| 461 |
KngPreloaderAdmin.updateRuleConditions($rule, condition); |
| 462 |
}); |
| 463 |
|
| 464 |
// Override colors toggle |
| 465 |
$(document).on('change', '.ka-rule-override-colors', function () { |
| 466 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 467 |
const $colorRows = $rule.find('.ka-rule-colors-row, .ka-rule-colors-grid'); |
| 468 |
|
| 469 |
if ($(this).is(':checked')) { |
| 470 |
$colorRows.slideDown(200); |
| 471 |
} else { |
| 472 |
$colorRows.slideUp(200); |
| 473 |
} |
| 474 |
}); |
| 475 |
|
| 476 |
// Rule type change |
| 477 |
$(document).on('change', '.ka-preloader-rule-type', function () { |
| 478 |
const $rule = $(this).closest('.ka-preloader-rule-item'); |
| 479 |
const type = $(this).val(); |
| 480 |
|
| 481 |
KngPreloaderAdmin.updateRuleConditions($rule, type); |
| 482 |
}); |
| 483 |
|
| 484 |
// Initialize condition fields on page load |
| 485 |
$('.ka-preloader-rule-item').each(function() { |
| 486 |
const $rule = $(this); |
| 487 |
const condition = $rule.find('.ka-rule-condition').val(); |
| 488 |
if (condition) { |
| 489 |
KngPreloaderAdmin.updateConditionFields($rule, condition); |
| 490 |
} |
| 491 |
}); |
| 492 |
}, |
| 493 |
|
| 494 |
/** |
| 495 |
* Update condition fields visibility based on selected condition |
| 496 |
*/ |
| 497 |
updateConditionFields: function ($rule, condition) { |
| 498 |
const $pagesRow = $rule.find('.ka-rule-pages-row'); |
| 499 |
const $posttypeRow = $rule.find('.ka-rule-posttype-row'); |
| 500 |
const $urlRow = $rule.find('.ka-rule-url-row'); |
| 501 |
|
| 502 |
// Hide all conditional rows first |
| 503 |
$pagesRow.hide(); |
| 504 |
$posttypeRow.hide(); |
| 505 |
$urlRow.hide(); |
| 506 |
|
| 507 |
// Show appropriate row based on condition |
| 508 |
switch (condition) { |
| 509 |
case 'specific_pages': |
| 510 |
$pagesRow.slideDown(200); |
| 511 |
break; |
| 512 |
case 'post_type': |
| 513 |
$posttypeRow.slideDown(200); |
| 514 |
break; |
| 515 |
case 'url_contains': |
| 516 |
case 'url_equals': |
| 517 |
$urlRow.slideDown(200); |
| 518 |
break; |
| 519 |
// Other conditions don't need additional fields |
| 520 |
} |
| 521 |
}, |
| 522 |
|
| 523 |
/** |
| 524 |
* Save rule via AJAX |
| 525 |
*/ |
| 526 |
saveRule: function ($rule) { |
| 527 |
const $saveBtn = $rule.find('.ka-rule-save-btn'); |
| 528 |
const originalText = $saveBtn.text(); |
| 529 |
|
| 530 |
// Get action from the active button or hidden input |
| 531 |
let action = 'show'; |
| 532 |
const $activeAction = $rule.find('.ka-rule-action-btn.active, .ka-rule-action-btns .ka-btn.active'); |
| 533 |
if ($activeAction.length) { |
| 534 |
action = $activeAction.data('action'); |
| 535 |
} else { |
| 536 |
const $actionInput = $rule.find('input.ka-rule-action'); |
| 537 |
if ($actionInput.length && $actionInput.val()) { |
| 538 |
action = $actionInput.val(); |
| 539 |
} |
| 540 |
} |
| 541 |
|
| 542 |
// Get condition |
| 543 |
const condition = $rule.find('.ka-rule-condition').val() || 'specific_pages'; |
| 544 |
|
| 545 |
// Get pages as array |
| 546 |
const pages = []; |
| 547 |
$rule.find('.ka-rule-pages option:selected').each(function() { |
| 548 |
pages.push($(this).val()); |
| 549 |
}); |
| 550 |
|
| 551 |
// Collect rule data with new structure |
| 552 |
const ruleData = { |
| 553 |
action: 'king_addons_preloader_save_rule', |
| 554 |
nonce: kngPreloaderAdmin.nonce, |
| 555 |
rule_id: $rule.attr('data-rule-id') || '', |
| 556 |
enabled: $rule.find('.ka-rule-enabled').is(':checked') ? '1' : '0', |
| 557 |
priority: $rule.find('.ka-rule-priority').val() || 10, |
| 558 |
rule_action: action, // show / hide / override |
| 559 |
condition: condition, |
| 560 |
condition_value: $rule.find('.ka-rule-condition-value, .ka-rule-url-value, .ka-rule-posttype').val() || '', |
| 561 |
pages: pages, |
| 562 |
template: $rule.find('.ka-rule-template').val() || '', |
| 563 |
override_colors: $rule.find('.ka-rule-override-colors').is(':checked') ? '1' : '0', |
| 564 |
bg_color: $rule.find('.ka-rule-bg-color').val() || '#ffffff', |
| 565 |
accent_color: $rule.find('.ka-rule-accent-color').val() || '#0071e3' |
| 566 |
}; |
| 567 |
|
| 568 |
// Show saving state |
| 569 |
$saveBtn.text('Saving...').prop('disabled', true); |
| 570 |
|
| 571 |
// console.log('Saving rule:', ruleData); |
| 572 |
|
| 573 |
// Send AJAX request |
| 574 |
$.ajax({ |
| 575 |
url: kngPreloaderAdmin.ajaxUrl, |
| 576 |
type: 'POST', |
| 577 |
data: ruleData, |
| 578 |
success: function (response) { |
| 579 |
// console.log('Save response:', response); |
| 580 |
if (response.success) { |
| 581 |
// Update rule ID if it was a new rule |
| 582 |
if (response.data.rule && response.data.rule.id) { |
| 583 |
$rule.attr('data-rule-id', response.data.rule.id); |
| 584 |
} |
| 585 |
|
| 586 |
// Update header display |
| 587 |
const actionLabels = { 'show': 'Show', 'hide': 'Hide', 'override': 'Override' }; |
| 588 |
const conditionLabels = { |
| 589 |
'specific_pages': 'Specific Pages', |
| 590 |
'all_pages': 'All Pages', |
| 591 |
'front_page': 'Front Page', |
| 592 |
'blog_page': 'Blog Page', |
| 593 |
'all_posts': 'All Posts', |
| 594 |
'post_type': 'Post Type', |
| 595 |
'archive': 'Archive', |
| 596 |
'search': 'Search', |
| 597 |
'404': '404 Page', |
| 598 |
'url_contains': 'URL Contains', |
| 599 |
'url_equals': 'URL Equals' |
| 600 |
}; |
| 601 |
|
| 602 |
$rule.find('.ka-preloader-rule-item__action').text(actionLabels[action] || action); |
| 603 |
$rule.find('.ka-preloader-rule-item__type').text(conditionLabels[condition] || condition); |
| 604 |
|
| 605 |
// Show pages count for specific_pages |
| 606 |
if (condition === 'specific_pages' && pages.length > 0) { |
| 607 |
$rule.find('.ka-preloader-rule-item__value').text(pages.length + ' page(s)'); |
| 608 |
} else { |
| 609 |
$rule.find('.ka-preloader-rule-item__value').text(ruleData.condition_value || ''); |
| 610 |
} |
| 611 |
|
| 612 |
// Hide details |
| 613 |
$rule.find('.ka-preloader-rule-item__details').slideUp(200); |
| 614 |
|
| 615 |
// Show success |
| 616 |
$saveBtn.text('Saved!'); |
| 617 |
setTimeout(() => { |
| 618 |
$saveBtn.text(originalText).prop('disabled', false); |
| 619 |
}, 1500); |
| 620 |
} else { |
| 621 |
alert(response.data?.message || kngPreloaderAdmin.strings.error); |
| 622 |
$saveBtn.text(originalText).prop('disabled', false); |
| 623 |
} |
| 624 |
}, |
| 625 |
error: function () { |
| 626 |
alert(kngPreloaderAdmin.strings.error); |
| 627 |
$saveBtn.text(originalText).prop('disabled', false); |
| 628 |
} |
| 629 |
}); |
| 630 |
}, |
| 631 |
|
| 632 |
/** |
| 633 |
* Delete rule via AJAX |
| 634 |
*/ |
| 635 |
deleteRule: function ($rule) { |
| 636 |
const ruleId = $rule.attr('data-rule-id'); |
| 637 |
|
| 638 |
// If it's a new unsaved rule, just remove from DOM |
| 639 |
if (!ruleId || ruleId.startsWith('new_')) { |
| 640 |
$rule.slideUp(200, function () { |
| 641 |
$(this).remove(); |
| 642 |
KngPreloaderAdmin.checkEmptyRules(); |
| 643 |
}); |
| 644 |
return; |
| 645 |
} |
| 646 |
|
| 647 |
// Send AJAX request |
| 648 |
$.ajax({ |
| 649 |
url: kngPreloaderAdmin.ajaxUrl, |
| 650 |
type: 'POST', |
| 651 |
data: { |
| 652 |
action: 'king_addons_preloader_delete_rule', |
| 653 |
nonce: kngPreloaderAdmin.nonce, |
| 654 |
rule_id: ruleId |
| 655 |
}, |
| 656 |
success: function (response) { |
| 657 |
if (response.success) { |
| 658 |
$rule.slideUp(200, function () { |
| 659 |
$(this).remove(); |
| 660 |
KngPreloaderAdmin.checkEmptyRules(); |
| 661 |
KngPreloaderAdmin.updateRuleIndices(); |
| 662 |
}); |
| 663 |
} else { |
| 664 |
alert(response.data?.message || kngPreloaderAdmin.strings.error); |
| 665 |
} |
| 666 |
}, |
| 667 |
error: function () { |
| 668 |
alert(kngPreloaderAdmin.strings.error); |
| 669 |
} |
| 670 |
}); |
| 671 |
}, |
| 672 |
|
| 673 |
/** |
| 674 |
* Cancel rule edit |
| 675 |
*/ |
| 676 |
cancelRuleEdit: function ($rule) { |
| 677 |
const ruleId = $rule.attr('data-rule-id'); |
| 678 |
|
| 679 |
// If it's a new unsaved rule, remove it |
| 680 |
if (ruleId && ruleId.startsWith('new_')) { |
| 681 |
$rule.slideUp(200, function () { |
| 682 |
$(this).remove(); |
| 683 |
KngPreloaderAdmin.checkEmptyRules(); |
| 684 |
}); |
| 685 |
} else { |
| 686 |
// Just hide details for existing rules |
| 687 |
$rule.find('.ka-preloader-rule-item__details').slideUp(200); |
| 688 |
} |
| 689 |
}, |
| 690 |
|
| 691 |
/** |
| 692 |
* Check if rules list is empty and show empty state |
| 693 |
*/ |
| 694 |
checkEmptyRules: function () { |
| 695 |
const $rulesList = $('#ka-rules-list'); |
| 696 |
const rulesCount = $rulesList.find('.ka-preloader-rule-item').length; |
| 697 |
|
| 698 |
if (rulesCount === 0) { |
| 699 |
$('#ka-rules-empty').show(); |
| 700 |
} |
| 701 |
}, |
| 702 |
|
| 703 |
/** |
| 704 |
* Add new rule |
| 705 |
*/ |
| 706 |
addNewRule: function () { |
| 707 |
// Get rules list, try ID first then class |
| 708 |
let $rulesList = $('#ka-rules-list'); |
| 709 |
if (!$rulesList.length) { |
| 710 |
$rulesList = this.elements.rulesList; |
| 711 |
} |
| 712 |
|
| 713 |
if (!$rulesList.length) { |
| 714 |
// console.error('Rules list container not found'); |
| 715 |
return; |
| 716 |
} |
| 717 |
|
| 718 |
// Hide empty state |
| 719 |
$('#ka-rules-empty').hide(); |
| 720 |
|
| 721 |
// Try to use template from PHP first |
| 722 |
const $template = $('#ka-rule-template'); |
| 723 |
let $newRule; |
| 724 |
|
| 725 |
if ($template.length) { |
| 726 |
// Clone template content |
| 727 |
$newRule = $($template.html()).clone(); |
| 728 |
$newRule.attr('data-rule-id', 'new_' + Date.now()); |
| 729 |
$newRule.find('.ka-preloader-rule-item__details').show(); |
| 730 |
} else { |
| 731 |
// Fallback to JS-generated HTML |
| 732 |
const ruleIndex = $rulesList.find('.ka-preloader-rule-item').length; |
| 733 |
$newRule = $(` |
| 734 |
<div class="ka-preloader-rule-item expanded" data-index="${ruleIndex}"> |
| 735 |
<div class="ka-preloader-rule-header"> |
| 736 |
<span class="ka-preloader-rule-title">New Rule</span> |
| 737 |
<div class="ka-preloader-rule-actions"> |
| 738 |
<button type="button" class="ka-preloader-rule-remove"> |
| 739 |
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 740 |
<path d="M18 6L6 18M6 6l12 12"/> |
| 741 |
</svg> |
| 742 |
</button> |
| 743 |
</div> |
| 744 |
</div> |
| 745 |
<div class="ka-preloader-rule-content"> |
| 746 |
<div class="ka-preloader-rule-field"> |
| 747 |
<label>Rule Name</label> |
| 748 |
<input type="text" name="rules[${ruleIndex}][name]" value="New Rule" class="ka-preloader-rule-name"> |
| 749 |
</div> |
| 750 |
<div class="ka-preloader-rule-field"> |
| 751 |
<label>Rule Type</label> |
| 752 |
<select name="rules[${ruleIndex}][type]" class="ka-preloader-rule-type"> |
| 753 |
<option value="include">Show On (Include)</option> |
| 754 |
<option value="exclude">Hide On (Exclude)</option> |
| 755 |
</select> |
| 756 |
</div> |
| 757 |
<div class="ka-preloader-rule-field"> |
| 758 |
<label>Condition</label> |
| 759 |
<select name="rules[${ruleIndex}][condition]" class="ka-preloader-rule-condition"> |
| 760 |
<option value="entire_site">Entire Site</option> |
| 761 |
<option value="front_page">Front Page</option> |
| 762 |
<option value="blog_page">Blog Page</option> |
| 763 |
<option value="posts">All Posts</option> |
| 764 |
<option value="pages">All Pages</option> |
| 765 |
<option value="archives">Archives</option> |
| 766 |
<option value="search">Search Results</option> |
| 767 |
<option value="404">404 Page</option> |
| 768 |
<option value="specific_page">Specific Page</option> |
| 769 |
<option value="specific_post">Specific Post</option> |
| 770 |
</select> |
| 771 |
</div> |
| 772 |
<div class="ka-preloader-rule-field ka-preloader-rule-value-field" style="display: none;"> |
| 773 |
<label>Value</label> |
| 774 |
<input type="text" name="rules[${ruleIndex}][value]" class="ka-preloader-rule-value" placeholder="Enter ID or slug"> |
| 775 |
</div> |
| 776 |
<div class="ka-preloader-rule-field"> |
| 777 |
<label> |
| 778 |
<input type="checkbox" name="rules[${ruleIndex}][enabled]" value="1" checked> |
| 779 |
Enable this rule |
| 780 |
</label> |
| 781 |
</div> |
| 782 |
</div> |
| 783 |
</div> |
| 784 |
`); |
| 785 |
} |
| 786 |
|
| 787 |
$rulesList.append($newRule); |
| 788 |
|
| 789 |
// Initialize WP color picker on newly added rule (alpha-enabled) |
| 790 |
if ($newRule && $newRule.length) { |
| 791 |
const $newPickers = $newRule.find('.ka-color-picker, .ka-preloader-wp-color-picker'); |
| 792 |
if ($.fn.wpColorPicker && $newPickers.length) { |
| 793 |
$newPickers.each(function () { |
| 794 |
const $input = $(this); |
| 795 |
if ($input.hasClass('wp-color-picker')) { |
| 796 |
return; |
| 797 |
} |
| 798 |
|
| 799 |
$input.wpColorPicker({ |
| 800 |
defaultColor: $input.data('default-color'), |
| 801 |
change: function () { |
| 802 |
KngPreloaderAdmin.updatePreview(); |
| 803 |
}, |
| 804 |
clear: function () { |
| 805 |
KngPreloaderAdmin.updatePreview(); |
| 806 |
} |
| 807 |
}); |
| 808 |
}); |
| 809 |
} |
| 810 |
} |
| 811 |
|
| 812 |
// Scroll to new rule |
| 813 |
if ($newRule && $newRule[0]) { |
| 814 |
$newRule[0].scrollIntoView({ behavior: 'smooth', block: 'center' }); |
| 815 |
} |
| 816 |
}, |
| 817 |
|
| 818 |
/** |
| 819 |
* Update rule conditions based on type |
| 820 |
*/ |
| 821 |
updateRuleConditions: function ($rule, condition) { |
| 822 |
// Find value field (support both class naming conventions) |
| 823 |
const $valueField = $rule.find('.ka-preloader-rule-value-field'); |
| 824 |
const $conditionValueRow = $rule.find('.ka-row').filter(function() { |
| 825 |
return $(this).find('.ka-rule-condition-value').length > 0; |
| 826 |
}); |
| 827 |
|
| 828 |
// Conditions that need a value input |
| 829 |
const needsValue = ['url_contains', 'url_equals', 'url_regex', 'query_param', 'specific_page', 'specific_post', 'specific_cpt', 'post_type', 'page_template']; |
| 830 |
|
| 831 |
if (needsValue.includes(condition)) { |
| 832 |
$valueField.slideDown(200); |
| 833 |
$conditionValueRow.slideDown(200); |
| 834 |
} else { |
| 835 |
$valueField.slideUp(200); |
| 836 |
$conditionValueRow.slideUp(200); |
| 837 |
} |
| 838 |
}, |
| 839 |
|
| 840 |
/** |
| 841 |
* Update rule indices after deletion |
| 842 |
*/ |
| 843 |
updateRuleIndices: function () { |
| 844 |
this.elements.rulesList.find('.ka-preloader-rule-item').each(function (index) { |
| 845 |
const $rule = $(this); |
| 846 |
$rule.attr('data-index', index); |
| 847 |
|
| 848 |
// Update all input names |
| 849 |
$rule.find('input, select').each(function () { |
| 850 |
const $field = $(this); |
| 851 |
const name = $field.attr('name'); |
| 852 |
if (name) { |
| 853 |
$field.attr('name', name.replace(/\[\d+\]/, '[' + index + ']')); |
| 854 |
} |
| 855 |
}); |
| 856 |
}); |
| 857 |
}, |
| 858 |
|
| 859 |
/** |
| 860 |
* Initialize import/export |
| 861 |
*/ |
| 862 |
initImportExport: function () { |
| 863 |
// Export button |
| 864 |
$(document).on('click', '.ka-preloader-export-btn', function (e) { |
| 865 |
e.preventDefault(); |
| 866 |
KngPreloaderAdmin.exportSettings(); |
| 867 |
}); |
| 868 |
|
| 869 |
// Import button |
| 870 |
$(document).on('click', '.ka-preloader-import-btn', function (e) { |
| 871 |
e.preventDefault(); |
| 872 |
KngPreloaderAdmin.importSettings(); |
| 873 |
}); |
| 874 |
|
| 875 |
// Copy to clipboard |
| 876 |
$(document).on('click', '.ka-preloader-copy-btn', function (e) { |
| 877 |
e.preventDefault(); |
| 878 |
const $textarea = $(this).siblings('textarea'); |
| 879 |
$textarea.select(); |
| 880 |
document.execCommand('copy'); |
| 881 |
|
| 882 |
const $btn = $(this); |
| 883 |
const originalText = $btn.text(); |
| 884 |
$btn.text('Copied!'); |
| 885 |
setTimeout(() => $btn.text(originalText), 2000); |
| 886 |
}); |
| 887 |
}, |
| 888 |
|
| 889 |
/** |
| 890 |
* Export settings |
| 891 |
*/ |
| 892 |
exportSettings: function () { |
| 893 |
const settings = this.collectFormSettings(); |
| 894 |
const exportData = JSON.stringify(settings, null, 2); |
| 895 |
|
| 896 |
const $exportArea = $('.ka-preloader-export-area'); |
| 897 |
$exportArea.val(exportData).show(); |
| 898 |
}, |
| 899 |
|
| 900 |
/** |
| 901 |
* Import settings |
| 902 |
*/ |
| 903 |
importSettings: function () { |
| 904 |
const $importArea = $('.ka-preloader-import-area'); |
| 905 |
const importData = $importArea.val().trim(); |
| 906 |
|
| 907 |
if (!importData) { |
| 908 |
alert('Please paste settings JSON to import.'); |
| 909 |
return; |
| 910 |
} |
| 911 |
|
| 912 |
try { |
| 913 |
const settings = JSON.parse(importData); |
| 914 |
this.applyImportedSettings(settings); |
| 915 |
alert('Settings imported successfully! Please save to apply.'); |
| 916 |
} catch (e) { |
| 917 |
alert('Invalid JSON format. Please check your import data.'); |
| 918 |
} |
| 919 |
}, |
| 920 |
|
| 921 |
/** |
| 922 |
* Apply imported settings to form |
| 923 |
*/ |
| 924 |
applyImportedSettings: function (settings) { |
| 925 |
for (const [key, value] of Object.entries(settings)) { |
| 926 |
const $field = this.elements.form.find('[name="' + key + '"]'); |
| 927 |
|
| 928 |
if (!$field.length) continue; |
| 929 |
|
| 930 |
if ($field.is(':checkbox')) { |
| 931 |
$field.prop('checked', value === '1'); |
| 932 |
} else if ($field.is(':radio')) { |
| 933 |
$field.filter('[value="' + value + '"]').prop('checked', true); |
| 934 |
} else if ($field.is('select')) { |
| 935 |
$field.val(value); |
| 936 |
} else { |
| 937 |
$field.val(value); |
| 938 |
} |
| 939 |
} |
| 940 |
|
| 941 |
// Update preview |
| 942 |
this.updatePreview(); |
| 943 |
|
| 944 |
// Update preset card selection |
| 945 |
const preset = settings.template || settings.preset; |
| 946 |
if (preset) { |
| 947 |
$('.ka-preloader-preset-card').removeClass('active'); |
| 948 |
$('.ka-preloader-preset-card[data-preset="' + preset + '"]').addClass('active'); |
| 949 |
} |
| 950 |
}, |
| 951 |
|
| 952 |
/** |
| 953 |
* Initialize dark mode toggle |
| 954 |
*/ |
| 955 |
initDarkModeToggle: function () { |
| 956 |
$(document).on('change', '.ka-preloader-dark-toggle input', function () { |
| 957 |
const isDark = $(this).is(':checked'); |
| 958 |
|
| 959 |
if (isDark) { |
| 960 |
$('.ka-preloader-admin-page').addClass('dark-mode'); |
| 961 |
localStorage.setItem('kng_preloader_dark_mode', '1'); |
| 962 |
} else { |
| 963 |
$('.ka-preloader-admin-page').removeClass('dark-mode'); |
| 964 |
localStorage.setItem('kng_preloader_dark_mode', '0'); |
| 965 |
} |
| 966 |
}); |
| 967 |
|
| 968 |
// Restore preference |
| 969 |
const savedDarkMode = localStorage.getItem('kng_preloader_dark_mode'); |
| 970 |
if (savedDarkMode === '1') { |
| 971 |
$('.ka-preloader-dark-toggle input').prop('checked', true).trigger('change'); |
| 972 |
} |
| 973 |
}, |
| 974 |
|
| 975 |
/** |
| 976 |
* Initialize form submit |
| 977 |
*/ |
| 978 |
initFormSubmit: function () { |
| 979 |
this.elements.form.on('submit', function (e) { |
| 980 |
// Let the form submit naturally, just show a loading state |
| 981 |
const $submitBtn = $(this).find('button[type="submit"]'); |
| 982 |
$submitBtn.prop('disabled', true).text('Saving...'); |
| 983 |
}); |
| 984 |
}, |
| 985 |
|
| 986 |
/** |
| 987 |
* Initialize preview modal |
| 988 |
*/ |
| 989 |
initPreviewModal: function () { |
| 990 |
$(document).on('click', '.ka-preloader-full-preview-btn', function (e) { |
| 991 |
e.preventDefault(); |
| 992 |
KngPreloaderAdmin.openPreviewModal(); |
| 993 |
}); |
| 994 |
|
| 995 |
// Close on Escape key |
| 996 |
$(document).on('keydown', function (e) { |
| 997 |
if (e.key === 'Escape') { |
| 998 |
KngPreloaderAdmin.closePreviewModal(); |
| 999 |
} |
| 1000 |
}); |
| 1001 |
}, |
| 1002 |
|
| 1003 |
/** |
| 1004 |
* Open preview modal |
| 1005 |
*/ |
| 1006 |
openPreviewModal: function () { |
| 1007 |
// Prefer template-provided modal implementation when available. |
| 1008 |
if (typeof window.kaPreloaderOpenPreview === 'function') { |
| 1009 |
window.kaPreloaderOpenPreview(); |
| 1010 |
return; |
| 1011 |
} |
| 1012 |
|
| 1013 |
const settings = this.collectFormSettings(); |
| 1014 |
const $modal = $('.ka-preloader-preview-modal'); |
| 1015 |
|
| 1016 |
if (!$modal.length) { |
| 1017 |
return; |
| 1018 |
} |
| 1019 |
|
| 1020 |
// Build preview HTML |
| 1021 |
const bgColor = settings.bg_color || settings.background_color || 'rgba(0,0,0,0)'; |
| 1022 |
const presetId = settings.template || settings.preset || 'spinner-circle'; |
| 1023 |
const sizePx = (settings.spinner_size || settings.animation_size || 48) + 'px'; |
| 1024 |
|
| 1025 |
const presetHtml = this.getPresetHtml(presetId); |
| 1026 |
const previewHtml = ` |
| 1027 |
<div class="kng-site-preloader" style=" |
| 1028 |
--kng-preloader-accent: ${settings.accent_color || '#0071e3'}; |
| 1029 |
--kng-preloader-bg: ${bgColor}; |
| 1030 |
--kng-preloader-text: ${settings.text_color || '#1d1d1f'}; |
| 1031 |
--kng-preloader-size: ${sizePx}; |
| 1032 |
"> |
| 1033 |
<div class="kng-site-preloader__overlay" style="background: ${bgColor}"></div> |
| 1034 |
<div class="kng-site-preloader__content"> |
| 1035 |
<div class="kng-site-preloader__animation">${presetHtml}</div> |
| 1036 |
${settings.text_content ? '<div class="kng-site-preloader__text">' + settings.text_content + '</div>' : ''} |
| 1037 |
</div> |
| 1038 |
</div> |
| 1039 |
`; |
| 1040 |
|
| 1041 |
const $container = $('#ka-preloader-preview-container'); |
| 1042 |
if ($container.length) { |
| 1043 |
$container.html(previewHtml); |
| 1044 |
$modal.css('display', 'flex'); |
| 1045 |
$('body').css('overflow', 'hidden'); |
| 1046 |
} |
| 1047 |
}, |
| 1048 |
|
| 1049 |
/** |
| 1050 |
* Close preview modal |
| 1051 |
*/ |
| 1052 |
closePreviewModal: function () { |
| 1053 |
// Prefer template-provided modal implementation when available. |
| 1054 |
if (typeof window.kaPreloaderClosePreview === 'function') { |
| 1055 |
window.kaPreloaderClosePreview(); |
| 1056 |
return; |
| 1057 |
} |
| 1058 |
|
| 1059 |
const $modal = $('.ka-preloader-preview-modal'); |
| 1060 |
if ($modal.length) { |
| 1061 |
$modal.css('display', 'none').removeClass('active'); |
| 1062 |
} |
| 1063 |
$('body').css('overflow', '').removeClass('ka-preloader-modal-open'); |
| 1064 |
}, |
| 1065 |
|
| 1066 |
/** |
| 1067 |
* Debounce helper |
| 1068 |
*/ |
| 1069 |
debounce: function (func, wait) { |
| 1070 |
let timeout; |
| 1071 |
return function executedFunction(...args) { |
| 1072 |
const later = () => { |
| 1073 |
clearTimeout(timeout); |
| 1074 |
func.apply(KngPreloaderAdmin, args); |
| 1075 |
}; |
| 1076 |
clearTimeout(timeout); |
| 1077 |
timeout = setTimeout(later, wait); |
| 1078 |
}; |
| 1079 |
} |
| 1080 |
}; |
| 1081 |
|
| 1082 |
// Initialize on DOM ready |
| 1083 |
$(document).ready(function () { |
| 1084 |
KngPreloaderAdmin.init(); |
| 1085 |
}); |
| 1086 |
|
| 1087 |
// Expose globally for debugging |
| 1088 |
window.KngPreloaderAdmin = KngPreloaderAdmin; |
| 1089 |
|
| 1090 |
})(jQuery); |
| 1091 |
|