/** * Maple Local Fonts - Admin JavaScript * * @package Maple_Local_Fonts */ (function($) { 'use strict'; var MLF = { /** * Search debounce timer. */ searchTimer: null, /** * Currently selected font. */ selectedFont: null, /** * Currently selected font version info. */ selectedFontVersion: null, selectedFontLastModified: null, /** * Loaded font preview stylesheets. */ loadedFonts: {}, /** * Initialize the admin functionality. */ init: function() { this.bindEvents(); }, /** * Bind event handlers. */ bindEvents: function() { // Search button click $('#mlf-search-btn').on('click', this.handleSearchClick.bind(this)); // Search on Enter key $('#mlf-font-search').on('keypress', this.handleSearchKeypress.bind(this)); // Click outside to close search results $(document).on('click', this.handleDocumentClick.bind(this)); // Prevent closing when clicking inside search area (but not on result items) $('.mlf-import-section').on('click', function(e) { // Don't stop propagation if clicking on a result item if (!$(e.target).closest('.mlf-result-item').length) { e.stopPropagation(); } }); // Font selection from results - bind to results container $('#mlf-search-results').on('click', '.mlf-result-item', this.handleFontSelect.bind(this)); // Change font button $('#mlf-change-font').on('click', this.handleChangeFont.bind(this)); // Form submission $('#mlf-import-form').on('submit', this.handleDownload.bind(this)); // Delete button clicks $(document).on('click', '.mlf-delete-btn', this.handleDelete.bind(this)); // Check for updates button $('#mlf-check-updates').on('click', this.handleCheckUpdates.bind(this)); // Update button clicks $(document).on('click', '.mlf-update-btn', this.handleUpdateFont.bind(this)); }, /** * Handle search button click. * * @param {Event} e Click event. */ handleSearchClick: function(e) { e.preventDefault(); this.triggerSearch(); }, /** * Handle Enter key in search input. * * @param {Event} e Keypress event. */ handleSearchKeypress: function(e) { if (e.which === 13) { e.preventDefault(); this.triggerSearch(); } }, /** * Trigger a search with the current input value. */ triggerSearch: function() { var query = $('#mlf-font-search').val().trim(); if (query.length < 2) { this.displayError(mapleLocalFontsData.strings.minChars || 'Please enter at least 2 characters.'); return; } this.performSearch(query); }, /** * Perform the search. * * @param {string} query Search query. */ performSearch: function(query) { var $spinner = $('#mlf-search-spinner'); var $button = $('#mlf-search-btn'); // Show spinner, disable button $spinner.addClass('is-active'); $button.prop('disabled', true); // Send AJAX request $.ajax({ url: mapleLocalFontsData.ajaxUrl, type: 'POST', data: { action: 'mlf_search_fonts', nonce: mapleLocalFontsData.searchNonce, query: query }, success: function(response) { if (response.success && response.data && response.data.fonts) { if (response.data.fonts.length > 0) { MLF.displaySearchResults(response.data.fonts); } else { MLF.displayNoResults(); } } else { // Handle error response var errorMsg = (response.data && response.data.message) ? response.data.message : (mapleLocalFontsData.strings.error || 'An error occurred.'); MLF.displayError(errorMsg); } }, error: function(xhr) { var errorMsg = mapleLocalFontsData.strings.error || 'An error occurred.'; if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) { errorMsg = xhr.responseJSON.data.message; } MLF.displayError(errorMsg); }, complete: function() { $spinner.removeClass('is-active'); $button.prop('disabled', false); } }); }, /** * Display search results. * * @param {Array} fonts Array of font objects. */ displaySearchResults: function(fonts) { var $results = $('#mlf-search-results'); var $list = $('#mlf-results-list'); if (!fonts || fonts.length === 0) { this.displayNoResults(); return; } var html = ''; var previewText = mapleLocalFontsData.strings.previewText || 'Maple Fonts Preview'; var validFonts = 0; fonts.forEach(function(font) { // Skip fonts with missing family name if (!font || !font.family) { return; } var fontFamily = font.family; var category = font.category || 'sans-serif'; var categoryLabel = MLF.getCategoryLabel(category); var badges = []; if (font.has_variable) { badges.push('Variable'); } html += '
No fonts installed yet. Search and select a font above to get started.
' ); } }); } else { alert(response.data.message || mapleLocalFontsData.strings.error); $button.prop('disabled', false).text(originalText); $fontItem.removeClass('mlf-loading'); } }, error: function(xhr) { var message = mapleLocalFontsData.strings.error; if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) { message = xhr.responseJSON.data.message; } alert(message); $button.prop('disabled', false).text(originalText); $fontItem.removeClass('mlf-loading'); } }); }, /** * Show a message to the user. * * @param {jQuery} $element Message element. * @param {string} message Message text. * @param {string} type Message type (success or error). */ showMessage: function($element, message, type) { $element .removeClass('mlf-message-success mlf-message-error') .addClass('mlf-message-' + type) .text(message) .show(); }, /** * Handle check for updates button click. * * @param {Event} e Click event. */ handleCheckUpdates: function(e) { e.preventDefault(); var $button = $('#mlf-check-updates'); var originalText = $button.text(); // Disable button and show checking state $button.prop('disabled', true).text(mapleLocalFontsData.strings.checking || 'Checking...'); // Send AJAX request $.ajax({ url: mapleLocalFontsData.ajaxUrl, type: 'POST', data: { action: 'mlf_check_updates', nonce: mapleLocalFontsData.checkUpdatesNonce }, success: function(response) { if (response.success) { var updates = response.data.updates || {}; var updateCount = Object.keys(updates).length; // Update UI for each font $('.mlf-font-item').each(function() { var $item = $(this); var fontId = $item.data('font-id'); var $badge = $item.find('.mlf-update-badge'); var $updateBtn = $item.find('.mlf-update-btn'); if (updates[fontId]) { // Show update available badge and button $badge.show(); $updateBtn.show(); // Store the latest version info on the button $updateBtn.data('latest-version', updates[fontId].latest_version); } else { // Hide update badge and button $badge.hide(); $updateBtn.hide(); } }); // Show summary message if (updateCount > 0) { var message = mapleLocalFontsData.strings.updatesFound || 'Updates available for %d font(s).'; alert(message.replace('%d', updateCount)); } else { alert(mapleLocalFontsData.strings.noUpdates || 'All fonts are up to date.'); } } else { alert(response.data.message || mapleLocalFontsData.strings.error); } }, error: function(xhr) { var message = mapleLocalFontsData.strings.error; if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) { message = xhr.responseJSON.data.message; } alert(message); }, complete: function() { $button.prop('disabled', false).text(originalText); } }); }, /** * Handle font update button click. * * @param {Event} e Click event. */ handleUpdateFont: function(e) { e.preventDefault(); var $button = $(e.currentTarget); var fontId = $button.data('font-id'); var fontName = $button.data('font-name'); var $fontItem = $button.closest('.mlf-font-item'); // Confirm update if (!confirm('Update ' + fontName + ' to the latest version?')) { return; } // Store original button text var originalText = $button.text(); // Disable button and show updating state $button.prop('disabled', true).text(mapleLocalFontsData.strings.updating || 'Updating...'); $fontItem.addClass('mlf-loading'); // Send AJAX request $.ajax({ url: mapleLocalFontsData.ajaxUrl, type: 'POST', data: { action: 'mlf_update_font', nonce: mapleLocalFontsData.updateFontNonce, font_id: fontId }, success: function(response) { if (response.success) { // Reload page to show updated font alert(response.data.message); window.location.reload(); } else { alert(response.data.message || mapleLocalFontsData.strings.error); $button.prop('disabled', false).text(originalText); $fontItem.removeClass('mlf-loading'); } }, error: function(xhr) { var message = mapleLocalFontsData.strings.error; if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) { message = xhr.responseJSON.data.message; } alert(message); $button.prop('disabled', false).text(originalText); $fontItem.removeClass('mlf-loading'); } }); } }; // Initialize on document ready $(document).ready(function() { MLF.init(); }); })(jQuery);