/home/techb158/balacoffee.com/wp-content/plugins/coming-soon/admin/js
NameSizeModeActions
admin.js1652670644editdlrm
review-notice.js21750644editdlrm
Edit: /home/techb158/balacoffee.com/wp-content/plugins/coming-soon/admin/js/admin.js (165267B)
/** * Admin JavaScript for SeedProd WordPress-native pages */ (function( $ ) { 'use strict'; $( document ).ready( function() { // Fix menu expansion for hidden pages (function() { var currentPage = new URLSearchParams(window.location.search).get('page'); var $seedprodMenu = $('#toplevel_page_seedprod_lite'); if (!$seedprodMenu.length) return; // Handle hidden pages that need menu expansion switch(currentPage) { case 'seedprod_lite_theme_kits_selection': // Expand menu and highlight Website Builder $seedprodMenu.removeClass('wp-not-current-submenu').addClass('wp-has-current-submenu wp-menu-open'); $seedprodMenu.find('.wp-submenu').show(); $seedprodMenu.find('a[href="admin.php?page=seedprod_lite_website_builder"]').parent().addClass('current'); break; case 'seedprod_lite_template_selection': // Expand menu and highlight Landing Pages $seedprodMenu.removeClass('wp-not-current-submenu').addClass('wp-has-current-submenu wp-menu-open'); $seedprodMenu.find('.wp-submenu').show(); $seedprodMenu.find('.wp-submenu li').removeClass('current'); $seedprodMenu.find('a[href="admin.php?page=seedprod_lite_landing_pages"]').parent().addClass('current'); break; } })(); // Handle notification dismissal $(document).on('click', '.seedprod-notification-dismiss', function(e) { e.preventDefault(); var $notification = $(this).closest('.seedprod-notification-bar'); var notificationId = $notification.data('id'); // Fade out the notification immediately for better UX $notification.fadeOut(300); // Make AJAX call to dismiss notification permanently $.post(seedprod_admin.ajax_url, { action: 'seedprod_lite_notification_dismiss', id: notificationId, _wpnonce: seedprod_admin.notification_dismiss_nonce }, function(response) { // Notification already hidden, no further action needed }).fail(function() { // If dismiss fails, show notification again $notification.fadeIn(300); }); }); // Dashboard-specific functionality (exclude landing pages) if ( $( '.seedprod-dashboard-page' ).length && ! $( '.seedprod-landing-pages-page' ).length ) { initDashboard(); } // Landing Pages-specific functionality if ( $( '.seedprod-landing-pages-page' ).length ) { initLandingPages(); } // Template Selection-specific functionality if ( $( '.seedprod-template-selection-page' ).length ) { initTemplateSelection(); } // Theme Kits Selection-specific functionality if ( $( '.seedprod-theme-kits-selection-page' ).length ) { initThemeKitsSelection(); } // Settings-specific functionality if ( $( '.seedprod-settings-page' ).length ) { initSettings(); } // Subscribers-specific functionality if ( $( '#seedprod-subscribers-tab' ).length ) { initSubscribers(); } // AI Themes external link handler $('a[href*="seedprod_lite_ai_themes"]').on('click', function(e) { e.preventDefault(); window.open(seedprod_admin.urls.ai_theme_builder, '_blank'); }); }); /** * Initialize dashboard functionality */ function initDashboard() { // License activation handler $('#seedprod-license-form').on('submit', function(e) { e.preventDefault(); var $form = $(this); var $button = $form.find('button'); var $message = $('#seedprod-license-message'); var licenseKey = $('#seedprod-license-key').val(); if (!licenseKey) { $message.html('
' + seedprod_admin.strings.license_empty + '
'); return; } // Show loading state $button.prop('disabled', true); $button.find('.button-text').hide(); $button.find('.button-spinner').css('display', 'inline-block'); $message.empty(); // Make AJAX call to validate license $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_save_api_key', api_key: licenseKey, _wpnonce: seedprod_admin.nonce }, success: function(response) { if (response.status === 'true') { $message.html('
' + ' ' + seedprod_admin.strings.license_success + '
'); // Keep the button in success state $button.find('.button-spinner').hide(); $button.find('.button-text').show(); setTimeout(function() { // Reload with activation success parameter window.location.href = window.location.pathname + '?page=seedprod_lite&activated=true'; }, 1500); } else { var errorMsg = response.msg || seedprod_admin.strings.license_invalid; // Show WordPress admin notice for error var noticeClass = 'notice-error'; var $notice = $('

' + errorMsg + '

'); // Insert notice at top of dashboard container if ($('.seedprod-dashboard-container').length) { $('.seedprod-dashboard-container').prepend($notice); } else { // Fallback - insert after header $('.seedprod-header').after($notice); } // Make dismissible $notice.on('click', '.notice-dismiss', function() { $(this).remove(); }); // Also show inline error message $message.html('
' + ' ' + errorMsg + '
'); // Reset button on error $button.prop('disabled', false); $button.find('.button-spinner').hide(); $button.find('.button-text').show(); } }, error: function() { $message.html('
' + ' ' + seedprod_admin.strings.license_error + '
'); // Reset button on error $button.prop('disabled', false); $button.find('.button-spinner').hide(); $button.find('.button-text').show(); } }); }); // Toggle switches for enable/disable modes $('.seedprod-toggle').on('change', function() { var $toggle = $(this); var mode = $toggle.data('mode'); var isChecked = $toggle.is(':checked'); // Disable toggle during AJAX $toggle.prop('disabled', true); // Get current settings var settings = { enable_coming_soon_mode: $('.seedprod-toggle[data-mode="coming_soon"]').is(':checked'), enable_maintenance_mode: $('.seedprod-toggle[data-mode="maintenance"]').is(':checked'), enable_login_mode: $('.seedprod-toggle[data-mode="login"]').is(':checked'), enable_404_mode: $('.seedprod-toggle[data-mode="404"]').is(':checked') }; // Apply the change if (mode === 'coming_soon') { settings.enable_coming_soon_mode = isChecked; // If enabling coming soon, disable maintenance if (isChecked && settings.enable_maintenance_mode) { settings.enable_maintenance_mode = false; $('.seedprod-toggle[data-mode="maintenance"]').prop('checked', false); updateStatusBadge('maintenance', false); } } else if (mode === 'maintenance') { settings.enable_maintenance_mode = isChecked; // If enabling maintenance, disable coming soon if (isChecked && settings.enable_coming_soon_mode) { settings.enable_coming_soon_mode = false; $('.seedprod-toggle[data-mode="coming_soon"]').prop('checked', false); updateStatusBadge('coming_soon', false); } } else if (mode === 'login') { settings.enable_login_mode = isChecked; } else if (mode === '404') { settings.enable_404_mode = isChecked; } // Save settings via AJAX $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_save_settings', settings: JSON.stringify(settings), _wpnonce: seedprod_admin.nonce }, success: function(response) { // Update status badge updateStatusBadge(mode, isChecked); // Refresh page for coming soon and maintenance modes to update admin bar notice if (mode === 'coming_soon' || mode === 'maintenance') { // Show success state briefly before refresh setTimeout(function() { window.location.reload(); }, 500); } else { // Re-enable toggle for other modes $toggle.prop('disabled', false); } }, error: function() { // Revert toggle on error $toggle.prop('checked', !isChecked); $toggle.prop('disabled', false); alert(seedprod_admin.strings.settings_error); } }); }); // Copy to clipboard functionality $('#seedprod-copy-system-info').on('click', function(e) { e.preventDefault(); var $button = $(this); var textarea = document.getElementById('seedprod-system-info-text'); if (!textarea) return; // Try modern clipboard API first (works on HTTPS) if (navigator.clipboard && window.isSecureContext) { navigator.clipboard.writeText(textarea.value).then(function() { $button.text(seedprod_admin.strings.copied || 'Copied!'); setTimeout(function() { $button.text(seedprod_admin.strings.copy_to_clipboard || 'Copy to Clipboard'); }, 2000); }).catch(function() { // Fallback to old method copyUsingExecCommand(); }); } else { // Use fallback for HTTP/localhost copyUsingExecCommand(); } function copyUsingExecCommand() { // Select the text textarea.select(); textarea.setSelectionRange(0, 99999); // For mobile devices try { // Copy using the old execCommand var successful = document.execCommand('copy'); if (successful) { $button.text(seedprod_admin.strings.copied || 'Copied!'); setTimeout(function() { $button.text(seedprod_admin.strings.copy_to_clipboard || 'Copy to Clipboard'); }, 2000); } } catch (err) { console.error('Failed to copy text: ', err); } // Deselect the text if (window.getSelection) { window.getSelection().removeAllRanges(); } } }); // Plugin installation/activation handlers $('.seedprod-plugin-button').on('click', function(e) { e.preventDefault(); var $button = $(this); var $item = $button.closest('.seedprod-plugin-item, .seedprod-plugin-card'); var pluginKey = $item.data('plugin'); var pluginSlug = $button.data('plugin-slug'); var pluginId = $button.data('plugin-id'); var status = parseInt($button.data('status')); // Prevent double clicks if ($button.prop('disabled')) { return; } // Show loading state (WordPress native spinner) $button.prop('disabled', true); // Remove any attention-grabbing indicators when user takes action $button.removeClass('seedprod-needs-activation'); var originalText = $button.text(); $button.data('original-text', originalText); // Change text and add WordPress native spinner var loadingText = ''; if (status === 0) { loadingText = seedprod_admin.strings.installing || 'Installing...'; } else if (status === 1) { loadingText = seedprod_admin.strings.deactivating || 'Deactivating...'; } else if (status === 2) { loadingText = seedprod_admin.strings.activating || 'Activating...'; } var spinner = $(''); $button.empty().append(spinner).append(loadingText); // Determine action based on status var action = ''; if (status === 0) { action = 'seedprod_lite_v2_install_plugin'; } else if (status === 1) { action = 'seedprod_lite_v2_deactivate_plugin'; } else if (status === 2) { action = 'seedprod_lite_v2_activate_plugin'; } // Prepare data - use plugin_id for install, plugin slug for activate/deactivate var data = { action: action, _wpnonce: seedprod_admin.nonce }; if (status === 0) { // Installing - send plugin ID (not URL for security) data.plugin_id = pluginId; } else { // Activating/deactivating - send plugin slug data.plugin = pluginSlug; } // Set timeout for stuck installations (30 seconds for install, 10 seconds for activate/deactivate) var timeoutDuration = (status === 0) ? 30000 : 10000; var requestTimeout = setTimeout(function() { // If we get here, the request is stuck // Reset button state $button.prop('disabled', false); $button.find('.spinner').remove(); $button.text(originalText); // Show timeout error var timeoutMsg = (status === 0) ? (seedprod_admin.strings.plugin_install_timeout || 'Installation is taking longer than expected. Please try again or check your server logs.') : (seedprod_admin.strings.plugin_timeout || 'Operation timed out. Please try again.'); showNotice('error', timeoutMsg); }, timeoutDuration); // Make AJAX request $.post(seedprod_admin.ajax_url, data, function(response) { // Clear the timeout since request completed clearTimeout(requestTimeout); if (response.success) { // Update button based on new status if (status === 0) { // Was not installed, now inactive - keep as primary button for activate $button.data('status', 2); // Update status text $item.find('.seedprod-plugin-status strong').text(seedprod_admin.strings.plugin_inactive); // Add attention-grabbing indicator since user needs to activate $button.addClass('seedprod-needs-activation'); // Remove the indicator after 10 seconds setTimeout(function() { $button.removeClass('seedprod-needs-activation'); }, 10000); showNotice('success', response.data.message || seedprod_admin.strings.plugin_installed); } else if (status === 1) { // Was active, now inactive - switch to primary button for activate $button.data('status', 2); $button.removeClass('seedprod-button-secondary').addClass('button-primary seedprod-button-primary'); // Update status text $item.find('.seedprod-plugin-status strong').text(seedprod_admin.strings.plugin_inactive); showNotice('success', response.data || seedprod_admin.strings.plugin_deactivated); // Reload page after deactivation to ensure UI is fully updated setTimeout(function() { window.location.reload(); }, 1000); } else if (status === 2) { // Was inactive, now active - switch to secondary button for deactivate $button.data('status', 1); $button.removeClass('button-primary seedprod-button-primary').addClass('seedprod-button-secondary'); // Update status text $item.find('.seedprod-plugin-status strong').text(seedprod_admin.strings.plugin_active); showNotice('success', response.data || seedprod_admin.strings.plugin_activated); // Reload page after activation to ensure UI is fully updated setTimeout(function() { window.location.reload(); }, 1000); } } else { var errorMsg = response.data || seedprod_admin.strings.plugin_error; showNotice('error', errorMsg); } }).fail(function() { // Clear the timeout since request completed (even if failed) clearTimeout(requestTimeout); showNotice('error', seedprod_admin.strings.plugin_network_error); }).always(function() { // Clear timeout in case it's still running clearTimeout(requestTimeout); // Reset button state (remove WordPress native spinner) $button.prop('disabled', false); $button.find('.spinner').remove(); // Update button text based on the new status var newStatus = $button.data('status'); var newText = ''; if (newStatus === 0) { newText = seedprod_admin.strings.plugin_install; } else if (newStatus === 1) { newText = seedprod_admin.strings.plugin_deactivate; } else if (newStatus === 2) { newText = seedprod_admin.strings.plugin_activate; } $button.text(newText); }); }); /** * Update status badge for toggles */ function updateStatusBadge(mode, isActive) { var $item = $('.seedprod-toggle[data-mode="' + mode + '"]').closest('.seedprod-setup-item'); var $badge = $item.find('.seedprod-status-badge'); var $icon = $item.find('.seedprod-setup-icon'); if ($badge.length === 0) { // Create badge if it doesn't exist $badge = $(''); $item.find('.seedprod-setup-item-controls').append($badge); } if (isActive) { $badge.removeClass('seedprod-status-inactive') .addClass('seedprod-status-active') .text(seedprod_admin.strings.status_active); $icon.addClass('active'); } else { $badge.removeClass('seedprod-status-active') .addClass('seedprod-status-inactive') .text(seedprod_admin.strings.status_inactive); $icon.removeClass('active'); } } /** * Helper function to show notices */ function showNotice(type, message) { var noticeClass = type === 'success' ? 'notice-success' : 'notice-error'; var $notice = $('

' + message + '

'); // Insert notice in appropriate container based on page if ($('.seedprod-dashboard-container').length) { // Dashboard page $('.seedprod-dashboard-container').prepend($notice); } else if ($('.seedprod-settings-container').length) { // Settings page $('.seedprod-settings-container').prepend($notice); } else { // Fallback - insert after any SeedProd header $('.seedprod-header').after($notice); } // Auto dismiss after 5 seconds setTimeout(function() { $notice.fadeOut(function() { $(this).remove(); }); }, 5000); // Make dismissible $notice.on('click', '.notice-dismiss', function() { $notice.fadeOut(function() { $(this).remove(); }); }); // Add dismiss button if not present if (!$notice.find('.notice-dismiss').length) { $notice.append(''); } } } /** * Initialize theme kits selection functionality */ function initThemeKitsSelection() { var themeKitsState = { currentTab: 'all-templates', search: '', filter: 'all', sort: '', themes: {}, favorites: [], currentPage: 1, totalPages: 1, searchTimeout: null }; // Initialize based on current tab if (typeof seedprodThemeKitsData !== 'undefined') { themeKitsState.currentTab = seedprodThemeKitsData.activeTab || 'all-templates'; } // Load themes immediately (we're already in document ready) if (themeKitsState.currentTab === 'all-templates') { loadThemes(); } else if (themeKitsState.currentTab === 'favorite-templates') { loadFavoriteThemes(); } // Search functionality with debouncing $('#seedprod-template-search').on('keyup', function() { var searchTerm = $(this).val(); themeKitsState.search = searchTerm; // When searching, reset filter to 'all' to search across all themes if (searchTerm && themeKitsState.filter !== 'all') { themeKitsState.filter = 'all'; $('.seedprod-filter-pill').removeClass('active'); $('.seedprod-filter-pill[data-filter="all"]').addClass('active'); } // Clear existing timeout if (themeKitsState.searchTimeout) { clearTimeout(themeKitsState.searchTimeout); } // Set new timeout for 300ms delay themeKitsState.searchTimeout = setTimeout(function() { themeKitsState.currentPage = 1; if (themeKitsState.currentTab === 'all-templates') { loadThemes(); } else if (themeKitsState.currentTab === 'favorite-templates') { loadFavoriteThemes(); } }, 300); }); // Filter functionality $('.seedprod-filter-pill').on('click', function() { var filter = $(this).data('filter'); themeKitsState.filter = filter; themeKitsState.currentPage = 1; // Clear search when selecting a filter themeKitsState.search = ''; $('#seedprod-template-search').val(''); // Update active states $('.seedprod-filter-pill').removeClass('active'); $(this).addClass('active'); loadThemes(); }); // Sort functionality $('#seedprod-theme-sort').on('change', function() { themeKitsState.sort = $(this).val(); themeKitsState.currentPage = 1; loadThemes(); }); // Pagination functionality $('#seedprod-first-page').on('click', function() { if (!$(this).prop('disabled')) { themeKitsState.currentPage = 1; loadThemes(); } }); $('#seedprod-prev-page').on('click', function() { if (!$(this).prop('disabled') && themeKitsState.currentPage > 1) { themeKitsState.currentPage--; loadThemes(); } }); $('#seedprod-next-page').on('click', function() { if (!$(this).prop('disabled') && themeKitsState.currentPage < themeKitsState.totalPages) { themeKitsState.currentPage++; loadThemes(); } }); $('#seedprod-last-page').on('click', function() { if (!$(this).prop('disabled')) { themeKitsState.currentPage = themeKitsState.totalPages; loadThemes(); } }); // Template hover effects (reuse the same hover logic as landing pages) $(document).on('mouseenter', '.seedprod-theme-kits-grid .seedprod-template-card', function() { $(this).find('.seedprod-template-overlay').show(); }); $(document).on('mouseleave', '.seedprod-theme-kits-grid .seedprod-template-card', function() { // Don't hide overlay if card is in processing state if (!$(this).hasClass('coming-sooncessing')) { $(this).find('.seedprod-template-overlay').hide(); } }); // Theme selection (import) $(document).on('click', '.seedprod-theme-kits-grid .seedprod-template-select', function(e) { e.preventDefault(); var $button = $(this); var themeId = $(this).data('template-id'); var themeName = $(this).data('template-name'); // Get total theme pages count first $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_get_total_theme_pages', nonce: seedprod_admin.v2_nonce }, success: function(response) { var totalThemePages = response.data ? response.data.count : 0; // If there are existing theme pages, ask if they want to delete them if (totalThemePages > 0) { if (confirm(seedprod_admin.strings.theme_import_confirm.replace('%d', totalThemePages))) { // Delete existing theme pages first deleteThemePages(function() { // Then import the new theme importTheme(themeId, themeName, $button); }); } else { // User cancelled - do nothing return; } } else { // No existing pages, just import importTheme(themeId, themeName, $button); } }, error: function() { // On error, just try to import anyway importTheme(themeId, themeName, $button); } }); }); // Function to delete theme pages function deleteThemePages(callback) { $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_delete_theme_pages', nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { if (callback) callback(); } else { alert(seedprod_admin.strings.theme_delete_error.replace('%s', response.data || seedprod_admin.strings.unknown_error)); } }, error: function() { alert(seedprod_admin.strings.theme_delete_general_error); } }); } // Function to import theme function importTheme(themeId, themeName, $button) { var $templateCard = $button.closest('.seedprod-template-card'); var $overlay = $button.closest('.seedprod-template-overlay'); // Keep overlay visible during processing $templateCard.addClass('coming-sooncessing'); $overlay.addClass('coming-sooncessing-active'); // Show loading state $button.prop('disabled', true); $button.find('.dashicons').removeClass('dashicons-yes').addClass('dashicons-update').addClass('seedprod-spin'); // Show importing message showNotice(seedprod_admin.strings.theme_import_starting.replace('%s', themeName), 'info'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_import_theme_request', theme_id: themeId, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { showNotice(seedprod_admin.strings.theme_import_success.replace('%s', themeName), 'success'); // Redirect to theme templates page after short delay setTimeout(function() { window.location.href = seedprod_admin.admin_url + 'admin.php?page=seedprod_lite_website_builder'; }, 2000); } else { showNotice(seedprod_admin.strings.theme_import_error.replace('%s', response.data || seedprod_admin.strings.unknown_error), 'error'); // Reset button state $templateCard.removeClass('coming-sooncessing'); $overlay.removeClass('coming-sooncessing-active'); $button.prop('disabled', false); $button.find('.dashicons').removeClass('dashicons-update seedprod-spin').addClass('dashicons-yes'); } }, error: function() { showNotice(seedprod_admin.strings.template_load_error, 'error'); // Reset button state $templateCard.removeClass('coming-sooncessing'); $overlay.removeClass('coming-sooncessing-active'); $button.prop('disabled', false); $button.find('.dashicons').removeClass('dashicons-update seedprod-spin').addClass('dashicons-yes'); } }); } // Theme preview $(document).on('click', '.seedprod-theme-kits-grid .seedprod-template-preview', function(e) { e.preventDefault(); var themeId = $(this).data('template-id'); // Open preview in new tab (matching Vue.js implementation) window.open('https://preview.seedprod.com/' + themeId, '_blank'); // Commented out iframe modal implementation for now // var themeName = $(this).data('template-name') || 'Theme Kit Preview'; // previewThemeKit(themeId, themeName); }); // Close preview modal for theme kits - commented out for now // $(document).on('click', '#seedprod-template-preview-modal .seedprod-modal-close, #seedprod-template-preview-modal .seedprod-modal-overlay', function() { // // Check if we're on theme kits page // if ($('.seedprod-theme-kits-selection-page').length > 0) { // closeThemePreviewModal(); // } // }); // Favorite toggle (matching landing page templates) $(document).on('click', '.seedprod-theme-kits-grid .seedprod-favorite-toggle', function(e) { e.preventDefault(); e.stopPropagation(); var $toggle = $(this); var templateId = $toggle.data('template-id'); var isFavorited = $toggle.hasClass('seedprod-favorited'); var method = isFavorited ? 'detach' : 'attach'; // Optimistically update UI $toggle.toggleClass('seedprod-favorited'); // Save favorite state via AJAX $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_toggle_favorite_theme', template_id: templateId, method: method, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (!response.success) { // Revert on error $toggle.toggleClass('seedprod-favorited'); console.error('Failed to toggle favorite:', response.data); } }, error: function() { // Revert on error $toggle.toggleClass('seedprod-favorited'); console.error('Failed to toggle favorite'); } }); }); /** * Load themes from API */ function loadThemes() { var $grid = $('#all-themes-grid'); showLoadingSpinner($grid); // Map filter to category ID (10 for WooCommerce) var categoryId = themeKitsState.filter === 'woocommerce' ? '10' : ''; // Build request data var requestData = { action: 'seedprod_lite_v2_get_theme_kits', nonce: seedprodThemeKitsData.nonce, page: themeKitsState.currentPage, filter: 'themes', category: categoryId, search: themeKitsState.search, sort: themeKitsState.sort }; $.ajax({ url: seedprodThemeKitsData.ajaxUrl, type: 'POST', data: requestData, success: function(response) { if (response.success && response.data) { // For All Themes, pagination info is in data.templates if (response.data.templates) { themeKitsState.themes = response.data.templates; renderThemes(response.data, false); // false = not favorites tab updatePagination(response.data.templates); // Pass templates object with pagination } else { // Fallback for unexpected structure themeKitsState.themes = response.data; renderThemes(response.data, false); updatePagination(response.data); } } else { showError($grid, response.data || seedprod_admin.strings.error_loading_templates); } }, error: function() { showError($grid, seedprod_admin.strings.error_loading_templates); } }); } /** * Load favorite themes from API */ function loadFavoriteThemes() { var $grid = $('#favorite-themes-grid'); showLoadingSpinner($grid); var requestData = { action: 'seedprod_lite_v2_get_theme_kits', nonce: seedprodThemeKitsData.nonce, page: themeKitsState.currentPage, filter: 'favorites', search: themeKitsState.search }; $.ajax({ url: seedprodThemeKitsData.ajaxUrl, type: 'POST', data: requestData, success: function(response) { if (response.success && response.data) { // For favorites, the API returns themes in data.data (like Vue component line 1126) var data = response.data; // Check if we have themes in the expected location if (data.data && Array.isArray(data.data)) { if (data.data.length > 0) { // Mark all as favorited (like Vue component line 1127-1129) data.data.forEach(function(v) { v.favorited = true; }); } // Always render, even if empty renderThemes(data, true); updatePagination(data); } else { // Show empty state renderThemes({data: []}, true); updatePagination({data: [], current_page: 1, last_page: 1}); } } else { showError($grid, response.data || seedprod_admin.strings.error_loading_templates); } }, error: function() { showError($grid, seedprod_admin.strings.error_loading_templates); } }); } /** * Render themes in the grid */ function renderThemes(data, isFavorites) { var gridId = isFavorites ? '#favorite-themes-grid' : '#all-themes-grid'; var $grid = $(gridId); $grid.empty(); // Handle response structure exactly like Vue component var themes = []; var favs = []; if (isFavorites === true) { // Favorites tab: themes come from data.data themes = data.data || []; // These are already favorited (set in loadFavoriteThemes) } else { // All themes tab: exactly like Vue component (line 1074-1079) if (data && data.templates && data.templates.data) { themes = data.templates.data; favs = data.favs || []; // Set favorited exactly like Vue component does (line 1077-1079) themes.forEach(function(v) { v.favorited = favs.includes(v.id); }); } else if (data && data.templates) { themes = data.templates; favs = data.favs || []; themes.forEach(function(v) { v.favorited = favs.includes(v.id); }); } } if (!themes || themes.length === 0) { $grid.html('
' + '

' + seedprod_admin.strings.no_templates_found + '

'); $('.seedprod-themes-pagination').hide(); return; } // Create theme cards themes.forEach(function(theme) { var card = createThemeCard(theme); $grid.append(card); }); // Show pagination $('.seedprod-themes-pagination').show(); } /** * Create a theme card element */ function createThemeCard(theme) { var templateId = theme.id; var templateName = theme.name || seedprod_admin.strings.untitled_theme; // Use the favorited property directly - it should be a boolean var isFavorited = !!theme.favorited; // Convert to boolean var heartClass = isFavorited ? 'seedprod-favorited' : ''; // Build image URL same as Vue version var imageUrl = 'https://assets.seedprod.com/themes/preview-' + templateId + '.jpg'; // Build favorite icon HTML (EXACTLY matching landing page templates) var actionIcon = '' + '' + ''; return '
' + '
' + '
' + '' + templateName + '' + '
' + '' + '
' + '
' + '' + templateName + '' + actionIcon + '
' + '
'; } /** * Update pagination controls */ function updatePagination(data) { themeKitsState.totalPages = data.last_page || 1; themeKitsState.currentPage = data.current_page || 1; $('#seedprod-current-page').text(themeKitsState.currentPage); $('#seedprod-total-pages').text(themeKitsState.totalPages); // Update button states $('#seedprod-first-page, #seedprod-prev-page').prop('disabled', themeKitsState.currentPage <= 1); $('#seedprod-next-page, #seedprod-last-page').prop('disabled', themeKitsState.currentPage >= themeKitsState.totalPages); } /** * Show loading spinner */ function showLoadingSpinner($container) { $container.html('
' + '' + '

' + seedprod_admin.strings.loading_templates + '

'); } /** * Show error message */ function showError($container, message) { $container.html('
' + '

' + message + '

'); } // Commented out iframe modal functions - keeping for potential future use // /** // * Preview theme kit in modal // */ // function previewThemeKit(themeId, themeName) { // // Use preview.seedprod.com URL for theme kits (as used in Vue.js version) // var previewUrl = 'https://preview.seedprod.com/' + themeId; // // // Update title // $('#seedprod-preview-title').text(themeName); // // // Show modal first // $('#seedprod-template-preview-modal').show(); // // // Add loading state to modal body // var $modalBody = $('#seedprod-template-preview-modal .seedprod-modal-body'); // var $iframe = $('#seedprod-preview-iframe'); // // // Hide iframe initially and show loading spinner // $iframe.hide(); // // // Add loading spinner if not already present // if (!$modalBody.find('.seedprod-preview-loading').length) { // $modalBody.append('
' + // '' + // '

Loading preview...

' + // '
'); // } else { // $modalBody.find('.seedprod-preview-loading').show(); // } // // // Handle iframe load completion // $iframe.off('load').on('load', function() { // // Hide loading spinner // $modalBody.find('.seedprod-preview-loading').hide(); // // Show iframe with fade-in effect // $iframe.fadeIn(200); // }); // // // Set iframe source (this triggers loading) // $iframe.attr('src', previewUrl); // } // // /** // * Close preview modal // */ // function closeThemePreviewModal() { // $('#seedprod-template-preview-modal').hide(); // // Reset iframe to prevent flash of old content on next open // var $iframe = $('#seedprod-preview-iframe'); // $iframe.attr('src', ''); // $iframe.hide(); // // Hide any loading spinner // $('#seedprod-template-preview-modal .seedprod-preview-loading').hide(); // } } /** * Initialize settings page functionality */ function initSettings() { // License key handlers $('#seedprod-verify-license, #seedprod-recheck-license').on('click', function(e) { e.preventDefault(); saveLicenseKey(); }); $('#seedprod-deactivate-license').on('click', function(e) { e.preventDefault(); deactivateLicenseKey(); }); // Settings form handler $('#seedprod-settings-form').on('submit', function(e) { e.preventDefault(); saveAppSettings(); }); // System info toggle $('#seedprod-toggle-system-info').on('click', function() { var $systemInfo = $('#seedprod-system-info'); var $icon = $(this).find('.dashicons'); if ($systemInfo.is(':visible')) { $systemInfo.slideUp(); $icon.removeClass('dashicons-arrow-up-alt2').addClass('dashicons-arrow-down-alt2'); } else { $systemInfo.slideDown(); $icon.removeClass('dashicons-arrow-down-alt2').addClass('dashicons-arrow-up-alt2'); } }); } /** * Save/verify license key */ function saveLicenseKey() { var $button = $('#seedprod-verify-license, #seedprod-recheck-license'); var $message = $('#seedprod-license-message'); var licenseKey = $('#seedprod-license-key').val(); if (!licenseKey) { showInlineNotice($message, 'error', seedprod_admin.strings.license_empty || 'Please enter a license key.'); return; } // Disable button and show loading $button.prop('disabled', true).text(seedprod_admin.strings.verifying); $message.empty(); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_save_api_key', api_key: licenseKey, _wpnonce: seedprod_admin.nonce }, success: function(response) { $button.prop('disabled', false); // Check response.status (string) not response.success (boolean) if (response.status === 'true') { showInlineNotice($message, 'success', response.msg || seedprod_admin.strings.license_verify_success); // Reload page to show updated license status setTimeout(function() { location.reload(); }, 1500); } else { $button.text(seedprod_admin.strings.verify_key); showInlineNotice($message, 'error', response.msg || seedprod_admin.strings.license_invalid); // Hide the active badge if it exists $('.seedprod-license-badge-active').hide(); } }, error: function() { $button.prop('disabled', false).text(seedprod_admin.strings.verify_key); showInlineNotice($message, 'error', seedprod_admin.strings.license_error); // Hide the active badge if it exists $('.seedprod-license-badge-active').hide(); } }); } /** * Deactivate license key */ function deactivateLicenseKey() { var $button = $('#seedprod-deactivate-license'); var $message = $('#seedprod-license-message'); var licenseKey = $('#seedprod-license-key').val(); if (!confirm(seedprod_admin.strings.license_deactivate_confirm)) { return; } $button.prop('disabled', true).text(seedprod_admin.strings.license_deactivating); $message.empty(); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_deactivate_api_key', api_key: licenseKey, _wpnonce: seedprod_admin.nonce }, success: function(response) { $button.prop('disabled', false).text(seedprod_admin.strings.deactivate_key); if (response.success) { showInlineNotice($message, 'success', response.data.message || seedprod_admin.strings.license_deactivate_success); // Clear the license field and reload $('#seedprod-license-key').val(''); setTimeout(function() { location.reload(); }, 1500); } else { showInlineNotice($message, 'error', response.data.message || seedprod_admin.strings.license_deactivate_error); } }, error: function() { $button.prop('disabled', false).text(seedprod_admin.strings.deactivate_key); showInlineNotice($message, 'error', seedprod_admin.strings.license_error); } }); } /** * Save app settings */ function saveAppSettings() { var $button = $('#seedprod-save-settings'); // Remove any existing notices $('.seedprod-dashboard-container > .notice').remove(); // Collect form data var appSettings = { facebook_g_app_id: $('#seedprod-facebook-app-id').val(), google_places_app_key: $('#seedprod-google-places-key').val(), yelp_app_api_key: $('#seedprod-yelp-api-key').val(), disable_seedprod_button: $('#seedprod-disable-button').is(':checked'), enable_usage_tracking: $('#seedprod-usage-tracking').is(':checked'), disable_seedprod_notification: $('#seedprod-disable-notifications').is(':checked') }; $button.prop('disabled', true).text(seedprod_admin.strings.saving); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_save_app_settings', app_settings: appSettings, _wpnonce: $('#seedprod_settings_nonce').val() }, success: function(response) { $button.prop('disabled', false).text(seedprod_admin.strings.save_settings); if (response.success) { // Show success notice above tabs, below header var $notice = $('

' + (response.data.message || seedprod_admin.strings.settings_save_success) + '

'); $('.seedprod-dashboard-container').prepend($notice); // Add dismiss button functionality $notice.on('click', '.notice-dismiss', function() { $notice.fadeOut(function() { $(this).remove(); }); }); // Add dismiss button if WordPress didn't add it if (!$notice.find('.notice-dismiss').length) { $notice.append(''); } // Scroll to notice to ensure it's visible // Try to scroll to the page top, accounting for WP admin bar if ($('.seedprod-dashboard-page').length) { var scrollTarget = Math.max(0, $('.seedprod-dashboard-page').offset().top - 32); window.scrollTo({ top: scrollTarget, behavior: 'smooth' }); } else { // Fallback to simple scroll to top window.scrollTo({ top: 0, behavior: 'smooth' }); } // Auto-remove after 3 seconds setTimeout(function() { $notice.fadeOut(function() { $(this).remove(); }); }, 3000); } else { var $notice = $('

' + (response.data.message || seedprod_admin.strings.settings_save_error) + '

'); $('.seedprod-dashboard-container').prepend($notice); // Add dismiss button functionality $notice.on('click', '.notice-dismiss', function() { $notice.fadeOut(function() { $(this).remove(); }); }); // Add dismiss button if WordPress didn't add it if (!$notice.find('.notice-dismiss').length) { $notice.append(''); } } }, error: function() { $button.prop('disabled', false).text(seedprod_admin.strings.save_settings); var $notice = $('

' + (seedprod_admin.strings.error_occurred || 'An error occurred. Please try again.') + '

'); $('.seedprod-dashboard-container').prepend($notice); // Add dismiss button functionality $notice.on('click', '.notice-dismiss', function() { $notice.fadeOut(function() { $(this).remove(); }); }); // Add dismiss button if WordPress didn't add it if (!$notice.find('.notice-dismiss').length) { $notice.append(''); } } }); } /** * Helper function to show inline notices */ function showInlineNotice($element, type, message) { var noticeClass = type === 'success' ? 'notice-success' : 'notice-error'; $element.html('

' + message + '

'); } /** * Initialize subscribers functionality */ function initSubscribers() { var subscribersTable = { currentPage: 1, perPage: 25, sortBy: 'created', sortOrder: 'desc', search: '', pageFilter: 'all', chartInstance: null }; // Load subscribers when tab becomes active if ($('#seedprod-subscribers-tab').is(':visible')) { loadSubscribers(); } // Reload when tab is clicked (if using tab navigation) $('.nav-tab').on('click', function() { if ($(this).attr('href').indexOf('subscribers') !== -1) { setTimeout(loadSubscribers, 100); } }); // Search functionality $('#seedprod-subscriber-search-btn').on('click', function() { performSearch(); }); $('#seedprod-subscriber-search').on('keypress', function(e) { if (e.which === 13) { e.preventDefault(); performSearch(); } }); $('#seedprod-subscriber-clear-search').on('click', function() { $('#seedprod-subscriber-search').val(''); subscribersTable.search = ''; subscribersTable.currentPage = 1; $('#seedprod-subscriber-clear-search').hide(); loadSubscribers(); }); // Filter functionality $('#seedprod-subscriber-page-filter').on('change', function() { subscribersTable.pageFilter = $(this).val(); subscribersTable.currentPage = 1; loadSubscribers(); }); // Sort functionality $('#seedprod-subscribers-table th.sortable a').on('click', function(e) { e.preventDefault(); var newSortBy = $(this).data('sort'); if (subscribersTable.sortBy === newSortBy) { subscribersTable.sortOrder = subscribersTable.sortOrder === 'desc' ? 'asc' : 'desc'; } else { subscribersTable.sortBy = newSortBy; subscribersTable.sortOrder = 'desc'; } subscribersTable.currentPage = 1; loadSubscribers(); }); // Select all functionality $(document).on('change', '#seedprod-subscriber-select-all', function() { var isChecked = $(this).is(':checked'); $('#seedprod-subscribers-list input[type="checkbox"]').prop('checked', isChecked); }); $(document).on('change', '.seedprod-subscriber-select-all-bottom', function() { var isChecked = $(this).is(':checked'); $('#seedprod-subscribers-list input[type="checkbox"]').prop('checked', isChecked); $('#seedprod-subscriber-select-all').prop('checked', isChecked); }); // Individual checkbox changes $(document).on('change', '#seedprod-subscribers-list input[type="checkbox"]', function() { var totalCheckboxes = $('#seedprod-subscribers-list input[type="checkbox"]').length; var checkedCheckboxes = $('#seedprod-subscribers-list input[type="checkbox"]:checked').length; $('#seedprod-subscriber-select-all, .seedprod-subscriber-select-all-bottom').prop('checked', totalCheckboxes === checkedCheckboxes); }); // Bulk actions $('#seedprod-subscriber-bulk-apply').on('click', function() { var action = $('#seedprod-subscriber-bulk-action').val(); var selectedIds = []; $('#seedprod-subscribers-list input[type="checkbox"]:checked').each(function() { selectedIds.push($(this).val()); }); if (!selectedIds.length) { alert(seedprod_admin.strings.subscriber_no_selection); return; } if (action === 'delete') { deleteSubscribers(selectedIds); } }); // Individual delete actions $(document).on('click', '.seedprod-delete-subscriber', function(e) { e.preventDefault(); var subscriberId = $(this).data('id'); deleteSubscribers([subscriberId]); }); // Export functionality $('#seedprod-export-subscribers').on('click', function() { exportSubscribers(); }); // Pagination $(document).on('click', '.seedprod-pagination-link', function(e) { e.preventDefault(); var page = parseInt($(this).data('page')); if (page && page !== subscribersTable.currentPage) { subscribersTable.currentPage = page; loadSubscribers(); } }); /** * Perform search */ function performSearch() { var searchTerm = $('#seedprod-subscriber-search').val().trim(); subscribersTable.search = searchTerm; subscribersTable.currentPage = 1; if (searchTerm) { $('#seedprod-subscriber-clear-search').show(); } else { $('#seedprod-subscriber-clear-search').hide(); } loadSubscribers(); } /** * Load subscribers data */ function loadSubscribers() { var $loading = $('#seedprod-subscribers-list'); $loading.html(' ' + seedprod_admin.strings.loading + ''); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_get_subscribers_datatable', page: subscribersTable.currentPage, per_page: subscribersTable.perPage, search: subscribersTable.search, page_filter: subscribersTable.pageFilter, sort_by: subscribersTable.sortBy, sort_order: subscribersTable.sortOrder, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { displaySubscribers(response.data); } else { $loading.html('' + seedprod_admin.strings.error + ': ' + (response.data || seedprod_admin.strings.subscriber_load_error || 'Could not load subscribers.') + ''); } }, error: function() { $loading.html('' + (seedprod_admin.strings.network_error || 'Network error. Please try again.') + ''); } }); } /** * Display subscribers in table */ function displaySubscribers(data) { var html = ''; if (data.subscribers.length > 0) { data.subscribers.forEach(function(subscriber) { html += ''; html += ''; html += '' + escapeHtml(subscriber.email) + ''; html += '' + escapeHtml(subscriber.name) + ''; html += '' + subscriber.created + ''; html += ''; html += ''; html += ''; html += ''; }); } // Add OptinMonster promo row if not active if (window.seedprodOptinMonster && !window.seedprodOptinMonster.active) { html += ''; html += ''; // Empty checkbox column html += ''; html += ''; html += 'Pro Tip: '; html += 'Get 3x more subscribers with OptinMonster\'s exit-intent popups'; html += ''; html += ''; html += 'Learn more'; html += ''; html += ''; var optinMonsterUrl = seedprod_admin.admin_url + 'admin.php?page=seedprod_lite_settings&tab=recommended-plugins&filter=optinmonster'; if (!window.seedprodOptinMonster.installed) { html += 'Install Free'; } else { html += 'Activate'; } html += ''; html += ''; } $('#seedprod-subscribers-list').html(html); // Update count $('#seedprod-subscriber-count').text(data.total); // Update pagination updatePagination(data); // Update sort indicators updateSortIndicators(); } /** * Update pagination */ function updatePagination(data) { var html = ''; if (data.pages > 1) { // Previous page if (subscribersTable.currentPage > 1) { html += ' '; } else { html += ' '; } // Page numbers var startPage = Math.max(1, subscribersTable.currentPage - 2); var endPage = Math.min(data.pages, subscribersTable.currentPage + 2); if (startPage > 1) { html += '1 '; if (startPage > 2) { html += '… '; } } for (var i = startPage; i <= endPage; i++) { if (i === subscribersTable.currentPage) { html += '' + i + ' '; } else { html += '' + i + ' '; } } if (endPage < data.pages) { if (endPage < data.pages - 1) { html += '… '; } html += '' + data.pages + ' '; } // Next page if (subscribersTable.currentPage < data.pages) { html += ''; } else { html += ''; } } $('#seedprod-subscriber-pagination').html(html); } /** * Update sort indicators */ function updateSortIndicators() { $('#seedprod-subscribers-table th.sortable').removeClass('asc desc'); var $currentSort = $('#seedprod-subscribers-table th.sortable a[data-sort="' + subscribersTable.sortBy + '"]').parent(); $currentSort.addClass(subscribersTable.sortOrder); } /** * Delete subscribers */ function deleteSubscribers(ids) { if (!confirm(seedprod_admin.strings.subscriber_delete_confirm)) { return; } $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_delete_subscribers', ids: ids, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { showNotice($('.seedprod-dashboard-container'), 'success', response.data.message || seedprod_admin.strings.subscriber_delete_success); loadSubscribers(); // Reload table } else { showNotice($('.seedprod-dashboard-container'), 'error', response.data || seedprod_admin.strings.subscriber_error); } }, error: function() { showNotice($('.seedprod-dashboard-container'), 'error', seedprod_admin.strings.subscriber_error); } }); } /** * Export subscribers to CSV */ function exportSubscribers() { var $button = $('#seedprod-export-subscribers'); var originalText = $button.text(); $button.prop('disabled', true).text(seedprod_admin.strings.exporting); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_export_subscribers', page_filter: subscribersTable.pageFilter, nonce: seedprod_admin.v2_nonce }, success: function(response) { $button.prop('disabled', false).text(originalText); if (response.success) { // Create download link var blob = new Blob([response.data.csv], { type: 'text/csv' }); var url = window.URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = response.data.filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(url); showNotice($('.seedprod-dashboard-container'), 'success', response.data.message || seedprod_admin.strings.subscriber_export_success); } else { showNotice($('.seedprod-dashboard-container'), 'error', response.data || seedprod_admin.strings.template_import_error); } }, error: function() { $button.prop('disabled', false).text(originalText); showNotice($('.seedprod-dashboard-container'), 'error', seedprod_admin.strings.template_import_error); } }); } /** * Escape HTML for safe display */ function escapeHtml(text) { var map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, function(m) { return map[m]; }); } } /** * Initialize landing pages functionality */ function initLandingPages() { // Toggle switches for enable/disable modes $('.seedprod-landing-pages-page .seedprod-toggle').on('change', function() { var $toggle = $(this); var mode = $toggle.data('mode'); var isChecked = $toggle.is(':checked'); // Don't process pro features in lite mode if ($toggle.closest('.coming-soon-feature').length && $('.seedprod-lite').length) { $toggle.prop('checked', false); return false; } // Disable toggle during AJAX $toggle.prop('disabled', true); // Get current settings var settings = { enable_coming_soon_mode: $('.seedprod-toggle[data-mode="coming_soon"]').is(':checked'), enable_maintenance_mode: $('.seedprod-toggle[data-mode="maintenance"]').is(':checked'), enable_login_mode: $('.seedprod-toggle[data-mode="login"]').is(':checked'), enable_404_mode: $('.seedprod-toggle[data-mode="404"]').is(':checked') }; // Apply the change if (mode === 'coming_soon') { settings.enable_coming_soon_mode = isChecked; // If enabling coming soon, disable maintenance if (isChecked && settings.enable_maintenance_mode) { settings.enable_maintenance_mode = false; $('.seedprod-toggle[data-mode="maintenance"]').prop('checked', false); updateModeCardStatus('maintenance', false); } } else if (mode === 'maintenance') { settings.enable_maintenance_mode = isChecked; // If enabling maintenance, disable coming soon if (isChecked && settings.enable_coming_soon_mode) { settings.enable_coming_soon_mode = false; $('.seedprod-toggle[data-mode="coming_soon"]').prop('checked', false); updateModeCardStatus('coming_soon', false); } } else if (mode === 'login') { settings.enable_login_mode = isChecked; } else if (mode === '404') { settings.enable_404_mode = isChecked; } // Update visual status immediately for better UX updateModeCardStatus(mode, isChecked); // Save settings via AJAX $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_save_settings', settings: JSON.stringify(settings), _wpnonce: seedprod_admin.nonce }, success: function() { // Refresh page for coming soon and maintenance modes to update admin bar notice if (mode === 'coming_soon' || mode === 'maintenance') { // Show success state briefly before refresh setTimeout(function() { window.location.reload(); }, 500); } else { // Re-enable toggle for other modes $toggle.prop('disabled', false); } }, error: function() { // Revert toggle on error $toggle.prop('checked', !isChecked); $toggle.prop('disabled', false); updateModeCardStatus(mode, !isChecked); alert(seedprod_admin.strings.settings_error || 'Could not save settings. Please try again.'); } }); }); /** * Helper function to update mode card status badge */ function updateModeCardStatus(mode, isActive) { var $card = $('.seedprod-mode-card[data-mode="' + mode + '"]'); var $label = $card.find('.seedprod-toggle-label'); if (isActive) { $label.html('' + (seedprod_admin.strings.active || 'ACTIVE') + ''); } else { $label.html('' + (seedprod_admin.strings.inactive || 'INACTIVE') + ''); } } // New landing page inline form functionality if ($('#seedprod-create-page-form').length > 0) { // Track if user has manually edited the slug var slugManuallyEdited = false; // Slugify function (same as Vue implementation) function slugify(text) { if (!text) return ''; return text.toString().toLowerCase() .replace(/\s+/g, '-') // Replace spaces with - .replace(/[^\w\-]+/g, '') // Remove all non-word chars .replace(/\-\-+/g, '-') // Replace multiple - with single - .replace(/^-+/, '') // Trim - from start of text .replace(/-+$/, ''); // Trim - from end of text } // Show/hide inline form $('#seedprod-show-new-page-form').on('click', function() { $('#seedprod-new-page-inline').slideDown(); $('#seedprod-page-name').focus(); $(this).prop('disabled', true); // Reset the manual edit flag when form is shown slugManuallyEdited = false; }); // Cancel button $('#seedprod-cancel-new-page').on('click', function() { $('#seedprod-new-page-inline').slideUp(); $('#seedprod-show-new-page-form').prop('disabled', false); // Reset form and flags $('#seedprod-create-page-form')[0].reset(); slugManuallyEdited = false; }); // Auto-generate slug from page name if user hasn't manually edited it $('#seedprod-page-name').on('input', function() { var pageName = $(this).val(); // Only auto-generate if user hasn't manually edited the slug if (!slugManuallyEdited) { var slug = slugify(pageName); $('#seedprod-page-slug').val(slug); } }); // When user types in slug field, mark it as manually edited $('#seedprod-page-slug').on('input', function() { slugManuallyEdited = true; }); // Clean up slug field on blur (when user leaves the field) $('#seedprod-page-slug').on('blur', function() { var originalVal = $(this).val(); var slug = slugify(originalVal); $(this).val(slug); }); // Handle form submission (use .off().on() to prevent duplicate handlers) $('#seedprod-create-page-form').off('submit').on('submit', function(e) { e.preventDefault(); var pageName = $('#seedprod-page-name').val(); var slug = $('#seedprod-page-slug').val(); // If no slug provided, generate from name if (!slug) { slug = slugify(pageName); } if (!pageName) { alert(seedprod_admin.strings.page_name_required || 'Please enter a page name'); $('#seedprod-page-name').focus(); return false; } // Hide any previous error messages $('#seedprod-page-slug-error').hide(); // Check if slug already exists $.ajax({ url: seedprod_slug_check_url, type: 'POST', data: { post_name: slug }, success: function(response) { if (response.success) { // Slug is available, proceed to template selection var templateUrl = seedprod_admin.admin_url + 'admin.php?page=seedprod_lite_template_selection' + '&type=lp' + '&_wpnonce=' + seedprod_admin.nonce + '&name=' + encodeURIComponent(pageName) + '&slug=' + encodeURIComponent(slug); window.location.href = templateUrl; } else { // Slug already exists - show error message below field $('#seedprod-page-slug-error').show(); $('#seedprod-page-slug').focus(); // Show alert after a brief delay so the error message is visible setTimeout(function() { alert(seedprod_admin.strings.slug_exists || 'This page URL already exists. Please choose a unique page URL.'); }, 100); } }, error: function(xhr, status, error) { // Only show error if it's not a validation error if (xhr.status !== 0) { alert(seedprod_admin.strings.network_error || 'Network error. Please try again.'); } } }); }); } // DataTable row actions initLandingPageTableActions(); // Search box clear functionality initLandingPageSearchClear(); } /** * Initialize search clear functionality for landing pages */ function initLandingPageSearchClear() { // Handle search input clear button (X button) // WordPress adds a clear button to search inputs in modern browsers var $searchInput = $('#seedprod-landing-pages-search-input'); if ($searchInput.length) { // Listen for the search event which fires when the X is clicked $searchInput.on('search', function() { // If the input is now empty (X was clicked) if ($(this).val() === '') { // Submit the form to clear the search $('#seedprod-landing-pages-form').submit(); } }); // Also handle the input event for older browsers $searchInput.on('input', function() { // If the input was cleared if ($(this).val() === '') { // Check if there was a search parameter in the URL var urlParams = new URLSearchParams(window.location.search); if (urlParams.has('s')) { // Clear the search by submitting the form $('#seedprod-landing-pages-form').submit(); } } }); } } /** * Initialize landing page table row actions (duplicate, trash, restore, delete) */ function initLandingPageTableActions() { // Helper function to show success message function showSuccessMessage(message) { var $message = $('

' + message + '

'); $('body').append($message); } // Duplicate page action $(document).on('click', '.seedprod-duplicate-page', function(e) { e.preventDefault(); var $link = $(this); var pageId = $link.data('id'); // Prevent duplicate clicks if ($link.hasClass('duplicating')) { return; } // Disable the link during AJAX $link.addClass('duplicating').css('pointer-events', 'none').css('opacity', '0.5'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_duplicate_lpage', id: pageId, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { // Show success message and reload showSuccessMessage(response.data.message); setTimeout(function() { window.location.reload(); }, 700); } else { alert(response.data || seedprod_admin.strings.duplicate_page_error); $link.removeClass('duplicating').css('pointer-events', '').css('opacity', ''); } }, error: function() { alert(seedprod_admin.strings.duplicate_page_error); $link.removeClass('duplicating').css('pointer-events', '').css('opacity', ''); } }); }); // Trash page action $(document).on('click', '.seedprod-trash-page', function(e) { e.preventDefault(); var $link = $(this); var pageId = $link.data('id'); // Prevent duplicate clicks if ($link.hasClass('trashing')) { return; } if (!confirm(seedprod_admin.strings.confirm_page_trash)) { return; } // Disable the link during AJAX $link.addClass('trashing').css('pointer-events', 'none').css('opacity', '0.5'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_trash_lpage', id: pageId, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { // Show success message and reload showSuccessMessage(response.data.message); setTimeout(function() { window.location.reload(); }, 700); } else { alert(response.data || seedprod_admin.strings.trash_page_error); $link.removeClass('trashing').css('pointer-events', '').css('opacity', ''); } }, error: function() { alert(seedprod_admin.strings.trash_page_error); $link.removeClass('trashing').css('pointer-events', '').css('opacity', ''); } }); }); // Restore page action $(document).on('click', '.seedprod-restore-page', function(e) { e.preventDefault(); var $link = $(this); var pageId = $link.data('id'); // Prevent duplicate clicks if ($link.hasClass('restoring')) { return; } // Disable the link during AJAX $link.addClass('restoring').css('pointer-events', 'none').css('opacity', '0.5'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_restore_lpage', id: pageId, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { // Show success message and reload showSuccessMessage(response.data.message); setTimeout(function() { window.location.reload(); }, 700); } else { alert(response.data || seedprod_admin.strings.restore_page_error); $link.removeClass('restoring').css('pointer-events', '').css('opacity', ''); } }, error: function() { alert(seedprod_admin.strings.restore_page_error); $link.removeClass('restoring').css('pointer-events', '').css('opacity', ''); } }); }); // Delete permanently action $(document).on('click', '.seedprod-delete-page', function(e) { e.preventDefault(); var $link = $(this); var pageId = $link.data('id'); // Prevent duplicate clicks if ($link.hasClass('deleting')) { return; } if (!confirm(seedprod_admin.strings.confirm_page_delete)) { return; } // Disable the link during AJAX $link.addClass('deleting').css('pointer-events', 'none').css('opacity', '0.5'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_delete_lpage', id: pageId, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { // Show success message and reload showSuccessMessage(response.data.message); setTimeout(function() { window.location.reload(); }, 700); } else { alert(response.data || seedprod_admin.strings.delete_page_error); $link.removeClass('deleting').css('pointer-events', '').css('opacity', ''); } }, error: function() { alert(seedprod_admin.strings.delete_page_error); $link.removeClass('deleting').css('pointer-events', '').css('opacity', ''); } }); }); // Handle bulk actions (unified handler) $('#doaction, #doaction2').off('click.bulk-actions').on('click.bulk-actions', function(e) { var action = $(this).prev('select').val(); if (action === '-1' || action === '') { return; } // Determine which page we're on var currentPage = new URLSearchParams(window.location.search).get('page'); if (currentPage === 'seedprod_lite_landing_pages') { // Handle landing pages bulk actions var checkedBoxes = $('#the-list input[name="page_id[]"]:checked'); if (checkedBoxes.length === 0) { alert(seedprod_admin.strings.no_pages_selected); e.preventDefault(); return; } // Collect page IDs var pageIds = []; checkedBoxes.each(function() { pageIds.push($(this).val()); }); // Confirm action var confirmMessage = ''; switch(action) { case 'trash': confirmMessage = seedprod_admin.strings.confirm_bulk_trash || 'Are you sure you want to trash the selected items?'; break; case 'restore': confirmMessage = seedprod_admin.strings.confirm_bulk_restore || 'Are you sure you want to restore the selected items?'; break; case 'delete': confirmMessage = seedprod_admin.strings.confirm_bulk_delete || 'Are you sure you want to permanently delete the selected items?'; break; default: return; } if (!confirm(confirmMessage)) { e.preventDefault(); return; } e.preventDefault(); // Prevent duplicate clicks var $button = $(this); if ($button.hasClass('bulk-processing')) { return; } // Disable the button during AJAX $button.addClass('bulk-processing').prop('disabled', true); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_bulk_action_lpages', bulk_action: action, page_ids: pageIds, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { // Show success message and reload showSuccessMessage(response.data.message); setTimeout(function() { window.location.reload(); }, 700); } else { alert(response.data || seedprod_admin.strings.bulk_action_error); $button.removeClass('bulk-processing').prop('disabled', false); } }, error: function() { alert(seedprod_admin.strings.bulk_action_error); $button.removeClass('bulk-processing').prop('disabled', false); } }); } else if (currentPage === 'seedprod_lite_website_builder') { // Handle templates bulk actions var templateIds = []; $('input[name="template_id[]"]:checked').each(function() { templateIds.push($(this).val()); }); if (templateIds.length === 0) { alert(seedprod_admin.strings.no_items_selected); e.preventDefault(); return; } var confirmMessage = ''; switch (action) { case 'trash': confirmMessage = seedprod_admin.strings.confirm_bulk_trash || 'Are you sure you want to trash the selected templates?'; break; case 'restore': confirmMessage = seedprod_admin.strings.confirm_bulk_restore || 'Are you sure you want to restore the selected templates?'; break; case 'delete': confirmMessage = seedprod_admin.strings.confirm_bulk_delete || 'Are you sure you want to permanently delete the selected templates?'; break; } if (!confirm(confirmMessage)) { e.preventDefault(); return; } e.preventDefault(); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_bulk_action_templates', bulk_action: action, template_ids: templateIds, nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { showNotice(response.data.message, 'success'); setTimeout(function() { location.reload(); }, 1000); } else { showNotice(response.data.message || seedprod_admin.strings.error, 'error'); } }, error: function() { showNotice(seedprod_admin.strings.error, 'error'); } }); } }); } /** * Initialize template selection functionality */ function initTemplateSelection() { var templateState = { currentTab: 'all-templates', search: '', filter: 'all', templates: {}, favorites: [], saved: [], templateHover: null, searchTimeout: null, resizeTimeout: null }; // Initialize based on current tab if (typeof seedprodTemplateData !== 'undefined') { templateState.currentTab = seedprodTemplateData.activeTab || 'all-templates'; } // Check for active filter pill set by PHP (for pre-filtering based on page type) var $activeFilter = $('.seedprod-filter-pill.active'); if ($activeFilter.length > 0) { templateState.filter = $activeFilter.data('filter') || 'all'; } // Load templates based on current tab (no need for nested document ready) if (templateState.currentTab === 'all-templates') { loadTemplates(); } else if (templateState.currentTab === 'favorite-templates') { loadFavoriteTemplates(); } else if (templateState.currentTab === 'saved-templates') { loadSavedTemplates(); } // Tab switching functionality $('.nav-tab').on('click', function() { var href = $(this).attr('href'); if (href && href.indexOf('tab=') !== -1) { var newTab = href.split('tab=')[1].split('&')[0]; templateState.currentTab = newTab; } }); // Search functionality with debouncing $('#seedprod-template-search').on('input', function() { var searchTerm = $(this).val().trim(); templateState.search = searchTerm; // Reset filter to 'all' when searching if (searchTerm !== '') { templateState.filter = 'all'; $('.seedprod-filter-pill').removeClass('active'); $('.seedprod-filter-pill[data-filter="all"]').addClass('active'); } // Clear existing timeout if (templateState.searchTimeout) { clearTimeout(templateState.searchTimeout); } // Set new timeout for 300ms delay templateState.searchTimeout = setTimeout(function() { if (templateState.currentTab === 'all-templates') { loadTemplates(); } }, 300); }); // Filter pill functionality $('.seedprod-filter-pill').on('click', function() { var filter = $(this).data('filter'); templateState.filter = filter; // Clear search when selecting a filter templateState.search = ''; $('#seedprod-template-search').val(''); // Update active states $('.seedprod-filter-pill').removeClass('active'); $(this).addClass('active'); loadTemplates(); }); // Template hover effects $(document).on('mouseenter', '.seedprod-template-card', function() { var templateId = $(this).data('template-id'); setTemplateHover(templateId, true); }); $(document).on('mouseleave', '.seedprod-template-card', function() { setTemplateHover(null, false); }); // Template selection $(document).on('click', '.seedprod-template-select', function(e) { e.preventDefault(); var templateId = $(this).data('template-id'); selectTemplate(templateId); }); // Template preview $(document).on('click', '.seedprod-template-preview', function(e) { e.preventDefault(); var templateId = $(this).data('template-id'); var templateName = $(this).data('template-name') || (seedprod_admin.strings.template_preview || 'Template Preview'); previewTemplate(templateId, templateName); }); // Blank template fallback button $(document).on('click', '.seedprod-blank-template-fallback', function(e) { e.preventDefault(); // Use blank template ID (99999 is SeedProd's convention for blank) selectTemplate('99999'); }); // Preview modal close $(document).on('click', '.seedprod-modal-close, .seedprod-modal-overlay', function() { closePreviewModal(); }); // Favorite toggle $(document).on('click', '.seedprod-favorite-toggle', function(e) { e.preventDefault(); var templateId = $(this).data('template-id'); toggleFavorite(templateId); }); /** * Load templates from API */ function loadTemplates() { var $grid = $('#all-templates-grid'); showLoadingSpinner($grid); // Map filter names to category IDs (matching Vue.js implementation) var categoryMap = { 'all': '', 'coming-soon': '1', 'maintenance': '2', '404': '3', 'sales': '4', 'webinar': '5', 'lead-squeeze': '6', 'thank-you': '7', 'login': '8' }; var category = categoryMap[templateState.filter] || ''; $.ajax({ url: seedprodTemplateData.ajaxUrl, type: 'POST', data: { action: 'seedprod_lite_v2_get_templates', filter: 'all', // Always use 'all' as filter type category: category, // Send category ID to backend search: templateState.search, is_lite_view: seedprodTemplateData.isLiteView || false, free_subscribed: seedprodTemplateData.freeTemplatesSubscribed || false, _wpnonce: seedprodTemplateData.nonce }, success: function(response) { hideLoadingSpinner($grid); if (response.success && response.data) { templateState.templates = response.data; renderTemplates(response.data, $grid); } else { showErrorFallback($grid, seedprod_admin.strings.template_load_error); } }, error: function() { hideLoadingSpinner($grid); showErrorFallback($grid, seedprod_admin.strings.template_network_error); } }); } /** * Load favorite templates */ function loadFavoriteTemplates() { var $grid = $('#favorite-templates-grid'); showLoadingSpinner($grid); $.ajax({ url: seedprodTemplateData.ajaxUrl, type: 'POST', data: { action: 'seedprod_lite_v2_get_favorite_templates', _wpnonce: seedprodTemplateData.nonce }, success: function(response) { hideLoadingSpinner($grid); if (response.success) { templateState.favorites = response.data; if (!response.data || response.data.length === 0) { showNoTemplatesMessage($grid, seedprod_admin.strings.template_no_favorites); } else { renderTemplates(response.data, $grid); } } else { showErrorFallback($grid, seedprod_admin.strings.template_load_error); } }, error: function() { hideLoadingSpinner($grid); showErrorFallback($grid, seedprod_admin.strings.network_error || 'Network error. Please try again.'); } }); } /** * Load saved templates */ function loadSavedTemplates() { var $grid = $('#saved-templates-grid'); showLoadingSpinner($grid); $.ajax({ url: seedprodTemplateData.ajaxUrl, type: 'POST', data: { action: 'seedprod_lite_v2_get_saved_templates', _wpnonce: seedprodTemplateData.nonce }, success: function(response) { hideLoadingSpinner($grid); if (response.success) { templateState.saved = response.data; if (response.data.length === 0) { showNoTemplatesMessage($grid, seedprod_admin.strings.template_no_saved); } else { renderTemplates(response.data, $grid); } } else { showErrorFallback($grid, seedprod_admin.strings.saved_template_load_error || 'Could not load saved templates.'); } }, error: function() { hideLoadingSpinner($grid); showErrorFallback($grid, seedprod_admin.strings.network_error || 'Network error. Please try again.'); } }); } /** * Render templates in grid */ function renderTemplates(templates, $container) { var html = ''; // Render templates if (templates && templates.length > 0) { templates.forEach(function(template) { html += renderTemplateCard(template); }); } // Clear existing templates and add new ones $container.find('.seedprod-template-card').remove(); $container.find('.seedprod-templates-loading, .seedprod-error-message, .seedprod-no-templates').remove(); // Add templates $container.append(html); // Initialize masonry layout after images load initializeMasonryLayout($container); } /** * Render individual template card */ function renderTemplateCard(template) { // Debug: Log template data to see available fields if (window.seedprodDebugTemplates) { console.log('Template data:', template); } var templateId = template.id || template.ID; var templateName = template.name || template.post_title || (seedprod_admin.strings.untitled_template || 'Untitled Template'); var thumbnailUrl = ''; var isFavorite = template.is_favorite || false; var heartClass = isFavorite ? 'seedprod-favorited' : ''; // Check if this is a Pro template for Lite users var isProTemplate = false; var cardClass = ''; var proBadge = ''; if (seedprodTemplateData.isLiteView) { // Check free_w_email FIRST since these are actually free templates if (template.free_w_email == 1 && !seedprodTemplateData.freeTemplatesSubscribed) { // Free template that requires email subscription cardClass = ' seedprod-email-template'; proBadge = 'FREE'; } else if (template.free == 0 && template.free_w_email != 1) { // Pro template (but not free with email) isProTemplate = true; cardClass = ' coming-soon-template'; proBadge = 'PRO'; } } // Determine thumbnail URL if (templateState.currentTab === 'saved-templates') { thumbnailUrl = 'https://assets.seedprod.com/preview-saved.png'; } else { thumbnailUrl = 'https://assets.seedprod.com/full_length_thumbnails/preview-' + templateId + '.jpeg'; } // Determine action icon (heart for templates, trash for saved) var actionIcon = ''; if (templateState.currentTab === 'saved-templates') { // Show trash icon for saved templates actionIcon = ` `; } else { // Show heart icon for regular/favorite templates actionIcon = ` `; } return `
${proBadge} ${templateName}
${templateName} ${actionIcon}
`; } /** * Show loading spinner */ function showLoadingSpinner($container) { $container.find('.seedprod-template-card').remove(); $container.find('.seedprod-error-message, .seedprod-no-templates').remove(); if (!$container.find('.seedprod-templates-loading').length) { var loadingHtml = `

${seedprod_admin.strings.loading_templates || 'Loading templates...'}

`; $container.append(loadingHtml); } $container.find('.seedprod-templates-loading').show(); } /** * Hide loading spinner */ function hideLoadingSpinner($container) { $container.find('.seedprod-templates-loading').remove(); } /** * Show error fallback with blank template option */ function showErrorFallback($container, message) { $container.find('.seedprod-template-card').remove(); $container.find('.seedprod-templates-loading').remove(); // Check if we have page name and slug to proceed with blank template var canCreateBlank = seedprodTemplateData && seedprodTemplateData.pageName && seedprodTemplateData.pageSlug; var errorHtml = `

' + (seedprod_admin.strings.unable_load_templates || 'Unable to Load Templates') + '

${message}

${canCreateBlank ? `

' + (seedprod_admin.strings.create_blank_template || 'You can still create a page with a blank template:') + '

' + (seedprod_admin.strings.refresh_templates || 'or try refreshing the page to reload templates') + '

` : `
`}
`; $container.append(errorHtml); } /** * Show no templates message */ function showNoTemplatesMessage($container, message) { $container.find('.seedprod-template-card').remove(); $container.find('.seedprod-templates-loading').remove(); var noTemplatesHtml = `

${message}

`; $container.append(noTemplatesHtml); } /** * Set template hover state */ function setTemplateHover(templateId, isHovering) { templateState.templateHover = isHovering ? templateId : null; // Show/hide overlays $('.seedprod-template-overlay').hide(); if (isHovering && templateId) { $('.seedprod-template-card[data-template-id="' + templateId + '"] .seedprod-template-overlay').show(); } } /** * Select template and redirect to builder */ function selectTemplate(templateId) { // Check if this is a Pro template in Lite view FIRST (before checking page data) if (seedprodTemplateData && seedprodTemplateData.isLiteView && templateId !== '99999') { // Find the template in our state to check if it's Pro var template = null; if (templateState.templates) { template = templateState.templates.find(function(t) { return t.id == templateId; }); } // Check if it requires email subscription FIRST (free_w_email == 1) // These templates have free: 0 but are actually free with email, so check them first if (template && template.free_w_email == 1 && !seedprodTemplateData.freeTemplatesSubscribed) { // Scroll to top to show subscription form window.scrollTo({ top: 0, behavior: 'smooth' }); // Add highlight effect to the subscription banner $('.seedprod-free-templates-banner').addClass('seedprod-highlight'); // Remove highlight after animation setTimeout(function() { $('.seedprod-free-templates-banner').removeClass('seedprod-highlight'); }, 3000); alert(seedprod_admin.strings.email_subscribe_required || 'Please subscribe with your email above to unlock this FREE template.'); return; } // Check if it's a Pro template (free == 0 but not free_w_email) if (template && template.free == 0 && template.free_w_email != 1) { // Redirect to upgrade page window.open(seedprod_admin.urls.upgrade_lite, '_blank'); return; } } // Only check for page data if we're actually going to create a page if (typeof seedprodTemplateData === 'undefined' || !seedprodTemplateData.pageName) { // If we're just testing, show a different message if (window.location.href.indexOf('test_lite=1') > -1) { alert(seedprod_admin.strings.test_mode_notice); } else { alert(seedprod_admin.strings.page_data_missing); } return; } // Show loading state var $button = $('.seedprod-template-select[data-template-id="' + templateId + '"]'); var $templateCard = $button.closest('.seedprod-template-card'); var $overlay = $button.closest('.seedprod-template-overlay'); // Keep overlay visible during processing $templateCard.addClass('coming-sooncessing'); $overlay.addClass('coming-sooncessing-active'); $button.prop('disabled', true); $button.find('.dashicons').removeClass('dashicons-yes').addClass('dashicons-update'); $button.find('.dashicons').addClass('seedprod-spin'); // Blank template should also go through page creation process // (Removed direct redirect - blank template needs to create a page too) // Prepare data for request var requestData = { action: 'seedprod_lite_v2_create_page_from_template', template_id: templateId, page_name: seedprodTemplateData.pageName, page_slug: seedprodTemplateData.pageSlug, page_type: seedprodTemplateData.pageType, _wpnonce: seedprodTemplateData.nonce }; // Include page_id if we're updating an existing page (edge case) if (seedprodTemplateData.pageId) { requestData.page_id = seedprodTemplateData.pageId; } // Create page from template $.ajax({ url: seedprodTemplateData.ajaxUrl, type: 'POST', data: requestData, success: function(response) { if (response.success && response.data.builder_url) { window.location.href = response.data.builder_url; } else { alert(response.data || seedprod_admin.strings.template_create_error || 'Could not create page from template. Please try again.'); resetSelectButton($button); } }, error: function() { alert(seedprod_admin.strings.network_error || 'Network error. Please try again.'); resetSelectButton($button); } }); } /** * Reset select button state */ function resetSelectButton($button) { var $templateCard = $button.closest('.seedprod-template-card'); var $overlay = $button.closest('.seedprod-template-overlay'); // Remove processing classes $templateCard.removeClass('coming-sooncessing'); $overlay.removeClass('coming-sooncessing-active'); $button.prop('disabled', false); $button.find('.dashicons').removeClass('dashicons-update seedprod-spin').addClass('dashicons-yes'); } /** * Preview template in modal */ function previewTemplate(templateId, templateName) { // Phase 1: Use static CDN previews from assets.seedprod.com (matching Vue.js implementation) var previewUrl = 'https://assets.seedprod.com/preview-' + templateId + '.html'; // Phase 2 TODO: Implement device switcher functionality // - Add device parameter to URL // - Handle responsive iframe sizing // - Update active device button state $('#seedprod-preview-title').text(templateName); $('#seedprod-preview-iframe').attr('src', previewUrl); $('#seedprod-template-preview-modal').show(); } /** * Close preview modal */ function closePreviewModal() { $('#seedprod-template-preview-modal').hide(); $('#seedprod-preview-iframe').attr('src', ''); } /** * Toggle favorite status */ function toggleFavorite(templateId) { var $favoriteButton = $('.seedprod-favorite-toggle[data-template-id="' + templateId + '"]'); var isFavorited = $favoriteButton.hasClass('seedprod-favorited'); var method = isFavorited ? 'detach' : 'attach'; // Optimistically update UI if (isFavorited) { $favoriteButton.removeClass('seedprod-favorited'); } else { $favoriteButton.addClass('seedprod-favorited'); } $.ajax({ url: seedprodTemplateData.ajaxUrl, type: 'POST', data: { action: 'seedprod_lite_v2_toggle_favorite_template', template_id: templateId, method: method, _wpnonce: seedprodTemplateData.nonce }, success: function(response) { if (response.success) { var isFavorite = response.data.is_favorite; // Update heart icon state to match server response if (isFavorite) { $favoriteButton.addClass('seedprod-favorited'); } else { $favoriteButton.removeClass('seedprod-favorited'); } // Update template state for (var i in templateState.templates) { if (templateState.templates[i].id == templateId) { templateState.templates[i].is_favorite = isFavorite; break; } } // If we're on favorites tab and unfavoriting, remove from display if (templateState.currentTab === 'favorite-templates' && !isFavorite) { $('.seedprod-template-card[data-template-id="' + templateId + '"]').fadeOut(function() { $(this).remove(); // Check if any favorites left if ($('#favorite-templates-grid .seedprod-template-card').length === 0) { showNoTemplatesMessage($('#favorite-templates-grid'), seedprod_admin.strings.no_favorites_found || 'No favorite templates found. Click the heart icon on any template to add it to your favorites.'); } }); } } else { // Revert optimistic update on failure if (method === 'attach') { $favoriteButton.removeClass('seedprod-favorited'); } else { $favoriteButton.addClass('seedprod-favorited'); } console.error(seedprod_admin.strings.favorite_toggle_error || 'Could not toggle favorite:', response.data); } }, error: function() { // Revert optimistic update on error if (method === 'attach') { $favoriteButton.removeClass('seedprod-favorited'); } else { $favoriteButton.addClass('seedprod-favorited'); } console.error(seedprod_admin.strings.favorite_network_error || 'Network error when toggling favorite'); } }); } /** * Initialize masonry layout */ function initializeMasonryLayout($container) { // Wait for images to load before calculating positions var $images = $container.find('.seedprod-template-image'); var imagesToLoad = $images.length; var imagesLoaded = 0; // If no images, layout immediately if (imagesToLoad === 0) { applyMasonryLayout($container); return; } // Wait for each image to load $images.each(function() { var $img = $(this); var img = new Image(); img.onload = img.onerror = function() { imagesLoaded++; if (imagesLoaded >= imagesToLoad) { // Small delay to ensure DOM is updated setTimeout(function() { applyMasonryLayout($container); }, 50); } }; // Trigger load (in case image is cached) if ($img.get(0).complete) { img.onload(); } else { img.src = $img.attr('src'); } }); } /** * Apply masonry layout to container */ function applyMasonryLayout($container) { var $cards = $container.find('.seedprod-template-card'); var containerWidth = $container.width(); var cardMargin = 24; // Calculate number of columns based on container width var columns; if (containerWidth > 1500) columns = 5; else if (containerWidth > 1000) columns = 4; else if (containerWidth > 700) columns = 3; else if (containerWidth > 400) columns = 2; else columns = 1; var cardWidth = Math.floor((containerWidth - (cardMargin * (columns - 1))) / columns); var columnHeights = new Array(columns).fill(0); // Position each card $cards.each(function() { var $card = $(this); // Set card width $card.css('width', cardWidth + 'px'); // Find shortest column var shortestColumn = 0; var shortestHeight = columnHeights[0]; for (var i = 1; i < columns; i++) { if (columnHeights[i] < shortestHeight) { shortestHeight = columnHeights[i]; shortestColumn = i; } } // Position card var left = shortestColumn * (cardWidth + cardMargin); var top = columnHeights[shortestColumn]; $card.css({ 'position': 'absolute', 'left': left + 'px', 'top': top + 'px' }); // Update column height columnHeights[shortestColumn] += $card.outerHeight() + cardMargin; }); // Set container height var maxHeight = Math.max.apply(Math, columnHeights); $container.css({ 'position': 'relative', 'height': maxHeight + 'px' }); } // Recalculate masonry on window resize $(window).on('resize.seedprodMasonry', function() { if ($('.seedprod-templates-grid').length) { clearTimeout(templateState.resizeTimeout); templateState.resizeTimeout = setTimeout(function() { $('.seedprod-templates-grid').each(function() { var $container = $(this); if ($container.find('.seedprod-template-card').length > 0) { applyMasonryLayout($container); } }); }, 250); } }); } /** * Website Builder Theme Toggle */ function initWebsiteBuilderThemeToggle() { var $toggle = $('#seedprod-theme-toggle'); if (!$toggle.length) return; var isProcessing = false; $toggle.on('change', function() { if (isProcessing) return; var $this = $(this); var enabled = $this.is(':checked'); var $label = $this.closest('.seedprod-theme-toggle-control').find('.seedprod-toggle-label'); var $stats = $('.seedprod-theme-stats'); // Show loading state isProcessing = true; $this.prop('disabled', true); $label.html(' ' + seedprod_admin.strings.loading + ''); // Make AJAX request $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_update_theme_enabled', nonce: seedprod_admin.v2_nonce, enabled: enabled }, success: function(response) { if (response.success) { // Update UI based on state if (response.data.enabled) { $label.html('' + seedprod_admin.strings.status_active + ''); $stats.fadeIn(); // Check if we should prompt to create default pages checkDefaultPages(); } else { $label.html('' + seedprod_admin.strings.status_inactive + ''); $stats.fadeOut(); } // Show success message showNotice(response.data.message, 'success'); // Scroll to top to show notice $('html, body').animate({ scrollTop: 0 }, 300); } else { // Revert toggle on error $this.prop('checked', !enabled); $label.html('' + (!enabled ? seedprod_admin.strings.status_active : seedprod_admin.strings.status_inactive) + ''); // Show error message showNotice(response.data || seedprod_admin.strings.settings_error, 'error'); // Scroll to top to show error $('html, body').animate({ scrollTop: 0 }, 300); } }, error: function() { // Revert toggle on error $this.prop('checked', !enabled); $label.html('' + (!enabled ? seedprod_admin.strings.status_active : seedprod_admin.strings.status_inactive) + ''); showNotice(seedprod_admin.strings.settings_error, 'error'); // Scroll to top to show error $('html, body').animate({ scrollTop: 0 }, 300); }, complete: function() { isProcessing = false; $this.prop('disabled', false); } }); }); } /** * Check if we should prompt to create default pages */ function checkDefaultPages() { // Check if WordPress is using static pages $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_check_default_pages', nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success && response.data.should_create) { // Show prompt to create default pages if (confirm(seedprod_admin.strings.create_default_pages_prompt)) { createDefaultPages(); } } }, error: function(xhr, status, error) { console.error('Error checking default pages:', error); } }); } /** * Create default home and blog pages */ function createDefaultPages() { $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_create_default_pages', nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { showNotice(response.data.message, 'success'); // Optionally refresh the page to show the new setup setTimeout(function() { window.location.reload(); }, 2000); } else { showNotice(response.message || 'Failed to create default pages', 'error'); } }, error: function(xhr, status, error) { console.error('Error creating default pages:', error); showNotice('An error occurred while creating default pages', 'error'); } }); } /** * Show admin notice */ function showNotice(message, type) { var noticeClass = type === 'success' ? 'notice-success' : 'notice-error'; var $notice = $('

' + message + '

'); // Insert at beginning of dashboard container for proper indentation $('.seedprod-dashboard-container').prepend($notice); // Auto-dismiss after 5 seconds setTimeout(function() { $notice.fadeOut(function() { $(this).remove(); }); }, 5000); // Make dismissible $notice.on('click', '.notice-dismiss', function() { $notice.fadeOut(function() { $(this).remove(); }); }); } /** * Theme Templates DataTable Functions */ function initThemeTemplatesTable() { // Toggle template publish status $(document).on('change', '.seedprod-template-toggle', function() { var $toggle = $(this); var templateId = $toggle.data('id'); var nonce = $toggle.data('nonce'); var $row = $toggle.closest('tr'); // Disable toggle during request $toggle.prop('disabled', true); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_toggle_template_status', template_id: templateId, nonce: nonce }, success: function(response) { if (response.success) { // Update row styling if needed if (response.data.status === 'publish') { $row.removeClass('status-draft').addClass('status-publish'); } else { $row.removeClass('status-publish').addClass('status-draft'); } showNotice(response.data.message, 'success'); } else { // Revert toggle $toggle.prop('checked', !$toggle.is(':checked')); showNotice(response.data || seedprod_admin.strings.error, 'error'); } }, error: function() { // Revert toggle $toggle.prop('checked', !$toggle.is(':checked')); showNotice(seedprod_admin.strings.error, 'error'); }, complete: function() { $toggle.prop('disabled', false); } }); }); // Duplicate template $(document).on('click', '.seedprod-duplicate-template', function(e) { e.preventDefault(); var $link = $(this); var templateId = $link.data('id'); var nonce = $link.data('nonce'); // Prevent duplicate clicks if ($link.hasClass('duplicating')) { return; } if (!confirm(seedprod_admin.strings.confirm_duplicate)) { return; } $link.addClass('duplicating disabled'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_duplicate_template', template_id: templateId, nonce: nonce }, success: function(response) { if (response.success) { showNotice(response.data.message, 'success'); // Always reload after a short delay for consistency setTimeout(function() { location.reload(); }, 700); } else { showNotice(response.data || seedprod_admin.strings.error, 'error'); $link.removeClass('duplicating disabled'); } }, error: function() { showNotice(seedprod_admin.strings.error, 'error'); $link.removeClass('duplicating disabled'); } }); }); // Trash template $(document).on('click', '.seedprod-trash-template', function(e) { e.preventDefault(); var $link = $(this); var templateId = $link.data('id'); var nonce = $link.data('nonce'); // Prevent duplicate clicks if ($link.hasClass('trashing')) { return; } if (!confirm(seedprod_admin.strings.confirm_trash)) { return; } $link.addClass('trashing disabled'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_trash_template', template_id: templateId, nonce: nonce }, success: function(response) { if (response.success) { showNotice(response.data.message, 'success'); // Always reload after a short delay for consistency setTimeout(function() { location.reload(); }, 700); } else { showNotice(response.data || seedprod_admin.strings.error, 'error'); $link.removeClass('trashing disabled'); } }, error: function() { showNotice(seedprod_admin.strings.error, 'error'); $link.removeClass('trashing disabled'); } }); }); // Restore template $(document).on('click', '.seedprod-restore-template', function(e) { e.preventDefault(); var $link = $(this); var templateId = $link.data('id'); var nonce = $link.data('nonce'); // Prevent duplicate clicks if ($link.hasClass('restoring')) { return; } $link.addClass('restoring disabled'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_restore_template', template_id: templateId, nonce: nonce }, success: function(response) { if (response.success) { showNotice(response.data.message, 'success'); // Always reload after a short delay for consistency setTimeout(function() { location.reload(); }, 700); } else { showNotice(response.data || seedprod_admin.strings.error, 'error'); $link.removeClass('restoring disabled'); } }, error: function() { showNotice(seedprod_admin.strings.error, 'error'); $link.removeClass('restoring disabled'); } }); }); // Delete template permanently $(document).on('click', '.seedprod-delete-template', function(e) { e.preventDefault(); var $link = $(this); var templateId = $link.data('id'); var nonce = $link.data('nonce'); // Prevent duplicate clicks if ($link.hasClass('deleting')) { return; } if (!confirm(seedprod_admin.strings.confirm_delete)) { return; } $link.addClass('deleting disabled'); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_delete_template', template_id: templateId, nonce: nonce }, success: function(response) { if (response.success) { showNotice(response.data.message, 'success'); // Always reload after a short delay for consistency setTimeout(function() { location.reload(); }, 700); } else { showNotice(response.data || seedprod_admin.strings.error, 'error'); $link.removeClass('deleting disabled'); } }, error: function() { showNotice(seedprod_admin.strings.error, 'error'); $link.removeClass('deleting disabled'); } }); }); // Handle bulk actions for theme templates $('#doaction, #doaction2').on('click', function(e) { console.log('Theme bulk action button clicked'); e.preventDefault(); // Stop any form submission first var action = $(this).prev('select').val(); console.log('Theme action selected:', action); if (action === '-1' || action === '') { return; } // Only handle on website builder page var currentPage = new URLSearchParams(window.location.search).get('page'); if (currentPage !== 'seedprod_lite_website_builder') { return; } // Get selected template IDs var templateIds = []; $('input[name="template_id[]"]:checked').each(function() { templateIds.push($(this).val()); }); console.log('Theme templates found:', templateIds.length, 'IDs:', templateIds); if (templateIds.length === 0) { alert(seedprod_admin.strings.no_items_selected || 'Please select at least one template.'); return; } // Confirm action var confirmMessage = ''; switch (action) { case 'trash': confirmMessage = seedprod_admin.strings.confirm_bulk_trash || 'Are you sure you want to trash the selected templates?'; break; case 'restore': confirmMessage = seedprod_admin.strings.confirm_bulk_restore || 'Are you sure you want to restore the selected templates?'; break; case 'delete': confirmMessage = seedprod_admin.strings.confirm_bulk_delete || 'Are you sure you want to permanently delete the selected templates?'; break; default: return; } if (!confirm(confirmMessage)) { return; } // Prevent duplicate clicks var $button = $(this); if ($button.hasClass('bulk-processing')) { return; } $button.addClass('bulk-processing').prop('disabled', true); $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_bulk_action_templates', bulk_action: action, template_ids: templateIds, nonce: seedprod_admin.v2_nonce }, success: function(response) { console.log('Theme bulk action response:', response); if (response.success) { showNotice(response.data.message, 'success'); setTimeout(function() { location.reload(); }, 1000); } else { showNotice(response.data.message || seedprod_admin.strings.error, 'error'); $button.removeClass('bulk-processing').prop('disabled', false); } }, error: function(xhr, status, error) { console.log('Theme bulk action error:', xhr, status, error); showNotice(seedprod_admin.strings.error, 'error'); $button.removeClass('bulk-processing').prop('disabled', false); } }); }); } /** * Initialize Add New Template Modal */ function initAddNewTemplateModal() { var $modal = $('#seedprod-new-template-modal'); if (!$modal.length) return; var $form = $('#seedprod-new-template-form'); var $overlay = $modal.find('.seedprod-modal-overlay'); var $closeBtn = $modal.find('.seedprod-modal-close'); var $cancelBtn = $modal.find('.seedprod-modal-cancel'); var $createBtn = $('#seedprod-create-template-btn'); var $templateType = $('#template-type'); var $templatePriority = $('#template-priority'); var $conditionsSection = $('#template-conditions-section'); var $conditionsList = $('#template-conditions-list'); var $addConditionBtn = $('.seedprod-add-template-condition'); var templateConditions = []; // Use PHP-provided conditions from localized script // This ensures conditions match the server-side logic and include WooCommerce + dynamic post types var conditionsMap = seedprod_admin.conditions || { 'General': [ { value: '_entire_site', text: 'Entire Site' }, { value: 'is_front_page', text: 'Front Page' }, { value: 'is_home', text: 'Blog Page' }, { value: 'is_page(x)', text: 'Pages' }, { value: 'is_singular', text: 'Pages and Posts' }, { value: 'is_404', text: 'Is 404' }, { value: 'is_author(x)', text: 'Is Author' } ], 'Posts': [ { value: 'is_single(x)', text: 'Posts' }, { value: 'has_category(x)', text: 'Has Category' }, { value: 'has_tag(x)', text: 'Has Tag' } ], 'Archives': [ { value: 'is_archive', text: 'All Archives' }, { value: 'is_date', text: 'Date Archives' }, { value: 'is_search', text: 'Search Results' }, { value: 'is_category(x)', text: 'Post Category Archives' }, { value: 'is_tag(x)', text: 'Post Tag Archives' } ] }; // Open modal when Add New Template button is clicked $(document).on('click', '.seedprod-add-new-template-btn', function(e) { e.preventDefault(); openModal(); }); // Close modal handlers $overlay.on('click', closeModal); $closeBtn.on('click', closeModal); $cancelBtn.on('click', closeModal); // Handle ESC key $(document).on('keydown', function(e) { if (e.key === 'Escape' && $modal.is(':visible')) { closeModal(); } }); // Handle template type change $templateType.on('change', function() { var type = $(this).val(); if (!type) { // Hide conditions if no type selected $conditionsSection.hide(); $conditionsList.empty(); templateConditions = []; return; } // Template parts don't need conditions if (type === 'part') { $conditionsSection.hide(); $conditionsList.empty(); templateConditions = []; $templatePriority.val(20); return; } // Show conditions section for all other types $conditionsSection.show(); // Clear existing conditions $conditionsList.empty(); templateConditions = []; // Set default priority and conditions based on type switch(type) { case 'header': case 'footer': // Headers and footers default to entire site $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: '_entire_site', value: '' }); break; case 'single_page': // Single page defaults to all pages $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: 'is_page(x)', value: '' }); break; case 'single_post': // Single post defaults to all posts $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: 'is_single(x)', value: '' }); break; case 'archive': // Archive defaults to all archives $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: 'is_archive', value: '' }); break; case 'search': // Search results page $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: 'is_search', value: '' }); break; case 'author': // Author page $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: 'is_author(x)', value: '' }); break; case 'custom': // Custom - let user define everything $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: '', value: '' }); break; case 'single_product': // WooCommerce single product $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: 'is_singular(product)', value: '' }); break; case 'archive_product': // WooCommerce product archive $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: 'is_post_type_archive(product)', value: '' }); break; default: // Default: entire site with lower priority $templatePriority.val(20); addTemplateConditionRow({ condition: 'include', type: '_entire_site', value: '' }); break; } }); // Add new condition button $addConditionBtn.on('click', function() { addTemplateConditionRow(); }); // Remove condition $(document).on('click', '#template-conditions-list .seedprod-remove-condition', function() { var $row = $(this).closest('.seedprod-condition-row'); var index = $row.index(); // Remove from array templateConditions.splice(index, 1); // Remove from DOM $row.remove(); // Update UI updateTemplateConditionsUI(); }); // Handle condition type change $(document).on('change', '#template-conditions-list .seedprod-condition-type', function() { var $row = $(this).closest('.seedprod-condition-row'); var selectedValue = $(this).val(); var $valueInput = $row.find('.seedprod-condition-value'); var index = $row.index(); // Update conditions array if (templateConditions[index]) { templateConditions[index].type = selectedValue; } // Show/hide value input based on condition type if (selectedValue.includes('(x)')) { $valueInput.show().attr('placeholder', 'Enter value (e.g., page ID, category name)'); } else { $valueInput.hide().val(''); if (templateConditions[index]) { templateConditions[index].value = ''; } } }); // Handle condition value change $(document).on('change', '#template-conditions-list .seedprod-condition-value', function() { var $row = $(this).closest('.seedprod-condition-row'); var index = $row.index(); if (templateConditions[index]) { templateConditions[index].value = $(this).val(); } }); // Handle include/exclude toggle $(document).on('change', '#template-conditions-list .seedprod-condition-mode', function() { var $row = $(this).closest('.seedprod-condition-row'); var index = $row.index(); $row.toggleClass('is-excluded', $(this).val() === 'exclude'); if (templateConditions[index]) { templateConditions[index].condition = $(this).val(); } }); // Handle form submission $createBtn.on('click', function(e) { e.preventDefault(); // Validate form var templateName = $('#template-name').val().trim(); var templateType = $('#template-type').val(); var templatePriority = $('#template-priority').val() || 10; if (!templateName) { showFieldError('#template-name', seedprod_admin.strings.template_name_required || 'Template name is required'); return; } if (!templateType) { showFieldError('#template-type', seedprod_admin.strings.template_type_required || 'Please select a template type'); return; } // Clear any previous errors clearFieldErrors(); // Show loading state var $buttonText = $createBtn.find('.button-text'); var $spinner = $createBtn.find('.spinner'); $createBtn.prop('disabled', true); $buttonText.hide(); $spinner.show(); // Prepare conditions for submission var finalConditions = []; templateConditions.forEach(function(cond) { if (cond.type) { var condition = { type: cond.type, condition: cond.condition || 'include', value: cond.value || '' }; // Keep type as-is with (x) placeholder, don't embed value // Value stays separate in the value field finalConditions.push(condition); } }); // Make AJAX request $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_create_template', template_name: templateName, template_type: templateType, template_priority: templatePriority, template_conditions: JSON.stringify(finalConditions), nonce: seedprod_admin.v2_nonce }, success: function(response) { if (response.success) { // Close modal closeModal(); // Show success message showNotice('success', response.data.message || 'Template created successfully'); // Redirect to builder if (response.data.redirect_url) { window.location.href = response.data.redirect_url; } else if (response.data.template_id) { // Fallback: construct builder URL var builderUrl = seedprod_admin.admin_url + 'admin.php?page=seedprod_lite_builder&id=' + response.data.template_id + '#/'; window.location.href = builderUrl; } } else { // Show error showModalError(response.data || 'Failed to create template'); } }, error: function() { showModalError(seedprod_admin.strings.template_error || 'An error occurred. Please try again.'); }, complete: function() { // Reset button state $createBtn.prop('disabled', false); $buttonText.show(); $spinner.hide(); } }); }); // Helper: Open modal function openModal() { // Reset form $form[0].reset(); clearFieldErrors(); clearModalError(); // Reset conditions $conditionsSection.hide(); $conditionsList.empty(); templateConditions = []; // Reset priority $templatePriority.val(20); // Show modal $modal.fadeIn(200); $('body').addClass('seedprod-modal-open'); // Focus first input setTimeout(function() { $('#template-name').focus(); }, 250); } // Helper: Close modal function closeModal() { $modal.fadeOut(200); $('body').removeClass('seedprod-modal-open'); } // Helper: Add template condition row function addTemplateConditionRow(condition) { condition = condition || { type: '', value: '', condition: 'include' }; // Add to array templateConditions.push(condition); var rowHtml = '
'; rowHtml += ''; rowHtml += ''; var showValue = condition.type && condition.type.includes('(x)'); var placeholderText = seedprod_admin.strings.condition_enter_value || 'Enter ids or slugs'; rowHtml += '' + message + '').insertAfter($field); } // Helper: Clear field errors function clearFieldErrors() { $form.find('.error').removeClass('error'); $form.find('.seedprod-field-error').remove(); } // Helper: Show modal error function showModalError(message) { clearModalError(); var $error = $('
' + message + '
'); $form.prepend($error); } // Helper: Clear modal error function clearModalError() { $form.find('.seedprod-modal-error').remove(); } // Helper: Show notice function showNotice(type, message) { var noticeClass = type === 'success' ? 'notice-success' : 'notice-error'; var $notice = $('

' + message + '

'); // Insert notice after page title $('.seedprod-dashboard-page .seedprod-header').after($notice); // Auto dismiss after 5 seconds setTimeout(function() { $notice.fadeOut(function() { $(this).remove(); }); }, 5000); // Make dismissible $notice.on('click', '.notice-dismiss', function() { $notice.fadeOut(function() { $(this).remove(); }); }); } } /** * Initialize Edit Conditions Modal */ function initEditConditionsModal() { var $modal = $('#seedprod-conditions-modal'); if (!$modal.length) return; var $overlay = $modal.find('.seedprod-modal-overlay'); var $closeBtn = $modal.find('.seedprod-modal-close'); var $cancelBtn = $modal.find('.seedprod-modal-cancel'); var $saveBtn = $('#seedprod-save-conditions-btn'); var $conditionsList = $('#seedprod-conditions-list'); var $addConditionBtn = $('.seedprod-add-condition'); var $templateName = $('#seedprod-template-name'); var $templateType = $('#seedprod-template-type-display'); var $templatePriority = $('#seedprod-template-priority'); var currentTemplateId = null; // Conditions options - use PHP-provided conditions from localized script // This ensures conditions match the server-side logic and include dynamic post types var conditionsMap = seedprod_admin.conditions || {}; // Condition modes from PHP (Include, Exclude, Custom) var conditionModes = seedprod_admin.condition_modes || { 'include': 'Include', 'exclude': 'Exclude', 'custom': 'Custom' }; // Template type labels var typeLabels = { 'header': 'Header', 'footer': 'Footer', 'part': 'Template Part', 'page': 'Page', 'post': 'Single Post', 'archive': 'Archive', 'search': 'Search', 'author': 'Author', 'single_page': 'Single Page', 'single_post': 'Single Post', 'single_product': 'Single Product', 'archive_product': 'Product Archive', 'woocommerce_single': 'Single Product', 'woocommerce_archive': 'Product Archive' }; // Open modal when Edit Conditions is clicked $(document).on('click', '.seedprod-edit-conditions', function(e) { e.preventDefault(); currentTemplateId = $(this).data('id'); openModal(); }); // Close modal handlers $overlay.on('click', closeModal); $closeBtn.on('click', closeModal); $cancelBtn.on('click', closeModal); // Handle ESC key $(document).on('keydown', function(e) { if (e.key === 'Escape' && $modal.is(':visible')) { closeModal(); } }); // Add new condition $addConditionBtn.on('click', function() { addConditionRow(); }); // Remove condition $(document).on('click', '.seedprod-remove-condition', function() { $(this).closest('.seedprod-condition-row').remove(); updateConditionsUI(); }); // Handle condition type change $(document).on('change', '.seedprod-condition-type', function() { var $row = $(this).closest('.seedprod-condition-row'); var selectedValue = $(this).val(); var $valueInput = $row.find('.seedprod-condition-value'); // Show/hide value input based on condition type if (selectedValue.includes('(x)')) { $valueInput.show().attr('placeholder', seedprod_admin.strings.condition_enter_value || 'Enter ids or slugs'); } else { $valueInput.hide().val(''); } }); // Handle include/exclude/custom toggle $(document).on('change', '.seedprod-condition-mode', function() { var $row = $(this).closest('.seedprod-condition-row'); var selectedMode = $(this).val(); var $typeSelect = $row.find('.seedprod-condition-type'); var $valueInput = $row.find('.seedprod-condition-value'); // Update row classes $row.toggleClass('is-excluded', selectedMode === 'exclude'); $row.toggleClass('is-custom', selectedMode === 'custom'); // Handle custom mode var placeholderText = seedprod_admin.strings.condition_enter_value || 'Enter ids or slugs'; if (selectedMode === 'custom') { // Hide type selector, show value input $typeSelect.hide(); $valueInput.show().attr('placeholder', placeholderText); } else { // Show type selector $typeSelect.show(); // Value input visibility depends on selected type var typeValue = $typeSelect.val(); if (typeValue && typeValue.includes('(x)')) { $valueInput.show().attr('placeholder', placeholderText); } else { $valueInput.hide().val(''); } } }); // Save conditions $saveBtn.on('click', function() { saveConditions(); }); // Helper: Decode HTML entities function decodeHtmlEntities(text) { var textArea = document.createElement('textarea'); textArea.innerHTML = text; return textArea.value; } // Helper: Open modal function openModal() { // Clear conditions list $conditionsList.empty(); // Show loading $conditionsList.html('
'); // Fetch current template data $.ajax({ url: seedprod_admin.ajax_url, type: 'POST', data: { action: 'seedprod_lite_v2_get_template_conditions', template_id: currentTemplateId, nonce: seedprod_admin.v2_nonce }, success: function(response) { $conditionsList.empty(); if (response.success) { // Load template name (decode HTML entities) if (response.data.name) { $templateName.val(decodeHtmlEntities(response.data.name)); } // Load template type var currentTemplateType = response.data.type; if (currentTemplateType) { var typeLabel = typeLabels[currentTemplateType] || currentTemplateType; $templateType.text(typeLabel); } // Load template priority if (response.data.priority !== undefined) { $templatePriority.val(response.data.priority); } else { $templatePriority.val(20); } // Cache selectors for performance var $conditionsFormGroup = $('.seedprod-form-group').has('#seedprod-conditions-list'); var $addConditionBtn = $('.seedprod-add-condition'); // Hide conditions section for Template Parts (type: 'part') if (currentTemplateType === 'part') { $conditionsFormGroup.hide(); $addConditionBtn.hide(); } else { // Show conditions section for other types $conditionsFormGroup.show(); $addConditionBtn.show(); // Load existing conditions var conditions = response.data.conditions; if (conditions && conditions.length > 0) { conditions.forEach(function(condition) { addConditionRow(condition); }); } else { // Add default empty row addConditionRow(); } } } else { // Add default empty row addConditionRow(); } }, error: function() { $conditionsList.empty(); addConditionRow(); } }); // Show modal $modal.fadeIn(200); $('body').addClass('seedprod-modal-open'); } // Helper: Close modal function closeModal() { $modal.fadeOut(200); $('body').removeClass('seedprod-modal-open'); } // Helper: Parse condition to separate type and value function parseCondition(condition) { condition = condition || { type: '', value: '', condition: 'include' }; // If the type contains a value in parentheses (e.g., "is_page(about)"), // extract the value and convert type to placeholder format var type = condition.type; var value = condition.value || ''; if (type && type.includes('(') && type.includes(')') && !type.includes('(x)')) { // Extract value from type like "is_page(about)" -> value: "about", type: "is_page(x)" var match = type.match(/^([^\(]+)\(([^\)]+)\)$/); if (match) { type = match[1] + '(x)'; value = match[2]; } } return { type: type, value: value, condition: condition.condition || 'include' }; } // Helper: Add condition row function addConditionRow(conditionData) { // Parse the condition to handle both formats var condition = parseCondition(conditionData); var isCustom = (condition.condition === 'custom'); var rowHtml = '
'; rowHtml += ''; // Type selector (hidden for custom mode) rowHtml += ''; // Value input (shown for custom mode or when type has (x)) var showValue = isCustom || (condition.type && condition.type.includes('(x)')); var placeholderText = seedprod_admin.strings.condition_enter_value || 'Enter ids or slugs'; rowHtml += ' 0) { $notice.find('.seedprod-review-step:visible').fadeOut(function() { $targetStepDiv.fadeIn(); }); } } }); // Handle "Ask me later" link $(document).on('click', '.seedprod-v2-review-notice .seedprod-review-dismiss-link', function(e) { e.preventDefault(); $.post(ajaxurl, { action: 'seedprod_v2_review_dismiss', permanent: 'false' }); $('.seedprod-v2-review-notice').fadeOut(); }); })( jQuery );