diff --git a/.gitignore b/.gitignore index 117a3a4530..2582940bad 100644 --- a/.gitignore +++ b/.gitignore @@ -62,8 +62,9 @@ docroot/themes/humsci/humsci_colorful/css/humsci_colorful-ckeditor.css docroot/themes/humsci/humsci_traditional/css/humsci_traditional-ckeditor.css docroot/themes/humsci/humsci_colorful/css/humsci_colorful-preview.css docroot/themes/humsci/humsci_traditional/css/humsci_traditional-preview.css -docroot/themes/humsci/humsci_traditional/js/index.js -docroot/themes/humsci/humsci_colorful/js/index.js +docroot/themes/humsci/humsci_basic/dist/js +docroot/themes/humsci/humsci_traditional/js +docroot/themes/humsci/humsci_colorful/js # Ignore build artifacts deployment_identifier /deploy diff --git a/docroot/modules/humsci/hs_layouts/hs_layouts.libraries.yml b/docroot/modules/humsci/hs_layouts/hs_layouts.libraries.yml index 61d574e51b..18dcf6af85 100644 --- a/docroot/modules/humsci/hs_layouts/hs_layouts.libraries.yml +++ b/docroot/modules/humsci/hs_layouts/hs_layouts.libraries.yml @@ -2,10 +2,12 @@ three_column_w_image: css: layout: css/three-column-w-image.css: {} + news_style: css: layout: css/news-style.css: {} + layout_builder_admin: css: theme: @@ -20,3 +22,8 @@ images_loaded: dependencies: - core/jquery +layout-builder-vertical-tabs: + js: + js/layout-builder-vertical-tabs.js: {} + dependencies: + - core/drupal diff --git a/docroot/modules/humsci/hs_layouts/hs_layouts.module b/docroot/modules/humsci/hs_layouts/hs_layouts.module index 110c2edb9b..261f0299ee 100644 --- a/docroot/modules/humsci/hs_layouts/hs_layouts.module +++ b/docroot/modules/humsci/hs_layouts/hs_layouts.module @@ -35,6 +35,16 @@ function hs_layouts_plugin_filter_block__layout_builder_alter(&$definitions, &$e } } +/** + * Implements hook_preprocess_HOOK(). + */ +function hs_layouts_preprocess_page(&$variables) { + // Load layout-builder-vertical-tabs lib in the layout builder override form. + if (\Drupal::routeMatch()->getRouteName() == 'layout_builder.overrides.node.view') { + $variables['#attached']['library'][] = 'hs_layouts/layout-builder-vertical-tabs'; + } +} + /** * Implements hook_preprocess(). */ diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/vertical-tabs/vertical-tabs.js b/docroot/modules/humsci/hs_layouts/js/layout-builder-vertical-tabs.js similarity index 80% rename from docroot/themes/humsci/humsci_basic/src/js/shared/vertical-tabs/vertical-tabs.js rename to docroot/modules/humsci/hs_layouts/js/layout-builder-vertical-tabs.js index b4972b1cc2..cc613d7dbd 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/vertical-tabs/vertical-tabs.js +++ b/docroot/modules/humsci/hs_layouts/js/layout-builder-vertical-tabs.js @@ -1,5 +1,5 @@ function closeDetails() { - // Close Revision Information Details element in Layout Builder by default. +// Close Revision Information Details element in Layout Builder by default. if (document.querySelector('.layout-builder-form')) { const details = document.querySelector('.layout-builder-form details'); if (details) { diff --git a/docroot/themes/humsci/humsci_basic/.eslintrc.json b/docroot/themes/humsci/humsci_basic/.eslintrc.json index 70d5eee29c..6641eee547 100644 --- a/docroot/themes/humsci/humsci_basic/.eslintrc.json +++ b/docroot/themes/humsci/humsci_basic/.eslintrc.json @@ -7,7 +7,9 @@ "node": true }, "globals": { - "Drupal": "readonly" + "Drupal": "readonly", + "jQuery": "readonly", + "once": "readonly" }, "rules": { "no-restricted-globals": 0, diff --git a/docroot/themes/humsci/humsci_basic/humsci_basic.info.yml b/docroot/themes/humsci/humsci_basic/humsci_basic.info.yml index 7958d3d5b3..b585c77238 100644 --- a/docroot/themes/humsci/humsci_basic/humsci_basic.info.yml +++ b/docroot/themes/humsci/humsci_basic/humsci_basic.info.yml @@ -4,7 +4,9 @@ description: A base for visually distinctive HumSci themes. package: 'Humanities & Sciences' core_version_requirement: ^9.4 || ^10 'base theme': stable9 -# libraries: Libraries are loaded via sub-themes +libraries: + - humsci_basic/main-content-fallback + - humsci_basic/editoria11y regions: page_top: 'Page top' @@ -27,9 +29,3 @@ libraries-override: css: layout: css/three-column-w-image.css: false - -# we_megamenu/form.we-mega-menu-frontend: -# css: -# theme: -# assets/css/we_megamenu_backend.css: false -# assets/includes/bootstrap/css/bootstrap.min.css: false diff --git a/docroot/themes/humsci/humsci_basic/humsci_basic.libraries.yml b/docroot/themes/humsci/humsci_basic/humsci_basic.libraries.yml index 0b4e3e3428..3913b0ed28 100644 --- a/docroot/themes/humsci/humsci_basic/humsci_basic.libraries.yml +++ b/docroot/themes/humsci/humsci_basic/humsci_basic.libraries.yml @@ -1,3 +1,132 @@ +accordion: + js: + dist/js/accordion.js: {} + dependencies: + - core/drupal + - core/once + +addtocal: + js: + dist/js/addtocal.js: {} + dependencies: + - core/drupal + - core/once + +carousel-slides-height: + js: + dist/js/carousel-slides-height.js: {} + dependencies: + - core/drupal + - core/once + +colorbox: + js: + dist/js/colorbox.js: {} + dependencies: + - core/drupal + - core/once + +editoria11y: + js: + dist/js/editoria11y.js: {} + dependencies: + - core/drupal + - core/once + +equal-height-grid: + js: + dist/js/equal-height-grid.js: {} + dependencies: + - core/drupal + - core/once + +linked-cards: + js: + dist/js/linked-cards.js: {} + dependencies: + - core/drupal + - core/once + +main-content-fallback: + js: + dist/js/main-content-fallback.js: {} + dependencies: + - core/drupal + - core/once + +main-menu: + js: + dist/js/main-menu.js: {} + dependencies: + - core/drupal + - core/once + +megamenu: + js: + dist/js/megamenu.js: {} + dependencies: + - core/drupal + - core/once + +page-scroll-animations: + js: + dist/js/page-scroll-animations.js: {} + dependencies: + - core/drupal + - core/once + +prefered-reduced-motion: + js: + dist/js/prefered-reduced-motion.js: {} + dependencies: + - core/drupal + - core/once + search: js: - src/js/shared/search/search-expand.js: {} + dist/js/search.js: {} + dependencies: + - core/drupal + - core/once + +secondary-menu: + js: + dist/js/secondary-toggler.js: {} + dependencies: + - core/drupal + - core/once + +table-pattern: + js: + dist/js/table-pattern.js: {} + dependencies: + - core/drupal + - core/once + +table-scope: + js: + dist/js/table-scope.js: {} + dependencies: + - core/drupal + - core/once + +table-wrap: + js: + dist/js/table-wrap.js: {} + dependencies: + - core/drupal + - core/once + +timeline: + js: + dist/js/timeline.js: {} + dependencies: + - core/drupal + - core/once + +video-with-caption: + js: + dist/js/video-with-caption.js: {} + dependencies: + - core/drupal + - core/once diff --git a/docroot/themes/humsci/humsci_basic/humsci_basic.theme b/docroot/themes/humsci/humsci_basic/humsci_basic.theme index d1faba0402..ae7d11e541 100644 --- a/docroot/themes/humsci/humsci_basic/humsci_basic.theme +++ b/docroot/themes/humsci/humsci_basic/humsci_basic.theme @@ -174,7 +174,6 @@ function _humsci_basic_check_link_access(array &$link_items) { } } - /** * Implements hook_preprocess_HOOK() for we_megamenu li. */ @@ -220,7 +219,6 @@ function humsci_basic_preprocess_we_megamenu_frontend(&$vars) { */ function humsci_basic_preprocess_views_view(&$variables) { $view = $variables['view']; - switch ($view->id()) { case 'hs_default_search': $variables['#attached']['library'][] = 'humsci_basic/search'; @@ -250,3 +248,22 @@ function humsci_basic_preprocess_paragraph(&$variables) { } $variables['content']['field_hs_view'][0]['#heading_tag'] = $heading_tag; } + +/** + * Implements hook_preprocess_HOOK(). + */ +function humsci_basic_preprocess_field(&$variables) { + $wysiwyg_types = ['text_long', 'text_with_summary']; + if (in_array($variables['field_type'], $wysiwyg_types)) { + $variables['#attached']['library'][] = 'humsci_basic/table-wrap'; + $variables['#attached']['library'][] = 'humsci_basic/table-scope'; + $variables['#attached']['library'][] = 'humsci_basic/page-scroll-animations'; + } +} + +/** + * Implements hook_preprocess_ENTITY__BUNDLE(). + */ +function humsci_basic_preprocess_node__hs_event(&$variables) { + $variables['#attached']['library'][] = 'humsci_basic/addtocal'; +} diff --git a/docroot/themes/humsci/humsci_basic/src/js/colorful/colorful.js b/docroot/themes/humsci/humsci_basic/src/js/colorful/colorful.js index 10a3940345..c04f7febd8 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/colorful/colorful.js +++ b/docroot/themes/humsci/humsci_basic/src/js/colorful/colorful.js @@ -1,3 +1 @@ -import '../shared/index'; - // Add Colorful and Airy specific JS below diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/accordion/accordion-toggle-all.js b/docroot/themes/humsci/humsci_basic/src/js/shared/accordion/accordion-toggle-all.js index 4140ccab4a..93a1717392 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/accordion/accordion-toggle-all.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/accordion/accordion-toggle-all.js @@ -1,102 +1,115 @@ -/** - * Loops through a list of accordions and either opens or closes all items - * - * @param {array} expects a list of accordion elements - * @param {string} expects a string that specifies if all accordions should be opened or closed - */ -function toggleAllAccordions(accordionList, command) { - if (command === 'closeAll') { - accordionList.forEach((accordion) => { - accordion.removeAttribute('open'); - }); - } else { - accordionList.forEach((accordion) => { - accordion.setAttribute('open', ''); - }); +(function (Drupal, once) { + /** + * Loops through a list of accordions and either opens or closes all items + * + * @param {array} expects a list of accordion elements + * @param {string} expects a string that specifies if all accordions should be opened or closed + */ + function toggleAllAccordions(accordionList, command) { + if (command === 'closeAll') { + accordionList.forEach((accordion) => { + accordion.removeAttribute('open'); + }); + } else { + accordionList.forEach((accordion) => { + accordion.setAttribute('open', ''); + }); + } } -} -/** - * Creates a button element that can act as a toggle for all accordions on a page. - * - * @return {element} - */ -function createToggle() { - const toggleButton = document.createElement('Button'); - toggleButton.innerText = 'Expand All'; - toggleButton.classList.add('hb-link'); - toggleButton.classList.add('hb-accordion-toggle-all'); + /** + * Creates a button element that can act as a toggle for all accordions on a page. + * + * @return {element} + */ + function createToggle() { + const toggleButton = document.createElement('Button'); + toggleButton.innerText = 'Expand All'; + toggleButton.classList.add('hb-link'); + toggleButton.classList.add('hb-accordion-toggle-all'); - return toggleButton; -} + return toggleButton; + } -/** - * Updates the all toggle buttons when one has been clicked depending on whether - * or not all accordions are being opened or closed. - * @param {array} expects the list of all accordion toggle buttons on the page - * @param {string} expects a string that specifies if all accordions should be opened or closed - */ -function updateToggle(toggleList, command) { - toggleList.forEach((toggleButton) => { - if (command === 'closeAll') { - toggleButton.innerText = 'Expand All'; - } else { - toggleButton.innerText = 'Collapse All'; - } - }); -} + /** + * Updates the all toggle buttons when one has been clicked depending on whether + * or not all accordions are being opened or closed. + * @param {array} expects the list of all accordion toggle buttons on the page + * @param {string} expects a string that specifies if all accordions should be opened or closed + */ + function updateToggle(toggleList, command) { + toggleList.forEach((toggleButton) => { + if (command === 'closeAll') { + toggleButton.innerText = 'Expand All'; + } else { + toggleButton.innerText = 'Collapse All'; + } + }); + } -// Create a list of all accordions on the page -const accordionList = [...document.querySelectorAll('details')]; + Drupal.behaviors.accordionToggleAllBehavior = { + attach(context) { + // Create a list of all accordions on the page + const accordionList = once('accordion', 'details', context); -if (accordionList.length >= 1) { - let allExpanded = false; + if (accordionList.length >= 1) { + let allExpanded = false; - // Loop through each accordion item - // If the toggle all class is present create a toggle button and place it above - // the accordion instance. - accordionList.forEach((accordion) => { - if (accordion.classList.contains('hb-accordion_toggle-all')) { - const toggleButton = createToggle(); - accordion.parentNode.insertBefore(toggleButton, accordion); - } - }); + // Loop through each accordion item + // If the toggle all class is present create a toggle button and place it above + // the accordion instance. + accordionList.forEach((accordion) => { + if (accordion.classList.contains('hb-accordion_toggle-all')) { + const toggleButton = createToggle(); + accordion.parentNode.insertBefore(toggleButton, accordion); + } + }); - // Create a list of all toggle buttons generated on the page. This has to run - // after the block of code that loops through the accordion lists and creates - // the buttons. - const allToggleButtons = [...document.querySelectorAll('.hb-accordion-toggle-all')]; + // Create a list of all toggle buttons generated on the page. This has to run + // after the block of code that loops through the accordion lists and creates + // the buttons. + const allToggleButtons = once( + 'accordion-toggle-all', + '.hb-accordion-toggle-all', + context, + ); - allToggleButtons.forEach((toggleButton) => { - toggleButton.addEventListener('click', (e) => { - e.preventDefault(); - if (allExpanded) { - toggleAllAccordions(accordionList, 'closeAll'); - updateToggle(allToggleButtons, 'closeAll'); - allExpanded = false; - } else { - toggleAllAccordions(accordionList, 'openAll'); - updateToggle(allToggleButtons, 'openAll'); - allExpanded = true; + allToggleButtons.forEach((toggleButton) => { + toggleButton.addEventListener('click', (e) => { + e.preventDefault(); + if (allExpanded) { + toggleAllAccordions(accordionList, 'closeAll'); + updateToggle(allToggleButtons, 'closeAll'); + allExpanded = false; + } else { + toggleAllAccordions(accordionList, 'openAll'); + updateToggle(allToggleButtons, 'openAll'); + allExpanded = true; + } + toggleButton.scrollIntoView(true); + }); + }); } - toggleButton.scrollIntoView(true); - }); - }); -} -const searchQuery = new URLSearchParams(window.location.search); -const params = Object.fromEntries(searchQuery.entries()); + const searchQuery = new URLSearchParams(window.location.search); + const params = Object.fromEntries(searchQuery.entries()); -function toggleAccordionFromSearch() { - const searchTerm = params.search.toLowerCase(); + function toggleAccordionFromSearch() { + const searchTerm = params.search.toLowerCase(); - accordionList.forEach((accordion) => { - if (accordion.textContent.toLowerCase().includes(searchTerm)) { - accordion.setAttribute('open', ''); - } - }); -} + accordionList.forEach((accordion) => { + if (accordion.textContent.toLowerCase().includes(searchTerm)) { + accordion.setAttribute('open', ''); + } + }); + } -if (Object.keys(params).length && Object.prototype.hasOwnProperty.call(params, 'search')) { - toggleAccordionFromSearch(); -} + if ( + Object.keys(params).length + && Object.prototype.hasOwnProperty.call(params, 'search') + ) { + toggleAccordionFromSearch(); + } + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/addtocal/addtocal.js b/docroot/themes/humsci/humsci_basic/src/js/shared/addtocal/addtocal.js index a1822a65b1..3cdab82283 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/addtocal/addtocal.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/addtocal/addtocal.js @@ -1,26 +1,33 @@ -function addToCalAria() { - const addToCal = document.querySelectorAll('.addtocal'); - const body = document.querySelector('body'); +(function (Drupal, once) { + Drupal.behaviors.accordionToggleAllBehavior = { + attach(context) { + const addToCal = once('addtocal', '.addtocal', context); - // For each .addtocal button, when clicked, change aria-expanded to true. - addToCal.forEach((button) => { - button.addEventListener('click', () => { - if (button.getAttribute('aria-expanded') === 'true') { - button.setAttribute('aria-expanded', 'false'); - } else { - button.setAttribute('aria-expanded', 'true'); + // Do nothing if no add to cal button found. + if (addToCal.length === 0) { + return; } - }); - }); - // When the body except button is clicked, change aria-expanded to false. - body.addEventListener('click', (e) => { - addToCal.forEach((button) => { - if (e.target !== button) { - button.setAttribute('aria-expanded', 'false'); - } - }); - }); -} + // For each .addtocal button, when clicked, change aria-expanded to true. + addToCal.forEach((button) => { + button.addEventListener('click', () => { + if (button.getAttribute('aria-expanded') === 'true') { + button.setAttribute('aria-expanded', 'false'); + } else { + button.setAttribute('aria-expanded', 'true'); + } + }); + }); -addToCalAria(); + // When the body except button is clicked, change aria-expanded to false. + const body = document.querySelector('body'); + body.addEventListener('click', (e) => { + addToCal.forEach((button) => { + if (e.target !== button) { + button.setAttribute('aria-expanded', 'false'); + } + }); + }); + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/animation/page-scroll.js b/docroot/themes/humsci/humsci_basic/src/js/shared/animation/page-scroll.js index 3ac6ef6c37..65d2aab0e3 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/animation/page-scroll.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/animation/page-scroll.js @@ -1,39 +1,53 @@ -const animationEnhancements = document.querySelector('.hb-has-animation-enhancements'); -const experimentalFeaturesClass = document.querySelector('.hb-experimental'); -const experimentalClassesToAnimate = [document.querySelectorAll('.hs-font-lead')]; +(function (Drupal, once) { + Drupal.behaviors.pageScrollBehavior = { + attach(context) { + // Selectors for elements + const animationEnhancements = context.querySelector( + '.hb-has-animation-enhancements', + ); + const experimentalFeaturesClass = context.querySelector('.hb-experimental'); + const experimentalClassesToAnimate = ['.hs-font-lead']; -// The classes of items we want to add animations to -const classesToAnimate = [ - document.querySelectorAll('.hb-gradient-hero'), - document.querySelectorAll('.hb-gradient-hero__text'), - document.querySelectorAll('.hb-gradient-hero__image-wrapper'), - document.querySelectorAll('.field-hs-gradient-hero-image'), - document.querySelectorAll('.hb-hero-overlay'), - document.querySelectorAll('.hb-hero-overlay__text'), - document.querySelectorAll('.hb-hero-overlay__image-wrapper'), - document.querySelectorAll('.field-hs-hero-image'), - document.querySelectorAll('.hs-font-splash'), -]; + // If the animation enhancements are not enabled, do nothing. + if (!animationEnhancements) { + return; + } -if (experimentalFeaturesClass) { - classesToAnimate.push(experimentalClassesToAnimate); -} + // The classes of items we want to add animations to + const classesToAnimate = [ + '.hb-gradient-hero', + '.hb-gradient-hero__text', + '.hb-gradient-hero__image-wrapper', + '.field-hs-gradient-hero-image', + '.hb-hero-overlay', + '.hb-hero-overlay__text', + '.hb-hero-overlay__image-wrapper', + '.field-hs-hero-image', + '.hs-font-splash', + ]; -// check if top of element is in viewport -const isElementVisible = new IntersectionObserver((items) => { - items.forEach((item) => { - if (item.intersectionRatio > 0) { - item.target.classList.add('animate'); - } - }); -}); + if (experimentalFeaturesClass) { + classesToAnimate.push(experimentalClassesToAnimate); + } -if (animationEnhancements) { - classesToAnimate.forEach((items) => { - if (items) { - items.forEach((item) => { - isElementVisible.observe(item); + const elementsToAnimate = once( + 'page-scroll-animate', + classesToAnimate.join(','), + context, + ); + + // check if top of element is in viewport + const isElementVisible = new IntersectionObserver((items) => { + items.forEach((item) => { + if (item.intersectionRatio > 0) { + item.target.classList.add('animate'); + } + }); + }); + + elementsToAnimate.forEach((element) => { + isElementVisible.observe(element); }); - } - }); -} + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/carousel-slides/carousel-slides-height.js b/docroot/themes/humsci/humsci_basic/src/js/shared/carousel-slides/carousel-slides-height.js index 10c729b917..35ba27c625 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/carousel-slides/carousel-slides-height.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/carousel-slides/carousel-slides-height.js @@ -1,91 +1,99 @@ // This work below applies uniform height to both the Hero Layered Slider (formerly Carousel), // the Hero Gradient Slider paragraph component slides. // and the Spotlight Slider. -const slides = document.querySelectorAll('.paragraph--type--hs-carousel, .paragraph--type--hs-gradient-hero-slider, .paragraph--type--hs-sptlght-slder'); -// Find slick arrow from hsCarousel. -const slidesTextboxClasses = '.hb-hero-overlay__text, .hb-gradient-hero__text, .hb-spotlight__text'; -let timeOutFunctionId; // a numeric ID which is used by clearTimeOut to reset the timer - -// @boolean to determine if the textBox is a spotlight textBox -const isSpotlightTextBox = (textBox) => textBox.classList.contains('hb-spotlight__text'); -const setMinHeight = (textBox, maxBoxHeight) => textBox.setAttribute('style', `min-height: ${maxBoxHeight}px`); - -// Set the height of all text boxes within a slider to that -// of the tallest text box -const restrictHeight = () => { - let boxHeightArray; - let maxBoxHeight; - - slides.forEach((slide) => { - // array must have a default entry of 0 for the banner components - // and must be declare within the loop to set a baseline for each indiviual slider on a page - boxHeightArray = [0]; - - // Find all the textBoxes inside each slider - const textBoxes = slide.querySelectorAll(slidesTextboxClasses); - - // Loop through all the textBoxes and gather their heights into an array - textBoxes.forEach((textBox) => { - // Clear any inline styles that may have been set previously - // This is necessary to determine the default height of text boxes - textBox.removeAttribute('style'); - - let boxHeight = textBox.offsetHeight; - - // Parse boxHeight to be a number that can be used to set the min-height value - boxHeight = parseInt(boxHeight, 10); - - // Create an array containing all the heights of textBoxes - boxHeightArray.push(boxHeight); - }); - - // Find largest number in array of textBoxes - maxBoxHeight = Math.max(...boxHeightArray); - - // Give all textBoxes the same height - textBoxes.forEach((textBox) => setMinHeight(textBox, maxBoxHeight)); - - // Give sickArrowWrapper a top that changes according to the height when resizing the window. - const slickArrowWrapper = slide.querySelector('.slick__arrow'); - if (slide.classList.contains('paragraph--type--hs-carousel') && slickArrowWrapper) { - setMinHeight(slickArrowWrapper, maxBoxHeight); - } - - // If the textBoxes are spotlight textBoxes, then give them the same height on all screen sizes - textBoxes.forEach((textBox) => { - const classicSpotlight = slide.querySelector('.hb-spotlight--classic'); - if (isSpotlightTextBox(textBox) && classicSpotlight) { - setMinHeight(textBox, maxBoxHeight); +(function (Drupal, window, once) { + Drupal.behaviors.restrictHeightBehavior = { + attach(context) { + const slides = once('restrict-height-slides', '.paragraph--type--hs-carousel, .paragraph--type--hs-gradient-hero-slider, .paragraph--type--hs-sptlght-slder', context); + // Find slick arrow from hsCarousel. + const slidesTextboxClasses = '.hb-hero-overlay__text, .hb-gradient-hero__text, .hb-spotlight__text'; + let timeOutFunctionId; // a numeric ID which is used by clearTimeOut to reset the timer + + // @boolean to determine if the textBox is a spotlight textBox + const isSpotlightTextBox = (textBox) => textBox.classList.contains('hb-spotlight__text'); + const setMinHeight = (textBox, maxBoxHeight) => textBox.setAttribute('style', `min-height: ${maxBoxHeight}px`); + + // Set the height of all text boxes within a slider to that + // of the tallest text box + const restrictHeight = () => { + let boxHeightArray; + let maxBoxHeight; + + slides.forEach((slide) => { + // array must have a default entry of 0 for the banner components and must be + // declare within the loop to set a baseline for each indiviual slider on a page + boxHeightArray = [0]; + + // Find all the textBoxes inside each slider + const textBoxes = slide.querySelectorAll(slidesTextboxClasses); + + // Loop through all the textBoxes and gather their heights into an array + textBoxes.forEach((textBox) => { + // Clear any inline styles that may have been set previously + // This is necessary to determine the default height of text boxes + textBox.removeAttribute('style'); + + let boxHeight = textBox.offsetHeight; + + // Parse boxHeight to be a number that can be used to set the min-height value + boxHeight = parseInt(boxHeight, 10); + + // Create an array containing all the heights of textBoxes + boxHeightArray.push(boxHeight); + }); + + // Find largest number in array of textBoxes + maxBoxHeight = Math.max(...boxHeightArray); + + // Give all textBoxes the same height + textBoxes.forEach((textBox) => setMinHeight(textBox, maxBoxHeight)); + + // Give sickArrowWrapper a top that changes according + // to the height when resizing the window. + const slickArrowWrapper = slide.querySelector('.slick__arrow'); + if (slide.classList.contains('paragraph--type--hs-carousel') && slickArrowWrapper) { + setMinHeight(slickArrowWrapper, maxBoxHeight); + } + + // If the textBoxes are spotlight textBoxes, + // then give them the same height on all screen sizes + textBoxes.forEach((textBox) => { + const classicSpotlight = slide.querySelector('.hb-spotlight--classic'); + if (isSpotlightTextBox(textBox) && classicSpotlight) { + setMinHeight(textBox, maxBoxHeight); + } + }); + + // Find all spotlights texBoxes wrappers to give them the same height on all screen sizes + const expandedSpotlights = slide.querySelectorAll('.hb-spotlight--expanded'); + if (expandedSpotlights) { + expandedSpotlights.forEach((expandedSpotlight) => { + const expandedSpotlightWrapper = expandedSpotlight.querySelector('.hb-spotlight__wrapper'); + setMinHeight(expandedSpotlightWrapper, maxBoxHeight); + }); + } + + // Find images inside each slider. + const imageWrapper = slide.querySelector('.hb-spotlight__image-wrapper'); + if (slide.classList.contains('paragraph--type--hs-sptlght-slder') && !imageWrapper) { + slide.classList.add('paragraph--type--hs-sptlght-slder--no-image'); + } + }); + }; + + const clearTimeoutOnResize = () => { + // Watch for when the browser window resizes, then run the restrictHeight + // function to reset the height of the text boxes + window.addEventListener('resize', () => { + clearTimeout(timeOutFunctionId); + timeOutFunctionId = setTimeout(restrictHeight, 100); + }); + }; + + if (slides.length > 0) { + restrictHeight(); + clearTimeoutOnResize(); } - }); - - // Find all spotlights texBoxes wrappers to give them the same height on all screen sizes - const expandedSpotlights = slide.querySelectorAll('.hb-spotlight--expanded'); - if (expandedSpotlights) { - expandedSpotlights.forEach((expandedSpotlight) => { - const expandedSpotlightWrapper = expandedSpotlight.querySelector('.hb-spotlight__wrapper'); - setMinHeight(expandedSpotlightWrapper, maxBoxHeight); - }); - } - - // Find images inside each slider. - const imageWrapper = slide.querySelector('.hb-spotlight__image-wrapper'); - if (slide.classList.contains('paragraph--type--hs-sptlght-slder') && !imageWrapper) { - slide.classList.add('paragraph--type--hs-sptlght-slder--no-image'); - } - }); -}; - -const clearTimeoutOnResize = () => { - // Watch for when the browser window resizes, then run the restrictHeight - // function to reset the height of the text boxes - window.addEventListener('resize', () => { - clearTimeout(timeOutFunctionId); - timeOutFunctionId = setTimeout(restrictHeight, 100); - }); -}; - -if (slides.length > 0) { - restrictHeight(); - clearTimeoutOnResize(); -} + }, + }; +}(Drupal, window, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/editoria11y/editoria11y.js b/docroot/themes/humsci/humsci_basic/src/js/shared/editoria11y/editoria11y.js index 454fc293ea..5f53f8ba77 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/editoria11y/editoria11y.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/editoria11y/editoria11y.js @@ -1,39 +1,46 @@ -/* global ed11yLang, ed11yOnce */ -window.editoria11yOptionsOverride = true; -window.editoria11yOptions = (options) => { - // Change the default button text for the Heading Outline tab. - if (ed11yLang && ed11yLang.en) { - ed11yLang.en.buttonOutlineContent = 'Heading Outline'; - } - return options; -}; +(function (Drupal) { + Drupal.behaviors.editoria11yOptionsOverride = { + // eslint-disable-next-line no-unused-vars + attach(context) { + /* global ed11yLang, ed11yOnce */ + window.editoria11yOptionsOverride = true; + window.editoria11yOptions = (options) => { + // Change the default button text for the Heading Outline tab. + if (ed11yLang && ed11yLang.en) { + ed11yLang.en.buttonOutlineContent = 'Heading Outline'; + } + return options; + }; -window.addEventListener('load', () => { - // If the editoria11y is not loaded, we don't need to do anything. - if (typeof ed11yOnce === 'undefined' || !ed11yOnce) { - return; - } + window.addEventListener('load', () => { + // If the editoria11y is not loaded, we don't need to do anything. + if (typeof ed11yOnce === 'undefined' || !ed11yOnce) { + return; + } - // Editoria11y element is added to the DOM after the load event, we need to - // observe the body element for changes. - const observer = new MutationObserver((mutationList) => { - mutationList.forEach((mutation) => { - if (mutation.addedNodes.length && mutation.addedNodes[0].nodeName === 'ED11Y-ELEMENT-PANEL') { - // Once we get the element, we update the styles to make the alert button text black. - const { shadowRoot } = mutation.addedNodes[0]; - if (shadowRoot) { - const style = document.createElement('style'); - style.textContent = ` + // Editoria11y element is added to the DOM after the load event, we need to + // observe the body element for changes. + const observer = new MutationObserver((mutationList) => { + mutationList.forEach((mutation) => { + if (mutation.addedNodes.length && mutation.addedNodes[0].nodeName === 'ED11Y-ELEMENT-PANEL') { + // Once we get the element, we update the styles to make the alert button text black. + const { shadowRoot } = mutation.addedNodes[0]; + if (shadowRoot) { + const style = document.createElement('style'); + style.textContent = ` .ed11y-shut.ed11y-errors #ed11y-toggle { color: #000000; } `; - shadowRoot.appendChild(style); - } - } - }); - }); - observer.observe(document.body, { - childList: true, - }); -}); + shadowRoot.appendChild(style); + } + } + }); + }); + observer.observe(document.body, { + childList: true, + }); + }); + }, + }; +}(Drupal)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/equal-height-grid.js b/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/equal-height-grid.js index 68e41a2ddc..8342ffd1ca 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/equal-height-grid.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/equal-height-grid.js @@ -5,11 +5,6 @@ const equalHeightGrid = (elements) => { // Create array with all of the heights of each element const elementHeights = Array.prototype.map.call(elements, (el) => el.scrollHeight); - // Create array with _unique_ height values - // const uniqueHeights = elementHeights.filter((height, index, array) => { - // return array.indexOf(height) == index; - // }); - return new Promise((resolve) => { const maxHeight = Math.max.apply(null, elementHeights); const tallestElementIndex = elementHeights.indexOf(maxHeight); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/index.js b/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/index.js index 54c4d03343..65d9981b3c 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/index.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/equal-height-grid/index.js @@ -1,59 +1,79 @@ import equalHeightGrid from './equal-height-grid'; import resetHeightGrid from './reset-height-grid'; -const applyStretchClass = () => { - const hasStretchClass = document.querySelector('.hb-stretch-vertical-linked-cards'); - const verticalLinkedCardTitles = [...document.querySelectorAll('.hb-vertical-linked-card__title')]; - const cardCollections = document.querySelectorAll('.ptype-hs-collection, .ptype-hs-priv-collection'); +(function (Drupal, window, once) { + Drupal.behaviors.hbStretchVerticalLinkedCards = { + attach(context) { + const applyStretchClass = (container) => { + // Matches the $su-breakpoint-sm variable. Screen sizes smaller than this variable + // stack all grid columns making it unnecessary to set a height on cards. + // See: https://github.com/SU-SWS/decanter/blob/master/core/src/scss/utilities/variables/core/_breakpoints.scss + const smallScreenBreakpoint = 576; - // Matches the $su-breakpoint-sm variable. Screen sizes smaller than this variable - // stack all grid columns making it unnecessary to set a height on cards. - // See: https://github.com/SU-SWS/decanter/blob/master/core/src/scss/utilities/variables/core/_breakpoints.scss - const smallScreenBreakpoint = 576; + const cardCollections = container.querySelectorAll( + '.ptype-hs-collection, .ptype-hs-priv-collection', + ); - Array.prototype.forEach.call(cardCollections, (collection) => { - const verticalLinkedCards = [...collection.querySelectorAll('.hb-vertical-linked-card')]; - // Reset any min-heights that were previously set. - // We need to do this so cards will not have a height set when resizing to small - // screen sizes. - if (hasStretchClass && verticalLinkedCards.length > 0) { - resetHeightGrid(verticalLinkedCards); - } + cardCollections.forEach((collection) => { + const verticalLinkedCards = [ + ...collection.querySelectorAll('.hb-vertical-linked-card'), + ]; + // Reset any min-heights that were previously set. + // We need to do this so cards will not have a height set when resizing to small + // screen sizes. + if (verticalLinkedCards.length > 0) { + resetHeightGrid(verticalLinkedCards); + } - // Reset any min-heights that were previously set. - // Because not all Vertical Linked Cards will have a title, this needs a separate - // if statement. - if (hasStretchClass && verticalLinkedCardTitles.length > 0) { - resetHeightGrid(verticalLinkedCardTitles); - } + const verticalLinkedCardTitles = [ + ...collection.querySelectorAll('.hb-vertical-linked-card__title'), + ]; + // Reset any min-heights that were previously set. + // Because not all Vertical Linked Cards will have a title, this needs a separate + // if statement. + if (verticalLinkedCardTitles.length > 0) { + resetHeightGrid(verticalLinkedCardTitles); + } - // Only set heights for certain screen sizes - if (hasStretchClass && window.innerWidth >= smallScreenBreakpoint) { - if (verticalLinkedCardTitles.length > 0) { - // Make the vertical linked card titles AND cards the same max height. - // The title height has to be set first because it influences the final - // height of the card. - equalHeightGrid(verticalLinkedCardTitles) - .then(() => equalHeightGrid(verticalLinkedCards)) - .catch((result) => console.error('issue loading equal height cards', result)); - } else if (verticalLinkedCards.length > 0) { - // Since card titles are not required we still want to run the equal height - // function on remaining cards - equalHeightGrid(verticalLinkedCards); - } - } - }); -}; + // Only set heights for certain screen sizes + if (window.innerWidth >= smallScreenBreakpoint) { + if (verticalLinkedCardTitles.length > 0) { + // Make the vertical linked card titles AND cards the same max height. + // The title height has to be set first because it influences the final + // height of the card. + equalHeightGrid(verticalLinkedCardTitles) + .then(() => equalHeightGrid(verticalLinkedCards)) + .catch((result) => console.error('issue loading equal height cards', result)); + } else if (verticalLinkedCards.length > 0) { + // Since card titles are not required we still want to run the equal height + // function on remaining cards + equalHeightGrid(verticalLinkedCards); + } + } + }); + }; + const stretchContainers = once( + 'stretch-vertical-linked-cards', + '.hb-stretch-vertical-linked-cards', + context, + ); -// Wait a 1 sec for page to load in before setting heights -setTimeout(() => { - applyStretchClass(); -}, 1000); + // Wait a 1 sec for page to load in before setting heights + setTimeout(() => { + stretchContainers.forEach((container) => { + applyStretchClass(container); + }); + }, 1000); -// Recalculate when the window is resized -window.addEventListener('resize', () => { - // Wait a half of a second before setting the heights - setTimeout(() => { - applyStretchClass(); - }, 500); -}); + // Recalculate when the window is resized + window.addEventListener('resize', () => { + // Wait a half of a second before setting the heights + setTimeout(() => { + stretchContainers.forEach((container) => { + applyStretchClass(container); + }); + }, 500); + }); + }, + }; +}(Drupal, window, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/index.js b/docroot/themes/humsci/humsci_basic/src/js/shared/index.js deleted file mode 100644 index a22cfc783d..0000000000 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/index.js +++ /dev/null @@ -1,20 +0,0 @@ -import './carousel-slides/carousel-slides-height'; -import './tables/wrap'; -import './tables/scope'; -import './tables/table-pattern'; -import './navigation/index'; -import './equal-height-grid/index'; -import './media/video-with-caption'; -import './animation/page-scroll'; -import './timeline/expand-collapse-timeline'; -import './accordion/accordion-toggle-all'; -import './linked-cards/linked-cards'; -import './photo-album/colorbox'; -import './editoria11y/editoria11y'; -import './vertical-tabs/vertical-tabs'; -import './addtocal/addtocal'; -import './prefered-reduced-motion/prefered-reduced-motion'; -import './main-content-fallback/main-content-fallback'; - -// PoC for new megamenu. -import './megamenu/index'; diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/linked-cards/linked-cards.js b/docroot/themes/humsci/humsci_basic/src/js/shared/linked-cards/linked-cards.js index c14d9758bd..5b28a2513b 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/linked-cards/linked-cards.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/linked-cards/linked-cards.js @@ -1,43 +1,51 @@ -(() => { - // find all hb-vertical-card elements - const cards = document.querySelectorAll('.hb-vertical-card, .hb-card--date-stacked, .hb-vertical-linked-card'); +(function (Drupal, once) { + Drupal.behaviors.linkedCardsBehavior = { + attach(context) { + // find all hb-vertical-card elements + const cards = once( + 'linked-cards-events', + '.hb-vertical-card, .hb-card--date-stacked, .hb-vertical-linked-card', + context, + ); - // Loop through each card - cards.forEach((card) => { - // Find the main link within each card - let mainLink = ''; + // Loop through each card + cards.forEach((card) => { + // Find the main link within each card + let mainLink = ''; - // Logic for vertical card and date stacked card. - if (card.querySelector('.hb-card__title a')) { - mainLink = card.querySelector('.hb-card__title a'); - // Logic for vertical linked card. - } else { - mainLink = card.querySelector( - '.hb-vertical-linked-card__title__link', - ); - } + // Logic for vertical card and date stacked card. + if (card.querySelector('.hb-card__title a')) { + mainLink = card.querySelector('.hb-card__title a'); + // Logic for vertical linked card. + } else { + mainLink = card.querySelector( + '.hb-vertical-linked-card__title__link', + ); + } - if (!mainLink) { - return; - } + if (!mainLink) { + return; + } - // Add a click event listener to each card - function handleClick() { - mainLink.click(); - } + // Add a click event listener to each card + function handleClick() { + mainLink.click(); + } - // Add a focus event listener to each main link - mainLink.addEventListener('focus', () => { - // Add a focus state class to card - card.classList.add('is-focused'); - }); + // Add a focus event listener to each main link + mainLink.addEventListener('focus', () => { + // Add a focus state class to card + card.classList.add('is-focused'); + }); - // Add a blur event listener to each main link - mainLink.addEventListener('blur', () => { - // Remove focus state class from card - card.classList.remove('is-focused'); - }); + // Add a blur event listener to each main link + mainLink.addEventListener('blur', () => { + // Remove focus state class from card + card.classList.remove('is-focused'); + }); - card.addEventListener('click', handleClick); - }); -})(); + card.addEventListener('click', handleClick); + }); + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/main-content-fallback/main-content-fallback.js b/docroot/themes/humsci/humsci_basic/src/js/shared/main-content-fallback/main-content-fallback.js index 5c7b691b3b..2558b41521 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/main-content-fallback/main-content-fallback.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/main-content-fallback/main-content-fallback.js @@ -1,14 +1,22 @@ -(() => { - // Return if main content target is found, nothing to do. - if (document.querySelector('#main-content')) { - return; - } +(function (Drupal, once) { + Drupal.behaviors.addMainContentFallback = { + attach(context) { + const [mainElement] = once('main-content-fallback', 'main', context); - const mainElement = document.querySelector('main'); - if (mainElement) { - mainElement.insertAdjacentHTML( - 'afterbegin', - '
Main content start
', - ); - } -})(); + // No main element or behavior already executed. + if (!mainElement) { + return; + } + + // Return if main content target is found, nothing to do. + if (document.querySelector('#main-content')) { + return; + } + + mainElement.insertAdjacentHTML( + 'afterbegin', + '
Main content start
', + ); + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/media/video-with-caption.js b/docroot/themes/humsci/humsci_basic/src/js/shared/media/video-with-caption.js index 3a893f0688..38ee32f042 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/media/video-with-caption.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/media/video-with-caption.js @@ -2,17 +2,31 @@ // This causes issues when there is a video in a figure because the video no longer // fills the entire space of the container. // This JS sets a width of 100% to figures that contain videos. -const videos = document.querySelectorAll('.field-media-oembed-video'); +(function (Drupal, once) { + Drupal.behaviors.videoWithCaptionBehavior = { + attach(context) { + const videos = once( + 'video-with-caption', + '.field-media-oembed-video', + context, + ); -if (videos && videos.length > 0) { - for (let i = 0; i < videos.length; i++) { - const video = videos[i]; - if (video.parentNode && video.parentNode.parentNode && video.parentNode.parentNode.nodeName === 'FIGURE') { - const figure = video.parentNode.parentNode; + if (videos && videos.length > 0) { + for (let i = 0; i < videos.length; i++) { + const video = videos[i]; + if ( + video.parentNode + && video.parentNode.parentNode + && video.parentNode.parentNode.nodeName === 'FIGURE' + ) { + const figure = video.parentNode.parentNode; - if (figure.classList.contains('caption')) { - figure.style.width = '100%'; + if (figure.classList.contains('caption')) { + figure.style.width = '100%'; + } + } + } } - } - } -} + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/megamenu/index.js b/docroot/themes/humsci/humsci_basic/src/js/shared/megamenu/index.js index d1600a67de..148e4d3da0 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/megamenu/index.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/megamenu/index.js @@ -1,107 +1,115 @@ -const menu = document.querySelector('.js-megamenu'); - -// Because all JS is smashed together instead of using libraries, -// we need to 'if' all the parent variables we create. -if (menu) { - const menuBtnMobile = document.querySelector('.js-megamenu__mobile-btn'); - const menuList = menu.querySelector('.js-megamenu__list--main'); - const menuBtns = menu.querySelectorAll('.js-megamenu__toggle'); - const mobileNavBreakpoint = 992; - let windowWidth = window.innerWidth; - let isMobile = windowWidth < mobileNavBreakpoint; - - window.addEventListener('resize', () => { - windowWidth = window.innerWidth; - - isMobile = windowWidth <= mobileNavBreakpoint; - }); - - // Toggle util function for expanded menus - const toggleMenu = (btn) => { - const list = btn.nextElementSibling; - - list.classList.remove('is-expanded'); - btn.classList.remove('is-expanded'); - btn.setAttribute('aria-expanded', 'false'); - }; - - // Closes open submenus if another menu btn is clicked. - const closeAllSubmenus = (currentBtn) => { - menuBtns.forEach((btn) => { - if (btn !== currentBtn) { - toggleMenu(btn); +(function (Drupal, window, once) { + Drupal.behaviors.megaMenuBehavior = { + attach(context) { + const menu = once('js-mega-menu', '.js-megamenu', context)[0]; + + // Because all JS is smashed together instead of using libraries, + // we need to 'if' all the parent variables we create. + if (menu) { + const menuBtnMobile = menu.querySelector('.js-megamenu__mobile-btn'); + const menuList = menu.querySelector('.js-megamenu__list--main'); + const menuBtns = menu.querySelectorAll('.js-megamenu__toggle'); + const mobileNavBreakpoint = 992; + let windowWidth = window.innerWidth; + let isMobile = windowWidth < mobileNavBreakpoint; + + window.addEventListener('resize', () => { + windowWidth = window.innerWidth; + + isMobile = windowWidth <= mobileNavBreakpoint; + }); + + // Toggle util function for expanded menus + const toggleMenu = (btn) => { + const list = btn.nextElementSibling; + + list.classList.remove('is-expanded'); + btn.classList.remove('is-expanded'); + btn.setAttribute('aria-expanded', 'false'); + }; + + // Closes open submenus if another menu btn is clicked. + const closeAllSubmenus = (currentBtn) => { + menuBtns.forEach((btn) => { + if (btn !== currentBtn) { + toggleMenu(btn); + } + }); + }; + + // Closes an open menu if user clicks outside + document.body.addEventListener('mousedown', (e) => { + const isClickInsideMenu = menu.contains(e.target); + + if (!isClickInsideMenu) { + menuBtns.forEach((btn) => { + toggleMenu(btn); + }); + } + }); + + // Toggle aria-[anything] attribute from true / false. + const toggleAria = (el, aria) => { + let x = el.getAttribute(`aria-${aria}`); + if (x === 'true') { + x = 'false'; + } else { + x = 'true'; + } + el.setAttribute(`aria-${aria}`, x); + }; + + // Displays nested child menus on mobile + const expandMobileSubmenus = () => { + const activeParent = context.querySelector( + '.js-megamenu__active-trail', + ); + // Only expand menu tree if active-trail exists. + if (activeParent) { + const childMenu = activeParent.nextElementSibling; + toggleAria(activeParent, 'expanded'); + activeParent.classList.add('is-expanded'); + childMenu.classList.add('is-expanded'); + } + }; + + if (menuBtnMobile) { + // Toggle nav immediately for JS visitors + toggleAria(menuBtnMobile, 'expanded'); + + if (isMobile) { + expandMobileSubmenus(); + } + + // Toggle the nav when the the button is clicked + menuBtnMobile.addEventListener('click', () => { + toggleAria(menuBtnMobile, 'expanded'); + + if (menuList) { + menuList.classList.toggle('is-active'); + } + }); + } + + menuBtns.forEach((btn) => { + btn.addEventListener('click', (e) => { + const currentBtn = e.currentTarget; + const menuItem = e.currentTarget.parentElement; + const subMenu = menuItem.querySelector( + '.js-megamenu__expanded-container', + ); + // We want to only close expanded menus on desktop to mimic current + // menu functionality. + if (!isMobile) { + closeAllSubmenus(currentBtn); + } + toggleAria(currentBtn, 'expanded'); + + btn.classList.toggle('is-expanded'); + subMenu.classList.toggle('is-expanded'); + }); + }); } - }); - }; - - // Closes an open menu if user clicks outside - document.body.addEventListener('mousedown', (e) => { - const isClickInsideMenu = menu.contains(e.target); - - if (!isClickInsideMenu) { - menuBtns.forEach((btn) => { - toggleMenu(btn); - }); - } - }); - - // Toggle aria-[anything] attribute from true / false. - const toggleAria = (el, aria) => { - let x = el.getAttribute(`aria-${aria}`); - if (x === 'true') { - x = 'false'; - } else { - x = 'true'; - } - el.setAttribute(`aria-${aria}`, x); + }, }; - - // Displays nested child menus on mobile - const expandMobileSubmenus = () => { - const activeParent = document.querySelector('.js-megamenu__active-trail'); - // Only expand menu tree if active-trail exists. - if (activeParent) { - const childMenu = activeParent.nextElementSibling; - toggleAria(activeParent, 'expanded'); - activeParent.classList.add('is-expanded'); - childMenu.classList.add('is-expanded'); - } - }; - - if (menuBtnMobile) { - // Toggle nav immediately for JS visitors - toggleAria(menuBtnMobile, 'expanded'); - - if (isMobile) { - expandMobileSubmenus(); - } - - // Toggle the nav when the the button is clicked - menuBtnMobile.addEventListener('click', () => { - toggleAria(menuBtnMobile, 'expanded'); - - if (menuList) { - menuList.classList.toggle('is-active'); - } - }); - } - - menuBtns.forEach((btn) => { - btn.addEventListener('click', (e) => { - const currentBtn = e.currentTarget; - const menuItem = e.currentTarget.parentElement; - const subMenu = menuItem.querySelector( - '.js-megamenu__expanded-container', - ); - // We want to only close expanded menus on desktop to mimic current - // menu functionality. - if (!isMobile) { - closeAllSubmenus(currentBtn); - } - toggleAria(currentBtn, 'expanded'); - - btn.classList.toggle('is-expanded'); - subMenu.classList.toggle('is-expanded'); - }); - }); -} +}(Drupal, window, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/collapse-main-menu.js b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/collapse-main-menu.js index 805fd8ceb8..c111e29628 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/collapse-main-menu.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/collapse-main-menu.js @@ -4,37 +4,55 @@ import changeNav from './change-nav'; // which allows users who have JavaScript disabled to navigate. // This script collapses the pre-expanded menus so // it's ready to use for those w/ JavaScript enabled. -const mainToggle = document.querySelector('.hb-main-nav__toggle'); -const mainNavContent = document.querySelector('.hb-main-nav__menu-lv1'); -const nestedTogglers = document.querySelectorAll('.hb-nested-toggler'); -const isBelowMobileNavBreakpoint = (window.innerWidth < 992); - -// Collapse the main hamburger nav on mobile. -if (isBelowMobileNavBreakpoint && mainToggle) { - changeNav(mainToggle, mainNavContent, false); -} - -// Collapse the subnavs at all screen sizes. -if (nestedTogglers) { - for (let i = 0; i < nestedTogglers.length; i += 1) { - const toggler = nestedTogglers[i]; - const togglerID = toggler.getAttribute('id'); - const togglerContent = document.querySelector('[aria-labelledby="'.concat(togglerID, '"]')); - const subnavIsActive = !!toggler.parentNode.classList.contains('hb-main-nav__item--active-trail'); - - if (!togglerContent) { - continue; - } - - // On page load, all menus in the active section should be expanded on mobile. - // All other menus should be hidden. - const isExpanded = !!((subnavIsActive && isBelowMobileNavBreakpoint)); - changeNav(toggler, togglerContent, isExpanded); - } -} - -// Now that we've manually collapsed the main nav and subnavs, -// we can remove the "still loading" class and disable the CSS-powered menu suppression. -if (mainToggle) { - document.querySelector('.hb-main-nav--is-still-loading').classList.remove('hb-main-nav--is-still-loading'); -} +(function (Drupal, once) { + Drupal.behaviors.collapseMainMenu = { + attach(context) { + const [mainNav] = once('main-nav-collapse', '.hb-main-nav', context); + + if (!mainNav) { + return; + } + + const mainToggle = mainNav.querySelector('.hb-main-nav__toggle'); + const mainNavContent = mainNav.querySelector('.hb-main-nav__menu-lv1'); + const nestedTogglers = mainNav.querySelectorAll('.hb-nested-toggler'); + const isBelowMobileNavBreakpoint = window.innerWidth < 992; + + // Collapse the main hamburger nav on mobile. + if (isBelowMobileNavBreakpoint && mainNavContent && mainToggle) { + changeNav(mainToggle, mainNavContent, false); + } + + // Collapse the subnavs at all screen sizes. + if (nestedTogglers) { + for (let i = 0; i < nestedTogglers.length; i += 1) { + const toggler = nestedTogglers[i]; + const togglerID = toggler.getAttribute('id'); + const togglerContent = context.querySelector( + '[aria-labelledby="'.concat(togglerID, '"]'), + ); + const subnavIsActive = !!toggler.parentNode.classList.contains( + 'hb-main-nav__item--active-trail', + ); + + if (!togglerContent) { + continue; + } + + // On page load, all menus in the active section should be expanded on mobile. + // All other menus should be hidden. + const isExpanded = !!(subnavIsActive && isBelowMobileNavBreakpoint); + changeNav(toggler, togglerContent, isExpanded); + } + } + + // Now that we've manually collapsed the main nav and subnavs, + // we can remove the "still loading" class and disable the CSS-powered menu suppression. + if (mainToggle) { + context + .querySelector('.hb-main-nav--is-still-loading') + .classList.remove('hb-main-nav--is-still-loading'); + } + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/index.js b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-index.js similarity index 76% rename from docroot/themes/humsci/humsci_basic/src/js/shared/navigation/index.js rename to docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-index.js index 611785dc6b..d1679e07ee 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/index.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-index.js @@ -1,4 +1,3 @@ import './main-menu-toggle'; import './main-menu-nested-toggler'; import './collapse-main-menu'; -import './secondary-toggler'; diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-nested-toggler.js b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-nested-toggler.js index 5d4d6c6d1e..48fe95c8d8 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-nested-toggler.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-nested-toggler.js @@ -1,61 +1,76 @@ import changeNav from './change-nav'; import togglerHandler from './toggler-handler'; -const togglers = document.querySelectorAll('.hb-nested-toggler'); -const mobileNavBreakpoint = 992; - -if (togglers) { - for (let i = 0; i < togglers.length; i += 1) { - let windowWidth = window.innerWidth; - const toggler = togglers[i]; - const togglerID = toggler.getAttribute('id'); - const togglerContent = document.querySelector('[aria-labelledby="'.concat(togglerID, '"]')); - const togglerParent = toggler.parentNode; - - // Togglers should always have content but in the event that they don't we - // don't want the rest of the togglers on the page to break. - if (!togglerContent) { - continue; - } - - toggler.addEventListener('click', (e) => togglerHandler(e, toggler, togglerContent)); - - // Some togglers will be anchor tags instead of buttons and they should behave - // like a button when the spacebar is pressed - toggler.addEventListener('keydown', (e) => { - // 32 is the keycode for the spacebar - if (e.which !== 32) { - return; - } +(function (Drupal, window, once) { + Drupal.behaviors.NestedToggler = { + attach(context) { + const togglers = once('nested-toggler', '.hb-nested-toggler', context); + const mobileNavBreakpoint = 992; - e.preventDefault(); + if (togglers) { + for (let i = 0; i < togglers.length; i += 1) { + let windowWidth = window.innerWidth; + const toggler = togglers[i]; + const togglerID = toggler.getAttribute('id'); + const togglerContent = context.querySelector( + `[aria-labelledby="${togglerID}"]`, + ); + const togglerParent = toggler.parentNode; - const isExpanded = e.target.getAttribute('aria-expanded') === 'true'; - changeNav(toggler, togglerContent, !isExpanded); - }); + // Togglers should always have content but in the event that they don't we + // don't want the rest of the togglers on the page to break. + if (!togglerContent) { + continue; + } - // At larger screen sizes: - // ========================================================================= - // All menus collapse when resizing larger than the lg breakpoint - window.addEventListener('resize', () => { - windowWidth = window.innerWidth; + toggler.addEventListener('click', (e) => togglerHandler(e, toggler, togglerContent)); - // When resizing from mobile to desktop, show the navigation - if (windowWidth >= mobileNavBreakpoint) { - changeNav(toggler, togglerContent, false); - } - }); - - // We want to close open dropdowns on desktop when the following events happen - // on the body, outside of the toggler component: - // 1. (focusin) When tabbing through the navigation the previously opened dropdown closes - // 2. (click) When clicking outside of the dropdown area it will close - ['focusin', 'click'].forEach((event) => { - document.body.addEventListener(event, (e) => { - if (windowWidth >= mobileNavBreakpoint && !togglerParent.contains(e.target)) { - changeNav(toggler, togglerContent, false); + // Some togglers will be anchor tags instead of buttons and they should behave + // like a button when the spacebar is pressed + toggler.addEventListener('keydown', (e) => { + // 32 is the keycode for the spacebar + if (e.which !== 32) { + return; + } + + e.preventDefault(); + + const isExpanded = e.target.getAttribute('aria-expanded') === 'true'; + changeNav(toggler, togglerContent, !isExpanded); + }); + + // At larger screen sizes: + // ========================================================================= + // All menus collapse when resizing larger than the lg breakpoint + window.addEventListener('resize', () => { + windowWidth = window.innerWidth; + + // When resizing from mobile to desktop, show the navigation + if (windowWidth >= mobileNavBreakpoint) { + changeNav(toggler, togglerContent, false); + } + }); + + // We want to close open dropdowns on desktop when the following events happen + // on the body, outside of the toggler component: + // 1. (focusin) When tabbing through the navigation the previously opened dropdown closes + // 2. (click) When clicking outside of the dropdown area it will close + ['focusin', 'click'].forEach((event) => { + document.body.addEventListener( + event, + (e) => { + if ( + windowWidth >= mobileNavBreakpoint + && !togglerParent.contains(e.target) + ) { + changeNav(toggler, togglerContent, false); + } + }, + false, + ); + }); } - }, false); - }); - } -} + } + }, + }; +}(Drupal, window, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-toggle.js b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-toggle.js index b5c61856c4..8a72a5a460 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-toggle.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/main-menu-toggle.js @@ -1,40 +1,54 @@ import changeNav from './change-nav'; -const menuToggle = document.querySelector('.hb-main-nav__toggle'); -const mainMenu = document.querySelector('.hb-main-nav__menu-lv1'); -const mobileNavBreakpoint = 992; -let windowWidth; -let wasDesktopSize; - -if (menuToggle) { - // Toggle the nav when the the button is clicked - menuToggle.addEventListener('click', () => { - const isExpanded = menuToggle.getAttribute('aria-expanded') === 'true'; - - changeNav(menuToggle, mainMenu, !isExpanded); - }); - - // Handle the showing/hiding of the nav when resizing the browser - window.addEventListener('resize', () => { - windowWidth = window.innerWidth; - - // When resizing from mobile to desktop, ensure navigation is displayed, not hidden - // If wasDesktopSize is false, it means we haven't gotten there yet and will to run this check - // Otherwise, if wasDesktopSize is true, - // we are above the mobileNavBreakpoint and don't need to keep showingNav - if (windowWidth >= mobileNavBreakpoint && !wasDesktopSize) { - changeNav(menuToggle, mainMenu, true); - wasDesktopSize = true; - } - - // When resizing from desktop to mobile, hide the navigation - if (windowWidth < mobileNavBreakpoint && wasDesktopSize) { - changeNav(menuToggle, mainMenu, false); - - // This keeps the navigation from collapsing every time the screen is resized - // below remains the mobileNavBreakpoint - // After the first time we resize to below the mobileNavBreakpoint, reset wasDesktopSize var - wasDesktopSize = false; - } - }); -} +(function (Drupal, window, once) { + Drupal.behaviors.toggleNavigation = { + attach(context) { + const [mainNav] = once('main-nav-toggle', '.hb-main-nav', context); + + if (!mainNav) { + return; + } + + const menuToggle = mainNav.querySelector('.hb-main-nav__toggle'); + const mainMenu = mainNav.querySelector('.hb-main-nav__menu-lv1'); + const mobileNavBreakpoint = 992; + let windowWidth; + let wasDesktopSize; + + if (menuToggle) { + // Toggle the nav when the the button is clicked + menuToggle.addEventListener('click', () => { + const isExpanded = menuToggle.getAttribute('aria-expanded') === 'true'; + + changeNav(menuToggle, mainMenu, !isExpanded); + }); + + // Handle the showing/hiding of the nav when resizing the browser + window.addEventListener('resize', () => { + windowWidth = window.innerWidth; + + // When resizing from mobile to desktop, ensure navigation is displayed, not hidden + // If wasDesktopSize is false, it means we haven't gotten there yet + // and will to run this check + // Otherwise, if wasDesktopSize is true, + // we are above the mobileNavBreakpoint and don't need to keep showingNav + if (windowWidth >= mobileNavBreakpoint && !wasDesktopSize) { + changeNav(menuToggle, mainMenu, true); + wasDesktopSize = true; + } + + // When resizing from desktop to mobile, hide the navigation + if (windowWidth < mobileNavBreakpoint && wasDesktopSize) { + changeNav(menuToggle, mainMenu, false); + + // This keeps the navigation from collapsing every time the screen is resized + // below remains the mobileNavBreakpoint + // After the first time we resize to below the mobileNavBreakpoint, + // reset wasDesktopSize var + wasDesktopSize = false; + } + }); + } + }, + }; +}(Drupal, window, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/secondary-toggler.js b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/secondary-toggler.js index ff99e25a24..e9ca2a7d33 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/secondary-toggler.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/navigation/secondary-toggler.js @@ -1,26 +1,32 @@ import changeNav from './change-nav'; import togglerHandler from './toggler-handler'; -const togglers = document.querySelectorAll('.hb-secondary-toggler'); +(function (Drupal, once) { + Drupal.behaviors.secondaryToggleNavigation = { + attach(context) { + const togglers = once('secondary-toggler', '.hb-secondary-toggler', context); -if (togglers) { - for (let i = 0; i < togglers.length; i += 1) { - const toggler = togglers[i]; - const togglerID = toggler.getAttribute('id'); - const togglerContent = document.querySelector('[aria-labelledby="'.concat(togglerID, '"]')); - const togglerParent = toggler.parentNode; - const activeTrail = togglerParent.classList.contains('hb-secondary-nav__item--active-trail'); + if (togglers) { + for (let i = 0; i < togglers.length; i += 1) { + const toggler = togglers[i]; + const togglerID = toggler.getAttribute('id'); + const togglerContent = document.querySelector('[aria-labelledby="'.concat(togglerID, '"]')); + const togglerParent = toggler.parentNode; + const activeTrail = togglerParent.classList.contains('hb-secondary-nav__item--active-trail'); - // Togglers should always have content but in the event that they don't we - // don't want the rest of the togglers on the page to break. - if (!togglerContent) { - continue; - } + // Togglers should always have content but in the event that they don't we + // don't want the rest of the togglers on the page to break. + if (!togglerContent) { + continue; + } - if (!activeTrail) { - changeNav(toggler, togglerContent, false); - } + if (!activeTrail) { + changeNav(toggler, togglerContent, false); + } - toggler.addEventListener('click', (e) => togglerHandler(e, toggler, togglerContent)); - } -} + toggler.addEventListener('click', (e) => togglerHandler(e, toggler, togglerContent)); + } + } + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/photo-album/colorbox.js b/docroot/themes/humsci/humsci_basic/src/js/shared/photo-album/colorbox.js index 2638c71c31..fbb5a24c3d 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/photo-album/colorbox.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/photo-album/colorbox.js @@ -1,15 +1,15 @@ -const attachStanfordColorbox = (context) => { - const colorboxElement = context.getElementById('colorbox'); - if (colorboxElement) { - const previousButton = context.getElementById('cboxPrevious'); - const nextButton = context.getElementById('cboxNext'); - const slideshowButton = context.getElementById('cboxSlideshow'); - previousButton.textContent = '« Prev'; - nextButton.textContent = 'Next »'; - slideshowButton.textContent = 'Slideshow'; - } -}; - -document.addEventListener('DOMContentLoaded', () => { - attachStanfordColorbox(document); -}); +(function (Drupal, once) { + Drupal.behaviors.attachStanfordColorbox = { + attach(context) { + const [colorboxElement] = once('colorbox', '#colorbox', context); + if (colorboxElement) { + const previousButton = colorboxElement.querySelector('#cboxPrevious'); + const nextButton = colorboxElement.querySelector('#cboxNext'); + const slideshowButton = colorboxElement('#cboxSlideshow'); + if (previousButton) previousButton.textContent = '« Prev'; + if (nextButton) nextButton.textContent = 'Next »'; + if (slideshowButton) slideshowButton.textContent = 'Slideshow'; + } + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/prefered-reduced-motion/prefered-reduced-motion.js b/docroot/themes/humsci/humsci_basic/src/js/shared/prefered-reduced-motion/prefered-reduced-motion.js index 7e0e5dc026..2e07a80649 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/prefered-reduced-motion/prefered-reduced-motion.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/prefered-reduced-motion/prefered-reduced-motion.js @@ -1,5 +1,5 @@ (function ($, Drupal, window) { - Drupal.behaviors.mySlickBehavior = { + Drupal.behaviors.preferedReducedMotionBehavior = { attach(context) { // Check for reduced motion preference const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); @@ -26,5 +26,4 @@ mediaQuery.addEventListener('change', handleReducedMotionPreference); }, }; -// eslint-disable-next-line no-undef -}(jQuery, Drupal, window, document)); +}(jQuery, Drupal, window)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/tables/scope.js b/docroot/themes/humsci/humsci_basic/src/js/shared/tables/scope.js index 3eff2a5cd6..cfd3ed228e 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/tables/scope.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/tables/scope.js @@ -3,21 +3,27 @@ * This improves table accessibility */ -/** - * Set a specific scope attribute value on each element - * @param elements - * @param scope - */ -function setScopeOnElements(elements, scope) { - for (let i = 0; i < elements.length; i++) { - elements[i].setAttribute('scope', scope); - } -} +(function (Drupal, once) { + Drupal.behaviors.addTableScopeAttributes = { + attach(context) { + /** + * Set a specific scope attribute value on each element + * @param elements + * @param scope + */ + function setScopeOnElements(elements, scope) { + for (let i = 0; i < elements.length; i++) { + elements[i].setAttribute('scope', scope); + } + } -// set scope attribute on column headers -const columnEls = document.querySelectorAll('thead th'); -setScopeOnElements(columnEls, 'col'); + // set scope attribute on column headers + const columnEls = once('table-scope', 'thead th', context); + setScopeOnElements(columnEls, 'col'); -// set scope attribute on row headers -const rowEls = document.querySelectorAll('tbody th'); -setScopeOnElements(rowEls, 'row'); + // set scope attribute on row headers + const rowEls = once('table-scope', 'tbody th', context); + setScopeOnElements(rowEls, 'row'); + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/tables/table-pattern.js b/docroot/themes/humsci/humsci_basic/src/js/shared/tables/table-pattern.js index 84a3521db8..dfd81db07b 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/tables/table-pattern.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/tables/table-pattern.js @@ -1,25 +1,40 @@ // account for different ways in which a table heading may be declared -const div = 'div.hb-table-pattern__header > div.hb-table-pattern__row > div'; -const span = 'div.hb-table-pattern__header > div.hb-table-pattern__row > span'; -const paragraph = 'div.hb-table-pattern__header > div.hb-table-pattern__row > p'; -// retrieve table column headings -const columnHeaders = document.querySelectorAll(`${div}, ${span}, ${paragraph}`); +(function (Drupal, once) { + Drupal.behaviors.updateTableHeaders = { + attach(context) { + const tables = once('table-pattern', '.hb-table-pattern', context); -// retrieve all rows -const tableRows = document.querySelectorAll('.hb-table-row'); + tables.forEach((table) => { + const div = 'div.hb-table-pattern__header > div.hb-table-pattern__row > div'; + const span = 'div.hb-table-pattern__header > div.hb-table-pattern__row > span'; + const paragraph = 'div.hb-table-pattern__header > div.hb-table-pattern__row > p'; -if (tableRows) { - // For each row in the table - for (let i = 0; i < tableRows.length; i += 1) { - // find the row headers in each cell - const tableRowHeaders = tableRows[i].querySelectorAll('.hb-table-row__heading'); + // retrieve table column headings + const columnHeaders = table.querySelectorAll( + `${div}, ${span}, ${paragraph}`, + ); - // we need h to step through columnHeaders and get the correct heading text - for (let h = 0; h < tableRowHeaders.length; h += 1) { - if (tableRowHeaders[h].innerHTML !== '') { - tableRowHeaders[h].innerHTML = columnHeaders[h].innerHTML; - } - } - } -} + // retrieve all rows + const tableRows = table.querySelectorAll('.hb-table-row'); + + if (tableRows) { + // For each row in the table + for (let i = 0; i < tableRows.length; i += 1) { + // find the row headers in each cell + const tableRowHeaders = tableRows[i].querySelectorAll( + '.hb-table-row__heading', + ); + + // we need h to step through columnHeaders and get the correct heading text + for (let h = 0; h < tableRowHeaders.length; h += 1) { + if (tableRowHeaders[h].innerHTML !== '') { + tableRowHeaders[h].innerHTML = columnHeaders[h].innerHTML; + } + } + } + } + }); + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/tables/wrap.js b/docroot/themes/humsci/humsci_basic/src/js/shared/tables/wrap.js index 776c4ac0e6..5ab125d8f0 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/tables/wrap.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/tables/wrap.js @@ -1,31 +1,31 @@ -/** - * Wrap every table in a class that will allow us to create more responsive styling - */ +(function (Drupal, once) { + Drupal.behaviors.wrapTableElements = { + attach(context) { + /** + * Wrap every table in a class that will allow us to create more responsive styling + */ -/** - * Wrap each element in a new parent - * @param elements - * @param wrapper - */ -function wrapElement(element) { - // Create a new div with a special class name - const wrapper = document.createElement('div'); - wrapper.className = 'hb-table-wrap'; + /** + * Wrap each element in a new parent + * @param elements + * @param wrapper + */ + function wrapElement(element) { + // Create a new div with a special class name + const wrapper = context.createElement('div'); + wrapper.className = 'hb-table-wrap'; - element.parentNode.insertBefore(wrapper, element); - wrapper.appendChild(element); -} + element.parentNode.insertBefore(wrapper, element); + wrapper.appendChild(element); + } -// Select every table element -const elements = document.querySelectorAll('table'); -const uiPatternTable = document.querySelectorAll('.hb-table-pattern'); + // Select every table and table pattern element + const elements = once('table-wrap', 'table, .hb-table-pattern', context); -// Wrap every table element -for (let i = 0; i < elements.length; i++) { - wrapElement(elements[i]); -} - -// Wrap every table UI pattern -for (let i = 0; i < uiPatternTable.length; i++) { - wrapElement(uiPatternTable[i]); -} + // Wrap every element + for (let i = 0; i < elements.length; i++) { + wrapElement(elements[i]); + } + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/shared/timeline/expand-collapse-timeline.js b/docroot/themes/humsci/humsci_basic/src/js/shared/timeline/expand-collapse-timeline.js index 4e3938451c..ddcfa35d26 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/shared/timeline/expand-collapse-timeline.js +++ b/docroot/themes/humsci/humsci_basic/src/js/shared/timeline/expand-collapse-timeline.js @@ -1,72 +1,86 @@ // Timelines are expanded by default // Find when a timeline has been set to collapsed so that we can // adjust the default attribute values -const timelineCollapsed = document.querySelectorAll('.hb-timeline__collapsed'); +(function (Drupal, once) { + Drupal.behaviors.timelineCollapseBehavior = { + attach(context) { + const timelineCollapsed = once( + 'collapsed-timeline', + '.hb-timeline__collapsed', + context, + ); -// Find timeline items are are open inside of timelineCollapsed and close them! -timelineCollapsed.forEach((timeline) => { - // let items; - // let summaries; + // Find timeline items are are open inside of timelineCollapsed and close them! + timelineCollapsed.forEach((timeline) => { + // Find all the timeline items inside of the collapsed timeline + const items = timeline.querySelectorAll('.hb-timeline-item'); - // Find all the timeline items inside of the collapsed timeline - const items = timeline.querySelectorAll('.hb-timeline-item'); + // Remove open attribute from these items + items.forEach((item) => { + item.removeAttribute('open'); + }); - // Remove open attribute from these items - items.forEach((item) => { - item.removeAttribute('open'); - }); + // Find the summary element and update the aria attribute values + const summaries = timeline.querySelectorAll( + '.hb-timeline-item__summary', + ); - // Find the summary element and update the aria attribute values - const summaries = timeline.querySelectorAll('.hb-timeline-item__summary'); + summaries.forEach((summary) => { + summary.setAttribute('aria-expanded', 'false'); + summary.setAttribute('aria-pressed', 'false'); + }); + }); - summaries.forEach((summary) => { - summary.setAttribute('aria-expanded', 'false'); - summary.setAttribute('aria-pressed', 'false'); - }); -}); + // When a user clicks on a timeline, update the aria properties accordingly + const timelineItems = once('timeline-item', '.hb-timeline-item', context); -// When a user clicks on a timeline, update the aria properties accordingly -const timelineItems = document.querySelectorAll('.hb-timeline-item'); + if (timelineItems) { + timelineItems.forEach((timelineItem) => { + const summary = timelineItem.querySelector( + '.hb-timeline-item__summary', + ); -if (timelineItems) { - timelineItems.forEach((timelineItem) => { - const summary = timelineItem.querySelector('.hb-timeline-item__summary'); + // Find the value of aria-expanded for a timeline item summary + let ariaExpanded = summary.getAttribute('aria-expanded'); - // Find the value of aria-expanded for a timeline item summary - let ariaExpanded = summary.getAttribute('aria-expanded'); + // Update aria values! + summary.addEventListener(('keypress', 'click'), () => { + if (ariaExpanded === 'true') { + summary.setAttribute('aria-expanded', 'false'); + summary.setAttribute('aria-pressed', 'false'); + } else { + summary.setAttribute('aria-expanded', 'true'); + summary.setAttribute('aria-pressed', 'true'); + } - // Update aria values! - summary.addEventListener(('keypress', 'click'), () => { - if (ariaExpanded === 'true') { - summary.setAttribute('aria-expanded', 'false'); - summary.setAttribute('aria-pressed', 'false'); - } else { - summary.setAttribute('aria-expanded', 'true'); - summary.setAttribute('aria-pressed', 'true'); + // Retain updated value for the aria-expanded attribute + ariaExpanded = summary.getAttribute('aria-expanded'); + }); + }); } - // Retain updated value for the aria-expanded attribute - ariaExpanded = summary.getAttribute('aria-expanded'); - }); - }); -} + const searchQuery = new URLSearchParams(window.location.search); + const params = Object.fromEntries(searchQuery.entries()); -const searchQuery = new URLSearchParams(window.location.search); -const params = Object.fromEntries(searchQuery.entries()); + function toggleTimelineFromSearch() { + const searchTerm = params.search.toLowerCase(); -function toggleTimelineFromSearch() { - const searchTerm = params.search.toLowerCase(); - - timelineItems.forEach((timeline) => { - if (timeline.textContent.toLowerCase().includes(searchTerm)) { - const summary = timeline.querySelector('summary'); - timeline.setAttribute('open', ''); - summary.setAttribute('aria-expanded', 'true'); - summary.setAttribute('aria-pressed', 'true'); - } - }); -} + timelineItems.forEach((timeline) => { + if (timeline.textContent.toLowerCase().includes(searchTerm)) { + const summary = timeline.querySelector('summary'); + timeline.setAttribute('open', ''); + summary.setAttribute('aria-expanded', 'true'); + summary.setAttribute('aria-pressed', 'true'); + } + }); + } -if (Object.keys(params).length && Object.prototype.hasOwnProperty.call(params, 'search')) { - toggleTimelineFromSearch(); -} + if ( + Object.keys(params).length + && Object.prototype.hasOwnProperty.call(params, 'search') + ) { + toggleTimelineFromSearch(); + } + }, + }; +}(Drupal, once)); diff --git a/docroot/themes/humsci/humsci_basic/src/js/traditional/traditional.js b/docroot/themes/humsci/humsci_basic/src/js/traditional/traditional.js index dc3f73875d..6a7375be37 100644 --- a/docroot/themes/humsci/humsci_basic/src/js/traditional/traditional.js +++ b/docroot/themes/humsci/humsci_basic/src/js/traditional/traditional.js @@ -1,3 +1 @@ -import '../shared/index'; - // Add Traditional specific JS below diff --git a/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-collection.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-collection.html.twig index a7d2bcd1fb..8e4b3ff8f8 100644 --- a/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-collection.html.twig +++ b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-collection.html.twig @@ -38,6 +38,8 @@ * @ingroup themeable */ #} +{{ attach_library('humsci_basic/equal-height-grid') }} + {% set raised_cards = false %} {% if paragraph.field_raised_cards.value == true %} {% set raised_cards = true %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-priv-collection.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-priv-collection.html.twig index 51c1c4eb7e..ef0ed21b00 100644 --- a/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-priv-collection.html.twig +++ b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--hs-priv-collection.html.twig @@ -38,6 +38,8 @@ * @ingroup themeable */ #} +{{ attach_library('humsci_basic/equal-height-grid') }} + {% set classes = [ 'paragraph', diff --git a/docroot/themes/humsci/humsci_basic/templates/components/paragraph--stanford-gallery--default.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--stanford-gallery--default.html.twig new file mode 100644 index 0000000000..a75f6fc294 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--stanford-gallery--default.html.twig @@ -0,0 +1,3 @@ +{{ attach_library('humsci_basic/colorbox') }} + +{% include '@humsci_basic/components/paragraph.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/paragraph--stanford-gallery--hs-gallery-slideshow.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--stanford-gallery--hs-gallery-slideshow.html.twig new file mode 100644 index 0000000000..5c0a8f1335 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/paragraph--stanford-gallery--hs-gallery-slideshow.html.twig @@ -0,0 +1,3 @@ +{{ attach_library('humsci_basic/prefered-reduced-motion') }} + +{% include '@humsci_basic/components/paragraph.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-accordion.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-accordion.html.twig new file mode 100644 index 0000000000..15eb4835ec --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-accordion.html.twig @@ -0,0 +1,3 @@ +{{ attach_library('humsci_basic/accordion') }} + +{% include '@hs_layouts/accordion/accordion.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-date-stacked-vertical-card.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-date-stacked-vertical-card.html.twig new file mode 100644 index 0000000000..6f31dda572 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-date-stacked-vertical-card.html.twig @@ -0,0 +1,3 @@ +{{ attach_library('humsci_basic/linked-cards') }} + +{% include '@hs_layouts/date-stacked-vertical-card/date-stacked-vertical-card.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-gradient-hero.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-gradient-hero.html.twig new file mode 100644 index 0000000000..b2c8f1f953 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-gradient-hero.html.twig @@ -0,0 +1,5 @@ +{{ attach_library('humsci_basic/page-scroll-animations') }} +{{ attach_library('humsci_basic/carousel-slides-height') }} +{{ attach_library('humsci_basic/prefered-reduced-motion') }} + +{% include '@hs_layouts/gradient-hero/gradient-hero.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-hero-text-overlay.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-hero-text-overlay.html.twig new file mode 100644 index 0000000000..e2a0897c1b --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-hero-text-overlay.html.twig @@ -0,0 +1,5 @@ +{{ attach_library('humsci_basic/page-scroll-animations') }} +{{ attach_library('humsci_basic/carousel-slides-height') }} +{{ attach_library('humsci_basic/prefered-reduced-motion') }} + +{% include '@hs_layouts/hero-text-overlay/hero-text-overlay.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-spotlight.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-spotlight.html.twig new file mode 100644 index 0000000000..f843657796 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-spotlight.html.twig @@ -0,0 +1,4 @@ +{{ attach_library('humsci_basic/carousel-slides-height') }} +{{ attach_library('humsci_basic/prefered-reduced-motion') }} + +{% include '@hs_layouts/spotlight/spotlight.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-table-pattern.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-table-pattern.html.twig new file mode 100644 index 0000000000..e3f7789dd6 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-table-pattern.html.twig @@ -0,0 +1,4 @@ +{{ attach_library('humsci_basic/table-wrap') }} +{{ attach_library('humsci_basic/table-pattern') }} + +{% include '@hs_layouts/table-pattern/table-pattern.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-timeline.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-timeline.html.twig new file mode 100644 index 0000000000..4bf51fd054 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-timeline.html.twig @@ -0,0 +1,3 @@ +{{ attach_library('humsci_basic/timeline') }} + +{% include '@hs_layouts/timeline/timeline.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-vertical-card.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-vertical-card.html.twig new file mode 100644 index 0000000000..f3b5efd05b --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-vertical-card.html.twig @@ -0,0 +1,3 @@ +{{ attach_library('humsci_basic/linked-cards') }} + +{% include '@hs_layouts/vertical-card/vertical-card.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/components/pattern-vertical-link-card.html.twig b/docroot/themes/humsci/humsci_basic/templates/components/pattern-vertical-link-card.html.twig new file mode 100644 index 0000000000..9a591f0f3d --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/components/pattern-vertical-link-card.html.twig @@ -0,0 +1,4 @@ +{{ attach_library('humsci_basic/linked-cards') }} + +{% include '@hs_layouts/vertical-link-card/vertical-link-card.html.twig' %} + diff --git a/docroot/themes/humsci/humsci_basic/templates/field/field--field-media-oembed-video.html.twig b/docroot/themes/humsci/humsci_basic/templates/field/field--field-media-oembed-video.html.twig new file mode 100644 index 0000000000..4bc3dbd061 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/field/field--field-media-oembed-video.html.twig @@ -0,0 +1,3 @@ +{{ attach_library('humsci_basic/video-with-caption') }} + +{% include '@humsci_basic/field/field.html.twig' %} diff --git a/docroot/themes/humsci/humsci_basic/templates/menus/menu--main.html.twig b/docroot/themes/humsci/humsci_basic/templates/menus/menu--main.html.twig index f0b2bb1d05..d7eee444d2 100644 --- a/docroot/themes/humsci/humsci_basic/templates/menus/menu--main.html.twig +++ b/docroot/themes/humsci/humsci_basic/templates/menus/menu--main.html.twig @@ -16,12 +16,15 @@ #} {% if use_hs_megamenu %} + {{ attach_library('humsci_basic/megamenu') }} + {# Twig megamenu attributes #} {% set attributes = attributes.addClass(['megamenu', 'js-megamenu']) %} {% set attributes = attributes.setAttribute('aria-label', 'main menu') %} {% include "@humsci_basic/menus-twig/secondary-menu.twig" %} +{% else %} + {{ attach_library('humsci_basic/main-menu') }} - {% else %} {# Legacy Drupal menu #} {% set attributes = attributes.addClass(['hb-main-nav', 'su-main-nav', 'hb-main-nav--is-still-loading']) %} {% set attributes = attributes.setAttribute('aria-label', 'main menu') %} diff --git a/docroot/themes/humsci/humsci_basic/templates/menus/menu--menu-block--main.html.twig b/docroot/themes/humsci/humsci_basic/templates/menus/menu--menu-block--main.html.twig index c60ebe3128..aa7c76df24 100644 --- a/docroot/themes/humsci/humsci_basic/templates/menus/menu--menu-block--main.html.twig +++ b/docroot/themes/humsci/humsci_basic/templates/menus/menu--menu-block--main.html.twig @@ -2,6 +2,8 @@ {# The main and only way it is used on the site now is to create secondary nav #} {%- import "@humsci_basic/menus/macros/secondary-nav-menu.twig" as menus -%} +{{ attach_library('humsci_basic/secondary-menu') }} + {% apply spaceless %} {% if items is iterable %} {{ menus.secondary_nav_menu(items, 1, 'hb-secondary-nav') }} diff --git a/docroot/themes/humsci/humsci_basic/templates/views/views-view-table.html.twig b/docroot/themes/humsci/humsci_basic/templates/views/views-view-table.html.twig new file mode 100644 index 0000000000..66c29bdce1 --- /dev/null +++ b/docroot/themes/humsci/humsci_basic/templates/views/views-view-table.html.twig @@ -0,0 +1,123 @@ +{# +/** + * @file + * Default theme implementation for displaying a view as a table. + * + * Available variables: + * - attributes: Remaining HTML attributes for the element. + * - class: HTML classes that can be used to style contextually through CSS. + * - title : The title of this group of rows. + * - header: The table header columns. + * - attributes: Remaining HTML attributes for the element. + * - content: HTML classes to apply to each header cell, indexed by + * the header's key. + * - default_classes: A flag indicating whether default classes should be + * used. + * - caption_needed: Is the caption tag needed. + * - caption: The caption for this table. + * - accessibility_description: Extended description for the table details. + * - accessibility_summary: Summary for the table details. + * - rows: Table row items. Rows are keyed by row number. + * - attributes: HTML classes to apply to each row. + * - columns: Row column items. Columns are keyed by column number. + * - attributes: HTML classes to apply to each column. + * - content: The column content. + * - default_classes: A flag indicating whether default classes should be + * used. + * - responsive: A flag indicating whether table is responsive. + * - sticky: A flag indicating whether table header is sticky. + * - summary_element: A render array with table summary information (if any). + * + * @see template_preprocess_views_view_table() + * + * @ingroup themeable + */ +#} +{{ attach_library('humsci_basic/table-wrap') }} +{{ attach_library('humsci_basic/table-scope') }} + +{% + set classes = [ + 'cols-' ~ header|length, + responsive ? 'responsive-enabled', + sticky ? 'sticky-enabled', + ] +%} + + {% if caption_needed %} + + {% if caption %} + {{ caption }} + {% else %} + {{ title }} + {% endif %} + {% if (summary_element is not empty) %} + {{ summary_element }} + {% endif %} + + {% endif %} + {% if header %} + + + {% for key, column in header %} + {% if column.default_classes %} + {% + set column_classes = [ + 'views-field', + 'views-field-' ~ fields[key], + ] + %} + {% endif %} + + {%- if column.wrapper_element -%} + <{{ column.wrapper_element }}> + {%- if column.url -%} + {{ column.content }}{{ column.sort_indicator }} + {%- else -%} + {{ column.content }}{{ column.sort_indicator }} + {%- endif -%} + + {%- else -%} + {%- if column.url -%} + {{ column.content }}{{ column.sort_indicator }} + {%- else -%} + {{- column.content }}{{ column.sort_indicator }} + {%- endif -%} + {%- endif -%} + + {% endfor %} + + + {% endif %} + + {% for row in rows %} + + {% for key, column in row.columns %} + {% if column.default_classes %} + {% + set column_classes = [ + 'views-field' + ] + %} + {% for field in column.fields %} + {% set column_classes = column_classes|merge(['views-field-' ~ field]) %} + {% endfor %} + {% endif %} + + {%- if column.wrapper_element -%} + <{{ column.wrapper_element }}> + {% for content in column.content %} + {{ content.separator }}{{ content.field_output }} + {% endfor %} + + {%- else -%} + {% for content in column.content %} + {{- content.separator }}{{ content.field_output -}} + {% endfor %} + {%- endif %} + + {% endfor %} + + {% endfor %} + + diff --git a/docroot/themes/humsci/humsci_basic/webpack.config.js b/docroot/themes/humsci/humsci_basic/webpack.config.js index df58480b11..e875d0ab5e 100644 --- a/docroot/themes/humsci/humsci_basic/webpack.config.js +++ b/docroot/themes/humsci/humsci_basic/webpack.config.js @@ -2,18 +2,67 @@ const path = require('path'); const ESLintPlugin = require('eslint-webpack-plugin'); -const srcDir = path.resolve(__dirname, 'src/'); +const srcDir = path.resolve(__dirname, 'src/js/'); + +// Shared JS files. Used in both traditional and colorful themes. +const shared = { + accordion: 'shared/accordion/accordion-toggle-all.js', + addtocal: 'shared/addtocal/addtocal.js', + 'page-scroll-animations': 'shared/animation/page-scroll.js', + 'carousel-slides-height': 'shared/carousel-slides/carousel-slides-height.js', + editoria11y: 'shared/editoria11y/editoria11y.js', + 'equal-height-grid': 'shared/equal-height-grid/index.js', + 'linked-cards': 'shared/linked-cards/linked-cards.js', + 'main-content-fallback': 'shared/main-content-fallback/main-content-fallback.js', + 'video-with-caption': 'shared/media/video-with-caption.js', + megamenu: 'shared/megamenu/index.js', + 'main-menu': 'shared/navigation/main-menu-index.js', + 'secondary-toggler': 'shared/navigation/secondary-toggler.js', + colorbox: 'shared/photo-album/colorbox.js', + 'prefered-reduced-motion': 'shared/prefered-reduced-motion/prefered-reduced-motion.js', + search: 'shared/search/search-expand.js', + 'table-scope': 'shared/tables/scope.js', + 'table-pattern': 'shared/tables/table-pattern.js', + 'table-wrap': 'shared/tables/wrap.js', + timeline: 'shared/timeline/expand-collapse-timeline.js', +}; + +// Colorful and traditional theme specific JS files. +const colorful = {}; +const traditional = {}; module.exports = { mode: 'production', - entry: { - humsci_colorful: `${srcDir}/js/colorful/colorful.js`, - humsci_traditional: `${srcDir}/js/traditional/traditional.js`, + entry() { + const entries = {}; + // Shared files have two entries, one for each theme. + Object.keys(shared).forEach((key) => { + const file = shared[key]; + entries[`shared.${key}`] = path.resolve(srcDir, file); + }); + + // Traditional theme specific files. + Object.keys(traditional).forEach((key) => { + const file = shared[key]; + entries[`humsci_traditional.${key}`] = path.resolve(srcDir, file); + }); + + // Colorful theme specific files. + Object.keys(colorful).forEach((key) => { + const file = shared[key]; + entries[`humsci_colorful.${key}`] = path.resolve(srcDir, file); + }); + + return entries; }, plugins: [new ESLintPlugin()], output: { - filename: (pathData) => `${pathData.chunk.name}/js/index.js`, - path: path.resolve(__dirname, '../'), + filename(pathData) { + const [theme, filename] = pathData.chunk.name.split('.'); + const themePath = theme === 'shared' ? 'dist/js' : `../${theme}/js`; + return `${themePath}/${filename}.js`; + }, + path: path.resolve(__dirname, '.'), }, module: { rules: [ diff --git a/docroot/themes/humsci/humsci_colorful/humsci_colorful.libraries.yml b/docroot/themes/humsci/humsci_colorful/humsci_colorful.libraries.yml index 2cf48f35a9..d62b7b5571 100644 --- a/docroot/themes/humsci/humsci_colorful/humsci_colorful.libraries.yml +++ b/docroot/themes/humsci/humsci_colorful/humsci_colorful.libraries.yml @@ -2,8 +2,6 @@ base: css: theme: css/humsci_colorful.css: {} - js: - js/index.js: {} dependencies: - core/modernizr @@ -16,5 +14,3 @@ admin-preview: css: theme: css/humsci_colorful-preview.css: {} - js: - js/index.js: {} diff --git a/docroot/themes/humsci/humsci_traditional/humsci_traditional.libraries.yml b/docroot/themes/humsci/humsci_traditional/humsci_traditional.libraries.yml index f762992c4b..5be0f7afc0 100644 --- a/docroot/themes/humsci/humsci_traditional/humsci_traditional.libraries.yml +++ b/docroot/themes/humsci/humsci_traditional/humsci_traditional.libraries.yml @@ -2,8 +2,6 @@ base: css: theme: css/humsci_traditional.css: {} - js: - js/index.js: {} dependencies: - core/modernizr @@ -16,5 +14,3 @@ admin-preview: css: theme: css/humsci_traditional-preview.css: {} - js: - js/index.js: {} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/su_humsci_gin_admin.theme b/docroot/themes/humsci/su_humsci_gin_admin/su_humsci_gin_admin.theme index 41239305a5..5cda033960 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/su_humsci_gin_admin.theme +++ b/docroot/themes/humsci/su_humsci_gin_admin/su_humsci_gin_admin.theme @@ -53,3 +53,15 @@ function su_humsci_gin_admin_preprocess(&$variables, $hook) { $variables['wrapper_attributes'] = new Attribute(); $variables['wrapper_attributes']->addClass($classes); } + +/** + * Implements hook_preprocess_HOOK(). + */ +function su_humsci_gin_admin_preprocess_field(&$variables) { + $wysiwyg_types = ['text_long', 'text_with_summary']; + if (in_array($variables['field_type'], $wysiwyg_types)) { + $variables['#attached']['library'][] = 'humsci_basic/table-wrap'; + $variables['#attached']['library'][] = 'humsci_basic/table-scope'; + $variables['#attached']['library'][] = 'humsci_basic/video-with-caption'; + } +} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--hs-priv-collection.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--hs-priv-collection.html.twig new file mode 100644 index 0000000000..53387291d7 --- /dev/null +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--hs-priv-collection.html.twig @@ -0,0 +1,5 @@ +
+ + {% include '@humsci_basic/components/paragraph--hs-priv-collection.html.twig' %} +
+ diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--stanford-gallery--default.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--stanford-gallery--default.html.twig new file mode 100644 index 0000000000..747ec9cb5d --- /dev/null +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--stanford-gallery--default.html.twig @@ -0,0 +1,6 @@ +
+ + {% include '@humsci_basic/components/paragraph--stanford-gallery--default.html.twig' %} +
+ + diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--stanford-gallery--hs-gallery-slideshow.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--stanford-gallery--hs-gallery-slideshow.html.twig new file mode 100644 index 0000000000..b8354c3ad2 --- /dev/null +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/paragraph/paragraph--stanford-gallery--hs-gallery-slideshow.html.twig @@ -0,0 +1,5 @@ +
+ + {% include '@humsci_basic/components/paragraph--stanford-gallery--hs-gallery-slideshow.html.twig' %} +
+ diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-accordion.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-accordion.html.twig index afaa069a9d..7861192a02 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-accordion.html.twig +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-accordion.html.twig @@ -1,3 +1,5 @@ +{{ attach_library('humsci_basic/accordion') }} +
{% include '@hs_layouts/accordion/accordion.html.twig' %} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-gradient-hero.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-gradient-hero.html.twig index d3955eaad7..2e1a20a813 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-gradient-hero.html.twig +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-gradient-hero.html.twig @@ -1,3 +1,6 @@ +{{ attach_library('humsci_basic/carousel-slides-height') }} +{{ attach_library('humsci_basic/prefered-reduced-motion') }} +
{% include '@hs_layouts/gradient-hero/gradient-hero.html.twig' %} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-hero-text-overlay.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-hero-text-overlay.html.twig index e14696ff20..f4c84d45c9 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-hero-text-overlay.html.twig +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-hero-text-overlay.html.twig @@ -1,3 +1,6 @@ +{{ attach_library('humsci_basic/carousel-slides-height') }} +{{ attach_library('humsci_basic/prefered-reduced-motion') }} +
{% include '@hs_layouts/hero-text-overlay/hero-text-overlay.html.twig' %} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-spotlight.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-spotlight.html.twig index 9bf500e532..f1a94870f2 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-spotlight.html.twig +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-spotlight.html.twig @@ -1,3 +1,6 @@ +{{ attach_library('humsci_basic/carousel-slides-height') }} +{{ attach_library('humsci_basic/prefered-reduced-motion') }} +
{% include '@hs_layouts/spotlight/spotlight.html.twig' %} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-timeline.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-timeline.html.twig index f142ddb331..e4d6452845 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-timeline.html.twig +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-timeline.html.twig @@ -1,3 +1,5 @@ +{{ attach_library('humsci_basic/timeline') }} +
{% include '@hs_layouts/timeline/timeline.html.twig' %} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-card.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-card.html.twig index acfec90862..35e20e1f2f 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-card.html.twig +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-card.html.twig @@ -1,3 +1,5 @@ +{{ attach_library('humsci_basic/linked-cards') }} +
{% include '@hs_layouts/vertical-card/vertical-card.html.twig' %} diff --git a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-link-card.html.twig b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-link-card.html.twig index 0a11ac344c..aa1e1d48a9 100644 --- a/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-link-card.html.twig +++ b/docroot/themes/humsci/su_humsci_gin_admin/templates/pattern/pattern-vertical-link-card.html.twig @@ -1,3 +1,5 @@ +{{ attach_library('humsci_basic/linked-cards') }} +
{% include '@hs_layouts/vertical-link-card/vertical-link-card.html.twig' %}