bootstrap_five_layouts-1.0.x-dev/js/behaviour.bsflDescriptionHelper.js
js/behaviour.bsflDescriptionHelper.js
/**
* @file
* Bootstrap Five Layouts bsflDescriptionHelper
* Provides enhanced settings tray item accessible tooltips
*/
(function (Drupal, drupalSettings) {
'use strict';
/**
* Drupal behavior for bsflDescriptionHelper
* Provides accessible tooltip functionality for form descriptions in settings tray
*/
Drupal.behaviors.bsflDescriptionHelper = {
attach: function (context, drupalSettings) {
var bsfl_parent = '.bootstrap-five-layouts-settings-tray-admin ';
// Get the configurable selector from settings, fallback to default
var selector = (drupalSettings && drupalSettings.bootstrap_five_layouts && drupalSettings.bootstrap_five_layouts.description_helper_selector)
? bsfl_parent + drupalSettings.bootstrap_five_layouts.description_helper_selector
: bsfl_parent + '.form-item__description';
// Find all description elements within the settings tray
var descriptionElements = context.querySelectorAll(selector);
// Convert NodeList to Array for easier manipulation
Array.from(descriptionElements).forEach(function(description) {
// Skip if already processed
if (description.classList.contains('bsfl-tooltip-processed')) {
return;
}
var formItem = description.closest('.form-item');
var label = formItem.querySelector('label');
var descriptionId = description.getAttribute('id');
// Use label's 'for' attribute as description ID if not present and label has 'for' attribute
if (!descriptionId) {
descriptionId = 'bsfl-description-' + (label && label.hasAttribute('for') ? label.getAttribute('for') : 'bsfl-tooltip-' + Math.random().toString(36).substr(2, 9));
description.setAttribute('id', descriptionId);
}
// Add ARIA attributes for accessibility
formItem.setAttribute('aria-describedby', descriptionId);
// Create toggle button for the description
var toggleButton = document.createElement('button');
toggleButton.type = 'button';
toggleButton.className = 'bsfl-description-toggle bsfl-description-toggle--floated';
toggleButton.setAttribute('aria-label', Drupal.t('Show description'));
toggleButton.setAttribute('aria-describedby', descriptionId);
toggleButton.setAttribute('aria-expanded', 'false');
// Create visually hidden span for screen readers
var visuallyHiddenSpan = document.createElement('span');
visuallyHiddenSpan.className = 'visually-hidden';
visuallyHiddenSpan.textContent = Drupal.t('Show description');
toggleButton.appendChild(visuallyHiddenSpan);
// Add question mark text
toggleButton.appendChild(document.createTextNode('?'));
// Insert toggle button after the label
var label = formItem.querySelector('label');
if (label) {
label.parentNode.insertBefore(toggleButton, label.nextSibling);
} else {
formItem.insertBefore(toggleButton, formItem.firstChild);
}
// Initially hide the description (CSS handles the visual hiding)
description.setAttribute('aria-hidden', 'true');
// Toggle functionality
toggleButton.addEventListener('click', function() {
var isExpanded = toggleButton.getAttribute('aria-expanded') === 'true';
var newState = !isExpanded;
toggleButton.setAttribute('aria-expanded', newState.toString());
description.setAttribute('aria-hidden', (!newState).toString());
// Update button labels
if (newState) {
toggleButton.setAttribute('aria-label', Drupal.t('Hide description'));
visuallyHiddenSpan.textContent = Drupal.t('Hide description');
} else {
toggleButton.setAttribute('aria-label', Drupal.t('Show description'));
visuallyHiddenSpan.textContent = Drupal.t('Show description');
}
});
// Keyboard support
toggleButton.addEventListener('keydown', function(e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
toggleButton.click();
}
});
// Mark as processed
description.classList.add('bsfl-tooltip-processed');
});
}
};
})(Drupal, drupalSettings);
