diff --git a/.ddev/commands/web/install b/.ddev/commands/web/install index 40b25e60e6..c8867cc485 100755 --- a/.ddev/commands/web/install +++ b/.ddev/commands/web/install @@ -23,4 +23,8 @@ composer install --no-interaction drush --root=/var/www/html/web site:install --account-mail=noreply@email.arizona.edu --account-name=azadmin --account-pass=azadmin2026 --db-url=mysql://db:db@db:3306/db -y --verbose drush --root=/var/www/html/web config:set -y az_cas.settings disable_login_form 0 drush --root=/var/www/html/web cache:rebuild -yarn --cwd /usr/local/quickstart-install-profile install + +# Install Yarn dev dependencies +cd /usr/local/quickstart-install-profile +yarn --version +yarn install --immutable diff --git a/.ddev/config.quickstart.yaml b/.ddev/config.quickstart.yaml index 81f87e37ef..e7593ea9d4 100644 --- a/.ddev/config.quickstart.yaml +++ b/.ddev/config.quickstart.yaml @@ -3,6 +3,7 @@ type: php docroot: web php_version: "8.3" webserver_type: nginx-fpm +corepack_enable: true # Default application ports router_http_port: "80" diff --git a/.eslintignore b/.eslintignore index 0d928f70a2..07e4fe7278 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1 @@ node_modules/**/* -*.js -!*.es6.js diff --git a/.gitattributes b/.gitattributes index f1252bfe45..e4159ab671 100644 --- a/.gitattributes +++ b/.gitattributes @@ -20,3 +20,5 @@ themes/custom/az_barrio/libraries/*.min.js linguist-generated=true .ddev/commands/web/phpstan text eol=lf .ddev/commands/web/phpstan-contrib text eol=lf .ddev/commands/web/phpunit text eol=lf + +yarn.lock export-ignore linguist-generated=true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 449a3e7745..ded46cbcd1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -180,7 +180,9 @@ jobs: - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: '20' - - run: yarn audit + - run: | + corepack enable + yarn npm audit --severity high eslint: name: eslint @@ -190,10 +192,13 @@ jobs: - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: '20' - - run: yarn install --ignore-scripts + - run: | + corepack enable + yarn install --immutable - name: Generate eslint report continue-on-error: true - run: yarn run eslint . --format json --output-file eslint-report.json + run: | + yarn run eslint . --format json --output-file eslint-report.json - name: Annotate eslint results continue-on-error: true uses: ataylorme/eslint-annotate-action@v3 @@ -201,7 +206,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} report-json: "eslint-report.json" - name: Run eslint - run: yarn run eslint --color . + run: | + yarn run eslint --color . phpunit: name: PHPUnit (${{ matrix.test.name }}) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 16771ac119..fd2da04b7d 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -56,12 +56,14 @@ jobs: cd az-quickstart-scaffolding composer audit - yarn-audit: - name: yarn audit (security) + yarn-npm-audit: + name: yarn npm audit (security) runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: '20' - - run: yarn audit + - run: | + corepack enable + yarn npm audit diff --git a/.gitignore b/.gitignore index 662dbc945e..ced49413f7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,8 @@ ### Node ### /node_modules/ /node_modules/* -/yarn.lock /yarn-error.log +.yarn/* ### Drupal ### settings.local.php diff --git a/.lando.yml b/.lando.yml index aee3543b4f..5a389fe81d 100644 --- a/.lando.yml +++ b/.lando.yml @@ -69,8 +69,12 @@ services: - ln -s /usr/local/quickstart-install-profile/.vscode /app/.vscode node: type: node:20 + overrides: + environment: + COREPACK_ENABLE_DOWNLOAD_PROMPT: '0' build: - - yarn install + - corepack enable + - yarn install --immutable chromedriver: type: compose services: diff --git a/.prettierignore b/.prettierignore index 1cda54be93..ad774406ef 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,2 @@ +node_modules/**/* *.yml diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000000..a388ff9027 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1,3 @@ +enableScripts: false + +nodeLinker: node-modules diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0242971676..18fc057a5e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -218,34 +218,6 @@ on the paragraph. This can be avoided currently by [a workaround](https://www.drupal.org/project/paragraphs/issues/2928759). There will likely be a more official paragraphs API for this in the future. -## Compiling Javascript in Local Development - -This project uses an ES6 to ES5 transpile process -[similar to Drupal core](https://www.drupal.org/node/2815083). - -This means that you should only update `.js` files named `.es6.js` and should -never manually edit files named `.js` as these are machine-generated. - -This can be done on demand with `yarn build`, or in response to changes -with `yarn watch`. When in watch mode, javascript files will be transpiled as -they are updated. - -### ES6 Transpiling on Lando - -``` -lando yarn build -OR -lando yarn watch -``` - -### ES6 Transpiling on DDEV - -``` -ddev yarn build -OR -ddev yarn watch -``` - ## ESLint in Local Development To maintain high-quality JavaScript code, contributors are encouraged to use diff --git a/modules/custom/az_alphabetical_listing/js/alphabetical_listing.es6.js b/modules/custom/az_alphabetical_listing/js/alphabetical_listing.es6.js deleted file mode 100644 index e60f59ab33..0000000000 --- a/modules/custom/az_alphabetical_listing/js/alphabetical_listing.es6.js +++ /dev/null @@ -1,202 +0,0 @@ -(($, Drupal) => { - Drupal.behaviors.azAlphabeticalListing = { - attach() { - /** - * Loop through each alpha navigation list item and determine if the - * corresponding search result group exists on the page. If it doesn't - * exist on the page, then hide the navigation item. - */ - $('#az-js-alpha-navigation li').each((index, element) => { - // Get ID of current nav item. - const groupId = $(element).children().attr('data-href'); - - // Enable nav item if results group exists on page - if ($(groupId).length !== 0) { - $(element).removeClass('disabled'); - $(element) - .children() - .attr('tabindex', '0') - .attr('aria-hidden', 'false') - .attr('href', groupId); - } - - // Disable nav item if no results group exists on page - else { - $(element).addClass('disabled'); - $(element) - .children() - .attr('tabindex', '-1') - .attr('aria-hidden', 'true') - .removeAttr('href'); - } - }); - - /** - * function azAlphabeticalListingCheckNoResults() - * - * Determines if there are no results that match the provided search query. - * If there are no results, then it will display the "no results" message. - * Otherwise, the "no results" message remains hidden; - */ - function azAlphabeticalListingCheckNoResults() { - let visibleResults = false; - $('.az-alphabetical-listing-group-title').each((index, element) => { - if (!$(element).hasClass('hide-result')) { - visibleResults = true; - } - }); - - if (!visibleResults) { - $('#az-js-alphabetical-listing-no-results').show(); - } else { - $('#az-js-alphabetical-listing-no-results').hide(); - } - } - - /** - * function azAlphabeticalListingGroupLoop() - * - * Check if search result "group" has no results by determining if it has - * an immediate sibling of .az-alphabetical-listing-group-title - */ - function azAlphabeticalListingGroupLoop() { - $('.az-alphabetical-listing-group-title').each((index, element) => { - // Get the ID of the current results group - const elementId = $(element).attr('id'); - const group = elementId.toLowerCase(); - // Set the target class to search with - const targetGroup = `.az-alphabetical-letter-group-${group}`; - - // Set variable to determine if there are visible children - let visibleChildren = false; - // Loop through each item in the results group - $(targetGroup).each((resultIndex, resultElement) => { - if (!$(resultElement).hasClass('hide-result')) { - // Set variable to true if item isn't hidden - visibleChildren = true; - } - }); - - // Get nav item with data attribute that matches the group's ID - const navTarget = $('#az-js-alpha-navigation').find( - `.page-link[data-href='#${elementId}']`, - ); - - if (!visibleChildren) { - // Hide title if no visible children in the group - $(element).hide(); - $(element).addClass('hide-result'); - - // Hide nav item if no visible children in the group - navTarget.parent().addClass('disabled'); - navTarget - .attr('tabindex', '-1') - .attr('aria-hidden', 'true') - .removeAttr('href'); - } else { - // Show title if visible children in the group - $(element).show(); - $(element).removeClass('hide-result'); - - // Show nav item if visible children in the group - navTarget.parent().removeClass('disabled'); - navTarget - .attr('tabindex', '0') - .attr('aria-hidden', 'false') - .attr('href', $(element).attr('id')); - } - }); - } - - /** - * Perform search as query is entered into the search input field. - */ - $('#az-js-alphabetical-listing-search').keyup((event) => { - // Retrieve the input field text - const filter = $(event.currentTarget).val(); - - /** - * Loop through the .az-js-alphabetical-listing-search-result items and - * determine if the item should be shown or hidden, based on the search - * query text provided. - */ - $('.az-js-alphabetical-listing-search-result').each( - (index, element) => { - // Get text for current item in loop. - const searchResultText = $(element) - .find('.az-alphabetical-listing-item') - .text(); - - // Hide the item if it doesn't contain search query text. - if (searchResultText.search(new RegExp(filter, 'i')) < 0) { - $(element) - .find('az-alphabetical-listing-item') - .attr('tabindex', '0'); - $(element).addClass('hide-result'); - $(element).hide(); - } - // Show the item is it does contain search query text. - else { - $(element) - .find('.az-alphabetical-listing-item') - .attr('tabindex', '0'); - $(element).removeClass('hide-result'); - $(element).show(); - } - }, - ); - - // Determine if groups have results shown - azAlphabeticalListingGroupLoop(); - - // Determine if "no results" message is needed - azAlphabeticalListingCheckNoResults(); - }); - - /** - * On click of alpha navigation items, create a smooth scrolling effect. - */ - const $root = $('html, body'); - const breakpoint = 600; - - $('#az-js-alpha-navigation a').on('click', (event) => { - event.preventDefault(); - const $alphaNav = $('#az-js-floating-alpha-nav-container'); - const href = $.attr(event.currentTarget, 'data-href'); - let fixedNavHeight = $alphaNav.outerHeight(); - const headingHeight = $( - '.az-alphabetical-listing-group-title:first', - ).outerHeight(); - const offsetHeight = fixedNavHeight + headingHeight; - - if ($(window).width() <= breakpoint) { - fixedNavHeight = 0; - } - - $root.animate( - { - scrollTop: $(href).offset().top - offsetHeight, - }, - 500, - () => { - window.location.hash = href; - }, - ); - }); - - /** - * Check if Drupal admin toolbar is present on the page, and if it is, - * increase the top value of the alpha navigation to prevent overlap with the - * Drupal admin toolbar. - */ - if ($('body.toolbar-tray-open').length) { - // Both toolbars open - $('#az-js-floating-alpha-nav-container').css('top', '79px'); - } - // Only black toolbar is open - else if ($('body.toolbar-horizontal').length) { - $('#az-js-floating-alpha-nav-container').css('top', '39px'); - } - }, - }; -})(jQuery, Drupal); diff --git a/modules/custom/az_alphabetical_listing/js/alphabetical_listing.js b/modules/custom/az_alphabetical_listing/js/alphabetical_listing.js index be036ec35a..e60f59ab33 100644 --- a/modules/custom/az_alphabetical_listing/js/alphabetical_listing.js +++ b/modules/custom/az_alphabetical_listing/js/alphabetical_listing.js @@ -1,100 +1,202 @@ -/** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function ($, Drupal) { +(($, Drupal) => { Drupal.behaviors.azAlphabeticalListing = { - attach: function attach() { - $('#az-js-alpha-navigation li').each(function (index, element) { - var groupId = $(element).children().attr('data-href'); + attach() { + /** + * Loop through each alpha navigation list item and determine if the + * corresponding search result group exists on the page. If it doesn't + * exist on the page, then hide the navigation item. + */ + $('#az-js-alpha-navigation li').each((index, element) => { + // Get ID of current nav item. + const groupId = $(element).children().attr('data-href'); + + // Enable nav item if results group exists on page if ($(groupId).length !== 0) { $(element).removeClass('disabled'); - $(element).children().attr('tabindex', '0').attr('aria-hidden', 'false').attr('href', groupId); - } else { + $(element) + .children() + .attr('tabindex', '0') + .attr('aria-hidden', 'false') + .attr('href', groupId); + } + + // Disable nav item if no results group exists on page + else { $(element).addClass('disabled'); - $(element).children().attr('tabindex', '-1').attr('aria-hidden', 'true').removeAttr('href'); + $(element) + .children() + .attr('tabindex', '-1') + .attr('aria-hidden', 'true') + .removeAttr('href'); } }); + + /** + * function azAlphabeticalListingCheckNoResults() + * + * Determines if there are no results that match the provided search query. + * If there are no results, then it will display the "no results" message. + * Otherwise, the "no results" message remains hidden; + */ function azAlphabeticalListingCheckNoResults() { - var visibleResults = false; - $('.az-alphabetical-listing-group-title').each(function (index, element) { + let visibleResults = false; + $('.az-alphabetical-listing-group-title').each((index, element) => { if (!$(element).hasClass('hide-result')) { visibleResults = true; } }); + if (!visibleResults) { $('#az-js-alphabetical-listing-no-results').show(); } else { $('#az-js-alphabetical-listing-no-results').hide(); } } + + /** + * function azAlphabeticalListingGroupLoop() + * + * Check if search result "group" has no results by determining if it has + * an immediate sibling of .az-alphabetical-listing-group-title + */ function azAlphabeticalListingGroupLoop() { - $('.az-alphabetical-listing-group-title').each(function (index, element) { - var elementId = $(element).attr('id'); - var group = elementId.toLowerCase(); - var targetGroup = ".az-alphabetical-letter-group-".concat(group); - var visibleChildren = false; - $(targetGroup).each(function (resultIndex, resultElement) { + $('.az-alphabetical-listing-group-title').each((index, element) => { + // Get the ID of the current results group + const elementId = $(element).attr('id'); + const group = elementId.toLowerCase(); + // Set the target class to search with + const targetGroup = `.az-alphabetical-letter-group-${group}`; + + // Set variable to determine if there are visible children + let visibleChildren = false; + // Loop through each item in the results group + $(targetGroup).each((resultIndex, resultElement) => { if (!$(resultElement).hasClass('hide-result')) { + // Set variable to true if item isn't hidden visibleChildren = true; } }); - var navTarget = $('#az-js-alpha-navigation').find(".page-link[data-href='#".concat(elementId, "']")); + + // Get nav item with data attribute that matches the group's ID + const navTarget = $('#az-js-alpha-navigation').find( + `.page-link[data-href='#${elementId}']`, + ); + if (!visibleChildren) { + // Hide title if no visible children in the group $(element).hide(); $(element).addClass('hide-result'); + + // Hide nav item if no visible children in the group navTarget.parent().addClass('disabled'); - navTarget.attr('tabindex', '-1').attr('aria-hidden', 'true').removeAttr('href'); + navTarget + .attr('tabindex', '-1') + .attr('aria-hidden', 'true') + .removeAttr('href'); } else { + // Show title if visible children in the group $(element).show(); $(element).removeClass('hide-result'); + + // Show nav item if visible children in the group navTarget.parent().removeClass('disabled'); - navTarget.attr('tabindex', '0').attr('aria-hidden', 'false').attr('href', $(element).attr('id')); + navTarget + .attr('tabindex', '0') + .attr('aria-hidden', 'false') + .attr('href', $(element).attr('id')); } }); } - $('#az-js-alphabetical-listing-search').keyup(function (event) { - var filter = $(event.currentTarget).val(); - $('.az-js-alphabetical-listing-search-result').each(function (index, element) { - var searchResultText = $(element).find('.az-alphabetical-listing-item').text(); - if (searchResultText.search(new RegExp(filter, 'i')) < 0) { - $(element).find('az-alphabetical-listing-item').attr('tabindex', '0'); - $(element).addClass('hide-result'); - $(element).hide(); - } else { - $(element).find('.az-alphabetical-listing-item').attr('tabindex', '0'); - $(element).removeClass('hide-result'); - $(element).show(); - } - }); + + /** + * Perform search as query is entered into the search input field. + */ + $('#az-js-alphabetical-listing-search').keyup((event) => { + // Retrieve the input field text + const filter = $(event.currentTarget).val(); + + /** + * Loop through the .az-js-alphabetical-listing-search-result items and + * determine if the item should be shown or hidden, based on the search + * query text provided. + */ + $('.az-js-alphabetical-listing-search-result').each( + (index, element) => { + // Get text for current item in loop. + const searchResultText = $(element) + .find('.az-alphabetical-listing-item') + .text(); + + // Hide the item if it doesn't contain search query text. + if (searchResultText.search(new RegExp(filter, 'i')) < 0) { + $(element) + .find('az-alphabetical-listing-item') + .attr('tabindex', '0'); + $(element).addClass('hide-result'); + $(element).hide(); + } + // Show the item is it does contain search query text. + else { + $(element) + .find('.az-alphabetical-listing-item') + .attr('tabindex', '0'); + $(element).removeClass('hide-result'); + $(element).show(); + } + }, + ); + + // Determine if groups have results shown azAlphabeticalListingGroupLoop(); + + // Determine if "no results" message is needed azAlphabeticalListingCheckNoResults(); }); - var $root = $('html, body'); - var breakpoint = 600; - $('#az-js-alpha-navigation a').on('click', function (event) { + + /** + * On click of alpha navigation items, create a smooth scrolling effect. + */ + const $root = $('html, body'); + const breakpoint = 600; + + $('#az-js-alpha-navigation a').on('click', (event) => { event.preventDefault(); - var $alphaNav = $('#az-js-floating-alpha-nav-container'); - var href = $.attr(event.currentTarget, 'data-href'); - var fixedNavHeight = $alphaNav.outerHeight(); - var headingHeight = $('.az-alphabetical-listing-group-title:first').outerHeight(); - var offsetHeight = fixedNavHeight + headingHeight; + const $alphaNav = $('#az-js-floating-alpha-nav-container'); + const href = $.attr(event.currentTarget, 'data-href'); + let fixedNavHeight = $alphaNav.outerHeight(); + const headingHeight = $( + '.az-alphabetical-listing-group-title:first', + ).outerHeight(); + const offsetHeight = fixedNavHeight + headingHeight; + if ($(window).width() <= breakpoint) { fixedNavHeight = 0; } - $root.animate({ - scrollTop: $(href).offset().top - offsetHeight - }, 500, function () { - window.location.hash = href; - }); + + $root.animate( + { + scrollTop: $(href).offset().top - offsetHeight, + }, + 500, + () => { + window.location.hash = href; + }, + ); }); + + /** + * Check if Drupal admin toolbar is present on the page, and if it is, + * increase the top value of the alpha navigation to prevent overlap with the + * Drupal admin toolbar. + */ if ($('body.toolbar-tray-open').length) { + // Both toolbars open $('#az-js-floating-alpha-nav-container').css('top', '79px'); - } else if ($('body.toolbar-horizontal').length) { + } + // Only black toolbar is open + else if ($('body.toolbar-horizontal').length) { $('#az-js-floating-alpha-nav-container').css('top', '39px'); } - } + }, }; -})(jQuery, Drupal); \ No newline at end of file +})(jQuery, Drupal); diff --git a/modules/custom/az_card/js/az-card-no-follow.es6.js b/modules/custom/az_card/js/az-card-no-follow.es6.js deleted file mode 100644 index c0e1b62cd9..0000000000 --- a/modules/custom/az_card/js/az-card-no-follow.es6.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file - * Adds event listener and handler for cards in order prevent links from working - * under certain circumstances. - */ - -((Drupal) => { - /** - * Behavior for card no-follow preview links. - * - * @type {Drupal~behavior} - * - * @prop {Drupal~behaviorAttach} attach - * Attaches to card preview links in node edit form. - */ - Drupal.behaviors.azCardNoFollow = { - attach(context) { - /** - * Disables links for cards. - * - * @param {ClickEvent} event - Click event. - */ - function noFollow(event) { - event.preventDefault(); - } - - /** - * Adds event listeners to card links. - */ - const cards = context.querySelectorAll('.az-card-no-follow'); - [...cards].forEach((card) => { - card.addEventListener('click', noFollow); - }); - }, - }; -})(this.Drupal); diff --git a/modules/custom/az_card/js/az-card-no-follow.js b/modules/custom/az_card/js/az-card-no-follow.js index ad2857c8be..c0e1b62cd9 100644 --- a/modules/custom/az_card/js/az-card-no-follow.js +++ b/modules/custom/az_card/js/az-card-no-follow.js @@ -1,25 +1,36 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } -function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } -function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } -function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } -function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } -function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } -(function (Drupal) { + * @file + * Adds event listener and handler for cards in order prevent links from working + * under certain circumstances. + */ + +((Drupal) => { + /** + * Behavior for card no-follow preview links. + * + * @type {Drupal~behavior} + * + * @prop {Drupal~behaviorAttach} attach + * Attaches to card preview links in node edit form. + */ Drupal.behaviors.azCardNoFollow = { - attach: function attach(context) { + attach(context) { + /** + * Disables links for cards. + * + * @param {ClickEvent} event - Click event. + */ function noFollow(event) { event.preventDefault(); } - var cards = context.querySelectorAll('.az-card-no-follow'); - _toConsumableArray(cards).forEach(function (card) { + + /** + * Adds event listeners to card links. + */ + const cards = context.querySelectorAll('.az-card-no-follow'); + [...cards].forEach((card) => { card.addEventListener('click', noFollow); }); - } + }, }; -})(this.Drupal); \ No newline at end of file +})(this.Drupal); diff --git a/modules/custom/az_event/az_event_trellis/js/az_event_trellis_date.es6.js b/modules/custom/az_event/az_event_trellis/js/az_event_trellis_date.es6.js deleted file mode 100644 index 911cef299d..0000000000 --- a/modules/custom/az_event/az_event_trellis/js/az_event_trellis_date.es6.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @file - * Trellis date range picker. - */ - -((Drupal, drupalSettings, once) => { - Drupal.behaviors.trellisDatePicker = { - attach(context) { - const elements = once('aztrellisdate', '.az-trellis-daterange', context); - elements.forEach((element) => { - const begin = element; - const id = element.dataset.azTrellisDaterangeEnd; - const end = document.getElementById(id); - // eslint-disable-next-line no-unused-vars, no-undef, new-cap - const picker = new easepick.create({ - element: begin, - css: drupalSettings.trellisDatePicker.css, - zIndex: 10, - RangePlugin: { - elementEnd: end, - }, - plugins: ['RangePlugin'], - }); - }); - }, - }; -})(Drupal, drupalSettings, once); diff --git a/modules/custom/az_event/az_event_trellis/js/az_event_trellis_date.js b/modules/custom/az_event/az_event_trellis/js/az_event_trellis_date.js index f51967d668..911cef299d 100644 --- a/modules/custom/az_event/az_event_trellis/js/az_event_trellis_date.js +++ b/modules/custom/az_event/az_event_trellis/js/az_event_trellis_date.js @@ -1,27 +1,27 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function (Drupal, drupalSettings, once) { + * @file + * Trellis date range picker. + */ + +((Drupal, drupalSettings, once) => { Drupal.behaviors.trellisDatePicker = { - attach: function attach(context) { - var elements = once('aztrellisdate', '.az-trellis-daterange', context); - elements.forEach(function (element) { - var begin = element; - var id = element.dataset.azTrellisDaterangeEnd; - var end = document.getElementById(id); - var picker = new easepick.create({ + attach(context) { + const elements = once('aztrellisdate', '.az-trellis-daterange', context); + elements.forEach((element) => { + const begin = element; + const id = element.dataset.azTrellisDaterangeEnd; + const end = document.getElementById(id); + // eslint-disable-next-line no-unused-vars, no-undef, new-cap + const picker = new easepick.create({ element: begin, css: drupalSettings.trellisDatePicker.css, zIndex: 10, RangePlugin: { - elementEnd: end + elementEnd: end, }, - plugins: ['RangePlugin'] + plugins: ['RangePlugin'], }); }); - } + }, }; -})(Drupal, drupalSettings, once); \ No newline at end of file +})(Drupal, drupalSettings, once); diff --git a/modules/custom/az_event/js/az_calendar_filter.es6.js b/modules/custom/az_event/js/az_calendar_filter.es6.js deleted file mode 100644 index 1c5d9cd384..0000000000 --- a/modules/custom/az_event/js/az_calendar_filter.es6.js +++ /dev/null @@ -1,233 +0,0 @@ -/** - * @file - * A JavaScript file for the datepicker calendar functionality. - * - */ - -(($, Drupal, drupalSettings, once) => { - Drupal.behaviors.azCalendarFilter = { - attach(context, settings) { - const filterInformation = drupalSettings.azCalendarFilter; - if (!drupalSettings.hasOwnProperty('calendarFilterRanges')) { - drupalSettings.calendarFilterRanges = []; - } - - // Drupal settings get merged rather than replaced during ajax. - // We should clear out stale entries when we process a new cells. - drupalSettings.azCalendarFilter = {}; - settings.azCalendarFilter = {}; - - // Process cell date strings into javascript dates. - Object.keys(filterInformation).forEach((property) => { - if (filterInformation.hasOwnProperty(property)) { - drupalSettings.calendarFilterRanges[property] = []; - const ranges = filterInformation[property]; - for (let i = 0; i < ranges.length; i++) { - drupalSettings.calendarFilterRanges[property].push([ - $.datepicker.parseDate('@', ranges[i][0] * 1000), - $.datepicker.parseDate('@', ranges[i][1] * 1000), - ]); - } - } - }); - - // We may have recieved new cell data. Refresh existing datepickers. - $('.az-calendar-filter-calendar').datepicker('refresh'); - - // Initialize calendar widget wrapper if needed. - $(once('azCalendarFilter', '.az-calendar-filter-wrapper', context)) - // eslint-disable-next-line func-names - .each(function () { - const $wrapper = $(this); - // rangeKey contains our filter identifier to find calendar cell data. - const rangeKey = $wrapper.data('az-calendar-filter'); - let rangeStart = null; - let rangeEnd = null; - $wrapper.append( - '
', - ); - const $buttonWrapper = $wrapper.children( - '.az-calendar-filter-buttons', - ); - const $calendar = $wrapper.children('.az-calendar-filter-calendar'); - const $submitButton = $wrapper - .closest('.views-exposed-form') - .find('button.form-submit'); - const $dropDown = $wrapper - .closest('.views-exposed-form') - .find('.form-select'); - let task = null; - - // Set task to trigger filter element change. - function triggerFilterChange($ancestor, delay) { - if (task != null) { - clearTimeout(task); - } - task = setTimeout(() => { - // Only trigger if submit buttion isn't disabled. - if (!$submitButton.prop('disabled')) { - $ancestor.find('input').eq(0).change(); - $submitButton.click(); - task = null; - } - // The form is disabled and we are probably ajaxing. - // Wait for a while. - else { - triggerFilterChange($ancestor, 200); - } - }, delay); - } - - // Handle dropdown, if present. - $dropDown.on('change', () => { - const $ancestor = $wrapper.closest( - '.views-widget-az-calendar-filter', - ); - triggerFilterChange($ancestor, 0); - }); - - // Function to update a filter's internal date fields from datepicker. - function updateCalendarFilters(startDate, endDate) { - const $ancestor = $wrapper.closest( - '.views-widget-az-calendar-filter', - ); - - const dates = [startDate, endDate]; - for (let i = 0; i < dates.length; i++) { - const month = dates[i].getMonth() + 1; - const day = dates[i].getDate(); - const year = dates[i].getFullYear(); - $ancestor.find('input').eq(i).val(`${year}-${month}-${day}`); - } - - // Signal to UI that the inputs were updated programmatically. - triggerFilterChange($ancestor, 0); - $ancestor - .find('.btn') - .removeClass('active') - .attr('aria-pressed', 'false'); - } - - // Get initial day if present. - const $inputWrapper = $wrapper.closest( - '.views-widget-az-calendar-filter', - ); - const initial = $inputWrapper.find('input').eq(0).val(); - let calendarInitialDay = new Date(); - if (typeof initial !== 'undefined') { - const initialDates = initial.split('-'); - if (initialDates.length === 3) { - calendarInitialDay = new Date( - initialDates[0], - initialDates[1] - 1, - initialDates[2], - ); - } - } - // Initialize the calendar datepicker options. - $calendar.datepicker({ - dateFormat: 'm-d-yy', - showOtherMonths: true, - selectOtherMonths: true, - defaultDate: calendarInitialDay, - dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], - beforeShowDay(date) { - // Loop through date ranges to determine if a day qualifies. - let dateClass = 'calendar-filter-day-no-events'; - const time = date.getTime(); - let withinRange = false; - // Check if the date is within the selection window. - if (rangeStart && rangeEnd) { - if (rangeStart <= time && rangeEnd >= time) { - withinRange = true; - // Highlight a single-day range even if it has no events. - if (rangeStart === rangeEnd) { - return [true, 'calendar-filter-window']; - } - } - } - // Check if the cell information encapsulates this date. - if ( - drupalSettings.calendarFilterRanges.hasOwnProperty(rangeKey) - ) { - const ranges = drupalSettings.calendarFilterRanges[rangeKey]; - for (let i = 0; i < ranges.length; i++) { - if ( - ranges[i][0].getTime() <= time && - ranges[i][1].getTime() >= time - ) { - dateClass = withinRange - ? 'calendar-filter-window' - : 'calendar-filter-day-events'; - } - } - } - return [true, dateClass]; - }, - onChangeMonthYear(year, month) { - // When the month is changed, update the date input fields. - const startDay = new Date(year, month - 1, 1); - const endDay = new Date(year, month, 0); - rangeStart = null; - rangeEnd = null; - updateCalendarFilters(startDay, endDay); - }, - onSelect(datetext) { - // When a day is selected, update the date input fields. - const newDate = $.datepicker.parseDate('m-d-yy', datetext); - rangeStart = newDate.getTime(); - rangeEnd = newDate.getTime(); - updateCalendarFilters(newDate, newDate); - }, - }); - $calendar.children('.ui-corner-all').removeClass('ui-corner-all'); - - // Create the range selection buttons. - $buttonWrapper.append( - '', - ); - $buttonWrapper.append( - '', - ); - $buttonWrapper.append( - '', - ); - - // Handle button presses for calendar range selection buttions. - $buttonWrapper - .children('.calendar-filter-button') - .on('click', (e) => { - const $pressed = $(e.currentTarget); - const current = new Date(Date.now()); - const today = new Date( - current.getFullYear(), - current.getMonth(), - current.getDate(), - ); - const month = current.getMonth(); - const year = current.getFullYear(); - const day = current.getDay(); - const diff = current.getDate() - day; - let startDay = today; - let endDay = today; - if ($pressed.hasClass('calendar-filter-week')) { - // Compute start and end days of the week. - startDay = new Date(year, month, diff); - endDay = new Date(year, month, diff + 6); - } else if ($pressed.hasClass('calendar-filter-month')) { - // Compute start and end days of the month. - startDay = new Date(year, month, 1); - endDay = new Date(year, month + 1, 0); - } - $calendar.datepicker('setDate', startDay); - $calendar.datepicker('setDate', null); - rangeStart = startDay.getTime(); - rangeEnd = endDay.getTime(); - updateCalendarFilters(startDay, endDay); - $('.az-calendar-filter-calendar').datepicker('refresh'); - $pressed.addClass('active').attr('aria-pressed', 'true'); - }); - }); - }, - }; -})(jQuery, Drupal, drupalSettings, once); diff --git a/modules/custom/az_event/js/az_calendar_filter.js b/modules/custom/az_event/js/az_calendar_filter.js index b5cf3631ae..1c5d9cd384 100644 --- a/modules/custom/az_event/js/az_calendar_filter.js +++ b/modules/custom/az_event/js/az_calendar_filter.js @@ -1,150 +1,233 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function ($, Drupal, drupalSettings, once) { + * @file + * A JavaScript file for the datepicker calendar functionality. + * + */ + +(($, Drupal, drupalSettings, once) => { Drupal.behaviors.azCalendarFilter = { - attach: function attach(context, settings) { - var filterInformation = drupalSettings.azCalendarFilter; + attach(context, settings) { + const filterInformation = drupalSettings.azCalendarFilter; if (!drupalSettings.hasOwnProperty('calendarFilterRanges')) { drupalSettings.calendarFilterRanges = []; } + + // Drupal settings get merged rather than replaced during ajax. + // We should clear out stale entries when we process a new cells. drupalSettings.azCalendarFilter = {}; settings.azCalendarFilter = {}; - Object.keys(filterInformation).forEach(function (property) { + + // Process cell date strings into javascript dates. + Object.keys(filterInformation).forEach((property) => { if (filterInformation.hasOwnProperty(property)) { drupalSettings.calendarFilterRanges[property] = []; - var ranges = filterInformation[property]; - for (var i = 0; i < ranges.length; i++) { - drupalSettings.calendarFilterRanges[property].push([$.datepicker.parseDate('@', ranges[i][0] * 1000), $.datepicker.parseDate('@', ranges[i][1] * 1000)]); + const ranges = filterInformation[property]; + for (let i = 0; i < ranges.length; i++) { + drupalSettings.calendarFilterRanges[property].push([ + $.datepicker.parseDate('@', ranges[i][0] * 1000), + $.datepicker.parseDate('@', ranges[i][1] * 1000), + ]); } } }); + + // We may have recieved new cell data. Refresh existing datepickers. $('.az-calendar-filter-calendar').datepicker('refresh'); - $(once('azCalendarFilter', '.az-calendar-filter-wrapper', context)).each(function () { - var $wrapper = $(this); - var rangeKey = $wrapper.data('az-calendar-filter'); - var rangeStart = null; - var rangeEnd = null; - $wrapper.append(''); - var $buttonWrapper = $wrapper.children('.az-calendar-filter-buttons'); - var $calendar = $wrapper.children('.az-calendar-filter-calendar'); - var $submitButton = $wrapper.closest('.views-exposed-form').find('button.form-submit'); - var $dropDown = $wrapper.closest('.views-exposed-form').find('.form-select'); - var task = null; - function triggerFilterChange($ancestor, delay) { - if (task != null) { - clearTimeout(task); + + // Initialize calendar widget wrapper if needed. + $(once('azCalendarFilter', '.az-calendar-filter-wrapper', context)) + // eslint-disable-next-line func-names + .each(function () { + const $wrapper = $(this); + // rangeKey contains our filter identifier to find calendar cell data. + const rangeKey = $wrapper.data('az-calendar-filter'); + let rangeStart = null; + let rangeEnd = null; + $wrapper.append( + '', + ); + const $buttonWrapper = $wrapper.children( + '.az-calendar-filter-buttons', + ); + const $calendar = $wrapper.children('.az-calendar-filter-calendar'); + const $submitButton = $wrapper + .closest('.views-exposed-form') + .find('button.form-submit'); + const $dropDown = $wrapper + .closest('.views-exposed-form') + .find('.form-select'); + let task = null; + + // Set task to trigger filter element change. + function triggerFilterChange($ancestor, delay) { + if (task != null) { + clearTimeout(task); + } + task = setTimeout(() => { + // Only trigger if submit buttion isn't disabled. + if (!$submitButton.prop('disabled')) { + $ancestor.find('input').eq(0).change(); + $submitButton.click(); + task = null; + } + // The form is disabled and we are probably ajaxing. + // Wait for a while. + else { + triggerFilterChange($ancestor, 200); + } + }, delay); } - task = setTimeout(function () { - if (!$submitButton.prop('disabled')) { - $ancestor.find('input').eq(0).change(); - $submitButton.click(); - task = null; - } else { - triggerFilterChange($ancestor, 200); + + // Handle dropdown, if present. + $dropDown.on('change', () => { + const $ancestor = $wrapper.closest( + '.views-widget-az-calendar-filter', + ); + triggerFilterChange($ancestor, 0); + }); + + // Function to update a filter's internal date fields from datepicker. + function updateCalendarFilters(startDate, endDate) { + const $ancestor = $wrapper.closest( + '.views-widget-az-calendar-filter', + ); + + const dates = [startDate, endDate]; + for (let i = 0; i < dates.length; i++) { + const month = dates[i].getMonth() + 1; + const day = dates[i].getDate(); + const year = dates[i].getFullYear(); + $ancestor.find('input').eq(i).val(`${year}-${month}-${day}`); } - }, delay); - } - $dropDown.on('change', function () { - var $ancestor = $wrapper.closest('.views-widget-az-calendar-filter'); - triggerFilterChange($ancestor, 0); - }); - function updateCalendarFilters(startDate, endDate) { - var $ancestor = $wrapper.closest('.views-widget-az-calendar-filter'); - var dates = [startDate, endDate]; - for (var i = 0; i < dates.length; i++) { - var month = dates[i].getMonth() + 1; - var day = dates[i].getDate(); - var year = dates[i].getFullYear(); - $ancestor.find('input').eq(i).val("".concat(year, "-").concat(month, "-").concat(day)); + + // Signal to UI that the inputs were updated programmatically. + triggerFilterChange($ancestor, 0); + $ancestor + .find('.btn') + .removeClass('active') + .attr('aria-pressed', 'false'); } - triggerFilterChange($ancestor, 0); - $ancestor.find('.btn').removeClass('active').attr('aria-pressed', 'false'); - } - var $inputWrapper = $wrapper.closest('.views-widget-az-calendar-filter'); - var initial = $inputWrapper.find('input').eq(0).val(); - var calendarInitialDay = new Date(); - if (typeof initial !== 'undefined') { - var initialDates = initial.split('-'); - if (initialDates.length === 3) { - calendarInitialDay = new Date(initialDates[0], initialDates[1] - 1, initialDates[2]); + + // Get initial day if present. + const $inputWrapper = $wrapper.closest( + '.views-widget-az-calendar-filter', + ); + const initial = $inputWrapper.find('input').eq(0).val(); + let calendarInitialDay = new Date(); + if (typeof initial !== 'undefined') { + const initialDates = initial.split('-'); + if (initialDates.length === 3) { + calendarInitialDay = new Date( + initialDates[0], + initialDates[1] - 1, + initialDates[2], + ); + } } - } - $calendar.datepicker({ - dateFormat: 'm-d-yy', - showOtherMonths: true, - selectOtherMonths: true, - defaultDate: calendarInitialDay, - dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], - beforeShowDay: function beforeShowDay(date) { - var dateClass = 'calendar-filter-day-no-events'; - var time = date.getTime(); - var withinRange = false; - if (rangeStart && rangeEnd) { - if (rangeStart <= time && rangeEnd >= time) { - withinRange = true; - if (rangeStart === rangeEnd) { - return [true, 'calendar-filter-window']; + // Initialize the calendar datepicker options. + $calendar.datepicker({ + dateFormat: 'm-d-yy', + showOtherMonths: true, + selectOtherMonths: true, + defaultDate: calendarInitialDay, + dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], + beforeShowDay(date) { + // Loop through date ranges to determine if a day qualifies. + let dateClass = 'calendar-filter-day-no-events'; + const time = date.getTime(); + let withinRange = false; + // Check if the date is within the selection window. + if (rangeStart && rangeEnd) { + if (rangeStart <= time && rangeEnd >= time) { + withinRange = true; + // Highlight a single-day range even if it has no events. + if (rangeStart === rangeEnd) { + return [true, 'calendar-filter-window']; + } } } - } - if (drupalSettings.calendarFilterRanges.hasOwnProperty(rangeKey)) { - var ranges = drupalSettings.calendarFilterRanges[rangeKey]; - for (var i = 0; i < ranges.length; i++) { - if (ranges[i][0].getTime() <= time && ranges[i][1].getTime() >= time) { - dateClass = withinRange ? 'calendar-filter-window' : 'calendar-filter-day-events'; + // Check if the cell information encapsulates this date. + if ( + drupalSettings.calendarFilterRanges.hasOwnProperty(rangeKey) + ) { + const ranges = drupalSettings.calendarFilterRanges[rangeKey]; + for (let i = 0; i < ranges.length; i++) { + if ( + ranges[i][0].getTime() <= time && + ranges[i][1].getTime() >= time + ) { + dateClass = withinRange + ? 'calendar-filter-window' + : 'calendar-filter-day-events'; + } } } - } - return [true, dateClass]; - }, - onChangeMonthYear: function onChangeMonthYear(year, month) { - var startDay = new Date(year, month - 1, 1); - var endDay = new Date(year, month, 0); - rangeStart = null; - rangeEnd = null; - updateCalendarFilters(startDay, endDay); - }, - onSelect: function onSelect(datetext) { - var newDate = $.datepicker.parseDate('m-d-yy', datetext); - rangeStart = newDate.getTime(); - rangeEnd = newDate.getTime(); - updateCalendarFilters(newDate, newDate); - } - }); - $calendar.children('.ui-corner-all').removeClass('ui-corner-all'); - $buttonWrapper.append(''); - $buttonWrapper.append(''); - $buttonWrapper.append(''); - $buttonWrapper.children('.calendar-filter-button').on('click', function (e) { - var $pressed = $(e.currentTarget); - var current = new Date(Date.now()); - var today = new Date(current.getFullYear(), current.getMonth(), current.getDate()); - var month = current.getMonth(); - var year = current.getFullYear(); - var day = current.getDay(); - var diff = current.getDate() - day; - var startDay = today; - var endDay = today; - if ($pressed.hasClass('calendar-filter-week')) { - startDay = new Date(year, month, diff); - endDay = new Date(year, month, diff + 6); - } else if ($pressed.hasClass('calendar-filter-month')) { - startDay = new Date(year, month, 1); - endDay = new Date(year, month + 1, 0); - } - $calendar.datepicker('setDate', startDay); - $calendar.datepicker('setDate', null); - rangeStart = startDay.getTime(); - rangeEnd = endDay.getTime(); - updateCalendarFilters(startDay, endDay); - $('.az-calendar-filter-calendar').datepicker('refresh'); - $pressed.addClass('active').attr('aria-pressed', 'true'); + return [true, dateClass]; + }, + onChangeMonthYear(year, month) { + // When the month is changed, update the date input fields. + const startDay = new Date(year, month - 1, 1); + const endDay = new Date(year, month, 0); + rangeStart = null; + rangeEnd = null; + updateCalendarFilters(startDay, endDay); + }, + onSelect(datetext) { + // When a day is selected, update the date input fields. + const newDate = $.datepicker.parseDate('m-d-yy', datetext); + rangeStart = newDate.getTime(); + rangeEnd = newDate.getTime(); + updateCalendarFilters(newDate, newDate); + }, + }); + $calendar.children('.ui-corner-all').removeClass('ui-corner-all'); + + // Create the range selection buttons. + $buttonWrapper.append( + '', + ); + $buttonWrapper.append( + '', + ); + $buttonWrapper.append( + '', + ); + + // Handle button presses for calendar range selection buttions. + $buttonWrapper + .children('.calendar-filter-button') + .on('click', (e) => { + const $pressed = $(e.currentTarget); + const current = new Date(Date.now()); + const today = new Date( + current.getFullYear(), + current.getMonth(), + current.getDate(), + ); + const month = current.getMonth(); + const year = current.getFullYear(); + const day = current.getDay(); + const diff = current.getDate() - day; + let startDay = today; + let endDay = today; + if ($pressed.hasClass('calendar-filter-week')) { + // Compute start and end days of the week. + startDay = new Date(year, month, diff); + endDay = new Date(year, month, diff + 6); + } else if ($pressed.hasClass('calendar-filter-month')) { + // Compute start and end days of the month. + startDay = new Date(year, month, 1); + endDay = new Date(year, month + 1, 0); + } + $calendar.datepicker('setDate', startDay); + $calendar.datepicker('setDate', null); + rangeStart = startDay.getTime(); + rangeEnd = endDay.getTime(); + updateCalendarFilters(startDay, endDay); + $('.az-calendar-filter-calendar').datepicker('refresh'); + $pressed.addClass('active').attr('aria-pressed', 'true'); + }); }); - }); - } + }, }; -})(jQuery, Drupal, drupalSettings, once); \ No newline at end of file +})(jQuery, Drupal, drupalSettings, once); diff --git a/modules/custom/az_finder/js/active-filter-count.es6.js b/modules/custom/az_finder/js/active-filter-count.es6.js deleted file mode 100644 index f82913907f..0000000000 --- a/modules/custom/az_finder/js/active-filter-count.es6.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file - * active-filter-count.es6.js - * - * This file contains the JavaScript needed to count active filters in - * exposed filter forms. - */ -((drupalSettings, Drupal) => { - Drupal.behaviors.azFinderFilterCount = { - attach(context, settings) { - const filterContainers = context.querySelectorAll( - '[data-az-better-exposed-filters]', - ); - - filterContainers.forEach((container) => { - const filterCountDisplay = container.querySelector( - '.js-active-filter-count', - ); - const textInputFields = container.querySelectorAll( - 'input[type="text"], input[type="search"]', - ); - const checkboxesAndRadios = container.querySelectorAll( - 'input[type="checkbox"], input[type="radio"]', - ); - const alwaysDisplayResetButton = - settings.azFinder.alwaysDisplayResetButton || false; - - const calculateActiveFilterCount = () => { - let count = container.querySelectorAll( - 'input[type="checkbox"]:checked, input[type="radio"]:checked', - ).length; - textInputFields.forEach((inputField) => { - if (inputField.value.trim().length >= 1) { - count += 1; - } - }); - return count; - }; - - const updateActiveFilterDisplay = () => { - const activeFilterCount = calculateActiveFilterCount(); - // See if the badge is already present. - let badge = filterCountDisplay.querySelector('.badge'); - if (!badge) { - badge = document.createElement('span'); - badge.classList.add('badge', 'badge-light'); - badge.textContent = '0'; - } - if (activeFilterCount > 0) { - badge.classList.remove('sr-only'); - badge.classList.remove('position-absolute'); - } else { - badge.classList.add('sr-only'); - badge.classList.add('position-absolute'); - } - let srText = badge.querySelector('.sr-only'); - if (!srText) { - // Create the screen reader-only text. - srText = document.createElement('span'); - srText.classList.add('sr-only'); - srText.textContent = `Active filters: `; - badge.appendChild(srText); - } - // Set the text value. - badge.firstChild.textContent = `${activeFilterCount}`; - // Replace the children of the filter count display with the badge. - filterCountDisplay.replaceChildren(badge); - - // Handle the reset button visibility. - const resetButton = container.querySelector( - '.js-active-filters-reset', - ); - - if (resetButton) { - if (alwaysDisplayResetButton || activeFilterCount > 0) { - resetButton.classList.remove('d-none'); - } else { - resetButton.classList.add('d-none'); - } - } - }; - - textInputFields.forEach((inputField) => - inputField.addEventListener('input', updateActiveFilterDisplay, { - passive: true, - }), - ); - checkboxesAndRadios.forEach((input) => - input.addEventListener('change', updateActiveFilterDisplay, { - passive: true, - }), - ); - container.addEventListener( - 'az-finder-filter-reset', - updateActiveFilterDisplay, - { passive: true }, - ); - - // Initial update call. - updateActiveFilterDisplay(); - }); - }, - }; -})(drupalSettings, Drupal); diff --git a/modules/custom/az_finder/js/active-filter-count.js b/modules/custom/az_finder/js/active-filter-count.js index 6efc361500..f82913907f 100644 --- a/modules/custom/az_finder/js/active-filter-count.js +++ b/modules/custom/az_finder/js/active-filter-count.js @@ -1,30 +1,46 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function (drupalSettings, Drupal) { + * @file + * active-filter-count.es6.js + * + * This file contains the JavaScript needed to count active filters in + * exposed filter forms. + */ +((drupalSettings, Drupal) => { Drupal.behaviors.azFinderFilterCount = { - attach: function attach(context, settings) { - var filterContainers = context.querySelectorAll('[data-az-better-exposed-filters]'); - filterContainers.forEach(function (container) { - var filterCountDisplay = container.querySelector('.js-active-filter-count'); - var textInputFields = container.querySelectorAll('input[type="text"], input[type="search"]'); - var checkboxesAndRadios = container.querySelectorAll('input[type="checkbox"], input[type="radio"]'); - var alwaysDisplayResetButton = settings.azFinder.alwaysDisplayResetButton || false; - var calculateActiveFilterCount = function calculateActiveFilterCount() { - var count = container.querySelectorAll('input[type="checkbox"]:checked, input[type="radio"]:checked').length; - textInputFields.forEach(function (inputField) { + attach(context, settings) { + const filterContainers = context.querySelectorAll( + '[data-az-better-exposed-filters]', + ); + + filterContainers.forEach((container) => { + const filterCountDisplay = container.querySelector( + '.js-active-filter-count', + ); + const textInputFields = container.querySelectorAll( + 'input[type="text"], input[type="search"]', + ); + const checkboxesAndRadios = container.querySelectorAll( + 'input[type="checkbox"], input[type="radio"]', + ); + const alwaysDisplayResetButton = + settings.azFinder.alwaysDisplayResetButton || false; + + const calculateActiveFilterCount = () => { + let count = container.querySelectorAll( + 'input[type="checkbox"]:checked, input[type="radio"]:checked', + ).length; + textInputFields.forEach((inputField) => { if (inputField.value.trim().length >= 1) { count += 1; } }); return count; }; - var updateActiveFilterDisplay = function updateActiveFilterDisplay() { - var activeFilterCount = calculateActiveFilterCount(); - var badge = filterCountDisplay.querySelector('.badge'); + + const updateActiveFilterDisplay = () => { + const activeFilterCount = calculateActiveFilterCount(); + // See if the badge is already present. + let badge = filterCountDisplay.querySelector('.badge'); if (!badge) { badge = document.createElement('span'); badge.classList.add('badge', 'badge-light'); @@ -37,16 +53,24 @@ badge.classList.add('sr-only'); badge.classList.add('position-absolute'); } - var srText = badge.querySelector('.sr-only'); + let srText = badge.querySelector('.sr-only'); if (!srText) { + // Create the screen reader-only text. srText = document.createElement('span'); srText.classList.add('sr-only'); - srText.textContent = "Active filters: "; + srText.textContent = `Active filters: `; badge.appendChild(srText); } - badge.firstChild.textContent = "".concat(activeFilterCount); + // Set the text value. + badge.firstChild.textContent = `${activeFilterCount}`; + // Replace the children of the filter count display with the badge. filterCountDisplay.replaceChildren(badge); - var resetButton = container.querySelector('.js-active-filters-reset'); + + // Handle the reset button visibility. + const resetButton = container.querySelector( + '.js-active-filters-reset', + ); + if (resetButton) { if (alwaysDisplayResetButton || activeFilterCount > 0) { resetButton.classList.remove('d-none'); @@ -55,21 +79,26 @@ } } }; - textInputFields.forEach(function (inputField) { - return inputField.addEventListener('input', updateActiveFilterDisplay, { - passive: true - }); - }); - checkboxesAndRadios.forEach(function (input) { - return input.addEventListener('change', updateActiveFilterDisplay, { - passive: true - }); - }); - container.addEventListener('az-finder-filter-reset', updateActiveFilterDisplay, { - passive: true - }); + + textInputFields.forEach((inputField) => + inputField.addEventListener('input', updateActiveFilterDisplay, { + passive: true, + }), + ); + checkboxesAndRadios.forEach((input) => + input.addEventListener('change', updateActiveFilterDisplay, { + passive: true, + }), + ); + container.addEventListener( + 'az-finder-filter-reset', + updateActiveFilterDisplay, + { passive: true }, + ); + + // Initial update call. updateActiveFilterDisplay(); }); - } + }, }; -})(drupalSettings, Drupal); \ No newline at end of file +})(drupalSettings, Drupal); diff --git a/modules/custom/az_finder/js/active-filter-reset.es6.js b/modules/custom/az_finder/js/active-filter-reset.es6.js deleted file mode 100644 index f518ca4dcf..0000000000 --- a/modules/custom/az_finder/js/active-filter-reset.es6.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file - * active-filter-reset.es6.js - * - * This file contains the JavaScript needed to reset active filters in - * exposed filter forms. - */ -((Drupal) => { - Drupal.behaviors.azFinderActiveFilterReset = { - attach(context) { - const clickHandler = (selector, action) => { - const element = selector.querySelector('.js-form-submit'); - if (element && action) action(element); - }; - - const resetFilters = (container) => { - const checkboxes = container.querySelectorAll('input[type="checkbox"]'); - const textFields = container.querySelectorAll('input[type="text"]'); - - checkboxes.forEach((checkbox) => { - checkbox.checked = false; - }); - textFields.forEach((textField) => { - textField.value = ''; - }); - clickHandler(container, (element) => element.click()); - - const event = new CustomEvent('az-finder-filter-reset', { - bubbles: true, - detail: { message: 'Filters have been reset.' }, - }); - container.dispatchEvent(event); - }; - - context - .querySelectorAll('[data-az-better-exposed-filters]') - .forEach((container) => { - const resetButton = container.querySelector( - '.js-active-filters-reset', - ); - if (resetButton) { - resetButton.addEventListener('click', (event) => { - event.preventDefault(); - resetFilters(container); - }); - } - }); - }, - }; -})(Drupal); diff --git a/modules/custom/az_finder/js/active-filter-reset.js b/modules/custom/az_finder/js/active-filter-reset.js index 07004e3d38..f518ca4dcf 100644 --- a/modules/custom/az_finder/js/active-filter-reset.js +++ b/modules/custom/az_finder/js/active-filter-reset.js @@ -1,45 +1,50 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function (Drupal) { + * @file + * active-filter-reset.es6.js + * + * This file contains the JavaScript needed to reset active filters in + * exposed filter forms. + */ +((Drupal) => { Drupal.behaviors.azFinderActiveFilterReset = { - attach: function attach(context) { - var clickHandler = function clickHandler(selector, action) { - var element = selector.querySelector('.js-form-submit'); + attach(context) { + const clickHandler = (selector, action) => { + const element = selector.querySelector('.js-form-submit'); if (element && action) action(element); }; - var resetFilters = function resetFilters(container) { - var checkboxes = container.querySelectorAll('input[type="checkbox"]'); - var textFields = container.querySelectorAll('input[type="text"]'); - checkboxes.forEach(function (checkbox) { + + const resetFilters = (container) => { + const checkboxes = container.querySelectorAll('input[type="checkbox"]'); + const textFields = container.querySelectorAll('input[type="text"]'); + + checkboxes.forEach((checkbox) => { checkbox.checked = false; }); - textFields.forEach(function (textField) { + textFields.forEach((textField) => { textField.value = ''; }); - clickHandler(container, function (element) { - return element.click(); - }); - var event = new CustomEvent('az-finder-filter-reset', { + clickHandler(container, (element) => element.click()); + + const event = new CustomEvent('az-finder-filter-reset', { bubbles: true, - detail: { - message: 'Filters have been reset.' - } + detail: { message: 'Filters have been reset.' }, }); container.dispatchEvent(event); }; - context.querySelectorAll('[data-az-better-exposed-filters]').forEach(function (container) { - var resetButton = container.querySelector('.js-active-filters-reset'); - if (resetButton) { - resetButton.addEventListener('click', function (event) { - event.preventDefault(); - resetFilters(container); - }); - } - }); - } + + context + .querySelectorAll('[data-az-better-exposed-filters]') + .forEach((container) => { + const resetButton = container.querySelector( + '.js-active-filters-reset', + ); + if (resetButton) { + resetButton.addEventListener('click', (event) => { + event.preventDefault(); + resetFilters(container); + }); + } + }); + }, }; -})(Drupal); \ No newline at end of file +})(Drupal); diff --git a/modules/custom/az_finder/js/taxonomy-index-tid-widget.es6.js b/modules/custom/az_finder/js/taxonomy-index-tid-widget.es6.js deleted file mode 100644 index a5d7e736ef..0000000000 --- a/modules/custom/az_finder/js/taxonomy-index-tid-widget.es6.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @file - * active-filter-count.es6.js - * - * This file contains the JavaScript needed to count active filters in - * exposed filter forms. - */ -((Drupal) => { - Drupal.behaviors.azFinderTaxonomyIndexTidWidget = { - attach(context, settings) { - const filterContainers = context.querySelectorAll( - '[data-az-better-exposed-filters]', - ); - - function setupSVGButtonListeners(container) { - const svgLevel0ReplaceButtons = container.querySelectorAll( - '.js-svg-replace-level-0', - ); - const svgLevel1ReplaceButtons = container.querySelectorAll( - '.js-svg-replace-level-1', - ); - const { icons } = settings.azFinder; - - function getNewSVGMarkup(isExpanded, level) { - if (level === 0) { - return isExpanded ? icons.level_0_expand : icons.level_0_collapse; - } - return isExpanded ? icons.level_1_expand : icons.level_1_collapse; - } - - function toggleSVG(event) { - const button = event.currentTarget; - const level = button.classList.contains('js-svg-replace-level-0') - ? 0 - : 1; - const isExpanded = button.getAttribute('aria-expanded') === 'true'; - const newSVGMarkup = getNewSVGMarkup(isExpanded, level); - button.querySelector('svg').outerHTML = newSVGMarkup; - } - - svgLevel0ReplaceButtons.forEach((button) => { - button.addEventListener('click', toggleSVG); - }); - - svgLevel1ReplaceButtons.forEach((button) => { - button.addEventListener('click', toggleSVG); - }); - } - - filterContainers.forEach((container) => { - setupSVGButtonListeners(container, settings); - }); - }, - }; -})(Drupal); diff --git a/modules/custom/az_finder/js/taxonomy-index-tid-widget.js b/modules/custom/az_finder/js/taxonomy-index-tid-widget.js index c975d26ac0..a5d7e736ef 100644 --- a/modules/custom/az_finder/js/taxonomy-index-tid-widget.js +++ b/modules/custom/az_finder/js/taxonomy-index-tid-widget.js @@ -1,40 +1,55 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function (Drupal) { + * @file + * active-filter-count.es6.js + * + * This file contains the JavaScript needed to count active filters in + * exposed filter forms. + */ +((Drupal) => { Drupal.behaviors.azFinderTaxonomyIndexTidWidget = { - attach: function attach(context, settings) { - var filterContainers = context.querySelectorAll('[data-az-better-exposed-filters]'); + attach(context, settings) { + const filterContainers = context.querySelectorAll( + '[data-az-better-exposed-filters]', + ); + function setupSVGButtonListeners(container) { - var svgLevel0ReplaceButtons = container.querySelectorAll('.js-svg-replace-level-0'); - var svgLevel1ReplaceButtons = container.querySelectorAll('.js-svg-replace-level-1'); - var icons = settings.azFinder.icons; + const svgLevel0ReplaceButtons = container.querySelectorAll( + '.js-svg-replace-level-0', + ); + const svgLevel1ReplaceButtons = container.querySelectorAll( + '.js-svg-replace-level-1', + ); + const { icons } = settings.azFinder; + function getNewSVGMarkup(isExpanded, level) { if (level === 0) { return isExpanded ? icons.level_0_expand : icons.level_0_collapse; } return isExpanded ? icons.level_1_expand : icons.level_1_collapse; } + function toggleSVG(event) { - var button = event.currentTarget; - var level = button.classList.contains('js-svg-replace-level-0') ? 0 : 1; - var isExpanded = button.getAttribute('aria-expanded') === 'true'; - var newSVGMarkup = getNewSVGMarkup(isExpanded, level); + const button = event.currentTarget; + const level = button.classList.contains('js-svg-replace-level-0') + ? 0 + : 1; + const isExpanded = button.getAttribute('aria-expanded') === 'true'; + const newSVGMarkup = getNewSVGMarkup(isExpanded, level); button.querySelector('svg').outerHTML = newSVGMarkup; } - svgLevel0ReplaceButtons.forEach(function (button) { + + svgLevel0ReplaceButtons.forEach((button) => { button.addEventListener('click', toggleSVG); }); - svgLevel1ReplaceButtons.forEach(function (button) { + + svgLevel1ReplaceButtons.forEach((button) => { button.addEventListener('click', toggleSVG); }); } - filterContainers.forEach(function (container) { + + filterContainers.forEach((container) => { setupSVGButtonListeners(container, settings); }); - } + }, }; -})(Drupal); \ No newline at end of file +})(Drupal); diff --git a/modules/custom/az_marketing_cloud/js/az-marketing-cloud-admin.es6.js b/modules/custom/az_marketing_cloud/js/az-marketing-cloud-admin.es6.js deleted file mode 100644 index 7a4dd7a352..0000000000 --- a/modules/custom/az_marketing_cloud/js/az-marketing-cloud-admin.es6.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @file - * Provides click to copy functionality. - */ - -((window, document) => { - function init() { - const copyLinks = document.querySelectorAll('.js-click2copy a'); - - function removeClass(element) { - setTimeout(() => { - element.classList.remove('js-click-copy--copied'); - }, 3000); - } - - /** - * Handles click events on the click to copy links. - * - * @param {Event} event - * The event object. - * @return {boolean} - * Returns false if the event type is not click. Otherwise, adds the link to - * the user's clipboard and adds a class to the link to indicate that it has been - * copied. - */ - function _handleClick(event) { - const baseUrl = window.location.origin; - if (event.type === 'click') { - event.preventDefault(); - const href = event.target.getAttribute('href'); - navigator.clipboard.writeText(baseUrl + href); - event.target.classList.add('js-click-copy--copied'); - removeClass(event.target); - } else { - return false; - } - } - - copyLinks.forEach((element) => { - element.addEventListener('click', _handleClick, false); - }); - } - - if (document.readyState === 'complete') { - init(); - } else { - document.addEventListener('DOMContentLoaded', init); - } -})(this, this.document); diff --git a/modules/custom/az_marketing_cloud/js/az-marketing-cloud-admin.js b/modules/custom/az_marketing_cloud/js/az-marketing-cloud-admin.js index c1bc3b61fb..7a4dd7a352 100644 --- a/modules/custom/az_marketing_cloud/js/az-marketing-cloud-admin.js +++ b/modules/custom/az_marketing_cloud/js/az-marketing-cloud-admin.js @@ -1,22 +1,33 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function (window, document) { + * @file + * Provides click to copy functionality. + */ + +((window, document) => { function init() { - var copyLinks = document.querySelectorAll('.js-click2copy a'); + const copyLinks = document.querySelectorAll('.js-click2copy a'); + function removeClass(element) { - setTimeout(function () { + setTimeout(() => { element.classList.remove('js-click-copy--copied'); }, 3000); } + + /** + * Handles click events on the click to copy links. + * + * @param {Event} event + * The event object. + * @return {boolean} + * Returns false if the event type is not click. Otherwise, adds the link to + * the user's clipboard and adds a class to the link to indicate that it has been + * copied. + */ function _handleClick(event) { - var baseUrl = window.location.origin; + const baseUrl = window.location.origin; if (event.type === 'click') { event.preventDefault(); - var href = event.target.getAttribute('href'); + const href = event.target.getAttribute('href'); navigator.clipboard.writeText(baseUrl + href); event.target.classList.add('js-click-copy--copied'); removeClass(event.target); @@ -24,13 +35,15 @@ return false; } } - copyLinks.forEach(function (element) { + + copyLinks.forEach((element) => { element.addEventListener('click', _handleClick, false); }); } + if (document.readyState === 'complete') { init(); } else { document.addEventListener('DOMContentLoaded', init); } -})(this, this.document); \ No newline at end of file +})(this, this.document); diff --git a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_vimeo.es6.js b/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_vimeo.es6.js deleted file mode 100644 index 7b60bcb7d3..0000000000 --- a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_vimeo.es6.js +++ /dev/null @@ -1,156 +0,0 @@ -((Drupal, once) => { - Drupal.behaviors.az_vimeo_video_bg = { - attach() { - function initVimeoBackgrounds() { - // Set default aspect ratio for Vimeo videos. - const defaultAspectRatio = 16 / 9; - - // Error messaging function - function vimeoError(error) { - switch (error.name) { - case 'PasswordError': - console.log('The Vimeo video is password-protected.'); - break; - case 'PrivacyError': - console.log('The Vimeo video is private.'); - break; - default: - console.log( - `Some errors occurred with the Vimeo video: ${error.name}`, - ); - break; - } - } - - // Resize Logic - function setDimensions(container) { - const parentParagraph = container.parentNode; - let parentHeight = parentParagraph.offsetHeight; - parentHeight = `${parentHeight.toString()}px`; - container.style.height = parentHeight; - if (container.dataset.style === 'bottom') { - container.style.top = 0; - } - const thisPlayer = - container.getElementsByClassName('az-video-player')[0].firstChild; - if (thisPlayer === null) { - return; - } - thisPlayer.style.zIndex = -100; - const width = container.offsetWidth; - const height = container.offsetHeight; - const pWidth = Math.ceil(height * defaultAspectRatio); // get new player width - const pHeight = Math.ceil(width / defaultAspectRatio); // get new player height - let widthMinuspWidthDividedByTwo = (width - pWidth) / 2; - widthMinuspWidthDividedByTwo = `${widthMinuspWidthDividedByTwo.toString()}px`; - let pHeightRatio = (height - pHeight) / 2; - pHeightRatio = `${pHeightRatio.toString()}px`; - // when screen aspect ratio differs from video, - // video must center and underlay one dimension. - if (width / defaultAspectRatio < height) { - // if new video height < window height (gap underneath) - thisPlayer.width = pWidth; - thisPlayer.height = height; - thisPlayer.style.left = widthMinuspWidthDividedByTwo; - thisPlayer.style.top = 0; - // player width is greater, offset left; reset top - } else { - // new video width < window width (gap to right) - // get new player height - thisPlayer.height = pHeight; - thisPlayer.width = width; - thisPlayer.style.top = pHeightRatio; - thisPlayer.style.left = 0; - } - } - - if (window.screen && window.screen.width > 768) { - // @see https://developer.vimeo.com/player/sdk/basics - const defaultOptions = { - vimeoId: '', - autopause: false, - autoplay: true, - controls: 0, - loop: true, - muted: true, - playButtonClass: 'az-video-play', - pauseButtonClass: 'az-video-pause', - }; - const bgVideoParagraphs = document.getElementsByClassName( - 'az-js-vimeo-video-background', - ); - - // Load Vimeo API - const tag = document.createElement('script'); - tag.src = 'https://player.vimeo.com/api/player.js'; - document.head.appendChild(tag); - - // Methods - // Ensure Vimeo API is loaded before proceeding - tag.onload = () => { - Array.from(bgVideoParagraphs).forEach((element) => { - const parentParagraph = element.parentNode; - const vimeoId = element.dataset.vimeoVideoId; - const videoPlayer = - element.getElementsByClassName('az-video-player')[0]; - const VimeoPlayer = window.Vimeo; - - // Initialize Vimeo Player - element.player = new VimeoPlayer.Player(videoPlayer, { - id: vimeoId, - autopause: defaultOptions.autopause, - autoplay: element.dataset.autoplay === 'true', - controls: 0, - loop: defaultOptions.loop, - muted: defaultOptions.muted, - }); - - // Event listener for starting play. - element.player.on('bufferend', () => { - setDimensions(element); - parentParagraph.classList.add('az-video-playing'); - }); - - // Play Button - const playButtons = - element.getElementsByClassName('az-video-play'); - if (playButtons[0]) { - playButtons[0].addEventListener('click', (event) => { - event.preventDefault(); - element.player.play().catch((error) => vimeoError(error)); - parentParagraph.classList.add('az-video-playing'); - parentParagraph.classList.remove('az-video-paused'); - }); - } - - // Pause Button - const pauseButtons = - element.getElementsByClassName('az-video-pause'); - if (pauseButtons[0]) { - pauseButtons[0].addEventListener('click', (event) => { - event.preventDefault(); - element.player.pause().catch((error) => vimeoError(error)); - parentParagraph.classList.add('az-video-paused'); - parentParagraph.classList.remove('az-video-playing'); - }); - } - }); - }; - - // Resize handler updates width, height and offset - // of player after resize/init. - const resize = () => { - Array.from(bgVideoParagraphs).forEach((element) => { - setDimensions(element); - }); - }; - window.addEventListener('resize', () => { - resize(); - }); - } - } - - once('vimeoTextOnMedia-init', 'body').forEach(initVimeoBackgrounds); - }, - }; -})(Drupal, once); diff --git a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_vimeo.js b/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_vimeo.js index 9487dd1b2a..7ae28021bc 100644 --- a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_vimeo.js +++ b/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_vimeo.js @@ -1,62 +1,145 @@ -/** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function (Drupal, once) { +((Drupal, once) => { Drupal.behaviors.az_vimeo_video_bg = { - attach: function attach() { + attach() { function initVimeoBackgrounds() { - var defaultAspectRatio = 16 / 9; + // Set default aspect ratio for Vimeo videos. + const defaultAspectRatio = 16 / 9; + + // Error messaging function function vimeoError(error) { switch (error.name) { case 'PasswordError': + // eslint-disable-next-line no-console console.log('The Vimeo video is password-protected.'); break; case 'PrivacyError': + // eslint-disable-next-line no-console console.log('The Vimeo video is private.'); break; default: - console.log("Some errors occurred with the Vimeo video: ".concat(error.name)); + // eslint-disable-next-line no-console + console.log( + `Some errors occurred with the Vimeo video: ${error.name}`, + ); break; } } + + // Resize Logic function setDimensions(container) { - var parentParagraph = container.parentNode; - var parentHeight = parentParagraph.offsetHeight; - parentHeight = "".concat(parentHeight.toString(), "px"); + const parentParagraph = container.parentNode; + let parentHeight = parentParagraph.offsetHeight; + parentHeight = `${parentHeight.toString()}px`; container.style.height = parentHeight; if (container.dataset.style === 'bottom') { container.style.top = 0; } - var thisPlayer = container.getElementsByClassName('az-video-player')[0].firstChild; + const thisPlayer = + container.getElementsByClassName('az-video-player')[0].firstChild; if (thisPlayer === null) { return; } thisPlayer.style.zIndex = -100; - var width = container.offsetWidth; - var height = container.offsetHeight; - var pWidth = Math.ceil(height * defaultAspectRatio); - var pHeight = Math.ceil(width / defaultAspectRatio); - var widthMinuspWidthDividedByTwo = (width - pWidth) / 2; - widthMinuspWidthDividedByTwo = "".concat(widthMinuspWidthDividedByTwo.toString(), "px"); - var pHeightRatio = (height - pHeight) / 2; - pHeightRatio = "".concat(pHeightRatio.toString(), "px"); + const width = container.offsetWidth; + const height = container.offsetHeight; + const pWidth = Math.ceil(height * defaultAspectRatio); // get new player width + const pHeight = Math.ceil(width / defaultAspectRatio); // get new player height + let widthMinuspWidthDividedByTwo = (width - pWidth) / 2; + widthMinuspWidthDividedByTwo = `${widthMinuspWidthDividedByTwo.toString()}px`; + let pHeightRatio = (height - pHeight) / 2; + pHeightRatio = `${pHeightRatio.toString()}px`; + // when screen aspect ratio differs from video, + // video must center and underlay one dimension. if (width / defaultAspectRatio < height) { + // if new video height < window height (gap underneath) thisPlayer.width = pWidth; thisPlayer.height = height; thisPlayer.style.left = widthMinuspWidthDividedByTwo; thisPlayer.style.top = 0; + // player width is greater, offset left; reset top } else { + // new video width < window width (gap to right) + // get new player height thisPlayer.height = pHeight; thisPlayer.width = width; thisPlayer.style.top = pHeightRatio; thisPlayer.style.left = 0; } } + + // Helper function for play button click + function handlePlayButtonClick(element, parentParagraph) { + return (event) => { + event.preventDefault(); + element.player.play().catch((error) => vimeoError(error)); + parentParagraph.classList.add('az-video-playing'); + parentParagraph.classList.remove('az-video-paused'); + }; + } + + // Helper function for pause button click + function handlePauseButtonClick(element, parentParagraph) { + return (event) => { + event.preventDefault(); + element.player.pause().catch((error) => vimeoError(error)); + parentParagraph.classList.add('az-video-paused'); + parentParagraph.classList.remove('az-video-playing'); + }; + } + + // Helper function to initialize a single Vimeo element + function initVimeoElement(element, defaultOptions) { + const parentParagraph = element.parentNode; + const vimeoId = element.dataset.vimeoVideoId; + const videoPlayer = + element.getElementsByClassName('az-video-player')[0]; + const VimeoPlayer = window.Vimeo; + + // Initialize Vimeo Player + element.player = new VimeoPlayer.Player(videoPlayer, { + id: vimeoId, + autopause: defaultOptions.autopause, + autoplay: element.dataset.autoplay === 'true', + controls: 0, + loop: defaultOptions.loop, + muted: defaultOptions.muted, + }); + + // Event listener for starting play. + element.player.on('bufferend', () => { + setDimensions(element); + parentParagraph.classList.add('az-video-playing'); + }); + + // Play Button + const playButtons = element.getElementsByClassName('az-video-play'); + if (playButtons[0]) { + playButtons[0].addEventListener( + 'click', + handlePlayButtonClick(element, parentParagraph), + ); + } + + // Pause Button + const pauseButtons = element.getElementsByClassName('az-video-pause'); + if (pauseButtons[0]) { + pauseButtons[0].addEventListener( + 'click', + handlePauseButtonClick(element, parentParagraph), + ); + } + } + + // Helper function to handle API loaded callback + function handleVimeoAPILoaded(bgVideoParagraphs, defaultOptions) { + Array.from(bgVideoParagraphs).forEach((element) => { + initVimeoElement(element, defaultOptions); + }); + } + if (window.screen && window.screen.width > 768) { - var defaultOptions = { + // @see https://developer.vimeo.com/player/sdk/basics + const defaultOptions = { vimeoId: '', autopause: false, autoplay: true, @@ -64,65 +147,36 @@ loop: true, muted: true, playButtonClass: 'az-video-play', - pauseButtonClass: 'az-video-pause' + pauseButtonClass: 'az-video-pause', }; - var bgVideoParagraphs = document.getElementsByClassName('az-js-vimeo-video-background'); - var tag = document.createElement('script'); + const bgVideoParagraphs = document.getElementsByClassName( + 'az-js-vimeo-video-background', + ); + + // Load Vimeo API + const tag = document.createElement('script'); tag.src = 'https://player.vimeo.com/api/player.js'; document.head.appendChild(tag); - tag.onload = function () { - Array.from(bgVideoParagraphs).forEach(function (element) { - var parentParagraph = element.parentNode; - var vimeoId = element.dataset.vimeoVideoId; - var videoPlayer = element.getElementsByClassName('az-video-player')[0]; - var VimeoPlayer = window.Vimeo; - element.player = new VimeoPlayer.Player(videoPlayer, { - id: vimeoId, - autopause: defaultOptions.autopause, - autoplay: element.dataset.autoplay === 'true', - controls: 0, - loop: defaultOptions.loop, - muted: defaultOptions.muted - }); - element.player.on('bufferend', function () { - setDimensions(element); - parentParagraph.classList.add('az-video-playing'); - }); - var playButtons = element.getElementsByClassName('az-video-play'); - if (playButtons[0]) { - playButtons[0].addEventListener('click', function (event) { - event.preventDefault(); - element.player.play().catch(function (error) { - return vimeoError(error); - }); - parentParagraph.classList.add('az-video-playing'); - parentParagraph.classList.remove('az-video-paused'); - }); - } - var pauseButtons = element.getElementsByClassName('az-video-pause'); - if (pauseButtons[0]) { - pauseButtons[0].addEventListener('click', function (event) { - event.preventDefault(); - element.player.pause().catch(function (error) { - return vimeoError(error); - }); - parentParagraph.classList.add('az-video-paused'); - parentParagraph.classList.remove('az-video-playing'); - }); - } - }); - }; - var resize = function resize() { - Array.from(bgVideoParagraphs).forEach(function (element) { + + // Methods + // Ensure Vimeo API is loaded before proceeding + tag.onload = () => + handleVimeoAPILoaded(bgVideoParagraphs, defaultOptions); + + // Resize handler updates width, height and offset + // of player after resize/init. + const resize = () => { + Array.from(bgVideoParagraphs).forEach((element) => { setDimensions(element); }); }; - window.addEventListener('resize', function () { + window.addEventListener('resize', () => { resize(); }); } } + once('vimeoTextOnMedia-init', 'body').forEach(initVimeoBackgrounds); - } + }, }; -})(Drupal, once); \ No newline at end of file +})(Drupal, once); diff --git a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_youtube.es6.js b/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_youtube.es6.js deleted file mode 100644 index bacdd26ca1..0000000000 --- a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_youtube.es6.js +++ /dev/null @@ -1,170 +0,0 @@ -((Drupal, once) => { - Drupal.behaviors.az_youtube_video_bg = { - attach(context) { - function initYouTubeBackgrounds() { - if (window.screen && window.screen.width > 768) { - // @see https://developers.google.com/youtube/player_parameters - const defaultSettings = { - loop: true, - mute: true, - pauseButtonClass: 'az-video-pause', - playButtonClass: 'az-video-play', - ratio: 16 / 9, - width: document.documentElement.clientWidth, - }; - const bgVideoSettings = {}; - - // Load YouTube IFrame player API - const tag = document.createElement('script'); - const firstScriptTag = document.getElementsByTagName('script')[0]; - tag.src = 'https://www.youtube.com/iframe_api'; - firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); - - // Set up IFrame player - const bgVideoParagraphs = document.getElementsByClassName( - 'az-js-video-background', - ); - window.onYouTubeIframeAPIReady = () => { - Array.from(bgVideoParagraphs).forEach((element) => { - const parentParagraph = document.getElementById( - element.dataset.parentid, - ); - const youtubeId = element.dataset.youtubeid; - bgVideoSettings[youtubeId] = { - autoplay: element.dataset.autoplay === 'true', - start: element.dataset.start, - }; - const videoPlayer = - element.getElementsByClassName('az-video-player')[0]; - const youTubePlayer = window.YT; - element.player = new youTubePlayer.Player(videoPlayer, { - width: defaultSettings.width, - height: Math.ceil( - defaultSettings.width / defaultSettings.ratio, - ), - videoId: youtubeId, - playerVars: { - controls: 0, - enablejsapi: 1, - origin: window.location.origin, - rel: 0, - }, - events: { - onReady: window.onPlayerReady, - onStateChange: window.onPlayerStateChange, - }, - }); - const playButton = - element.getElementsByClassName('az-video-play')[0]; - playButton.addEventListener('click', (event) => { - event.preventDefault(); - element.player.playVideo(); - parentParagraph.classList.remove('az-video-paused'); - parentParagraph.classList.add('az-video-playing'); - }); - const pauseButton = - element.getElementsByClassName('az-video-pause')[0]; - pauseButton.addEventListener('click', (event) => { - event.preventDefault(); - element.player.pauseVideo(); - parentParagraph.classList.remove('az-video-playing'); - parentParagraph.classList.add('az-video-paused'); - }); - }); - }; - - // Updates width, height, and offset of player after resize/init. - const setDimensions = (container) => { - container.style.height = `${container.parentNode.offsetHeight}px`; - if (container.dataset.style === 'bottom') { - container.style.top = 0; - } - const thisPlayer = - container.getElementsByClassName('az-video-player')[0]; - if (thisPlayer === null) { - return; - } - thisPlayer.style.zIndex = -100; - const width = container.offsetWidth; - const height = container.offsetHeight; - const pWidth = Math.ceil(height * defaultSettings.ratio); - const pHeight = Math.ceil(width / defaultSettings.ratio); - let widthMinuspWidthDividedByTwo = (width - pWidth) / 2; - widthMinuspWidthDividedByTwo = `${widthMinuspWidthDividedByTwo.toString()}px`; - const pHeightRatio = `${(height - pHeight) / 2}px`; - // When screen aspect ratio differs from video, - // video must center and underlay one dimension. - if (width / defaultSettings.ratio < height) { - // If new video height < window height (gap underneath) - thisPlayer.width = pWidth; - thisPlayer.height = height; - thisPlayer.style.left = widthMinuspWidthDividedByTwo; - thisPlayer.style.top = 0; - // Player width is greater, offset left; reset top - } else { - // New video width < window width (gap to right) - // Get new player height - thisPlayer.height = pHeight; - thisPlayer.width = width; - thisPlayer.style.top = pHeightRatio; - thisPlayer.style.left = 0; - } - }; - - // Resize handler - const resize = () => { - Array.from(bgVideoParagraphs).forEach((element) => { - setDimensions(element); - }); - }; - - window.onPlayerReady = (event) => { - const id = event.target.options.videoId; - if (!bgVideoSettings[id].autoplay) { - return; - } - if (defaultSettings.mute) { - event.target.mute(); - } - event.target.seekTo(bgVideoSettings[id].start); - event.target.playVideo(); - // Create and dispatch a new event when video starts playing. - dispatchEvent(new Event('azVideoPlay')); - }; - - window.onPlayerStateChange = (event) => { - const id = event.target.options.videoId; - const stateChangeContainer = document.getElementById( - `${id}-bg-video-container`, - ); - const parentContainer = document.getElementById( - stateChangeContainer.dataset.parentid, - ); - if (event.data === 0 && defaultSettings.loop) { - // Video ended and loop option is set true. - stateChangeContainer.player.seekTo(bgVideoSettings[id].start); - } - if (event.data === 1) { - resize(); - parentContainer.classList.add('az-video-playing'); - parentContainer.classList.remove('az-video-loading'); - } - }; - - // Events - window.addEventListener('load', () => { - resize(); - }); - window.addEventListener('resize', () => { - resize(); - }); - } - } - - once('youTubeTextOnMedia-init', 'body').forEach( - initYouTubeBackgrounds, - context, - ); - }, - }; -})(Drupal, once); diff --git a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_youtube.js b/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_youtube.js index 6f0220bea4..bacdd26ca1 100644 --- a/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_youtube.js +++ b/modules/custom/az_paragraphs/az_paragraphs_text_media/js/az_paragraphs_az_text_media_youtube.js @@ -1,62 +1,70 @@ -/** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function (Drupal, once) { +((Drupal, once) => { Drupal.behaviors.az_youtube_video_bg = { - attach: function attach(context) { + attach(context) { function initYouTubeBackgrounds() { if (window.screen && window.screen.width > 768) { - var defaultSettings = { + // @see https://developers.google.com/youtube/player_parameters + const defaultSettings = { loop: true, mute: true, pauseButtonClass: 'az-video-pause', playButtonClass: 'az-video-play', ratio: 16 / 9, - width: document.documentElement.clientWidth + width: document.documentElement.clientWidth, }; - var bgVideoSettings = {}; - var tag = document.createElement('script'); - var firstScriptTag = document.getElementsByTagName('script')[0]; + const bgVideoSettings = {}; + + // Load YouTube IFrame player API + const tag = document.createElement('script'); + const firstScriptTag = document.getElementsByTagName('script')[0]; tag.src = 'https://www.youtube.com/iframe_api'; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); - var bgVideoParagraphs = document.getElementsByClassName('az-js-video-background'); - window.onYouTubeIframeAPIReady = function () { - Array.from(bgVideoParagraphs).forEach(function (element) { - var parentParagraph = document.getElementById(element.dataset.parentid); - var youtubeId = element.dataset.youtubeid; + + // Set up IFrame player + const bgVideoParagraphs = document.getElementsByClassName( + 'az-js-video-background', + ); + window.onYouTubeIframeAPIReady = () => { + Array.from(bgVideoParagraphs).forEach((element) => { + const parentParagraph = document.getElementById( + element.dataset.parentid, + ); + const youtubeId = element.dataset.youtubeid; bgVideoSettings[youtubeId] = { autoplay: element.dataset.autoplay === 'true', - start: element.dataset.start + start: element.dataset.start, }; - var videoPlayer = element.getElementsByClassName('az-video-player')[0]; - var youTubePlayer = window.YT; + const videoPlayer = + element.getElementsByClassName('az-video-player')[0]; + const youTubePlayer = window.YT; element.player = new youTubePlayer.Player(videoPlayer, { width: defaultSettings.width, - height: Math.ceil(defaultSettings.width / defaultSettings.ratio), + height: Math.ceil( + defaultSettings.width / defaultSettings.ratio, + ), videoId: youtubeId, playerVars: { controls: 0, enablejsapi: 1, origin: window.location.origin, - rel: 0 + rel: 0, }, events: { onReady: window.onPlayerReady, - onStateChange: window.onPlayerStateChange - } + onStateChange: window.onPlayerStateChange, + }, }); - var playButton = element.getElementsByClassName('az-video-play')[0]; - playButton.addEventListener('click', function (event) { + const playButton = + element.getElementsByClassName('az-video-play')[0]; + playButton.addEventListener('click', (event) => { event.preventDefault(); element.player.playVideo(); parentParagraph.classList.remove('az-video-paused'); parentParagraph.classList.add('az-video-playing'); }); - var pauseButton = element.getElementsByClassName('az-video-pause')[0]; - pauseButton.addEventListener('click', function (event) { + const pauseButton = + element.getElementsByClassName('az-video-pause')[0]; + pauseButton.addEventListener('click', (event) => { event.preventDefault(); element.player.pauseVideo(); parentParagraph.classList.remove('az-video-playing'); @@ -64,42 +72,54 @@ }); }); }; - var setDimensions = function setDimensions(container) { - container.style.height = "".concat(container.parentNode.offsetHeight, "px"); + + // Updates width, height, and offset of player after resize/init. + const setDimensions = (container) => { + container.style.height = `${container.parentNode.offsetHeight}px`; if (container.dataset.style === 'bottom') { container.style.top = 0; } - var thisPlayer = container.getElementsByClassName('az-video-player')[0]; + const thisPlayer = + container.getElementsByClassName('az-video-player')[0]; if (thisPlayer === null) { return; } thisPlayer.style.zIndex = -100; - var width = container.offsetWidth; - var height = container.offsetHeight; - var pWidth = Math.ceil(height * defaultSettings.ratio); - var pHeight = Math.ceil(width / defaultSettings.ratio); - var widthMinuspWidthDividedByTwo = (width - pWidth) / 2; - widthMinuspWidthDividedByTwo = "".concat(widthMinuspWidthDividedByTwo.toString(), "px"); - var pHeightRatio = "".concat((height - pHeight) / 2, "px"); + const width = container.offsetWidth; + const height = container.offsetHeight; + const pWidth = Math.ceil(height * defaultSettings.ratio); + const pHeight = Math.ceil(width / defaultSettings.ratio); + let widthMinuspWidthDividedByTwo = (width - pWidth) / 2; + widthMinuspWidthDividedByTwo = `${widthMinuspWidthDividedByTwo.toString()}px`; + const pHeightRatio = `${(height - pHeight) / 2}px`; + // When screen aspect ratio differs from video, + // video must center and underlay one dimension. if (width / defaultSettings.ratio < height) { + // If new video height < window height (gap underneath) thisPlayer.width = pWidth; thisPlayer.height = height; thisPlayer.style.left = widthMinuspWidthDividedByTwo; thisPlayer.style.top = 0; + // Player width is greater, offset left; reset top } else { + // New video width < window width (gap to right) + // Get new player height thisPlayer.height = pHeight; thisPlayer.width = width; thisPlayer.style.top = pHeightRatio; thisPlayer.style.left = 0; } }; - var resize = function resize() { - Array.from(bgVideoParagraphs).forEach(function (element) { + + // Resize handler + const resize = () => { + Array.from(bgVideoParagraphs).forEach((element) => { setDimensions(element); }); }; - window.onPlayerReady = function (event) { - var id = event.target.options.videoId; + + window.onPlayerReady = (event) => { + const id = event.target.options.videoId; if (!bgVideoSettings[id].autoplay) { return; } @@ -108,13 +128,20 @@ } event.target.seekTo(bgVideoSettings[id].start); event.target.playVideo(); + // Create and dispatch a new event when video starts playing. dispatchEvent(new Event('azVideoPlay')); }; - window.onPlayerStateChange = function (event) { - var id = event.target.options.videoId; - var stateChangeContainer = document.getElementById("".concat(id, "-bg-video-container")); - var parentContainer = document.getElementById(stateChangeContainer.dataset.parentid); + + window.onPlayerStateChange = (event) => { + const id = event.target.options.videoId; + const stateChangeContainer = document.getElementById( + `${id}-bg-video-container`, + ); + const parentContainer = document.getElementById( + stateChangeContainer.dataset.parentid, + ); if (event.data === 0 && defaultSettings.loop) { + // Video ended and loop option is set true. stateChangeContainer.player.seekTo(bgVideoSettings[id].start); } if (event.data === 1) { @@ -123,15 +150,21 @@ parentContainer.classList.remove('az-video-loading'); } }; - window.addEventListener('load', function () { + + // Events + window.addEventListener('load', () => { resize(); }); - window.addEventListener('resize', function () { + window.addEventListener('resize', () => { resize(); }); } } - once('youTubeTextOnMedia-init', 'body').forEach(initYouTubeBackgrounds, context); - } + + once('youTubeTextOnMedia-init', 'body').forEach( + initYouTubeBackgrounds, + context, + ); + }, }; -})(Drupal, once); \ No newline at end of file +})(Drupal, once); diff --git a/modules/custom/az_paragraphs/js/az_paragraphs_full_width.es6.js b/modules/custom/az_paragraphs/js/az_paragraphs_full_width.es6.js deleted file mode 100644 index e6cbdaabda..0000000000 --- a/modules/custom/az_paragraphs/js/az_paragraphs_full_width.es6.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * @file - * Provides helper functions to ensure proper display of full-width-paragraphs. - */ -(() => { - /** - * Calculates scroll bar width if any and assigns the value to the - * `--scrollbar-width` CSS variable on the html element. - */ - function calculateScrollbarWidth() { - document.documentElement.style.setProperty( - '--scrollbar-width', - `${window.innerWidth - document.documentElement.clientWidth}px`, - ); - } - - /** - * Calculates and sets margin required to push sidebars beneath the last - * full-width paragraph in the Content region of the page. - * - * This function assigns values to the `--sidebar-top-margin` CSS variable on - * the `html` element. - */ - function pushSidebarsDown() { - const contentRegion = document.querySelector('main.main-content'); - if (contentRegion !== null) { - const allFullWidthElements = contentRegion.querySelectorAll( - '.paragraph.full-width-background', - ); - if (allFullWidthElements.length === 0) { - return; - } - const lastFullWidthElement = - allFullWidthElements[allFullWidthElements.length - 1]; - const contentRegionPosition = contentRegion.getBoundingClientRect(); - const style = window.getComputedStyle(lastFullWidthElement, ''); - const bottomMargin = parseFloat(style.marginBottom); - const contentRegionTop = contentRegionPosition.top; - const lastFullWidthElementPosition = - lastFullWidthElement.getBoundingClientRect(); - const lastFullWidthElementBottom = lastFullWidthElementPosition.bottom; - const sidebarTopMargin = - lastFullWidthElementBottom - contentRegionTop + bottomMargin; - if (sidebarTopMargin) { - document.documentElement.style.setProperty( - '--sidebar-top-margin', - `${sidebarTopMargin}px`, - ); - } - } - } - - /** - * Calculates and sets negative margins required for full width backgrounds. - * - * This function assigns values to the `--full-width-left-distance` and - * `--full-width-right-distance` CSS variables on the `html` element. - */ - function calculateFullWidthNegativeMargins() { - const contentRegion = document.querySelectorAll('.block-system-main-block'); - if (contentRegion.length > 0) { - const contentRegionPosition = contentRegion[0].getBoundingClientRect(); - const distanceFromLeft = contentRegionPosition.left; - const distanceFromRight = contentRegionPosition.right; - const negativeLeftMargin = 0 - distanceFromLeft; - const negativeRightMargin = - distanceFromRight - document.documentElement.clientWidth; - document.documentElement.style.setProperty( - '--full-width-left-distance', - `${negativeLeftMargin}px`, - ); - document.documentElement.style.setProperty( - '--full-width-right-distance', - `${negativeRightMargin}px`, - ); - } - const contentTopAndBottomBlocks = document.querySelectorAll( - '.region-content-top > .block, .region-content-bottom > .block', - ); - if (contentTopAndBottomBlocks.length > 0) { - const negativeAutoMargin = - -( - document.documentElement.clientWidth - - contentTopAndBottomBlocks[0].getBoundingClientRect().width - ) / 2; - document.documentElement.style.setProperty( - '--full-width-auto-distance', - `${negativeAutoMargin}px`, - ); - } - } - - /** - * Calculates and sets width required for full width content-width split screens. - * - * This function assigns values to the `--full-width-sidebar-width` - * CSS variables on the `html` element. - */ - function calculateFullWidthSidebarWidth() { - const sidebarRegion = document.querySelectorAll('.sidebar'); - if (sidebarRegion.length > 0) { - const sidebarRegionPosition = sidebarRegion[0].getBoundingClientRect(); - const sidebarWidth = sidebarRegionPosition.width; - document.documentElement.style.setProperty( - '--full-width-sidebar-width', - `${sidebarWidth}px`, - ); - } - } - - /** - * Executes functions to set up the page layout. - */ - function setFullWidthLayout() { - calculateScrollbarWidth(); - calculateFullWidthNegativeMargins(); - calculateFullWidthSidebarWidth(); - pushSidebarsDown(); - } - - // Initialize on page load - document.addEventListener('DOMContentLoaded', setFullWidthLayout); - - // Recalculate values on window resize - window.addEventListener('resize', setFullWidthLayout); - - // Recalculate values when azVideoPlay custom event fires - window.addEventListener('azVideoPlay', setFullWidthLayout); -})(); diff --git a/modules/custom/az_paragraphs/js/az_paragraphs_full_width.js b/modules/custom/az_paragraphs/js/az_paragraphs_full_width.js index 925cb2231a..e6cbdaabda 100644 --- a/modules/custom/az_paragraphs/js/az_paragraphs_full_width.js +++ b/modules/custom/az_paragraphs/js/az_paragraphs_full_width.js @@ -1,65 +1,129 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function () { + * @file + * Provides helper functions to ensure proper display of full-width-paragraphs. + */ +(() => { + /** + * Calculates scroll bar width if any and assigns the value to the + * `--scrollbar-width` CSS variable on the html element. + */ function calculateScrollbarWidth() { - document.documentElement.style.setProperty('--scrollbar-width', "".concat(window.innerWidth - document.documentElement.clientWidth, "px")); + document.documentElement.style.setProperty( + '--scrollbar-width', + `${window.innerWidth - document.documentElement.clientWidth}px`, + ); } + + /** + * Calculates and sets margin required to push sidebars beneath the last + * full-width paragraph in the Content region of the page. + * + * This function assigns values to the `--sidebar-top-margin` CSS variable on + * the `html` element. + */ function pushSidebarsDown() { - var contentRegion = document.querySelector('main.main-content'); + const contentRegion = document.querySelector('main.main-content'); if (contentRegion !== null) { - var allFullWidthElements = contentRegion.querySelectorAll('.paragraph.full-width-background'); + const allFullWidthElements = contentRegion.querySelectorAll( + '.paragraph.full-width-background', + ); if (allFullWidthElements.length === 0) { return; } - var lastFullWidthElement = allFullWidthElements[allFullWidthElements.length - 1]; - var contentRegionPosition = contentRegion.getBoundingClientRect(); - var style = window.getComputedStyle(lastFullWidthElement, ''); - var bottomMargin = parseFloat(style.marginBottom); - var contentRegionTop = contentRegionPosition.top; - var lastFullWidthElementPosition = lastFullWidthElement.getBoundingClientRect(); - var lastFullWidthElementBottom = lastFullWidthElementPosition.bottom; - var sidebarTopMargin = lastFullWidthElementBottom - contentRegionTop + bottomMargin; + const lastFullWidthElement = + allFullWidthElements[allFullWidthElements.length - 1]; + const contentRegionPosition = contentRegion.getBoundingClientRect(); + const style = window.getComputedStyle(lastFullWidthElement, ''); + const bottomMargin = parseFloat(style.marginBottom); + const contentRegionTop = contentRegionPosition.top; + const lastFullWidthElementPosition = + lastFullWidthElement.getBoundingClientRect(); + const lastFullWidthElementBottom = lastFullWidthElementPosition.bottom; + const sidebarTopMargin = + lastFullWidthElementBottom - contentRegionTop + bottomMargin; if (sidebarTopMargin) { - document.documentElement.style.setProperty('--sidebar-top-margin', "".concat(sidebarTopMargin, "px")); + document.documentElement.style.setProperty( + '--sidebar-top-margin', + `${sidebarTopMargin}px`, + ); } } } + + /** + * Calculates and sets negative margins required for full width backgrounds. + * + * This function assigns values to the `--full-width-left-distance` and + * `--full-width-right-distance` CSS variables on the `html` element. + */ function calculateFullWidthNegativeMargins() { - var contentRegion = document.querySelectorAll('.block-system-main-block'); + const contentRegion = document.querySelectorAll('.block-system-main-block'); if (contentRegion.length > 0) { - var contentRegionPosition = contentRegion[0].getBoundingClientRect(); - var distanceFromLeft = contentRegionPosition.left; - var distanceFromRight = contentRegionPosition.right; - var negativeLeftMargin = 0 - distanceFromLeft; - var negativeRightMargin = distanceFromRight - document.documentElement.clientWidth; - document.documentElement.style.setProperty('--full-width-left-distance', "".concat(negativeLeftMargin, "px")); - document.documentElement.style.setProperty('--full-width-right-distance', "".concat(negativeRightMargin, "px")); + const contentRegionPosition = contentRegion[0].getBoundingClientRect(); + const distanceFromLeft = contentRegionPosition.left; + const distanceFromRight = contentRegionPosition.right; + const negativeLeftMargin = 0 - distanceFromLeft; + const negativeRightMargin = + distanceFromRight - document.documentElement.clientWidth; + document.documentElement.style.setProperty( + '--full-width-left-distance', + `${negativeLeftMargin}px`, + ); + document.documentElement.style.setProperty( + '--full-width-right-distance', + `${negativeRightMargin}px`, + ); } - var contentTopAndBottomBlocks = document.querySelectorAll('.region-content-top > .block, .region-content-bottom > .block'); + const contentTopAndBottomBlocks = document.querySelectorAll( + '.region-content-top > .block, .region-content-bottom > .block', + ); if (contentTopAndBottomBlocks.length > 0) { - var negativeAutoMargin = -(document.documentElement.clientWidth - contentTopAndBottomBlocks[0].getBoundingClientRect().width) / 2; - document.documentElement.style.setProperty('--full-width-auto-distance', "".concat(negativeAutoMargin, "px")); + const negativeAutoMargin = + -( + document.documentElement.clientWidth - + contentTopAndBottomBlocks[0].getBoundingClientRect().width + ) / 2; + document.documentElement.style.setProperty( + '--full-width-auto-distance', + `${negativeAutoMargin}px`, + ); } } + + /** + * Calculates and sets width required for full width content-width split screens. + * + * This function assigns values to the `--full-width-sidebar-width` + * CSS variables on the `html` element. + */ function calculateFullWidthSidebarWidth() { - var sidebarRegion = document.querySelectorAll('.sidebar'); + const sidebarRegion = document.querySelectorAll('.sidebar'); if (sidebarRegion.length > 0) { - var sidebarRegionPosition = sidebarRegion[0].getBoundingClientRect(); - var sidebarWidth = sidebarRegionPosition.width; - document.documentElement.style.setProperty('--full-width-sidebar-width', "".concat(sidebarWidth, "px")); + const sidebarRegionPosition = sidebarRegion[0].getBoundingClientRect(); + const sidebarWidth = sidebarRegionPosition.width; + document.documentElement.style.setProperty( + '--full-width-sidebar-width', + `${sidebarWidth}px`, + ); } } + + /** + * Executes functions to set up the page layout. + */ function setFullWidthLayout() { calculateScrollbarWidth(); calculateFullWidthNegativeMargins(); calculateFullWidthSidebarWidth(); pushSidebarsDown(); } + + // Initialize on page load document.addEventListener('DOMContentLoaded', setFullWidthLayout); + + // Recalculate values on window resize window.addEventListener('resize', setFullWidthLayout); + + // Recalculate values when azVideoPlay custom event fires window.addEventListener('azVideoPlay', setFullWidthLayout); -})(); \ No newline at end of file +})(); diff --git a/modules/custom/az_publication/js/az_publication_date_picker.es6.js b/modules/custom/az_publication/js/az_publication_date_picker.es6.js deleted file mode 100644 index 2a14177900..0000000000 --- a/modules/custom/az_publication/js/az_publication_date_picker.es6.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file - * Default date values. - */ - -(($, Drupal, once) => { - Drupal.behaviors.datetimeTweaksDefaultDate = { - attach(context) { - $(once('azpublicationdate', '.az-publication-date-picker input', context)) - // eslint-disable-next-line func-names - .each(function () { - // Fetch field date settings. - const dateFormat = $(this) - .data('drupal-date-format') - .replace('Y', 'yyyy') - .replace('m', 'mm') - .replace('d', 'dd'); - // Get datepicker settings. - const viewmode = $(this).data('az-publication-date-mode'); - const components = dateFormat.split('-'); - // Modify form value to correct number of components. - let value = $(this).val(); - if (value) { - value = value.split('-'); - while (value.length < components.length) { - value.push('01'); - } - value = value.slice(0, components.length); - value = value.join('-'); - $(this).val(value); - } - // Initialize datepicker. - $(this).datepicker({ - clear: true, - autoclose: true, - format: dateFormat, - viewMode: viewmode, - minViewMode: viewmode, - }); - }); - }, - }; -})(jQuery, Drupal, once); diff --git a/modules/custom/az_publication/js/az_publication_date_picker.js b/modules/custom/az_publication/js/az_publication_date_picker.js index 47b40fcec8..2a14177900 100644 --- a/modules/custom/az_publication/js/az_publication_date_picker.js +++ b/modules/custom/az_publication/js/az_publication_date_picker.js @@ -1,34 +1,43 @@ /** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function ($, Drupal, once) { + * @file + * Default date values. + */ + +(($, Drupal, once) => { Drupal.behaviors.datetimeTweaksDefaultDate = { - attach: function attach(context) { - $(once('azpublicationdate', '.az-publication-date-picker input', context)).each(function () { - var dateFormat = $(this).data('drupal-date-format').replace('Y', 'yyyy').replace('m', 'mm').replace('d', 'dd'); - var viewmode = $(this).data('az-publication-date-mode'); - var components = dateFormat.split('-'); - var value = $(this).val(); - if (value) { - value = value.split('-'); - while (value.length < components.length) { - value.push('01'); + attach(context) { + $(once('azpublicationdate', '.az-publication-date-picker input', context)) + // eslint-disable-next-line func-names + .each(function () { + // Fetch field date settings. + const dateFormat = $(this) + .data('drupal-date-format') + .replace('Y', 'yyyy') + .replace('m', 'mm') + .replace('d', 'dd'); + // Get datepicker settings. + const viewmode = $(this).data('az-publication-date-mode'); + const components = dateFormat.split('-'); + // Modify form value to correct number of components. + let value = $(this).val(); + if (value) { + value = value.split('-'); + while (value.length < components.length) { + value.push('01'); + } + value = value.slice(0, components.length); + value = value.join('-'); + $(this).val(value); } - value = value.slice(0, components.length); - value = value.join('-'); - $(this).val(value); - } - $(this).datepicker({ - clear: true, - autoclose: true, - format: dateFormat, - viewMode: viewmode, - minViewMode: viewmode + // Initialize datepicker. + $(this).datepicker({ + clear: true, + autoclose: true, + format: dateFormat, + viewMode: viewmode, + minViewMode: viewmode, + }); }); - }); - } + }, }; -})(jQuery, Drupal, once); \ No newline at end of file +})(jQuery, Drupal, once); diff --git a/modules/custom/az_select_menu/js/az-select-menu.es6.js b/modules/custom/az_select_menu/js/az-select-menu.es6.js deleted file mode 100644 index b866de0607..0000000000 --- a/modules/custom/az_select_menu/js/az-select-menu.es6.js +++ /dev/null @@ -1,128 +0,0 @@ -(($, Drupal, window, document, once) => { - Drupal.azSelectMenu = Drupal.azSelectMenu || {}; - - /** - * Attaches behavior for select menu. - */ - Drupal.behaviors.azSelectMenu = { - attach(context, settings) { - // az_select_menu form id's are added in an array depending - // on the page you are on, and how many select menus are on the page. - Object.keys(settings.azSelectMenu.ids).forEach(function (property) { - if (settings.azSelectMenu.ids.hasOwnProperty(property)) { - const selectFormId = settings.azSelectMenu.ids[property]; - const selectForm = document.querySelector(`#${selectFormId}`); - once('azSelectMenu', selectForm, context).forEach((element) => { - $(element).popover(); - element.addEventListener('focus', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - element.addEventListener('change', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - element.addEventListener('mouseenter', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - const button = element.querySelector('button'); - button.addEventListener('click', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('touchstart', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('mouseenter', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('mouseleave', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('focus', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('blur', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - document.addEventListener('touchstart', (event) => { - Drupal.azSelectMenu.handleEvents(event); - }); - element.classList.add('processed'); - }); - } - }); - }, - }; - - /** - * Select menu event handler. - * - * Handles mouse and click events for the select menu - * elements. - * @param {object} event The javascript event object. - */ - - Drupal.azSelectMenu.handleEvents = (event) => { - // Hide the popover when user touches any part of the screen, except the - // select form button regardless of state. - if (event.type === 'touchstart') { - if (event.target.classList.contains('js_select_menu_button')) { - event.stopPropagation(); - } else { - $('.az-select-menu').popover('hide'); - return; - } - } - - const selectForm = event.target.closest('form'); - const $selectForm = $(selectForm); - const selectElement = selectForm.querySelector('select'); - const [optionsSelected] = selectElement.selectedOptions; - const selectElementHref = optionsSelected.dataset.href; - const button = selectForm.querySelector('button'); - - // If a navigable link is selected in the dropdown. - if (selectElementHref !== '') { - $selectForm.popover('hide'); - button.classList.remove('disabled'); - button.setAttribute('aria-disabled', 'false'); - switch (event.type) { - case 'click': - // If the link works, don't allow the button to focus. - event.stopImmediatePropagation(); - window.location = selectElementHref; - break; - default: - break; - } - } - - // Don't follow link if using the nolink setting. - else { - button.classList.add('disabled'); - button.setAttribute('aria-disabled', 'true'); - selectElement.setAttribute('aria-disabled', 'true'); - switch (event.type) { - case 'click': - if (event.target.classList.contains('js_select_menu_button')) { - $selectForm.popover('show'); - selectElement.focus(); - } - break; - - case 'focus': - case 'mouseenter': - if (event.target.classList.contains('js_select_menu_button')) { - $selectForm.popover('show'); - } else { - $selectForm.popover('hide'); - } - break; - - case 'mouseleave': - $selectForm.popover('hide'); - break; - default: - break; - } - } - }; -})(jQuery, Drupal, this, this.document, once); diff --git a/modules/custom/az_select_menu/js/az-select-menu.js b/modules/custom/az_select_menu/js/az-select-menu.js index bb7c4f948c..50da582b51 100644 --- a/modules/custom/az_select_menu/js/az-select-menu.js +++ b/modules/custom/az_select_menu/js/az-select-menu.js @@ -1,115 +1,129 @@ -/** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } -function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } -function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } -function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } -function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } -function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } -(function ($, Drupal, window, document, once) { +((Drupal, window, document, once) => { Drupal.azSelectMenu = Drupal.azSelectMenu || {}; + + /** + * Attaches behavior for select menu. + */ Drupal.behaviors.azSelectMenu = { - attach: function attach(context, settings) { - Object.keys(settings.azSelectMenu.ids).forEach(function (property) { + attach(context, settings) { + // az_select_menu form id's are added in an array depending + // on the page you are on, and how many select menus are on the page. + Object.keys(settings.azSelectMenu.ids).forEach((property) => { if (settings.azSelectMenu.ids.hasOwnProperty(property)) { - var selectFormId = settings.azSelectMenu.ids[property]; - var selectForm = document.querySelector("#".concat(selectFormId)); - once('azSelectMenu', selectForm, context).forEach(function (element) { - $(element).popover(); - element.addEventListener('focus', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - element.addEventListener('change', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - element.addEventListener('mouseenter', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - var button = element.querySelector('button'); - button.addEventListener('click', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('touchstart', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('mouseenter', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('mouseleave', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('focus', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - button.addEventListener('blur', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); - document.addEventListener('touchstart', function (event) { - Drupal.azSelectMenu.handleEvents(event); - }); + const selectFormId = settings.azSelectMenu.ids[property]; + const selectForm = document.querySelector(`#${selectFormId}`); + once('azSelectMenu', selectForm, context).forEach((element) => { + // Add event listeners using the handler function directly + const { handleEvents } = Drupal.azSelectMenu; + element.addEventListener('focus', handleEvents); + element.addEventListener('change', handleEvents); + element.addEventListener('mouseenter', handleEvents); + + const button = element.querySelector('button'); + button.addEventListener('click', handleEvents); + button.addEventListener('touchstart', handleEvents); + button.addEventListener('mouseenter', handleEvents); + button.addEventListener('mouseleave', handleEvents); + button.addEventListener('focus', handleEvents); + button.addEventListener('blur', handleEvents); + document.addEventListener('touchstart', handleEvents); element.classList.add('processed'); }); } }); - } + }, }; - Drupal.azSelectMenu.handleEvents = function (event) { + + /** + * Select menu event handler. + * + * Handles mouse and click events for the select menu + * elements. + * @param {object} event The javascript event object. + */ + + Drupal.azSelectMenu.handleEvents = (event) => { + // Hide the popover when user touches any part of the screen, except the + // select form button regardless of state. if (event.type === 'touchstart') { if (event.target.classList.contains('js_select_menu_button')) { - event.stopPropagation(); + // Don't stop propagation - let it fall through to main logic + // This will handle disabled state and popover display for touch events } else { - $('.az-select-menu').popover('hide'); + // Hide all popovers + document.querySelectorAll('.az-select-menu').forEach((form) => { + const popoverInstance = + window.arizonaBootstrap?.Popover?.getInstance(form); + if (popoverInstance) popoverInstance.hide(); + }); return; } } - var selectForm = event.target.closest('form'); - var $selectForm = $(selectForm); - var selectElement = selectForm.querySelector('select'); - var _selectElement$select = _slicedToArray(selectElement.selectedOptions, 1), - optionsSelected = _selectElement$select[0]; - var selectElementHref = optionsSelected.dataset.href; - var button = selectForm.querySelector('button'); + + const selectForm = event.target.closest('form'); + const selectElement = selectForm.querySelector('select'); + const [optionsSelected] = selectElement.selectedOptions; + const selectElementHref = optionsSelected.dataset.href; + const button = selectForm.querySelector('button'); + let popoverInstance = + window.arizonaBootstrap?.Popover?.getInstance(selectForm); + + // If a navigable link is selected in the dropdown. if (selectElementHref !== '') { - $selectForm.popover('hide'); + // Destroy popover when button is enabled + if (popoverInstance) { + popoverInstance.dispose(); + } button.classList.remove('disabled'); button.setAttribute('aria-disabled', 'false'); switch (event.type) { case 'click': + // If the link works, don't allow the button to focus. event.stopImmediatePropagation(); window.location = selectElementHref; break; default: break; } - } else { + } + + // Don't follow link if using the nolink setting. + else { button.classList.add('disabled'); button.setAttribute('aria-disabled', 'true'); selectElement.setAttribute('aria-disabled', 'true'); + + // Recreate popover when button becomes disabled + if (!popoverInstance && window.arizonaBootstrap?.Popover) { + popoverInstance = window.arizonaBootstrap.Popover.getOrCreateInstance + ? window.arizonaBootstrap.Popover.getOrCreateInstance(selectForm) + : window.arizonaBootstrap.Popover.getInstance(selectForm); + } + switch (event.type) { case 'click': + case 'touchstart': if (event.target.classList.contains('js_select_menu_button')) { - $selectForm.popover('show'); + if (popoverInstance) popoverInstance.show(); selectElement.focus(); } break; + case 'focus': case 'mouseenter': if (event.target.classList.contains('js_select_menu_button')) { - $selectForm.popover('show'); - } else { - $selectForm.popover('hide'); + if (popoverInstance) popoverInstance.show(); + } else if (popoverInstance) { + popoverInstance.hide(); } break; + case 'mouseleave': - $selectForm.popover('hide'); + if (popoverInstance) popoverInstance.hide(); break; default: break; } } }; -})(jQuery, Drupal, this, this.document, once); \ No newline at end of file +})(Drupal, this, this.document, once); diff --git a/package.json b/package.json index abec16482f..8cd26ea412 100644 --- a/package.json +++ b/package.json @@ -6,47 +6,14 @@ "yarn": ">= 1.6", "node": ">= 18.0" }, - "scripts": { - "build": "yarn build:js", - "watch": "yarn watch:js", - "build:js": "cross-env BABEL_ENV=quickstart node ./scripts/js/babel-es6-build.js", - "watch:js": "cross-env BABEL_ENV=quickstart node ./scripts/js/babel-es6-watch.js" - }, "devDependencies": { - "@babel/core": "^7.0.0", - "@babel/preset-env": "^7.0.0", - "@babel/register": "^7.7.7", - "babel-plugin-add-header-comment": "^1.0.3", - "chalk": "^4.1.0", - "chokidar": "^4.0.1", - "cross-env": "^7.0.2", - "dotenv-safe": "^9.1.0", "eslint": "^8.53.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^9.1.2", "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jquery": "^1.5.1", "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-yml": "^1.8.0", - "glob": "10.5.0", - "minimist": "^1.2.8", - "mkdirp": "^3.0.1", - "prettier": "^3.0.3", - "terser": "^5.19.0" - }, - "babel": { - "env": { - "quickstart": { - "presets": [ - [ - "@babel/preset-env", - { - "modules": false - } - ] - ] - } - } + "prettier": "^3.0.3" }, "browserslist": [ "last 2 Chrome major versions", @@ -61,5 +28,6 @@ "last 1 Samsung version", "last 1 OperaMini version", "Firefox ESR" - ] + ], + "packageManager": "yarn@4.14.1" } diff --git a/scripts/js/babel-es6-build.js b/scripts/js/babel-es6-build.js deleted file mode 100644 index a1af158b12..0000000000 --- a/scripts/js/babel-es6-build.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file - * - * Provides the build:js command to compile *.es6.js files to ES5. - * - * Run build:js with --file to only parse a specific file. Using the --check - * flag build:js can be run to check if files are compiled correctly. - * @example