/**
* Contact Forms - Tab component for WordPress admin.
*
* Implements the W3C ARIA Tabs pattern with keyboard navigation.
* Supports nesting (each instance scopes to its own direct tabs/panels).
*
* HTML structure:
*
*
*
* ...
*
*
* ...content...
*
* ...
*
*
* Usage:
* $(selector).cfTabs();
* $(selector).cfTabs({ onSelect: function(tabId, $panel) { ... } });
*/
(function($) {
'use strict';
$.fn.cfTabs = function(options) {
var defaults = {
onSelect: null
};
var settings = $.extend({}, defaults, options);
return this.each(function() {
var $container = $(this);
// Prevent double-init
if ($container.hasClass('is-initialized')) {
return;
}
// Scope: only direct tablist and panels (not nested ones)
// Tablist may be a direct child or inside a header wrapper
var $tablist = $container.children('[role="tablist"]');
if (!$tablist.length) {
$tablist = $container.children('.accua-tabs__header').children('[role="tablist"]');
}
var $tabs = $tablist.find('> [role="tab"]');
var $panels = $container.children('[role="tabpanel"]');
if (!$tabs.length || !$panels.length) {
return;
}
// Wire up ARIA ids
$tabs.each(function() {
var $tab = $(this);
var tabId = $tab.attr('data-tab');
var tabElId = $container.attr('id') + '-tab-' + tabId;
var panelElId = $container.attr('id') + '-panel-' + tabId;
$tab.attr('id', tabElId);
$tab.attr('aria-controls', panelElId);
$panels.filter('[data-tab="' + tabId + '"]')
.attr('id', panelElId)
.attr('aria-labelledby', tabElId);
});
// Determine default tab
var defaultTab = $container.attr('data-default-tab') || $tabs.first().attr('data-tab');
function selectTab(tabId, focus) {
// Deselect all
$tabs.attr('aria-selected', 'false').attr('tabindex', '-1');
$panels.attr('hidden', '');
// Select target
var $activeTab = $tabs.filter('[data-tab="' + tabId + '"]');
var $activePanel = $panels.filter('[data-tab="' + tabId + '"]');
$activeTab.attr('aria-selected', 'true').attr('tabindex', '0');
$activePanel.removeAttr('hidden');
if (focus) {
$activeTab.trigger('focus');
}
if (typeof settings.onSelect === 'function') {
settings.onSelect(tabId, $activePanel);
}
}
// Click handler
$tabs.on('click', function(e) {
e.preventDefault();
selectTab($(this).attr('data-tab'), false);
});
// Keyboard navigation (roving tabindex)
$tabs.on('keydown', function(e) {
var index = $tabs.index(this);
var newIndex = null;
switch (e.key) {
case 'ArrowLeft':
case 'ArrowUp':
newIndex = index > 0 ? index - 1 : $tabs.length - 1;
break;
case 'ArrowRight':
case 'ArrowDown':
newIndex = index < $tabs.length - 1 ? index + 1 : 0;
break;
case 'Home':
newIndex = 0;
break;
case 'End':
newIndex = $tabs.length - 1;
break;
}
if (newIndex !== null) {
e.preventDefault();
selectTab($tabs.eq(newIndex).attr('data-tab'), true);
}
});
// Initialize: select default tab, mark container
selectTab(defaultTab, false);
$container.addClass('is-initialized');
});
};
// Form editor initialization
$(document).ready(function() {
var $tabs = $('#accua_tabs');
if (!$tabs.length) {
return;
}
var $preview = $('#accua_form_preview_pane');
var $saveBtn = $('#accua_form_save_settings_top');
// Tabs that show the preview pane alongside
var previewTabs = { fields: true, customise: true };
$tabs.find('.hidden').removeClass('hidden');
$tabs.cfTabs({
onSelect: function(tabId) {
// Show/hide preview (no DOM movement - avoids iframe reload)
if (previewTabs[tabId]) {
$preview.removeAttr('hidden');
} else {
$preview.attr('hidden', '');
}
// Hide save button on tokens tab (read-only reference)
if (tabId === 'tokens') {
$saveBtn.hide();
} else {
$saveBtn.show();
}
}
});
});
})(jQuery);