Issue #3173832 by Pooja Ganjage, mherchel, adamzimmermann, paulocs, KapilV, markdorison, Sakthivel M, Gauravmahlawat, nod_, kostyashupenko, sulfikar_s, bnjmnm: Ensure Olivero's JS documentation matches standards
parent
d523586d78
commit
f0a97d0cdd
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @file
|
||||
* Theme override for checkbox.
|
||||
* Customization of checkbox.
|
||||
*/
|
||||
|
||||
((Drupal) => {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* @file
|
||||
* Adds show/hide functionality for indented comments.
|
||||
* Customization of comments.
|
||||
*/
|
||||
|
||||
((Drupal, once) => {
|
||||
/**
|
||||
* Init function for comments.
|
||||
* Initialize show/hide button for the comments.
|
||||
*
|
||||
* @param {object} comments
|
||||
* The comment section.
|
||||
* @param {Element} comments
|
||||
* The comment wrapper element.
|
||||
*/
|
||||
function init(comments) {
|
||||
comments
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/**
|
||||
* @file
|
||||
* Messages.
|
||||
* Customization of messages.
|
||||
*/
|
||||
|
||||
((Drupal, once) => {
|
||||
/**
|
||||
* Adds close button to the message.
|
||||
* Adds a close button to the message.
|
||||
*
|
||||
* @param {object} message
|
||||
* The message object.
|
||||
|
@ -108,7 +108,12 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Getting messages from context.
|
||||
* Get messages from context.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches the close button behavior for messages.
|
||||
*/
|
||||
Drupal.behaviors.messages = {
|
||||
attach(context) {
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
/**
|
||||
* @file
|
||||
* Customization of navigation.
|
||||
*/
|
||||
|
||||
((Drupal, once, tabbable) => {
|
||||
/**
|
||||
* Checks if navWrapper contains "is-active" class.
|
||||
* @param {object} navWrapper
|
||||
*
|
||||
* @param {Element} navWrapper
|
||||
* Header navigation.
|
||||
*
|
||||
* @return {boolean}
|
||||
* True if navWrapper contains "is-active" class, false if not.
|
||||
*/
|
||||
|
@ -12,6 +19,7 @@
|
|||
|
||||
/**
|
||||
* Opens or closes the header navigation.
|
||||
*
|
||||
* @param {object} props
|
||||
* Navigation props.
|
||||
* @param {boolean} state
|
||||
|
@ -33,7 +41,8 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Init function for header navigation.
|
||||
* Initialize the header navigation.
|
||||
*
|
||||
* @param {object} props
|
||||
* Navigation props.
|
||||
*/
|
||||
|
@ -45,7 +54,7 @@
|
|||
toggleNav(props, !isNavOpen(props.navWrapper));
|
||||
});
|
||||
|
||||
// Closes any open sub navigation first, then close header navigation.
|
||||
// Close any open sub-navigation first, then close the header navigation.
|
||||
document.addEventListener('keyup', (e) => {
|
||||
if (e.key === 'Escape' || e.key === 'Esc') {
|
||||
if (props.olivero.areAnySubNavsOpen()) {
|
||||
|
@ -107,7 +116,12 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Initialize the navigation JS.
|
||||
* Initialize the navigation.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attach context and settings for navigation.
|
||||
*/
|
||||
Drupal.behaviors.oliveroNavigation = {
|
||||
attach(context) {
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* @file
|
||||
* Controls the visibility of desktop navigation.
|
||||
*
|
||||
* Shows and hides the desktop navigation based on scroll position and controls
|
||||
* the functionality of the button that shows/hides the navigation.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-inner-declarations */
|
||||
((Drupal) => {
|
||||
/**
|
||||
|
@ -7,6 +15,12 @@
|
|||
*/
|
||||
Drupal.olivero = {};
|
||||
|
||||
/**
|
||||
* Checks if the mobile navigation button is visible.
|
||||
*
|
||||
* @return {boolean}
|
||||
* True if navButtons is hidden, false if not.
|
||||
*/
|
||||
function isDesktopNav() {
|
||||
const navButtons = document.querySelector(
|
||||
'[data-drupal-selector="mobile-buttons"]',
|
||||
|
@ -25,6 +39,12 @@
|
|||
'[data-drupal-selector="site-header-fixable"]',
|
||||
);
|
||||
|
||||
/**
|
||||
* Checks if the sticky header is enabled.
|
||||
*
|
||||
* @return {boolean}
|
||||
* True if sticky header is enabled, false if not.
|
||||
*/
|
||||
function stickyHeaderIsEnabled() {
|
||||
return stickyHeaderToggleButton.getAttribute('aria-checked') === 'true';
|
||||
}
|
||||
|
@ -33,7 +53,8 @@
|
|||
* Save the current sticky header expanded state to localStorage, and set
|
||||
* it to expire after two weeks.
|
||||
*
|
||||
* @param {boolean} expandedState - Current state of the sticky header button.
|
||||
* @param {boolean} expandedState
|
||||
* Current state of the sticky header button.
|
||||
*/
|
||||
function setStickyHeaderStorage(expandedState) {
|
||||
const now = new Date();
|
||||
|
@ -52,7 +73,8 @@
|
|||
* Toggle the state of the sticky header between always pinned and
|
||||
* only pinned when scrolled to the top of the viewport.
|
||||
*
|
||||
* @param {boolean} pinnedState - State to change the sticky header to.
|
||||
* @param {boolean} pinnedState
|
||||
* State to change the sticky header to.
|
||||
*/
|
||||
function toggleStickyHeaderState(pinnedState) {
|
||||
if (isDesktopNav()) {
|
||||
|
@ -70,7 +92,8 @@
|
|||
/**
|
||||
* Return the sticky header's stored state from localStorage.
|
||||
*
|
||||
* @return {boolean} Stored state of the sticky header.
|
||||
* @return {boolean}
|
||||
* Stored state of the sticky header.
|
||||
*/
|
||||
function getStickyHeaderStorage() {
|
||||
const stickyHeaderState = localStorage.getItem(
|
||||
|
@ -91,7 +114,8 @@
|
|||
return item.value;
|
||||
}
|
||||
|
||||
// Only enable scroll effects if the browser supports Intersection Observer.
|
||||
// Only enable scroll interactivity if the browser supports Intersection
|
||||
// Observer.
|
||||
// @see https://github.com/w3c/IntersectionObserver/blob/master/polyfill/intersection-observer.js#L19-L21
|
||||
if (
|
||||
'IntersectionObserver' in window &&
|
||||
|
@ -106,7 +130,7 @@
|
|||
if (!isDesktopNav()) return;
|
||||
|
||||
entries.forEach((entry) => {
|
||||
// FF doesn't seem to support entry.isIntersecting properly,
|
||||
// Firefox doesn't seem to support entry.isIntersecting properly,
|
||||
// so we check the intersectionRatio.
|
||||
if (entry.intersectionRatio < 1) {
|
||||
fixableElements.forEach((el) => el.classList.add('is-fixed'));
|
||||
|
@ -116,6 +140,12 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the root margin by checking for various toolbar classes.
|
||||
*
|
||||
* @return {string}
|
||||
* Root margin for the Intersection Observer options object.
|
||||
*/
|
||||
function getRootMargin() {
|
||||
let rootMarginTop = 72;
|
||||
const { body } = document;
|
||||
|
@ -134,6 +164,9 @@
|
|||
return `${rootMarginTop}px 0px 0px 0px`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitor the navigation position.
|
||||
*/
|
||||
function monitorNavPosition() {
|
||||
const primaryNav = document.querySelector(
|
||||
'[data-drupal-selector="site-header"]',
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* @file
|
||||
* Customization of search.
|
||||
*/
|
||||
|
||||
((Drupal) => {
|
||||
const searchWideButton = document.querySelector(
|
||||
'[data-drupal-selector="block-search-wide-button"]',
|
||||
|
@ -6,11 +11,20 @@
|
|||
'[data-drupal-selector="block-search-wide-wrapper"]',
|
||||
);
|
||||
|
||||
/**
|
||||
* Determine if search is visible.
|
||||
*
|
||||
* @return {boolean}
|
||||
* True if the search wrapper contains "is-active" class, false if not.
|
||||
*/
|
||||
function searchIsVisible() {
|
||||
return searchWideWrapper.classList.contains('is-active');
|
||||
}
|
||||
Drupal.olivero.searchIsVisible = searchIsVisible;
|
||||
|
||||
/**
|
||||
* Set focus for the search input element.
|
||||
*/
|
||||
function handleFocus() {
|
||||
if (searchIsVisible()) {
|
||||
searchWideWrapper.querySelector('input[type="search"]').focus();
|
||||
|
@ -19,6 +33,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle search functionality visibility.
|
||||
*
|
||||
* @param {boolean} visibility
|
||||
* True if we want to show the form, false if we want to hide it.
|
||||
*/
|
||||
function toggleSearchVisibility(visibility) {
|
||||
searchWideButton.setAttribute('aria-expanded', visibility === true);
|
||||
searchWideWrapper.addEventListener('transitionend', handleFocus, {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* @file
|
||||
* Provides functionality for second level submenu navigation.
|
||||
*/
|
||||
|
||||
((Drupal) => {
|
||||
const { isDesktopNav } = Drupal.olivero;
|
||||
const secondLevelNavMenus = document.querySelectorAll(
|
||||
|
@ -7,8 +12,10 @@
|
|||
/**
|
||||
* Shows and hides the specified menu item's second level submenu.
|
||||
*
|
||||
* @param {element} topLevelMenuItem - the <li> element that is the container for the menu and submenus.
|
||||
* @param {boolean} [toState] - Optional state where we want the submenu to end up.
|
||||
* @param {Element} topLevelMenuItem
|
||||
* The <li> element that is the container for the menu and submenus.
|
||||
* @param {boolean} [toState]
|
||||
* Optional state where we want the submenu to end up.
|
||||
*/
|
||||
function toggleSubNav(topLevelMenuItem, toState) {
|
||||
const buttonSelector =
|
||||
|
@ -60,7 +67,8 @@
|
|||
* Sets a timeout and closes current desktop navigation submenu if it
|
||||
* does not contain the focused element.
|
||||
*
|
||||
* @param {object} e - event object
|
||||
* @param {Event} e
|
||||
* The event object.
|
||||
*/
|
||||
function handleBlur(e) {
|
||||
if (!Drupal.olivero.isDesktopNav()) return;
|
||||
|
@ -147,7 +155,9 @@
|
|||
|
||||
/**
|
||||
* Checks if any sub navigation items are currently active.
|
||||
* @return {boolean} If sub nav is currently open.
|
||||
*
|
||||
* @return {boolean}
|
||||
* If sub navigation is currently open.
|
||||
*/
|
||||
function areAnySubNavsOpen() {
|
||||
let subNavsAreOpen = false;
|
||||
|
@ -168,7 +178,7 @@
|
|||
|
||||
Drupal.olivero.areAnySubNavsOpen = areAnySubNavsOpen;
|
||||
|
||||
// Ensure that desktop submenus close when ESC key is pressed.
|
||||
// Ensure that desktop submenus close when escape key is pressed.
|
||||
document.addEventListener('keyup', (e) => {
|
||||
if (e.key === 'Escape' || e.key === 'Esc') {
|
||||
if (isDesktopNav()) closeAllSubNav();
|
||||
|
|
|
@ -1,13 +1,36 @@
|
|||
/**
|
||||
* @file
|
||||
* Provides interactivity for showing and hiding the tabs at mobile widths.
|
||||
*/
|
||||
|
||||
((Drupal, once) => {
|
||||
/**
|
||||
* Initialize the tabs.
|
||||
*
|
||||
* @param {HTMLElement} el
|
||||
* The DOM element containing the tabs.
|
||||
*/
|
||||
function init(el) {
|
||||
const tabs = el.querySelector('.tabs');
|
||||
const expandedClass = 'is-expanded';
|
||||
const activeTab = tabs.querySelector('.is-active');
|
||||
|
||||
/**
|
||||
* Determines if tabs are expanded for mobile layouts.
|
||||
*
|
||||
* @return {boolean}
|
||||
* Whether the tabs trigger element is expanded.
|
||||
*/
|
||||
function isTabsMobileLayout() {
|
||||
return tabs.querySelector('.tabs__trigger').clientHeight > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls tab visibility on click events.
|
||||
*
|
||||
* @param {Event} e
|
||||
* The event object.
|
||||
*/
|
||||
function handleTriggerClick(e) {
|
||||
if (!tabs.classList.contains(expandedClass)) {
|
||||
e.currentTarget.setAttribute('aria-expanded', 'true');
|
||||
|
@ -30,6 +53,14 @@
|
|||
.addEventListener('click', handleTriggerClick);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the tabs.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Display tabs according to the screen width.
|
||||
*/
|
||||
Drupal.behaviors.tabs = {
|
||||
attach(context) {
|
||||
once('olivero-tabs', '[data-drupal-nav-tabs]', context).forEach(init);
|
||||
|
|
Loading…
Reference in New Issue