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 -%}
+ {{ column.wrapper_element }}>
+ {%- 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 %}
+ {{ column.wrapper_element }}>
+ {%- 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' %}