/**
* Accepta Typography Control JavaScript
* Handles typography controls with font family styling
*/
(function($) {
'use strict';
// Initialize typography controls when customizer is ready
wp.customize.bind('ready', function() {
initializeTypographyControls();
});
function initializeTypographyControls() {
$('.accepta-typography-control-wrapper').each(function() {
var $wrapper = $(this);
var controlId = $wrapper.data('control-id');
initializeTypographyControl($wrapper, controlId);
});
}
function initializeTypographyControl($wrapper, controlId) {
var $hiddenInput = $wrapper.find('.accepta-typography-hidden');
// Function to load and populate values
function loadSavedValues() {
var savedValue = '';
var hasSavedData = false;
// Try to get value from customizer setting first (most reliable)
if (wp.customize && wp.customize.control(controlId)) {
try {
savedValue = wp.customize.control(controlId).setting.get();
} catch (e) {
// Fallback to hidden input
savedValue = $hiddenInput.val();
}
} else {
// Fallback to hidden input
savedValue = $hiddenInput.val();
}
if (savedValue) {
try {
var savedData = JSON.parse(savedValue);
hasSavedData = true;
// Populate all inputs with saved values
$wrapper.find('.accepta-typography-select, .accepta-typography-input').each(function() {
var $field = $(this);
var fieldName = $field.data('field');
if (fieldName && savedData.hasOwnProperty(fieldName)) {
var fieldValue = savedData[fieldName];
// Set the value if it exists (including empty strings for responsive font sizes)
if (fieldValue !== null && fieldValue !== undefined) {
$field.val(fieldValue);
}
}
});
} catch (e) {
// Silent error handling
}
}
return hasSavedData;
}
// Try to load immediately
var hasSavedData = loadSavedValues();
// Also try after a delay in case WordPress hasn't populated the setting yet
if (!hasSavedData) {
setTimeout(function() {
loadSavedValues();
}, 300);
}
// If no saved data exists, capture current input values (which have PHP defaults) and save them
// Use a delay to ensure all inputs are rendered with their PHP default values
setTimeout(function() {
// Check again if we have saved data now
var currentSavedValue = '';
if (wp.customize && wp.customize.control(controlId)) {
try {
currentSavedValue = wp.customize.control(controlId).setting.get();
} catch (e) {
currentSavedValue = $hiddenInput.val();
}
} else {
currentSavedValue = $hiddenInput.val();
}
// Only save defaults if we still don't have saved data
if (!currentSavedValue || currentSavedValue === '{}' || currentSavedValue === '') {
// Capture all current input values (which include PHP defaults)
var defaultValues = {};
$wrapper.find('.accepta-typography-select, .accepta-typography-input').each(function() {
var $field = $(this);
var fieldName = $field.data('field');
var fieldValue = $field.val();
// Capture all non-empty values, including responsive font sizes
if (fieldName && fieldValue !== '' && fieldValue !== null && fieldValue !== undefined) {
defaultValues[fieldName] = fieldValue;
}
});
// If we found default values, save them
if (Object.keys(defaultValues).length > 0) {
$hiddenInput.val(JSON.stringify(defaultValues));
if (wp.customize && wp.customize.control(controlId)) {
wp.customize.control(controlId).setting.set(JSON.stringify(defaultValues));
}
}
}
}, 500);
// Handle field changes
$wrapper.find('.accepta-typography-select, .accepta-typography-input').on('change input', function() {
updateTypographyValue($wrapper, controlId);
});
// Handle responsive tabs
$wrapper.find('.accepta-responsive-tab').on('click', function(e) {
e.preventDefault();
var $tab = $(this);
var device = $tab.data('device');
var $field = $tab.closest('.accepta-responsive-field');
// Update tab states
$field.find('.accepta-responsive-tab').removeClass('active');
$tab.addClass('active');
// Update input visibility
$field.find('.accepta-responsive-input').removeClass('active');
$field.find('.accepta-responsive-input[data-device="' + device + '"]').addClass('active');
// Trigger customizer viewport change if available
if (typeof wp !== 'undefined' && wp.customize && wp.customize.previewedDevice) {
wp.customize.previewedDevice.set(device);
}
});
// Style font family select options
styleFontFamilySelect($wrapper);
// Listen for customizer setting changes (when value is updated from outside)
if (wp.customize && wp.customize.control(controlId)) {
var setting = wp.customize.control(controlId).setting;
// Bind to setting changes
setting.bind(function(newValue) {
if (newValue) {
try {
var newData = JSON.parse(newValue);
// Update all inputs with new values
$wrapper.find('.accepta-typography-select, .accepta-typography-input').each(function() {
var $field = $(this);
var fieldName = $field.data('field');
if (fieldName && newData[fieldName] !== undefined && newData[fieldName] !== null) {
$field.val(newData[fieldName]);
}
});
} catch (e) {
// Silent error handling
}
}
});
// Also trigger immediately to load initial value
setTimeout(function() {
try {
var initialValue = setting.get();
if (initialValue) {
var initialData = JSON.parse(initialValue);
// Update all inputs with initial values
$wrapper.find('.accepta-typography-select, .accepta-typography-input').each(function() {
var $field = $(this);
var fieldName = $field.data('field');
if (fieldName && initialData[fieldName] !== undefined && initialData[fieldName] !== null) {
$field.val(initialData[fieldName]);
}
});
}
} catch (e) {
// Silent error handling
}
}, 100);
}
}
function updateTypographyValue($wrapper, controlId) {
var $hiddenInput = $wrapper.find('.accepta-typography-hidden');
// Start with existing saved values to preserve data
var existingValue = {};
try {
var existingData = $hiddenInput.val();
if (existingData) {
existingValue = JSON.parse(existingData);
}
} catch (e) {
// If parsing fails, start fresh
existingValue = {};
}
// Merge with current input values
var value = $.extend({}, existingValue);
// Get desktop font size for fallback
var desktopFontSize = '';
$wrapper.find('.accepta-typography-input[data-field="font_size_desktop"]').each(function() {
desktopFontSize = $(this).val();
});
// Collect all typography field values (including hidden responsive inputs)
// jQuery finds all elements in DOM regardless of visibility
$wrapper.find('.accepta-typography-select, .accepta-typography-input').each(function() {
var $field = $(this);
var fieldName = $field.data('field');
var fieldValue = $field.val();
if (fieldName) {
if (fieldName.indexOf('font_size_') === 0) {
// For responsive font size fields
if (fieldValue !== '' && fieldValue !== null && fieldValue !== undefined) {
// Input has a value (including defaults from PHP), always save it
value[fieldName] = fieldValue;
} else if (existingValue[fieldName] !== undefined && existingValue[fieldName] !== '') {
// Input is empty but we have a previously saved value, preserve it
value[fieldName] = existingValue[fieldName];
}
// If input is empty and no saved value exists, don't include it
// This allows the field to use PHP defaults on next load
} else if (fieldValue !== '') {
// For other fields, only include if not empty
value[fieldName] = fieldValue;
} else if (existingValue[fieldName] !== undefined) {
// Preserve existing value if current is empty
value[fieldName] = existingValue[fieldName];
}
}
});
$hiddenInput.val(JSON.stringify(value)).trigger('change');
// Trigger customizer setting change
if (wp.customize && wp.customize.control(controlId)) {
wp.customize.control(controlId).setting.set(JSON.stringify(value));
}
}
function styleFontFamilySelect($wrapper) {
var $select = $wrapper.find('.accepta-font-family-select');
if ($select.length === 0) {
return;
}
// Load Google Fonts for preview
loadGoogleFontsForSelect();
// Apply font styles to options after fonts are loaded
setTimeout(function() {
applyFontStylesToOptions($select);
}, 1000);
// Update font style when selection changes
$select.on('change', function() {
var selectedFont = $(this).val();
if (selectedFont && selectedFont !== '') {
loadGoogleFont(selectedFont);
}
});
}
function loadGoogleFontsForSelect() {
// Load common Google Fonts for the select dropdown
var commonFonts = [
'Open Sans', 'Roboto', 'Lato', 'Montserrat', 'Poppins',
'Source Sans Pro', 'Raleway', 'Ubuntu', 'Nunito', 'Inter',
'Work Sans', 'Rubik', 'DM Sans', 'Manrope', 'Fira Sans',
'Playfair Display', 'Merriweather', 'PT Serif', 'Roboto Slab',
'EB Garamond', 'Source Code Pro', 'Roboto Mono'
];
// Load all common fonts at once
var fontUrl = 'https://fonts.googleapis.com/css2?family=' +
commonFonts.map(function(font) {
return encodeURIComponent(font) + ':wght@300;400;500;600;700';
}).join('&family=') + '&display=swap';
if ($('#accepta-select-fonts').length === 0) {
$('')
.attr('id', 'accepta-select-fonts')
.attr('rel', 'stylesheet')
.attr('href', fontUrl)
.appendTo('head');
}
}
function applyFontStylesToOptions($select) {
$select.find('option').each(function() {
var $option = $(this);
var fontFamily = $option.data('font-family');
if (fontFamily && fontFamily !== '') {
// Apply font family to option if available
$option.css('font-family', '"' + fontFamily + '", sans-serif');
}
});
}
function loadGoogleFont(fontName) {
if (!fontName) return;
// Extract only the first font name (before any comma) and clean it
var cleanFontName = fontName.split(',')[0].trim().replace(/['"]/g, '');
// Check if it's a system font - if so, don't try to load from Google
var systemFonts = [
'Arial', 'Helvetica', 'Times New Roman', 'Times', 'Courier New', 'Courier',
'Verdana', 'Georgia', 'Palatino', 'Garamond', 'Bookman', 'Comic Sans MS',
'Trebuchet MS', 'Arial Black', 'Impact', 'Lucida Sans Unicode', 'Tahoma',
'Lucida Console', 'Monaco', 'Brush Script MT', 'Copperplate', 'Papyrus'
];
if (systemFonts.indexOf(cleanFontName) !== -1) {
return;
}
// Check if font is already loaded by backend (accepta-google-fonts)
var backendFonts = $('#accepta-google-fonts-css');
if (backendFonts.length > 0) {
var backendUrl = backendFonts.attr('href');
if (backendUrl && backendUrl.indexOf(encodeURIComponent(cleanFontName)) !== -1) {
return;
}
}
// Create a safe ID by removing all non-alphanumeric characters except hyphens
var fontId = 'accepta-google-font-' + cleanFontName.replace(/[^a-zA-Z0-9\s]/g, '').replace(/\s+/g, '-').toLowerCase();
if ($('#' + fontId).length === 0) {
var fontUrl = 'https://fonts.googleapis.com/css2?family=' +
encodeURIComponent(cleanFontName) + ':wght@300;400;500;600;700&display=swap';
$('')
.attr('id', fontId)
.attr('rel', 'stylesheet')
.attr('href', fontUrl)
.appendTo('head');
}
}
// Add control to customizer control types
wp.customize.controlConstructor['accepta-typography'] = wp.customize.Control.extend({
ready: function() {
var control = this;
var $wrapper = this.container.find('.accepta-typography-control-wrapper');
initializeTypographyControl($wrapper, control.id);
}
});
})(jQuery);