| 1 |
// noinspection DuplicatedCode,JSUnresolvedReference,JSValidateTypes |
| 2 |
|
| 3 |
jQuery(document).ready(function ($) { |
| 4 |
$(document).on('click', '.template-item', function () { |
| 5 |
let templateKey = $(this).data('template-key'); |
| 6 |
let templatePlan = $(this).data('template-plan'); |
| 7 |
let templateBtn = $('#install-template'); |
| 8 |
templateBtn.attr('data-template-key', templateKey); |
| 9 |
templateBtn.attr('data-template-plan', templatePlan); |
| 10 |
let planActive = templateBtn.attr('data-plan-active'); |
| 11 |
|
| 12 |
if (templatePlan === 'premium') { |
| 13 |
if (planActive === 'premium') { |
| 14 |
templateBtn.text('Import Premium Template'); |
| 15 |
} else { |
| 16 |
templateBtn.text('Import Premium Template'); |
| 17 |
} |
| 18 |
} else { |
| 19 |
templateBtn.text('Import Free Template'); |
| 20 |
} |
| 21 |
|
| 22 |
$('#template-preview-iframe').attr('src', 'https://demo.kingaddons.com/' + templateKey); |
| 23 |
$('#template-preview-link').attr('href', 'https://demo.kingaddons.com/' + templateKey); |
| 24 |
$('#template-preview-popup').fadeIn(); |
| 25 |
}); |
| 26 |
|
| 27 |
// Listen for clicks on any button inside .preview-mode-switcher |
| 28 |
$('.preview-mode-switcher button').on('click', function () { |
| 29 |
// Remove the .active class from all buttons |
| 30 |
$('.preview-mode-switcher button').removeClass('active'); |
| 31 |
// Add .active to the clicked button |
| 32 |
$(this).addClass('active'); |
| 33 |
|
| 34 |
// Determine which mode was clicked: desktop, tablet, or mobile |
| 35 |
let mode = $(this).data('mode'); |
| 36 |
|
| 37 |
// Select the preview iframe |
| 38 |
let $iframe = $('#template-preview-iframe'); |
| 39 |
|
| 40 |
// Remove any previous mode classes |
| 41 |
$iframe.removeClass('preview-tablet preview-mobile'); |
| 42 |
|
| 43 |
// If tablet, add .preview-tablet class |
| 44 |
if (mode === 'tablet') { |
| 45 |
$iframe.addClass('preview-tablet'); |
| 46 |
} |
| 47 |
// If mobile, add .preview-mobile class |
| 48 |
else if (mode === 'mobile') { |
| 49 |
$iframe.addClass('preview-mobile'); |
| 50 |
} |
| 51 |
// If desktop, no extra class (width:100% by default). |
| 52 |
}); |
| 53 |
|
| 54 |
$(document).on('click', '#close-popup', function () { |
| 55 |
$('#template-preview-popup').fadeOut(); |
| 56 |
}); |
| 57 |
|
| 58 |
$(document).on('click', '#activate-license-btn', function () { |
| 59 |
$('#templates-catalog').addClass('kng-whole-overlay'); |
| 60 |
$('#license-activating-popup').fadeIn(); |
| 61 |
}); |
| 62 |
|
| 63 |
$(document).on('click', '#close-license-activating-popup', function () { |
| 64 |
$('#templates-catalog').removeClass('kng-whole-overlay'); |
| 65 |
$('#license-activating-popup').fadeOut(); |
| 66 |
}); |
| 67 |
|
| 68 |
$(document).on('click', '#close-premium-promo-popup', function () { |
| 69 |
$('#templates-catalog').removeClass('kng-whole-overlay'); |
| 70 |
$('#premium-promo-popup').fadeOut(); |
| 71 |
}); |
| 72 |
|
| 73 |
$(document).on('click', '#close-installing-popup', function () { |
| 74 |
$('#templates-catalog').removeClass('kng-whole-overlay'); |
| 75 |
$('#template-installing-popup').fadeOut(); |
| 76 |
$('#go-to-imported-page').fadeOut(); |
| 77 |
$('#close-installing-popup').fadeOut(); |
| 78 |
document.getElementById('final_response').innerText = ''; |
| 79 |
document.getElementById('progress').innerText = ''; |
| 80 |
document.getElementById('progress-bar').style.width = '0%'; |
| 81 |
document.getElementById('progress-bar').innerText = '0%'; |
| 82 |
}); |
| 83 |
|
| 84 |
$(document).on('click', '#install-template', function () { |
| 85 |
|
| 86 |
$('#templates-catalog').addClass('kng-whole-overlay'); |
| 87 |
$('#template-preview-popup').fadeOut(); |
| 88 |
|
| 89 |
let templateBtn = $('#install-template'); |
| 90 |
let templateKey = templateBtn.attr('data-template-key'); |
| 91 |
let templatePlan = templateBtn.attr('data-template-plan'); |
| 92 |
let planActive = templateBtn.attr('data-plan-active'); |
| 93 |
|
| 94 |
let api_request_url; |
| 95 |
let installId; |
| 96 |
|
| 97 |
if (planActive === 'premium') { |
| 98 |
if (templatePlan === 'premium') { |
| 99 |
api_request_url = 'https://api.kingaddons.com/get-template.php'; |
| 100 |
installId = window.kingAddons.installId; |
| 101 |
} else { |
| 102 |
api_request_url = 'https://api.kingaddons.com/get-template-free.php'; |
| 103 |
installId = 0; |
| 104 |
} |
| 105 |
} else { |
| 106 |
if (templatePlan === 'free') { |
| 107 |
api_request_url = 'https://api.kingaddons.com/get-template-free.php'; |
| 108 |
installId = 0; |
| 109 |
} else { |
| 110 |
$('#premium-promo-popup').fadeIn(); |
| 111 |
return; |
| 112 |
} |
| 113 |
} |
| 114 |
|
| 115 |
fetch(api_request_url, { |
| 116 |
method: 'POST', |
| 117 |
headers: { |
| 118 |
'Content-Type': 'application/json', |
| 119 |
}, |
| 120 |
body: JSON.stringify({ |
| 121 |
key: templateKey, |
| 122 |
install: installId, |
| 123 |
}), |
| 124 |
}) |
| 125 |
.then(response => { |
| 126 |
if (!response.ok) { |
| 127 |
// The server returned a 4xx or 5xx, read the text and throw an error |
| 128 |
return response.text().then(html => { |
| 129 |
console.error('Server error:\n' + html); |
| 130 |
throw new Error('Server error (not JSON).'); |
| 131 |
}); |
| 132 |
} |
| 133 |
// If ok, parse JSON |
| 134 |
return response.json(); |
| 135 |
}) |
| 136 |
.then(data => { |
| 137 |
if (!data.success) { |
| 138 |
console.error('API error:', data); |
| 139 |
} |
| 140 |
if (data.success) { |
| 141 |
$('#template-installing-popup').fadeIn(); |
| 142 |
doImport(data); |
| 143 |
} else { |
| 144 |
$('#premium-promo-popup').fadeIn(); |
| 145 |
} |
| 146 |
}) |
| 147 |
.catch(error => { |
| 148 |
console.error('Fetch error:', error); |
| 149 |
alert('Connection error: ' + error); |
| 150 |
}); |
| 151 |
}); |
| 152 |
|
| 153 |
function doImport(data) { |
| 154 |
document.getElementById('progress').innerText = 'Starting import...'; |
| 155 |
document.getElementById('image-list').innerHTML = ''; |
| 156 |
document.getElementById('progress').innerText = 'Import initialized.'; |
| 157 |
document.getElementById('progress-bar').style.width = '10%'; |
| 158 |
document.getElementById('progress-bar').innerText = '10%'; |
| 159 |
|
| 160 |
let images = data.landing.images; |
| 161 |
|
| 162 |
if (images && images.length > 0) { |
| 163 |
let imageList = images.map(function (img) { |
| 164 |
return '<li data-id="' + img.id + '" data-url="' + img.url + '">' + img.url + ' (ID: ' + img.id + ')</li>'; |
| 165 |
}).join(''); |
| 166 |
|
| 167 |
document.getElementById('image-list').innerHTML = '<ul>' + imageList + '</ul>'; |
| 168 |
|
| 169 |
startImport(data.landing); |
| 170 |
} else { |
| 171 |
document.getElementById('final_response').innerText = 'No images to import.'; |
| 172 |
} |
| 173 |
} |
| 174 |
|
| 175 |
function startImport(initial_data) { |
| 176 |
fetch(kingAddonsData.ajaxUrl, { |
| 177 |
method: 'POST', |
| 178 |
body: new URLSearchParams({ |
| 179 |
action: 'import_elementor_page_with_images', |
| 180 |
data: JSON.stringify(initial_data), |
| 181 |
}) |
| 182 |
}) |
| 183 |
.then(response => { |
| 184 |
if (!response.ok) { |
| 185 |
// The server returned a 4xx or 5xx, read the text and throw an error |
| 186 |
return response.text().then(html => { |
| 187 |
console.error('Server error:\n' + html); |
| 188 |
throw new Error('Server error:\n' + html); |
| 189 |
}); |
| 190 |
} |
| 191 |
// If ok, parse JSON |
| 192 |
return response.json(); |
| 193 |
}) |
| 194 |
.then(data => { |
| 195 |
if (data.success) { |
| 196 |
processNextImage(); |
| 197 |
} else { |
| 198 |
alert('Error getting template: ' + data.message); |
| 199 |
} |
| 200 |
}) |
| 201 |
.catch(error => { |
| 202 |
alert('Error: ' + error); |
| 203 |
}); |
| 204 |
} |
| 205 |
|
| 206 |
function processNextImage() { |
| 207 |
const maxRetries = 3; |
| 208 |
let currentRetry = 0; |
| 209 |
let retryTimeout = 1000; |
| 210 |
|
| 211 |
function attemptProcessImage() { |
| 212 |
fetch(kingAddonsData.ajaxUrl, { |
| 213 |
method: 'POST', |
| 214 |
body: new URLSearchParams({ |
| 215 |
action: 'process_import_images', |
| 216 |
}) |
| 217 |
}) |
| 218 |
.then(response => { |
| 219 |
if (!response.ok) { |
| 220 |
// The server returned a 4xx or 5xx, read the text and throw an error |
| 221 |
return response.text().then(html => { |
| 222 |
console.error('Server error:\n' + html); |
| 223 |
throw new Error('Server error:\n' + html); |
| 224 |
}); |
| 225 |
} |
| 226 |
// If ok, parse JSON |
| 227 |
return response.json(); |
| 228 |
}) |
| 229 |
.then(data => { |
| 230 |
if (data.success) { |
| 231 |
if (data.data.progress !== undefined) { |
| 232 |
|
| 233 |
let progressBar = document.getElementById('progress-bar'); |
| 234 |
let progress = data.data.progress; |
| 235 |
progressBar.style.width = progress + '%'; |
| 236 |
progressBar.innerText = progress + '%'; |
| 237 |
|
| 238 |
document.getElementById('progress').innerText = data.data.message; |
| 239 |
|
| 240 |
let imageUrlElement = document.querySelector('li[data-url="' + data.data.image_url + '"]'); |
| 241 |
if (imageUrlElement) { |
| 242 |
imageUrlElement.innerHTML += ' - done'; |
| 243 |
} |
| 244 |
currentRetry = 0; |
| 245 |
retryTimeout = 1000; |
| 246 |
processNextImage(); |
| 247 |
} else { |
| 248 |
// Both templates and sections from main admin catalog create new pages |
| 249 |
document.getElementById('final_response').innerText = data.data.message; |
| 250 |
document.getElementById('progress').innerText = 'Import completed.'; |
| 251 |
document.getElementById('progress-bar').style.width = '100%'; |
| 252 |
document.getElementById('progress-bar').innerText = '100%'; |
| 253 |
let goToPage = $('#go-to-imported-page'); |
| 254 |
goToPage.attr('href', data.data.page_url); |
| 255 |
goToPage.fadeIn(); |
| 256 |
$('#close-installing-popup').fadeIn(); |
| 257 |
} |
| 258 |
} else { |
| 259 |
console.error('Process image issue:', data); |
| 260 |
// Skip image |
| 261 |
if (data.data && data.data.retry) { |
| 262 |
processNextImage(); |
| 263 |
} |
| 264 |
} |
| 265 |
}) |
| 266 |
.catch(error => { |
| 267 |
console.error('Catch Error:', error); |
| 268 |
if (currentRetry < maxRetries) { |
| 269 |
currentRetry++; |
| 270 |
retryTimeout *= 2; |
| 271 |
setTimeout(attemptProcessImage, retryTimeout); |
| 272 |
} else { |
| 273 |
let imageUrlElement = document.querySelector('li[data-url="unknown"]'); |
| 274 |
if (imageUrlElement) { |
| 275 |
imageUrlElement.innerHTML += ' - SKIPPED'; |
| 276 |
} |
| 277 |
console.error('Error:', error); |
| 278 |
document.getElementById('final_response').innerText = 'Error: ' + error.message; |
| 279 |
currentRetry = 0; |
| 280 |
retryTimeout = 1000; |
| 281 |
processNextImage(); |
| 282 |
} |
| 283 |
}); |
| 284 |
} |
| 285 |
|
| 286 |
attemptProcessImage(); |
| 287 |
} |
| 288 |
|
| 289 |
$(document).on('click', '.pagination a', function (e) { |
| 290 |
e.preventDefault(); |
| 291 |
let page = $(this).attr('href').split('paged=')[1]; |
| 292 |
filterTemplates(page); |
| 293 |
}); |
| 294 |
|
| 295 |
let templateSearch = $('#template-search'); |
| 296 |
let templateCategory = $('#template-category'); |
| 297 |
let templateCollection = $('#template-collection'); |
| 298 |
|
| 299 |
function filterTemplates(page = 1) { |
| 300 |
let searchQuery = templateSearch.val().toLowerCase(); |
| 301 |
let selectedCategory = templateCategory.val(); |
| 302 |
let selectedCollection = templateCollection.val(); |
| 303 |
let selectedTags = []; |
| 304 |
|
| 305 |
$('#template-tags input:checked').each(function () { |
| 306 |
selectedTags.push($(this).val()); |
| 307 |
}); |
| 308 |
|
| 309 |
$.ajax({ |
| 310 |
url: kingAddonsData.ajaxUrl, |
| 311 |
type: 'POST', |
| 312 |
data: { |
| 313 |
action: 'filter_templates', |
| 314 |
s: searchQuery, |
| 315 |
category: selectedCategory, |
| 316 |
collection: selectedCollection, |
| 317 |
tags: selectedTags.join(','), |
| 318 |
paged: page |
| 319 |
}, |
| 320 |
success: function (response) { |
| 321 |
if (response.success) { |
| 322 |
|
| 323 |
// Scroll to top after the new content is loaded with admin bar offset |
| 324 |
const scrollOffset = $('#king-addons-templates-top').offset().top - 32; // Subtract 32px for admin bar |
| 325 |
$('html, body').animate({scrollTop: scrollOffset}, 0); |
| 326 |
|
| 327 |
$('.templates-grid').html(response.data.grid_html); |
| 328 |
$('.pagination').html(response.data.pagination_html); |
| 329 |
} else { |
| 330 |
alert('Error: ' + response.data); |
| 331 |
} |
| 332 |
}, |
| 333 |
error: function (xhr, status, error) { |
| 334 |
console.error('AJAX Error: ', status, error); |
| 335 |
} |
| 336 |
}); |
| 337 |
} |
| 338 |
|
| 339 |
templateSearch.on('keyup', function () { |
| 340 |
templateCategory.val(''); |
| 341 |
templateCollection.val(''); |
| 342 |
$('#template-tags input:checked').prop('checked', false); |
| 343 |
filterTemplates(); |
| 344 |
}); |
| 345 |
|
| 346 |
templateCategory.on('change', function () { |
| 347 |
templateSearch.val(''); |
| 348 |
templateCollection.val(''); |
| 349 |
$('#template-tags input:checked').prop('checked', false); |
| 350 |
filterTemplates(); |
| 351 |
}); |
| 352 |
|
| 353 |
templateCollection.on('change', function () { |
| 354 |
templateSearch.val(''); |
| 355 |
templateCategory.val(''); |
| 356 |
$('#template-tags input:checked').prop('checked', false); |
| 357 |
filterTemplates(); |
| 358 |
}); |
| 359 |
|
| 360 |
$('#template-tags input').on('change', function () { |
| 361 |
templateSearch.val(''); |
| 362 |
templateCategory.val(''); |
| 363 |
templateCollection.val(''); |
| 364 |
if ($(this).is(':checked')) { |
| 365 |
$('#template-tags input').not(this).prop('checked', false); |
| 366 |
} |
| 367 |
filterTemplates(); |
| 368 |
}); |
| 369 |
|
| 370 |
$('#reset-filters').on('click', function () { |
| 371 |
templateSearch.val(''); |
| 372 |
templateCategory.val(''); |
| 373 |
templateCollection.val(''); |
| 374 |
$('#template-tags input:checked').prop('checked', false); |
| 375 |
filterTemplates(); |
| 376 |
}); |
| 377 |
|
| 378 |
// Load sections count on page load |
| 379 |
if ($('#sections-count').length) { |
| 380 |
loadSectionsCount(); |
| 381 |
} |
| 382 |
|
| 383 |
// ===== TABS FUNCTIONALITY ===== |
| 384 |
|
| 385 |
// Tab switching |
| 386 |
$('.king-addons-tab-button').on('click', function() { |
| 387 |
var tabId = $(this).data('tab'); |
| 388 |
|
| 389 |
// Remove active class from all tabs and content |
| 390 |
$('.king-addons-tab-button').removeClass('active'); |
| 391 |
$('.king-addons-tab-content').removeClass('active'); |
| 392 |
|
| 393 |
// Add active class to clicked tab and corresponding content |
| 394 |
$(this).addClass('active'); |
| 395 |
$('#' + tabId + '-catalog').addClass('active'); |
| 396 |
|
| 397 |
// Load sections on first visit to sections tab |
| 398 |
if (tabId === 'sections' && !window.sectionsLoaded) { |
| 399 |
loadSections(); |
| 400 |
} |
| 401 |
}); |
| 402 |
|
| 403 |
// ===== SECTIONS FUNCTIONALITY ===== |
| 404 |
|
| 405 |
window.sectionsLoaded = false; |
| 406 |
window.sectionsData = null; |
| 407 |
window.sectionsPage = 1; |
| 408 |
window.sectionsFilters = {}; |
| 409 |
|
| 410 |
function loadSections(page = 1) { |
| 411 |
if (!window.kingAddonsData || !window.kingAddonsData.ajaxUrl) { |
| 412 |
console.error('King Addons data not available'); |
| 413 |
return; |
| 414 |
} |
| 415 |
|
| 416 |
var searchQuery = $('#sections-search').val() || ''; |
| 417 |
var selectedCategory = $('#sections-category').val() || ''; |
| 418 |
var selectedType = $('#sections-type').val() || ''; |
| 419 |
var selectedPlan = $('#sections-plan').val() || ''; |
| 420 |
|
| 421 |
$('.sections-grid').html(` |
| 422 |
<div class="sections-loading"> |
| 423 |
Loading sections... |
| 424 |
</div> |
| 425 |
`); |
| 426 |
|
| 427 |
$.ajax({ |
| 428 |
url: window.kingAddonsData.ajaxUrl, |
| 429 |
type: 'POST', |
| 430 |
data: { |
| 431 |
action: 'king_addons_get_sections_catalog', |
| 432 |
nonce: window.kingAddonsData.nonce || '', |
| 433 |
search: searchQuery, |
| 434 |
category: selectedCategory, |
| 435 |
section_type: selectedType, |
| 436 |
plan: selectedPlan, |
| 437 |
page: page |
| 438 |
}, |
| 439 |
success: function(response) { |
| 440 |
if (response.success) { |
| 441 |
// Scroll to top after new content is loaded with admin bar offset (same as templates) |
| 442 |
const scrollOffset = $('#king-addons-templates-top').offset().top - 32; // Subtract 32px for admin bar |
| 443 |
$('html, body').animate({scrollTop: scrollOffset}, 0); |
| 444 |
|
| 445 |
window.sectionsData = response.data; |
| 446 |
window.sectionsLoaded = true; |
| 447 |
renderSections(); |
| 448 |
updateSectionsFilters(); |
| 449 |
updateSectionsCount(); |
| 450 |
} else { |
| 451 |
$('.sections-grid').html(` |
| 452 |
<div class="sections-loading"> |
| 453 |
Error loading sections: ${response.data || 'Unknown error'} |
| 454 |
</div> |
| 455 |
`); |
| 456 |
} |
| 457 |
}, |
| 458 |
error: function(xhr, status, error) { |
| 459 |
console.error('AJAX Error loading sections:', status, error); |
| 460 |
$('.sections-grid').html(` |
| 461 |
<div class="sections-loading"> |
| 462 |
Failed to load sections. Please try again. |
| 463 |
</div> |
| 464 |
`); |
| 465 |
} |
| 466 |
}); |
| 467 |
} |
| 468 |
|
| 469 |
function renderSections() { |
| 470 |
if (!window.sectionsData || !window.sectionsData.sections) { |
| 471 |
$('.sections-grid').html(` |
| 472 |
<div class="sections-loading"> |
| 473 |
<p>No sections found. Try adjusting your search or filters to find more sections.</p> |
| 474 |
</div> |
| 475 |
`); |
| 476 |
return; |
| 477 |
} |
| 478 |
|
| 479 |
var sectionsHtml = ''; |
| 480 |
var sections = window.sectionsData.sections; |
| 481 |
|
| 482 |
sections.forEach(function(section) { |
| 483 |
// Use the correct screenshot URL pattern with plan-based paths |
| 484 |
var screenshotUrl = `https://thumbnails.kingaddons.com/sections/${section.plan}/${section.section_key}.png?v=4`; |
| 485 |
|
| 486 |
sectionsHtml += ` |
| 487 |
<div class="section-item" |
| 488 |
data-section-key="${section.section_key}" |
| 489 |
data-section-plan="${section.plan}" |
| 490 |
data-category="${section.category || ''}" |
| 491 |
data-tags="${(section.tags || []).join(',')}" |
| 492 |
data-section-type="${section.section_type || ''}"> |
| 493 |
<img class="kng-addons-section-thumbnail" loading="lazy" |
| 494 |
src="${screenshotUrl}" |
| 495 |
alt="${section.title}" |
| 496 |
onerror="this.src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjE4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImciIHgxPSIwJSIgeTE9IjAlIiB4Mj0iMTAwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNmOGY5ZmEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlNWU3ZWIiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2cpIi8+PGNpcmNsZSBjeD0iMTUwIiBjeT0iNzAiIHI9IjE2IiBmaWxsPSIjOWNhM2FmIiBvcGFjaXR5PSIwLjQiLz48cmVjdCB4PSIxMzQiIHk9Ijg2IiB3aWR0aD0iMzIiIGhlaWdodD0iNCIgZmlsbD0iIzljYTNhZiIgb3BhY2l0eT0iMC40IiByeD0iMiIvPjxyZWN0IHg9IjEyNiIgeT0iOTQiIHdpZHRoPSI0OCIgaGVpZ2h0PSI0IiBmaWxsPSIjOWNhM2FmIiBvcGFjaXR5PSIwLjMiIHJ4PSIyIi8+PHRleHQgeD0iNTAlIiB5PSIxMjAiIGZvbnQtZmFtaWx5PSItYXBwbGUtc3lzdGVtLCBCbGlua01hY1N5c3RlbUZvbnQsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IiM2Yjc1ODQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIG9wYWNpdHk9IjAuNyI+U2VjdGlvbiBQcmV2aWV3PC90ZXh0Pjwvc3ZnPg=='"> |
| 497 |
<div class="section-content"> |
| 498 |
<h3>${section.title}</h3> |
| 499 |
<div class="section-plan section-plan-${section.plan}">${section.plan}</div> |
| 500 |
</div> |
| 501 |
<div class="section-overlay"> |
| 502 |
<div class="section-actions"> |
| 503 |
<button class="section-import-btn" data-section-key="${section.section_key}" data-section-plan="${section.plan}"> |
| 504 |
Import Section |
| 505 |
</button> |
| 506 |
<a href="https://sections.kingaddons.com/${section.section_key}" class="section-preview-btn" target="_blank"> |
| 507 |
Live Preview |
| 508 |
</a> |
| 509 |
</div> |
| 510 |
</div> |
| 511 |
</div> |
| 512 |
`; |
| 513 |
}); |
| 514 |
|
| 515 |
$('.sections-grid').html(sectionsHtml); |
| 516 |
|
| 517 |
// Render pagination if available |
| 518 |
if (window.sectionsData.pagination) { |
| 519 |
renderSectionsPagination(); |
| 520 |
} |
| 521 |
} |
| 522 |
|
| 523 |
|
| 524 |
|
| 525 |
function renderSectionsPagination() { |
| 526 |
var pagination = window.sectionsData.pagination; |
| 527 |
var paginationHtml = ''; |
| 528 |
|
| 529 |
if (pagination.total_pages > 1) { |
| 530 |
paginationHtml += '<div class="pagination-inner">'; |
| 531 |
|
| 532 |
var current = pagination.current_page; |
| 533 |
var total = pagination.total_pages; |
| 534 |
var endSize = 3; // Show 3 pages at beginning and end |
| 535 |
var midSize = 2; // Show 2 pages around current |
| 536 |
|
| 537 |
// Previous page |
| 538 |
if (current > 1) { |
| 539 |
paginationHtml += `<a class="page-numbers" href="#" data-page="${current - 1}">← Previous</a>`; |
| 540 |
} |
| 541 |
|
| 542 |
// Smart pagination logic with proper ellipsis |
| 543 |
var pages = []; |
| 544 |
|
| 545 |
// Always show first pages |
| 546 |
for (var i = 1; i <= Math.min(endSize, total); i++) { |
| 547 |
pages.push(i); |
| 548 |
} |
| 549 |
|
| 550 |
// Calculate middle range around current page |
| 551 |
var start = Math.max(current - midSize, 1); |
| 552 |
var end = Math.min(current + midSize, total); |
| 553 |
|
| 554 |
// Add first ellipsis if there's a gap |
| 555 |
if (start > endSize + 1) { |
| 556 |
pages.push('...'); |
| 557 |
} |
| 558 |
|
| 559 |
// Add middle pages around current (avoid duplicates with start/end) |
| 560 |
for (var i = Math.max(start, endSize + 1); i <= Math.min(end, total - endSize); i++) { |
| 561 |
if (pages.indexOf(i) === -1) { |
| 562 |
pages.push(i); |
| 563 |
} |
| 564 |
} |
| 565 |
|
| 566 |
// Add second ellipsis if there's a gap |
| 567 |
if (end < total - endSize) { |
| 568 |
pages.push('...'); |
| 569 |
} |
| 570 |
|
| 571 |
// Always show last pages (avoid duplicates) |
| 572 |
for (var i = Math.max(total - endSize + 1, endSize + 1); i <= total; i++) { |
| 573 |
if (pages.indexOf(i) === -1) { |
| 574 |
pages.push(i); |
| 575 |
} |
| 576 |
} |
| 577 |
|
| 578 |
// Render pages |
| 579 |
pages.forEach(function(page) { |
| 580 |
if (page === '...') { |
| 581 |
paginationHtml += `<span class="page-numbers dots">…</span>`; |
| 582 |
} else if (page === current) { |
| 583 |
paginationHtml += `<span class="page-numbers current">${page}</span>`; |
| 584 |
} else { |
| 585 |
paginationHtml += `<a class="page-numbers" href="#" data-page="${page}">${page}</a>`; |
| 586 |
} |
| 587 |
}); |
| 588 |
|
| 589 |
// Next page |
| 590 |
if (current < total) { |
| 591 |
paginationHtml += `<a class="page-numbers" href="#" data-page="${current + 1}">Next →</a>`; |
| 592 |
} |
| 593 |
|
| 594 |
paginationHtml += '</div>'; |
| 595 |
} |
| 596 |
|
| 597 |
$('.sections-pagination').html(paginationHtml); |
| 598 |
} |
| 599 |
|
| 600 |
function updateSectionsFilters() { |
| 601 |
if (!window.sectionsData) return; |
| 602 |
|
| 603 |
// Update categories dropdown |
| 604 |
var categoriesHtml = '<option value="">All Categories</option>'; |
| 605 |
if (window.sectionsData.categories) { |
| 606 |
window.sectionsData.categories.forEach(function(category) { |
| 607 |
var displayName = category.charAt(0).toUpperCase() + category.slice(1).replace(/-/g, ' '); |
| 608 |
categoriesHtml += `<option value="${category}">${displayName}</option>`; |
| 609 |
}); |
| 610 |
} |
| 611 |
$('#sections-category').html(categoriesHtml); |
| 612 |
|
| 613 |
// Update types dropdown |
| 614 |
var typesHtml = '<option value="">All Types</option>'; |
| 615 |
if (window.sectionsData.section_types) { |
| 616 |
window.sectionsData.section_types.forEach(function(type) { |
| 617 |
var displayName = type.charAt(0).toUpperCase() + type.slice(1).replace(/-/g, ' '); |
| 618 |
typesHtml += `<option value="${type}">${displayName}</option>`; |
| 619 |
}); |
| 620 |
} |
| 621 |
$('#sections-type').html(typesHtml); |
| 622 |
} |
| 623 |
|
| 624 |
function updateSectionsCount() { |
| 625 |
if (window.sectionsData && window.sectionsData.pagination) { |
| 626 |
$('#sections-count').text(window.sectionsData.pagination.total_sections); |
| 627 |
} |
| 628 |
} |
| 629 |
|
| 630 |
// Sections filters event handlers - Same logic as templates |
| 631 |
var sectionsSearch = $('#sections-search'); |
| 632 |
var sectionsCategory = $('#sections-category'); |
| 633 |
var sectionsType = $('#sections-type'); |
| 634 |
var sectionsPlan = $('#sections-plan'); |
| 635 |
|
| 636 |
sectionsSearch.on('keyup', function() { |
| 637 |
// Reset other filters when searching (same as templates) |
| 638 |
sectionsCategory.val(''); |
| 639 |
sectionsType.val(''); |
| 640 |
sectionsPlan.val(''); |
| 641 |
|
| 642 |
clearTimeout(window.sectionsSearchTimeout); |
| 643 |
window.sectionsSearchTimeout = setTimeout(function() { |
| 644 |
loadSections(1); |
| 645 |
}, 500); |
| 646 |
}); |
| 647 |
|
| 648 |
sectionsCategory.on('change', function() { |
| 649 |
// Reset search and other filters (same as templates) |
| 650 |
sectionsSearch.val(''); |
| 651 |
sectionsType.val(''); |
| 652 |
sectionsPlan.val(''); |
| 653 |
loadSections(1); |
| 654 |
}); |
| 655 |
|
| 656 |
sectionsType.on('change', function() { |
| 657 |
// Reset search and other filters (same as templates) |
| 658 |
sectionsSearch.val(''); |
| 659 |
sectionsCategory.val(''); |
| 660 |
sectionsPlan.val(''); |
| 661 |
loadSections(1); |
| 662 |
}); |
| 663 |
|
| 664 |
sectionsPlan.on('change', function() { |
| 665 |
// Reset search and other filters (same as templates) |
| 666 |
sectionsSearch.val(''); |
| 667 |
sectionsCategory.val(''); |
| 668 |
sectionsType.val(''); |
| 669 |
loadSections(1); |
| 670 |
}); |
| 671 |
|
| 672 |
$('#sections-reset-filters').on('click', function() { |
| 673 |
sectionsSearch.val(''); |
| 674 |
sectionsCategory.val(''); |
| 675 |
sectionsType.val(''); |
| 676 |
sectionsPlan.val(''); |
| 677 |
loadSections(1); |
| 678 |
}); |
| 679 |
|
| 680 |
// Sections pagination handler |
| 681 |
$(document).on('click', '.sections-pagination .page-numbers', function(e) { |
| 682 |
e.preventDefault(); |
| 683 |
var page = $(this).data('page'); |
| 684 |
if (page) { |
| 685 |
loadSections(page); |
| 686 |
} |
| 687 |
}); |
| 688 |
|
| 689 |
// Section import button handler |
| 690 |
$(document).on('click', '.section-import-btn', function(e) { |
| 691 |
e.preventDefault(); |
| 692 |
e.stopPropagation(); // Prevent triggering parent click |
| 693 |
|
| 694 |
var sectionKey = $(this).data('section-key'); |
| 695 |
var sectionPlan = $(this).data('section-plan'); |
| 696 |
|
| 697 |
// Check if this is a premium section and user doesn't have premium |
| 698 |
var planActive = $('#install-template').attr('data-plan-active'); |
| 699 |
|
| 700 |
if (sectionPlan === 'premium' && planActive !== 'premium') { |
| 701 |
// Show premium promo popup |
| 702 |
$('#templates-catalog').addClass('kng-whole-overlay'); |
| 703 |
$('#premium-promo-popup').fadeIn(); |
| 704 |
return; |
| 705 |
} |
| 706 |
|
| 707 |
// For free sections or premium sections with premium license, trigger import |
| 708 |
if (confirm('Import this section?\n\nSection: ' + sectionKey + '\nPlan: ' + sectionPlan + '\n\nNote: This will be added to your current page in Elementor.')) { |
| 709 |
importSection(sectionKey, sectionPlan); |
| 710 |
} |
| 711 |
}); |
| 712 |
|
| 713 |
// Section preview button handler (handled by href, but we can add tracking here) |
| 714 |
$(document).on('click', '.section-preview-btn', function(e) { |
| 715 |
e.stopPropagation(); // Prevent triggering parent click |
| 716 |
// The link will open in new tab automatically due to target="_blank" |
| 717 |
}); |
| 718 |
|
| 719 |
// Section item click handler - now only for general clicks (not on buttons) |
| 720 |
$(document).on('click', '.section-item', function(e) { |
| 721 |
// Don't trigger if clicking on buttons or overlay |
| 722 |
if ($(e.target).closest('.section-overlay, .section-import-btn, .section-preview-btn').length) { |
| 723 |
return; |
| 724 |
} |
| 725 |
|
| 726 |
var sectionKey = $(this).data('section-key'); |
| 727 |
var sectionPlan = $(this).data('section-plan'); |
| 728 |
|
| 729 |
// Check if this is a premium section and user doesn't have premium |
| 730 |
var planActive = $('#install-template').attr('data-plan-active'); |
| 731 |
|
| 732 |
if (sectionPlan === 'premium' && planActive !== 'premium') { |
| 733 |
// Show premium promo popup |
| 734 |
$('#templates-catalog').addClass('kng-whole-overlay'); |
| 735 |
$('#premium-promo-popup').fadeIn(); |
| 736 |
return; |
| 737 |
} |
| 738 |
|
| 739 |
// For free sections or premium sections with premium license, trigger import |
| 740 |
if (confirm('Import this section?\n\nSection: ' + sectionKey + '\nPlan: ' + sectionPlan + '\n\nNote: This will be added to your current page in Elementor.')) { |
| 741 |
importSection(sectionKey, sectionPlan); |
| 742 |
} |
| 743 |
}); |
| 744 |
|
| 745 |
// Function to import section from main catalog |
| 746 |
function importSection(sectionKey, sectionPlan) { |
| 747 |
// Show importing popup |
| 748 |
$('#templates-catalog').addClass('kng-whole-overlay'); |
| 749 |
$('#template-installing-popup').fadeIn(); |
| 750 |
|
| 751 |
// Initialize progress |
| 752 |
document.getElementById('progress').innerText = 'Loading section data...'; |
| 753 |
document.getElementById('progress-bar').style.width = '5%'; |
| 754 |
document.getElementById('progress-bar').innerText = '5%'; |
| 755 |
|
| 756 |
// Get section data |
| 757 |
$.ajax({ |
| 758 |
url: window.kingAddonsData.ajaxUrl, |
| 759 |
type: 'POST', |
| 760 |
data: { |
| 761 |
action: 'king_addons_import_section_admin', |
| 762 |
nonce: window.kingAddonsData.nonce, |
| 763 |
section_key: sectionKey, |
| 764 |
section_plan: sectionPlan |
| 765 |
}, |
| 766 |
success: function(response) { |
| 767 |
if (response.success) { |
| 768 |
var sectionData = response.data.section_data; |
| 769 |
var imageCount = sectionData.images ? sectionData.images.length : 0; |
| 770 |
|
| 771 |
document.getElementById('progress').innerText = 'Section loaded! Found ' + imageCount + ' images to process...'; |
| 772 |
document.getElementById('progress-bar').style.width = '25%'; |
| 773 |
document.getElementById('progress-bar').innerText = '25%'; |
| 774 |
|
| 775 |
// Process section import (use existing system) |
| 776 |
processSectionImport(sectionData); |
| 777 |
} else { |
| 778 |
document.getElementById('progress').innerText = 'Error: ' + (response.data || 'Failed to load section'); |
| 779 |
$('#close-installing-popup').fadeIn(); |
| 780 |
} |
| 781 |
}, |
| 782 |
error: function(xhr, status, error) { |
| 783 |
document.getElementById('progress').innerText = 'Network error: ' + error; |
| 784 |
$('#close-installing-popup').fadeIn(); |
| 785 |
} |
| 786 |
}); |
| 787 |
} |
| 788 |
|
| 789 |
// Process section import using existing Templates system |
| 790 |
function processSectionImport(sectionData) { |
| 791 |
document.getElementById('progress').innerText = 'Preparing section import...'; |
| 792 |
document.getElementById('progress-bar').style.width = '45%'; |
| 793 |
document.getElementById('progress-bar').innerText = '45%'; |
| 794 |
|
| 795 |
// Use existing Templates import system |
| 796 |
var importData = { |
| 797 |
content: sectionData.content, |
| 798 |
images: sectionData.images || [], |
| 799 |
title: sectionData.title || 'Imported Section', |
| 800 |
elementor_version: sectionData.elementor_version || '3.0.0', |
| 801 |
existing_page_id: 0, |
| 802 |
create_new_page: true // Create new page for sections from main admin catalog |
| 803 |
}; |
| 804 |
|
| 805 |
// Call Templates import system |
| 806 |
$.ajax({ |
| 807 |
url: window.kingAddonsData.ajaxUrl, |
| 808 |
type: 'POST', |
| 809 |
data: { |
| 810 |
action: 'import_elementor_page_with_images', |
| 811 |
data: JSON.stringify(importData) |
| 812 |
}, |
| 813 |
success: function(result) { |
| 814 |
if (result.success) { |
| 815 |
document.getElementById('progress').innerText = 'Section import initialized! Processing images...'; |
| 816 |
document.getElementById('progress-bar').style.width = '65%'; |
| 817 |
document.getElementById('progress-bar').innerText = '65%'; |
| 818 |
|
| 819 |
// Start processing images using existing system |
| 820 |
processNextImage(); |
| 821 |
} else { |
| 822 |
document.getElementById('progress').innerText = 'Error: ' + (result.data || 'Failed to initialize section import'); |
| 823 |
$('#close-installing-popup').fadeIn(); |
| 824 |
} |
| 825 |
}, |
| 826 |
error: function(xhr, status, error) { |
| 827 |
document.getElementById('progress').innerText = 'Import error: ' + error; |
| 828 |
$('#close-installing-popup').fadeIn(); |
| 829 |
} |
| 830 |
}); |
| 831 |
} |
| 832 |
|
| 833 |
// Load sections count for tab |
| 834 |
function loadSectionsCount() { |
| 835 |
$.ajax({ |
| 836 |
url: window.kingAddonsData.ajaxUrl, |
| 837 |
type: 'POST', |
| 838 |
data: { |
| 839 |
action: 'king_addons_get_sections_catalog', |
| 840 |
nonce: window.kingAddonsData.nonce || '', |
| 841 |
search: '', |
| 842 |
category: '', |
| 843 |
section_type: '', |
| 844 |
plan: '', |
| 845 |
page: 1 |
| 846 |
}, |
| 847 |
success: function(response) { |
| 848 |
if (response.success && response.data.pagination) { |
| 849 |
$('#sections-count').text(response.data.pagination.total_sections); |
| 850 |
} |
| 851 |
}, |
| 852 |
error: function(xhr, status, error) { |
| 853 |
console.log('Failed to load sections count:', error); |
| 854 |
} |
| 855 |
}); |
| 856 |
} |
| 857 |
}); |
| 858 |
|