{"version":3,"file":"main.js","sources":["webpack:///webpack/bootstrap","webpack:///./app_lre/cartridge/client/default/js/components/clientSideValidation.js","webpack:///./app_lre/cartridge/client/default/js/components/contactUs.js","webpack:///./app_lre/cartridge/client/default/js/components/eyebrowBar.js","webpack:///./app_lre/cartridge/client/default/js/components/mqlPopUp.js","webpack:///./app_lre/cartridge/client/default/js/components/search.js","webpack:///./app_lre/cartridge/client/default/js/components/utmParams.js","webpack:///./app_lre/cartridge/client/default/js/main.js","webpack:///./google_cartridge/int_gtm_sfra/cartridge/client/default/js/gtm/init.js","webpack:///./google_cartridge/int_gtm_sfra/cartridge/client/default/js/gtm/polyfills.js","webpack:///./google_cartridge/int_gtm_sfra/cartridge/client/default/js/gtm/preprocessors.js","webpack:///./node_modules/bootstrap/js/src/alert.js","webpack:///./node_modules/bootstrap/js/src/carousel.js","webpack:///./node_modules/bootstrap/js/src/collapse.js","webpack:///./node_modules/bootstrap/js/src/modal.js","webpack:///./node_modules/bootstrap/js/src/scrollspy.js","webpack:///./node_modules/bootstrap/js/src/tab.js","webpack:///./node_modules/bootstrap/js/src/util.js","webpack:///./node_modules/intersection-observer/intersection-observer.js","webpack:///./node_modules/jquery/dist/jquery.js","webpack:///./node_modules/lodash/_Symbol.js","webpack:///./node_modules/lodash/_baseGetTag.js","webpack:///./node_modules/lodash/_freeGlobal.js","webpack:///./node_modules/lodash/_getRawTag.js","webpack:///./node_modules/lodash/_objectToString.js","webpack:///./node_modules/lodash/_root.js","webpack:///./node_modules/lodash/debounce.js","webpack:///./node_modules/lodash/isObject.js","webpack:///./node_modules/lodash/isObjectLike.js","webpack:///./node_modules/lodash/isSymbol.js","webpack:///./node_modules/lodash/now.js","webpack:///./node_modules/lodash/toNumber.js","webpack:///./node_modules/lozad/dist/lozad.min.js","webpack:///./node_modules/slick-carousel/slick/slick.js","webpack:///(webpack)/buildin/global.js","webpack:///(webpack)/buildin/module.js","webpack:///./plugin_wishlists/cartridges/plugin_wishlists/cartridge/client/default/js/components/miniCart.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/cart/cart.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/collapsibleItem.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/cookie.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/countrySelector.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/focus.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/footer.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/keyboardAccessibility.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/menu.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/miniCart.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/scrollAnimate.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/search.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/spinner.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/components/toolTip.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/product/base.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/thirdParty/bootstrap.js","webpack:///./storefront-reference-architecture/cartridges/app_storefront_base/cartridge/client/default/js/util.js"],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./app_lre/cartridge/client/default/js/main.js\");\n","'use strict';\n\nfunction enforcePatternValidationInclusion(ths) {\n var zipRegexPattern = '(^\\\\d{5}(-\\\\d{4})?$)|(^[abceghjklmnprstvxyABCEGHJKLMNPRSTVXY]{1}\\\\d{1}[A-Za-z]{1} *\\\\d{1}[A-Za-z]{1}\\\\d{1}$)'; // '(^\\d{5}(-\\d{4})?$)|(^[abceghjklmnprstvxyABCEGHJKLMNPRSTVXY]{1}\\d{1}[A-Za-z]{1} *\\d{1}[A-Za-z]{1}\\d{1}$';\n var countryFieldRef = $('select[name=dwfrm_registration_country]');\n var accountPostalcodeFieldRef = $('input[name=dwfrm_registration_postalCode]');\n var billingPostalcodeFieldRef = $('input[name=dwfrm_billing_addressFields_postalCode]');\n\n var countryWhiteList = ['US', 'CA']; // To be moved to site preference if any additional changes countries will be added to whitelist\n var countryValue = \"\";\n\n if (countryFieldRef.length > 0) {\n countryValue = \"\" + countryFieldRef.val();\n }\n\n if (accountPostalcodeFieldRef.length > 0) {\n if (countryWhiteList.indexOf(countryValue.toUpperCase()) > -1) {\n accountPostalcodeFieldRef.attr('pattern', zipRegexPattern);\n } else {\n accountPostalcodeFieldRef.removeAttr('pattern');\n }\n }\n if (billingPostalcodeFieldRef.length > 0) {\n countryFieldRef = $('select[name=dwfrm_billing_addressFields_country]');\n if (countryFieldRef.length > 0) {\n countryValue = \"\" + countryFieldRef.val();\n }\n if (countryWhiteList.indexOf(countryValue.toUpperCase()) > -1) {\n billingPostalcodeFieldRef.attr('pattern', zipRegexPattern);\n } else {\n billingPostalcodeFieldRef.removeAttr('pattern');\n }\n }\n}\n\n/**\n * Validate whole form. Requires `this` to be set to form object\n * @param {jQuery.event} event - Event to be canceled if form is invalid.\n * @returns {boolean} - Flag to indicate if form is valid\n */\nfunction validateForm(event) {\n var valid = true;\n enforcePatternValidationInclusion(this);\n\n var validityResult = (this.checkValidity && !this.checkValidity());\n if (validityResult) {\n // safari\n valid = false;\n if (event) {\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n }\n $(this).find('input, select').each(function () {\n if (!this.validity.valid) {\n $(this).trigger('invalid', this.validity);\n }\n });\n }\n return valid;\n}\n\n/**\n * Remove all validation. Should be called every time before revalidating form\n * @param {element} form - Form to be cleared\n * @returns {void}\n */\nfunction clearForm(form) {\n $(form).find('.form-control.is-invalid').removeClass('is-invalid');\n}\n\nmodule.exports = {\n invalid: function () {\n $('form input, form select').on('invalid', function (e) {\n e.preventDefault();\n this.setCustomValidity('');\n if (!this.validity.valid) {\n var validationMessage = this.validationMessage;\n $(this).addClass('is-invalid');\n if (this.validity.patternMismatch && $(this).data('pattern-mismatch')) {\n validationMessage = $(this).data('pattern-mismatch');\n }\n if ((this.validity.rangeOverflow || this.validity.rangeUnderflow)\n && $(this).data('range-error')) {\n validationMessage = $(this).data('range-error');\n }\n if ((this.validity.tooLong || this.validity.tooShort)\n && $(this).data('range-error')) {\n validationMessage = $(this).data('range-error');\n }\n if (this.validity.valueMissing && $(this).data('missing-error')) {\n validationMessage = $(this).data('missing-error');\n }\n // 119989\n if (this.validity.patternMismatch && $(this).data('pattern-mismatch') && (this.validity.tooLong || this.validity.tooShort) && $(this).data('range-error')) {\n validationMessage = $(this).data('pattern-mismatch');\n }\n $(this).parents('.form-group').find('.invalid-feedback')\n .text(validationMessage);\n }\n });\n },\n\n submit: function () {\n $('form').on('submit', function (e) {\n return validateForm.call(this, e);\n });\n },\n\n buttonClick: function () {\n $('form button[type=\"submit\"], form input[type=\"submit\"]').on('click', function () {\n // clear all errors when trying to submit the form\n clearForm($(this).parents('form'));\n });\n },\n /*\n * Story 29419 Unauthorized Access To Order\n * Displays an help text message when the input email box is focused or customer tries to change the email ID\n */\n onEmailChange: function () {\n $('#dwfrm_registration input[name=\"dwfrm_registration_email\"]').focus(function () {\n var message = $(this).parents('.form-group').attr('data-emailchangemsg');\n $(this).addClass('is-invalid');\n $(this).parents('.form-group').find('.invalid-feedback').html(message);\n });\n },\n\n onBlur: function () {\n $('form input, form select').on('blur', function (e) {\n // clear this specific error, then validate\n clearForm($(this).closest('.form-group'));\n return validateForm.call(this, e);\n });\n /*\n * Story 29419 Unauthorized Access To Order.\n * When customer enters email in the PI page during checkout, it is checked if a customer exists with the email given.\n * If customer exists, it will display a error message.\n * If customer doesn't exist, the flow will be continued.\n */\n $('#dwfrm_registration input[name=\"dwfrm_registration_email\"]').blur(function () {\n if ($(this).val() !== '') {\n var url = $(this).parents('.form-group').attr('data-url');\n var currentEmail = $(this).val();\n $.spinner().start();\n $.ajax({\n url: url,\n type: 'GET',\n data: { currentEmail: currentEmail },\n success: function (data) {\n if (data.error === true) {\n $('input#email').addClass('is-invalid');\n $('input[name=\"dwfrm_registration_email\"]').parents('.form-group').find('.invalid-feedback').html(data.message);\n }\n $.spinner().stop();\n },\n error: function () {\n $.spinner().stop();\n }\n });\n }\n });\n },\n\n functions: {\n validateForm: function (form, event) {\n validateForm.call($(form), event || null);\n },\n clearForm: clearForm\n }\n};\n","'use strict';\n\nfunction disableFileSubmit() {\n $('form.contactus-info-form').spinner().start();\n $('.contactus-info-submit').prop('disabled', true);\n}\nfunction enableFileSubmit() {\n $('.contactus-info-submit').prop('disabled', false);\n}\n\n$(document).ready(function () {\n var isFormSubmitted = false;\n function validDescription() {\n var description = $('.cus-description').val();\n if (description === '') {\n $('.cus-description').addClass('is-invalid');\n } else {\n $('.cus-description').removeClass('is-invalid');\n }\n }\n\n function clearFormFile() {\n $('#fileInput, #fileName, #fileData').val('');\n $('.file-name').text('No document uploaded');\n $('.invalid-uploadSize').empty();\n $(\"span.add-file\").removeClass('d-none').addClass('d-flex');\n $(\"span.delete-file\").removeClass('d-flex').addClass('d-none');\n }\n\n function clearFormErrors() {\n $('form.contactus-info-form input, form.contactus-info-form .form-control').removeClass('is-invalid');\n $('form.contactus-info-form .invalid-feedback').empty().hide();\n }\n\n $('.contactus-info-submit').click(function (e) {\n validDescription();\n });\n $('.cus-description').change(function () {\n validDescription();\n });\n\n $('#fileInput').on('change', function (e) {\n var file = e.target.files[0];\n if (file) {\n var reader = new FileReader();\n reader.onload = function (event) {\n var fileName = file.name;\n var fileData = event.target.result.split(',')[1];\n var fileSize = file.size;\n $('#fileName').val(fileName);\n $('#fileData').val(fileData);\n $('#fileSize').val(fileSize);\n $('.file-name').text(fileName);\n $('.invalid-uploadSize').empty();\n $(\"span.add-file\").removeClass('d-flex').addClass('d-none');\n $(\"span.delete-file\").removeClass('d-none').addClass('d-flex');\n };\n reader.readAsDataURL(file);\n }\n });\n\n $('.delete-file-reset').on('click', function () {\n clearFormFile();\n });\n\n $('form.contactus-info-form').submit(function (e) {\n e.preventDefault();\n disableFileSubmit();\n var fileInput = document.getElementById('fileInput');\n var form = $(this);\n var button = $('.contactus-info-submit');\n var url = form.attr('action');\n var formData = $(this).serialize();\n if (fileInput.files.length !== 0) {\n var file = fileInput.files[0];\n var fileSize = file.size / 1024 / 1024; // in MB\n if (fileSize > 4) {\n enableFileSubmit();\n $.spinner().stop();\n $('.invalid-uploadSize').html('File size exceeds 4 MB, please select a smaller file.');\n $('.invalid-uploadSize').show();\n $(file).val('');\n return false;\n }\n formData += '&fileName=' + $('#fileName').val();\n formData += '&fileData=' + $('#fileData').val();\n formData += '&fileSize=' + $('#fileValue').val();\n }\n $.ajax({\n url: url,\n type: 'post',\n dataType: 'json',\n data: formData,\n success: function (data) {\n enableFileSubmit();\n $.spinner().stop();\n if (data.success) {\n form.trigger('reset');\n $('.contactus-info-form').hide();\n $('.contact-us-message').empty().append('
' + data.msgh + '
' + data.msg + '
').show();\n $('.contactus-modal').addClass('form-submitted');\n isFormSubmitted = true;\n } else if (data.error) {\n $('#contactemail').addClass('is-invalid');\n $('#contactemail').next('.invalid-feedback').empty().append(data.msg);\n isFormSubmitted = false;\n } else {\n $('.contact-us-message').empty().append('
' + data.msg + '
').show();\n isFormSubmitted = false;\n }\n button.attr('disabled', false);\n },\n error: function (err) {\n $.spinner().stop();\n button.attr('disabled', false);\n }\n });\n return true;\n });\n\n $('.close-contactUs').on('click', function (e) {\n var isValue = false;\n if (isFormSubmitted) {\n $('#contactusModal').modal('hide');\n } else {\n $('form.contactus-info-form').find('input[type=text]:required, input[type=email]:required, select:required, textarea:required, input[type=radio]:checked').each(function () {\n if ($(this).val().trim() !== '') {\n isValue = true;\n }\n });\n if (isValue) {\n $('form.contactus-info-form').spinner().start();\n $('#contactUsconfirmationModal').modal('show');\n e.preventDefault();\n } else {\n clearFormErrors();\n $('#contactusModal').modal('hide');\n }\n }\n $('#confirmYes').click(function () {\n $('.contactus-info-form')[0].reset();\n clearFormErrors();\n clearFormFile();\n $('.contact-us-message').empty();\n $('.contactus-info-form').show();\n $('#contactUsconfirmationModal,#contactusModal').modal('hide');\n });\n $('#contactUsconfirmationModal').on('hide.bs.modal', function () {\n $('form.contactus-info-form').spinner().stop();\n });\n $('#contactusModal').on('hidden.bs.modal', function () {\n $('form.contactus-info-form').trigger('reset');\n $('.contact-us-message').empty();\n $('.contactus-info-form').show();\n isFormSubmitted = false;\n });\n });\n});\n\n","// 26357 Story - Allow Customer to Close the Eyebrow Bar on the Storefront\n// 26357 Story - Renamed file to eyebrowBar.js and changed the code accordingly\n'use strict';\n\nvar eyebrowBar = function () {\n var headerBannerStatus = window.sessionStorage.getItem('hide_header_banner');\n var browserMessageStatus = window.sessionStorage.getItem('hide_browser_message_banner');\n $('#promo-slot').on('click', function () {\n $(this).parent('.header-top-banner').remove();\n window.sessionStorage.setItem('hide_header_banner', '1');\n });\n $('#browser-message').on('click', function () {\n $(this).parent('.header-top-banner').remove();\n window.sessionStorage.setItem('hide_browser_message_banner', '1');\n });\n if (headerBannerStatus && headerBannerStatus > 0) {\n $('#promo-slot').parent('.header-top-banner').remove();\n } else {\n $('#promo-slot').parent('.header-top-banner').removeClass('d-none');\n }\n if (browserMessageStatus && browserMessageStatus > 0) {\n $('#browser-message').parent('.header-top-banner').remove();\n } else {\n $('#browser-message').parent('.header-top-banner').removeClass('d-none');\n }\n // 60324\n if ($('.header-top-banner').length !== 0) {\n $('#learnMoreModal').detach().appendTo('body');\n }\n // 60324\n};\nmodule.exports = eyebrowBar;\n","'use strict';\n// 69358\n// 69359\n// 168198\nfunction loadMqlModel() {\n $(window).on('load', function () {\n setTimeout(function () {\n $('#mqlModal').modal('show');\n }, 300);\n });\n}\n// 45260\nfunction closeMqlModel() {\n var url = $(\"#mqlClose\").data('url');\n $.ajax({\n url: url,\n type: 'get',\n dataType: 'json',\n success: function () {\n $(\"#mqlModal\").modal('hide');\n }\n });\n}\n// 38477 - mql integration work - show error message when api call fails\nfunction showError($modal, message) {\n var errorContainer = $modal.find('.form-error');\n var errorMessage = errorContainer.find('.form-error__message');\n errorContainer.show();\n errorMessage.text(message);\n}\n// 38477 - mql integration work - hide error message\nfunction hideError($modal, message) {\n var errorContainer = $modal.find('.form-error');\n var errorMessage = errorContainer.find('.form-error__message');\n errorContainer.hide();\n errorMessage.text('');\n}\n// 48846 - SFCC sends commCode cookie value whenever calling Marketo MQL\nfunction trackCodeForMql() {\n var url = $(\"#emailButton\").data('url');\n var tracking = '';\n $.ajax({\n async: false,\n url: url,\n type: 'GET',\n success: function (response) {\n tracking = response.trackingCode;\n },\n failure: function () {\n // eslint-disable-next-line\n console.log('fetching tracking code failed');\n }\n });\n return tracking;\n}\nmodule.exports = {\n formSubmit: function () {\n // $('#mqlModal').modal('show');\n loadMqlModel();\n\n $('#mqlModal').on('hidden.bs.modal', function (e) {\n closeMqlModel();\n });\n $(\"#mqlClose\").on('click', function () {\n closeMqlModel();\n });\n var mailformat = /^[\\w.%+-]+@[\\w.-]+\\.[\\w]{2,6}$/;\n // 38477 - mql integration work -Start\n var $modal = $('.mql-modal-data');\n hideError($modal);\n $modal.on('click', '#emailButton', function () {\n var jnEmail = $(\"#emailCapture\").val();\n if ($.trim(jnEmail).length === 0) {\n $(\"#emailCaptureFeedback\").text(\"Please enter your email address.\");\n $(\"#emailCapture\").addClass('is-invalid');\n } else if ($.trim(jnEmail).length !== 0 && mailformat.test(jnEmail)) {\n $(\"#emailCapture\").removeClass('is-invalid');\n var valid = true;\n var errorMessage = 'Error encountered when submitting the form. Please try again.';\n var url = $modal.data('mql-api-endpoint');\n var token = $modal.data('mql-api-token');\n var rawTrackingCode = trackCodeForMql(); // 48846 - To check commcode value and if available assign as rawTrackingCode\n var country = $modal.data('mql-country');\n var institution = $modal.data('mql-institution-code');\n var rawPrimaryProgramOfInterest = $modal.data('mql-program-of-interest');\n var data = {\n email: (jnEmail !== null) ? jnEmail : '',\n raw_tracking_comm_code: (rawTrackingCode !== null) ? rawTrackingCode : '',\n country: (country !== null) ? country : '',\n institution: (institution !== null) ? institution : '',\n raw_primary_program_of_interest: (rawPrimaryProgramOfInterest !== null) ? rawPrimaryProgramOfInterest : ''\n };\n if (typeof url === 'undefined' || typeof token === 'undefined') {\n valid = false;\n }\n if (valid) {\n $modal.find('.mqlPopUp').spinner().start();\n $.ajax({\n url: url,\n type: 'post',\n headers: {\n 'API-TOKEN': token,\n 'Content-Type': 'application/json'\n },\n dataType: 'json',\n data: JSON.stringify(data),\n success: function success(obj) {\n $modal.find('.mqlPopUp').spinner().stop();\n if (obj.status === \"200\") {\n $(\"#thankyouModal\").removeClass(\"d-none\").addClass(\"d-block\");\n $(\"#signUpModal\").removeClass(\"d-block\").addClass(\"d-none\");\n } else {\n showError($modal, errorMessage);\n }\n },\n error: function error(err) {\n $modal.find('.mqlPopUp').spinner().stop();\n showError($modal, errorMessage);\n }\n });\n } else {\n showError($modal, errorMessage);\n }\n // 38477 - mql integration work - End\n } else {\n $(\"#emailCaptureFeedback\").text(\"Please enter a valid email address.\");\n $(\"#emailCapture\").addClass('is-invalid');\n }\n });\n }\n};\n// 45260\n","'use strict';\n\nvar base = require('base/components/search');\n\nbase = typeof base === 'function' ? { baseInit: base } : { ...base };\n\nbase.initMobileHeaderSearch = function () {\n $('.show-mobile-search').on('click', function (e) {\n e.stopImmediatePropagation();\n $(this).toggleClass('active');\n if ($(this).hasClass('active')) {\n $(this).find('.mobile-menu').hide();\n } else {\n $(this).find('.mobile-menu').show();\n }\n $('.search-mobile').toggleClass('d-none');\n });\n};\n\nmodule.exports = base;\n","if (window.location) {\n var urlParams = new URLSearchParams(window.location.search);\n var params = {};\n urlParams.forEach(function (value, key) {\n if (key.includes(\"utm\")) {\n params[key] = value;\n }\n });\n var utmUrl = $(\"#utmHiddenUrl\").val();\n $.ajax({\n contentType: 'application/json',\n url: utmUrl,\n method: 'POST',\n data: JSON.stringify(params),\n dataType: 'json',\n success: function (data) {\n console.log('Success');\n },\n error: function () {\n\n }\n });\n}\n","window.jQuery = window.$ = require('jquery');\nrequire('slick-carousel');\n\nvar processInclude = require('base/util');\n// 69358\n// 69359\n// 76175\n// 165827\nvar lozad = require('lozad');\nvar observer = lozad('.lozad', {\n rootMargin: '10px 0px',\n threshold: 0.1,\n enableAutoReload: true,\n load: function (el) {\n el.src = el.getAttribute(\"data-src\");\n el.onload = function () {\n if (el.complete) {\n el.classList.add('loaded');\n el.parentElement.classList.remove('skeleton-box');\n }\n };\n }\n});\nobserver.observe();\n\n$(document).ajaxComplete(function (event, request, settings, slick) {\n observer.observe();\n});\n\n// 26274 start\nvar cache = [];\nfunction preLoadImages(imglist) {\n var argsLen = imglist.length;\n for (var i = argsLen; i--;) {\n var cacheImage = document.createElement('img');\n cacheImage.src = imglist[i];\n cache.push(cacheImage);\n }\n}\nvar imgLength = $('body').find('img').length;\nvar imgSrcs = [];\n\nif (imgLength !== 0) {\n $('body').find('img').each(function () {\n if ($(this).hasClass('lazyloaded') === true) {\n imgSrcs.push($(this).attr('src'));\n }\n });\n preLoadImages(imgSrcs);\n}\n// 26274 end\n$(document).ready(function () {\n processInclude(require('base/components/menu'));\t// 26357 Eyebrow bar - changed the path back to base cartridge\n processInclude(require('base/components/cookie'));\n processInclude(require('base/components/footer'));\n processInclude(require('plugin_wishlists/components/miniCart'));\n processInclude(require('base/components/collapsibleItem'));\n processInclude(require('base/components/countrySelector'));\n processInclude(require('base/components/toolTip'));\n processInclude(require('./components/contactUs')); // 318259\n processInclude(require('./components/search'));\n processInclude(require('./components/clientSideValidation'));\n processInclude(require('./components/eyebrowBar')); // 26357 Renamed menu.js to eyebrowBar.js\n processInclude(require('./components/mqlPopUp')); // 168198\n processInclude(require('./components/utmParams'));\n var GTM = require('gtm/gtm/init');\n GTM.init();\n\n var targetNav = $('.desktop-navigation .category-nav__sub');\n var catNav = $('.desktop-navigation .category-nav .navbar-nav .nav-item');\n var targetSubNav = catNav.eq(0).children('.navbar-nav').clone();\n var catNavLink = catNav.children('.nav-link');\n // subCatNav = catNav.children('.navbar-nav');\n catNav.eq(0).children('.nav-link').addClass('active');\n targetNav.html('');\n targetSubNav.appendTo(targetNav);\n // 146186\n targetNav.find('.navbar-nav').children('.nav-item:last-child').append('Back to Category');\n targetNav.prepend('skip to back');\n // targetNav.find('.sr-only').removeClass('sr-only');\n\n if ($('.featured-dropdown-mobile').find('.content-asset').length === 0) {\n $('.featured-dropdown-mobile').remove();\n }\n if ($('.featured-dropdown__wrapper').find('.content-asset').length === 0) {\n $('.featured-dropdown').remove();\n }\n catNavLink.on('focus mouseenter', function () {\n targetNav.html('');\n catNavLink.removeClass('active');\n $(this).next('.navbar-nav').clone().appendTo(targetNav);\n $(this).addClass('active');\n targetNav.find('.navbar-nav').children('.nav-item:last-child').append('Back to Category');\n targetNav.prepend('skip to back');\n // targetNav.find('.sr-only').removeClass('sr-only');\n });\n $(document).on('focus', '.subcat', function (e) {\n e.preventDefault();\n catNavLink.removeClass('active');\n $(this).parent('.nav-item').children('.nav-link').addClass('active');\n });\n $(document).on('focus', '.skip-to-cat', function (e) {\n e.preventDefault();\n $('a#' + $(this).next('.navbar-nav').attr('aria-label')).focus();\n });\n $(document).on('keyup click', '.subcat', function (e) {\n e.preventDefault();\n if (e.keyCode === 13) {\n targetNav.find('.navbar-nav').children('.nav-item').eq(0).children('.nav-link')\n .focus();\n }\n });\n $(document).on('keyup click', '.backcat', function (e) {\n e.preventDefault();\n if (e.keyCode === 13) {\n catNav.children('.nav-link.active').focus();\n }\n });\n $(document).on('keyup click', '.mainnav', function (e) {\n e.preventDefault();\n if (e.keyCode === 13) {\n $(this).parents('.nav-item').next('.nav-item').children('.nav-link')\n .focus();\n $('.mega-menu').css({ height: '0' });\n $('.mega-menu, .backcat').attr('tabindex', '-1');\n }\n });\n $(document).on('focus', '.skip-to-main-nav', function (e) {\n e.preventDefault();\n $(this).parent('.nav-item').prev('.nav-item').children('.nav-link')\n .focus();\n $('.skip-to-main-nav').remove();\n });\n $(document).on('focus', '.mega-menu', function () {\n $('.mega-menu').css({ height: 'auto' });\n $('.mega-menu__wrapper').css('position', 'relative');\n });\n $(document).on('focus', '.next-link', function () {\n $('.skip-to-main-nav').remove();\n $(this).parents('.nav-item').prepend('skip to main nav');\n });\n $(document).on('blur', '.mega-menu', function () {\n $('.mega-menu').css({ height: '0' });\n });\n\n // 54929\n $('.jump-to-close').on('focus', function () {\n $('.mobile-menu__close').focus();\n });\n\n $('.mobile-arrow-down').off('click').on('click', function (e) {\n e.stopImmediatePropagation();\n var thisParent = $(this).parent();\n if (thisParent[0].nodeName === 'H5') {\n $(this).parent().next('.navbar-nav').slideToggle();\n $(this).toggleClass('active');\n if ($(this).attr('aria-expanded') === 'true') {\n $(this).attr('aria-expanded', 'false');\n $(this).parent().attr('aria-expanded', 'false');\n } else {\n $(this).attr('aria-expanded', 'true');\n $(this).parent().attr('aria-expanded', 'false');\n }\n } else {\n $(this).parent().children('.navbar-nav').slideToggle();\n $(this).toggleClass('active');\n if ($(this).attr('aria-expanded') === 'true') {\n $(this).attr('aria-expanded', 'false');\n $(this).prev('.nav-link').attr('aria-expanded', 'false');\n } else {\n $(this).attr('aria-expanded', 'true');\n $(this).prev('.nav-link').attr('aria-expanded', 'false');\n }\n }\n });\n\n $('.navbar-toggler').on('click', function () {\n $('body').addClass('overflow-hidden');\n $('.navbar-toggleable-sm').addClass('active');\n $('.modal-background').show();\n $('.mobile-menu__close').focus();\n $(this).attr('aria-expanded', 'true');\n if ($('.user-mobile .user-message').attr('data-login') === 'loggedIn') {\n $('.mobile-logout').show();\n } else {\n $('.mobile-logout').hide();\n }\n });\n $('.mobile-menu__close').on('click', function () {\n $('body').removeClass('overflow-hidden');\n $('.navbar-toggleable-sm').removeClass('active in');\n $('.modal-background').hide();\n $('.navbar-toggle').attr('aria-expanded', 'false');\n $(this).attr('aria-expanded', 'false');\n });\n // 54929\n\n $('.back-to-top a').on('click', function () {\n $(\"html, body\").animate({ scrollTop: 0 }, \"slow\");\n });\n // 68814\n $('.featurecCourses li').each(function () {\n $(this).children('a').attr('title', $(this).children('a').text());\n });\n\n $('.has-mega-menu').on('click focus mouseenter', function () {\n $('.backcat').attr('tabindex', '0');\n });\n\n $('.go-to-enroll').on('click', function (e) {\n e.preventDefault();\n var thisTarget = $(this).attr('href');\n var targetOffset = $(thisTarget).offset().top;\n $(\"html, body\").animate({ scrollTop: targetOffset - 170 }, \"slow\");\n $('#howToEnroll h3').focus();\n });\n $('.pdp-tab-list a').on('click', function (e) {\n e.preventDefault();\n var thisTarget = $(this).attr('href');\n var targetOffset = $(thisTarget).offset().top;\n $(\"html, body\").animate({ scrollTop: targetOffset - 200 }, \"slow\");\n $(thisTarget).children().eq(0).focus();\n });\n if ($('body').find('.product-detail').length > 0) {\n $('body').addClass('page-pdp');\n }\n if ($('body').find('#howToEnroll').length === 0) {\n $('.go-to-enroll').remove();\n }\n\n $('.s-date label').keydown(function (e) {\n var scrollVal = true;\n if (e.which === 32 || e.which === 13) {\n $('.s-date input').prop('checked', false);\n $(this).prev('input').prop('checked', true);\n scrollVal = false;\n } else {\n scrollVal = true;\n }\n return scrollVal;\n });\n\n $(document).on('click', '.cart-box__add-tocart .add-to-cart', function () {\n var thisParentInputs = $(this).parents('.cart-box').find('.cart-box__start-date').find('input')\n .attr('name');\n if ($(this).parents('.cart-box').find('.cart-box__start-date').length > 0) {\n if ($('.cart-box__start-date input[name=\"' + thisParentInputs + '\"]:checked').length === 0) {\n $(this).parents('.cart-box').find('.cart-box__start-date').find('.alert')\n .show();\n $(this).parents('.cart-box').find('.cart-box__start-date').find('.alert')\n .focus();\n }\n }\n });\n\n $('.s-date input').on('change', function () {\n $('.cart-box__start-date').find('.alert').hide();\n });\n\n $(document).on('click', '.atc-modal-header .close', function () {\n $('body').removeClass('modal-open').css('padding-left', '');\n });\n});\n\n$(window).scroll(function () {\n if ($(window).scrollTop() > 0) {\n // $('.header-top-banner').slideUp(); Story#60324\n $('.back-to-top').fadeIn();\n } else {\n // $('.header-top-banner').slideDown(); Story#60324\n $('.back-to-top').fadeOut();\n }\n});\n// 156512\n$(window).on('load', function () {\n if (window.location.hash) {\n var hash = window.location.hash;\n if (hash === \"#rfi\") {\n var sghn = $('.st-global-header__nav').height();\n $('html, body').animate({\n scrollTop: $(hash).offset().top - sghn\n }, 150, 'swing');\n }\n }\n});\n// 37075\n$(\".btn-feedback-survey\").click(function () {\n document.getElementById('feedbacksurvey').src += '';\n});\n// 37075\nrequire('base/thirdParty/bootstrap');\nrequire('base/components/spinner');\n","/* eslint no-underscore-dangle:0,no-console:0,no-unused-vars:0 */\n/**\n * @module GTM\n *\n * Google Tag Manager data layer support for Storefront Reference Architechture (SFRA)\n *\n * Assumes jQuery available on window object as this is the current methodology of\n * SFRA. If that changes to use webpack and commonjs properly this would need refactoring to\n * include it properly.\n */\n\nrequire('./polyfills');\nrequire('intersection-observer');\n\nvar preprocessors = require('./preprocessors');\nvar $ = window.jQuery;\n\nvar GDL_MARKER = /gdl:(.*?)(\\s|-)/;\n\nfunction debounce(func, wait, immediate) {\n var timeout;\n return function () {\n var context = this;\n var args = arguments;\n var later = function () {\n timeout = null;\n if (!immediate) func.apply(context, args);\n };\n var callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) func.apply(context, args);\n };\n}\n\nfunction findGDLNode(parent, id) {\n var node = null;\n if (parent.childNodes) {\n for (var i = 0; i < parent.childNodes.length; i++) {\n var n = parent.childNodes[i];\n if (n.nodeType === 1) {\n var candidate = findGDLNode(n, id);\n if (candidate) {\n node = candidate;\n }\n } else if (n.nodeType === 8) {\n var match = n.textContent.match(GDL_MARKER);\n if (match && match[1] === id) {\n var elementSibling = n.nextElementSibling;\n if (!elementSibling) {\n elementSibling = n.nextSibling;\n var count = 0;\n while (!elementSibling || elementSibling.nodeType !== 1) {\n count++;\n elementSibling = elementSibling.nextSibling;\n\n if (count > 10) {\n break;\n }\n }\n }\n node = { id: match[1], node: n, element: elementSibling };\n }\n }\n }\n }\n return node;\n}\n\nfunction findGDLNodesR(parent, nodes) {\n if (parent.childNodes) {\n for (var i = 0; i < parent.childNodes.length; i++) {\n var n = parent.childNodes[i];\n if (n.nodeType === 1) {\n findGDLNodesR(n, nodes);\n } else if (n.nodeType === 8) {\n var match = n.textContent.match(GDL_MARKER);\n if (match) {\n var elementSibling = n.nextElementSibling;\n nodes.push({ ID: match[1], node: n, element: elementSibling });\n }\n }\n }\n }\n}\n\n/**\n * Find Datalayer Comment Nodes and related information\n *\n * @arg {Element} parent parent node to begin search\n * @returns {Array} array of node information\n */\nfunction findGDLNodes(parent) {\n var nodes = [];\n\n findGDLNodesR(parent, nodes);\n return nodes;\n}\n\nfunction processDataLayer(dataLayer) {\n window.dataLayer = window.dataLayer || [];\n for (var i = 0; i < dataLayer.length; i++) {\n window.dataLayer.push(dataLayer[i]);\n }\n}\n\nfunction processGlobalData(globalData) {\n // shallow merge incoming global data\n if (globalData) {\n for (var attr in globalData) { //eslint-disable-line\n if (Object.prototype.hasOwnProperty.call(globalData, attr)) {\n window._gtmGlobalData[attr] = globalData[attr];\n }\n }\n }\n}\n\nfunction enqueueDataLayerUpdate(dataLayer, globalData) {\n setTimeout(function () {\n processDataLayer(dataLayer);\n processGlobalData(globalData);\n }, 0);\n}\n\nfunction GTMPageContext() {\n var i;\n var This = this;\n window._gdl = window._gdl || []; // eslint-disable-line\n var existingDataLayer = window._gdl;\n\n this.dataLayer = [];\n this.nodes = [];\n this.nodesByID = {};\n this.dataLayerByID = {};\n this.reportedImpressions = [];\n this.observedImpressions = [];\n\n window._gdl = this.dataLayer;\n\n this.io = new IntersectionObserver(this.observer.bind(this), {\n threshold: 0.5\n });\n this.io.POLL_INTERVAL = 1000;\n\n var originalPush = this.dataLayer.push;\n this.dataLayer.push = function () {\n for (var j = 0; j < arguments.length; j++) {\n var item = arguments[j];\n var node = findGDLNode(document, item.ID);\n This.addInlineDataLayer(item, node);\n }\n originalPush.apply(This.dataLayer, arguments);\n };\n\n for (i = 0; i < existingDataLayer.length; i++) {\n var dl = existingDataLayer[i];\n this.dataLayer.push(dl);\n }\n\n GTMPageContext.prototype.impressionReporterDebounced = debounce.call(this, function () {\n this.impressionReporter();\n }, 1000);\n}\n\nGTMPageContext.prototype.observer = function (entries, io) {\n for (var i = 0; i < entries.length; i++) {\n var entry = entries[i];\n if (entry.intersectionRatio <= 0) {\n continue; // eslint-disable-line\n }\n io.unobserve(entry.target);\n\n if (this.reportedImpressions.indexOf(entry.target) === -1 &&\n this.observedImpressions.indexOf(entry.target) === -1) {\n this.observedImpressions.push(entry.target);\n }\n }\n\n this.impressionReporterDebounced();\n};\n\nGTMPageContext.prototype.impressionReporter = function () {\n if (this.observedImpressions.length === 0) {\n return;\n }\n\n var _dataLayer = {\n ecommerce: {}\n };\n\n _dataLayer.event = \"impressions\";\n\n var impressions = [];\n for (var i = 0; i < this.observedImpressions.length; i++) {\n var el = this.observedImpressions[i];\n var dataLayer = this.dataLayerByID[el._gtmDataLayerID];\n if (dataLayer) {\n impressions.push(dataLayer.d);\n }\n }\n\n Array.prototype.push.apply(this.reportedImpressions, this.observedImpressions);\n\n this.observedImpressions = [];\n _dataLayer.ecommerce.impressions = impressions;\n\n window.dataLayer.push(_dataLayer);\n};\n\nGTMPageContext.prototype.addInlineDataLayer = function (item, node) {\n var This = this;\n if (node) {\n if (item.e === 'impressions') {\n item.d = preprocessors.preprocessImpression(item.d, node.element);\n this.io.observe(node.element);\n\n $(node.element).on('click', 'a', function (e) {\n This.impressionReporter();\n var list = item.d.list;\n window.dataLayer.push({\n event: 'productClick',\n ecommerce: {\n click: {\n actionField: {\n list: list\n },\n products: [item.d]\n }\n }\n });\n });\n }\n\n this.nodes.push(node);\n this.nodesByID[item.ID] = node;\n node.element._gtmDataLayerID = item.ID;\n this.dataLayerByID[item.ID] = item;\n }\n};\n\n/**\n * Initialize SFRA GTM Datalayer routines\n *\n * This should only be called once per page load.\n */\nexports.init = function () {\n // Find data layer \"nodes\" rendered prior to initialization\n window.gtmPageContext = new GTMPageContext();\n\n // Ensure post requests contain contextual gtm data\n // TODO: support json (not a requirement at this time)\n $.ajaxPrefilter(function (options, originalOptions, jqXHR) {\n if (options.contentType && options.contentType.indexOf('www-form-urlencoded') !== -1 &&\n options.method === 'POST' && window._gtmGlobalData &&\n options.data && options.data.indexOf('_gtmGlobalData') === -1) {\n options.data = options.data + \"&_gtmGlobalData=\" + JSON.stringify(window._gtmGlobalData);\n }\n });\n\n // Listen for datalayer and contextual updates in json responses\n $(document).ajaxComplete(function (event, xhr, settings) {\n if (xhr.readyState === 4) {\n if (xhr.status === 200) {\n var contentType = xhr.getResponseHeader('content-type');\n if (contentType && contentType.indexOf('json')) {\n try {\n var rawResponse = xhr.responseText;\n var resp = JSON.parse(rawResponse); //eslint-disable-line\n if (resp.GTMDataLayer || resp.GTMGlobalData) {\n enqueueDataLayerUpdate(resp.GTMDataLayer, resp.GTMGlobalData);\n }\n\n } catch (e) { //eslint-disable-line\n }\n }\n }\n }\n });\n};\n","if (!(\"nextElementSibling\" in document.documentElement)) {\n Object.defineProperty(Element.prototype, \"nextElementSibling\", {\n get: function () {\n var e = this.nextSibling;\n while (e && e.nodeType !== 1) {\n e = e.nextSibling;\n }\n return e;\n }\n });\n}\n","/* eslint no-underscore-dangle:0 */\nvar $ = window.jQuery;\n\nexports.preprocessImpression = function (impression, element) {\n var $el = $(element);\n\n var listID = $el.closest('[data-gtmcurrentlist]').attr('data-gtmcurrentlist');\n var categoryPath = $el.closest('[data-gtmcurrentcategorypath]').attr('data-gtmcurrentcategorypath');\n\n if (!listID && window._gtmGlobalData && window._gtmGlobalData.GTMCurrentList) {\n listID = window._gtmGlobalData.GTMCurrentList;\n }\n\n if (!categoryPath && window._gtmGlobalData && window._gtmGlobalData.GTMCurrentCategoryPath) {\n categoryPath = window._gtmGlobalData.GTMCurrentCategoryPath;\n }\n\n if (categoryPath) {\n impression.category = categoryPath;\n }\n\n var position = $el.closest('[data-gtmcurrentposition]').attr('data-gtmcurrentposition');\n if (position) {\n impression.position = parseInt(position, 10);\n }\n\n if (listID) {\n impression.list = listID;\n }\n return impression;\n};\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'alert'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Selector = {\n DISMISS : '[data-dismiss=\"alert\"]'\n}\n\nconst Event = {\n CLOSE : `close${EVENT_KEY}`,\n CLOSED : `closed${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n ALERT : 'alert',\n FADE : 'fade',\n SHOW : 'show'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Alert {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n close(element) {\n let rootElement = this._element\n if (element) {\n rootElement = this._getRootElement(element)\n }\n\n const customEvent = this._triggerCloseEvent(rootElement)\n\n if (customEvent.isDefaultPrevented()) {\n return\n }\n\n this._removeElement(rootElement)\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Private\n\n _getRootElement(element) {\n const selector = Util.getSelectorFromElement(element)\n let parent = false\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n if (!parent) {\n parent = $(element).closest(`.${ClassName.ALERT}`)[0]\n }\n\n return parent\n }\n\n _triggerCloseEvent(element) {\n const closeEvent = $.Event(Event.CLOSE)\n\n $(element).trigger(closeEvent)\n return closeEvent\n }\n\n _removeElement(element) {\n $(element).removeClass(ClassName.SHOW)\n\n if (!$(element).hasClass(ClassName.FADE)) {\n this._destroyElement(element)\n return\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(element)\n\n $(element)\n .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event))\n .emulateTransitionEnd(transitionDuration)\n }\n\n _destroyElement(element) {\n $(element)\n .detach()\n .trigger(Event.CLOSED)\n .remove()\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Alert(this)\n $element.data(DATA_KEY, data)\n }\n\n if (config === 'close') {\n data[config](this)\n }\n })\n }\n\n static _handleDismiss(alertInstance) {\n return function (event) {\n if (event) {\n event.preventDefault()\n }\n\n alertInstance.close(this)\n }\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(\n Event.CLICK_DATA_API,\n Selector.DISMISS,\n Alert._handleDismiss(new Alert())\n)\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Alert._jQueryInterface\n$.fn[NAME].Constructor = Alert\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Alert._jQueryInterface\n}\n\nexport default Alert\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'carousel'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.carousel'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key\nconst ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key\nconst TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\nconst SWIPE_THRESHOLD = 40\n\nconst Default = {\n interval : 5000,\n keyboard : true,\n slide : false,\n pause : 'hover',\n wrap : true,\n touch : true\n}\n\nconst DefaultType = {\n interval : '(number|boolean)',\n keyboard : 'boolean',\n slide : '(boolean|string)',\n pause : '(string|boolean)',\n wrap : 'boolean',\n touch : 'boolean'\n}\n\nconst Direction = {\n NEXT : 'next',\n PREV : 'prev',\n LEFT : 'left',\n RIGHT : 'right'\n}\n\nconst Event = {\n SLIDE : `slide${EVENT_KEY}`,\n SLID : `slid${EVENT_KEY}`,\n KEYDOWN : `keydown${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`,\n TOUCHSTART : `touchstart${EVENT_KEY}`,\n TOUCHMOVE : `touchmove${EVENT_KEY}`,\n TOUCHEND : `touchend${EVENT_KEY}`,\n POINTERDOWN : `pointerdown${EVENT_KEY}`,\n POINTERUP : `pointerup${EVENT_KEY}`,\n DRAG_START : `dragstart${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n CAROUSEL : 'carousel',\n ACTIVE : 'active',\n SLIDE : 'slide',\n RIGHT : 'carousel-item-right',\n LEFT : 'carousel-item-left',\n NEXT : 'carousel-item-next',\n PREV : 'carousel-item-prev',\n ITEM : 'carousel-item',\n POINTER_EVENT : 'pointer-event'\n}\n\nconst Selector = {\n ACTIVE : '.active',\n ACTIVE_ITEM : '.active.carousel-item',\n ITEM : '.carousel-item',\n ITEM_IMG : '.carousel-item img',\n NEXT_PREV : '.carousel-item-next, .carousel-item-prev',\n INDICATORS : '.carousel-indicators',\n DATA_SLIDE : '[data-slide], [data-slide-to]',\n DATA_RIDE : '[data-ride=\"carousel\"]'\n}\n\nconst PointerType = {\n TOUCH : 'touch',\n PEN : 'pen'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\nclass Carousel {\n constructor(element, config) {\n this._items = null\n this._interval = null\n this._activeElement = null\n this._isPaused = false\n this._isSliding = false\n this.touchTimeout = null\n this.touchStartX = 0\n this.touchDeltaX = 0\n\n this._config = this._getConfig(config)\n this._element = element\n this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)\n this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0\n this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent)\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n next() {\n if (!this._isSliding) {\n this._slide(Direction.NEXT)\n }\n }\n\n nextWhenVisible() {\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden &&\n ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) {\n this.next()\n }\n }\n\n prev() {\n if (!this._isSliding) {\n this._slide(Direction.PREV)\n }\n }\n\n pause(event) {\n if (!event) {\n this._isPaused = true\n }\n\n if (this._element.querySelector(Selector.NEXT_PREV)) {\n Util.triggerTransitionEnd(this._element)\n this.cycle(true)\n }\n\n clearInterval(this._interval)\n this._interval = null\n }\n\n cycle(event) {\n if (!event) {\n this._isPaused = false\n }\n\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n\n if (this._config.interval && !this._isPaused) {\n this._interval = setInterval(\n (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),\n this._config.interval\n )\n }\n }\n\n to(index) {\n this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n\n const activeIndex = this._getItemIndex(this._activeElement)\n\n if (index > this._items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n $(this._element).one(Event.SLID, () => this.to(index))\n return\n }\n\n if (activeIndex === index) {\n this.pause()\n this.cycle()\n return\n }\n\n const direction = index > activeIndex\n ? Direction.NEXT\n : Direction.PREV\n\n this._slide(direction, this._items[index])\n }\n\n dispose() {\n $(this._element).off(EVENT_KEY)\n $.removeData(this._element, DATA_KEY)\n\n this._items = null\n this._config = null\n this._element = null\n this._interval = null\n this._isPaused = null\n this._isSliding = null\n this._activeElement = null\n this._indicatorsElement = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _handleSwipe() {\n const absDeltax = Math.abs(this.touchDeltaX)\n\n if (absDeltax <= SWIPE_THRESHOLD) {\n return\n }\n\n const direction = absDeltax / this.touchDeltaX\n\n // swipe left\n if (direction > 0) {\n this.prev()\n }\n\n // swipe right\n if (direction < 0) {\n this.next()\n }\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n $(this._element)\n .on(Event.KEYDOWN, (event) => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n $(this._element)\n .on(Event.MOUSEENTER, (event) => this.pause(event))\n .on(Event.MOUSELEAVE, (event) => this.cycle(event))\n }\n\n if (this._config.touch) {\n this._addTouchEventListeners()\n }\n }\n\n _addTouchEventListeners() {\n if (!this._touchSupported) {\n return\n }\n\n const start = (event) => {\n if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n this.touchStartX = event.originalEvent.clientX\n } else if (!this._pointerEvent) {\n this.touchStartX = event.originalEvent.touches[0].clientX\n }\n }\n\n const move = (event) => {\n // ensure swiping with one touch and not pinching\n if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {\n this.touchDeltaX = 0\n } else {\n this.touchDeltaX = event.originalEvent.touches[0].clientX - this.touchStartX\n }\n }\n\n const end = (event) => {\n if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n this.touchDeltaX = event.originalEvent.clientX - this.touchStartX\n }\n\n this._handleSwipe()\n if (this._config.pause === 'hover') {\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n }\n }\n\n $(this._element.querySelectorAll(Selector.ITEM_IMG)).on(Event.DRAG_START, (e) => e.preventDefault())\n if (this._pointerEvent) {\n $(this._element).on(Event.POINTERDOWN, (event) => start(event))\n $(this._element).on(Event.POINTERUP, (event) => end(event))\n\n this._element.classList.add(ClassName.POINTER_EVENT)\n } else {\n $(this._element).on(Event.TOUCHSTART, (event) => start(event))\n $(this._element).on(Event.TOUCHMOVE, (event) => move(event))\n $(this._element).on(Event.TOUCHEND, (event) => end(event))\n }\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n switch (event.which) {\n case ARROW_LEFT_KEYCODE:\n event.preventDefault()\n this.prev()\n break\n case ARROW_RIGHT_KEYCODE:\n event.preventDefault()\n this.next()\n break\n default:\n }\n }\n\n _getItemIndex(element) {\n this._items = element && element.parentNode\n ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM))\n : []\n return this._items.indexOf(element)\n }\n\n _getItemByDirection(direction, activeElement) {\n const isNextDirection = direction === Direction.NEXT\n const isPrevDirection = direction === Direction.PREV\n const activeIndex = this._getItemIndex(activeElement)\n const lastItemIndex = this._items.length - 1\n const isGoingToWrap = isPrevDirection && activeIndex === 0 ||\n isNextDirection && activeIndex === lastItemIndex\n\n if (isGoingToWrap && !this._config.wrap) {\n return activeElement\n }\n\n const delta = direction === Direction.PREV ? -1 : 1\n const itemIndex = (activeIndex + delta) % this._items.length\n\n return itemIndex === -1\n ? this._items[this._items.length - 1] : this._items[itemIndex]\n }\n\n _triggerSlideEvent(relatedTarget, eventDirectionName) {\n const targetIndex = this._getItemIndex(relatedTarget)\n const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM))\n const slideEvent = $.Event(Event.SLIDE, {\n relatedTarget,\n direction: eventDirectionName,\n from: fromIndex,\n to: targetIndex\n })\n\n $(this._element).trigger(slideEvent)\n\n return slideEvent\n }\n\n _setActiveIndicatorElement(element) {\n if (this._indicatorsElement) {\n const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE))\n $(indicators)\n .removeClass(ClassName.ACTIVE)\n\n const nextIndicator = this._indicatorsElement.children[\n this._getItemIndex(element)\n ]\n\n if (nextIndicator) {\n $(nextIndicator).addClass(ClassName.ACTIVE)\n }\n }\n }\n\n _slide(direction, element) {\n const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n const activeElementIndex = this._getItemIndex(activeElement)\n const nextElement = element || activeElement &&\n this._getItemByDirection(direction, activeElement)\n const nextElementIndex = this._getItemIndex(nextElement)\n const isCycling = Boolean(this._interval)\n\n let directionalClassName\n let orderClassName\n let eventDirectionName\n\n if (direction === Direction.NEXT) {\n directionalClassName = ClassName.LEFT\n orderClassName = ClassName.NEXT\n eventDirectionName = Direction.LEFT\n } else {\n directionalClassName = ClassName.RIGHT\n orderClassName = ClassName.PREV\n eventDirectionName = Direction.RIGHT\n }\n\n if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n this._isSliding = false\n return\n }\n\n const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)\n if (slideEvent.isDefaultPrevented()) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n return\n }\n\n this._isSliding = true\n\n if (isCycling) {\n this.pause()\n }\n\n this._setActiveIndicatorElement(nextElement)\n\n const slidEvent = $.Event(Event.SLID, {\n relatedTarget: nextElement,\n direction: eventDirectionName,\n from: activeElementIndex,\n to: nextElementIndex\n })\n\n if ($(this._element).hasClass(ClassName.SLIDE)) {\n $(nextElement).addClass(orderClassName)\n\n Util.reflow(nextElement)\n\n $(activeElement).addClass(directionalClassName)\n $(nextElement).addClass(directionalClassName)\n\n const nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10)\n if (nextElementInterval) {\n this._config.defaultInterval = this._config.defaultInterval || this._config.interval\n this._config.interval = nextElementInterval\n } else {\n this._config.interval = this._config.defaultInterval || this._config.interval\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(activeElement)\n\n $(activeElement)\n .one(Util.TRANSITION_END, () => {\n $(nextElement)\n .removeClass(`${directionalClassName} ${orderClassName}`)\n .addClass(ClassName.ACTIVE)\n\n $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`)\n\n this._isSliding = false\n\n setTimeout(() => $(this._element).trigger(slidEvent), 0)\n })\n .emulateTransitionEnd(transitionDuration)\n } else {\n $(activeElement).removeClass(ClassName.ACTIVE)\n $(nextElement).addClass(ClassName.ACTIVE)\n\n this._isSliding = false\n $(this._element).trigger(slidEvent)\n }\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n let _config = {\n ...Default,\n ...$(this).data()\n }\n\n if (typeof config === 'object') {\n _config = {\n ..._config,\n ...config\n }\n }\n\n const action = typeof config === 'string' ? config : _config.slide\n\n if (!data) {\n data = new Carousel(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'number') {\n data.to(config)\n } else if (typeof action === 'string') {\n if (typeof data[action] === 'undefined') {\n throw new TypeError(`No method named \"${action}\"`)\n }\n data[action]()\n } else if (_config.interval && _config.ride) {\n data.pause()\n data.cycle()\n }\n })\n }\n\n static _dataApiClickHandler(event) {\n const selector = Util.getSelectorFromElement(this)\n\n if (!selector) {\n return\n }\n\n const target = $(selector)[0]\n\n if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n return\n }\n\n const config = {\n ...$(target).data(),\n ...$(this).data()\n }\n const slideIndex = this.getAttribute('data-slide-to')\n\n if (slideIndex) {\n config.interval = false\n }\n\n Carousel._jQueryInterface.call($(target), config)\n\n if (slideIndex) {\n $(target).data(DATA_KEY).to(slideIndex)\n }\n\n event.preventDefault()\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)\n\n$(window).on(Event.LOAD_DATA_API, () => {\n const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE))\n for (let i = 0, len = carousels.length; i < len; i++) {\n const $carousel = $(carousels[i])\n Carousel._jQueryInterface.call($carousel, $carousel.data())\n }\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Carousel._jQueryInterface\n$.fn[NAME].Constructor = Carousel\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Carousel._jQueryInterface\n}\n\nexport default Carousel\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'collapse'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.collapse'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Default = {\n toggle : true,\n parent : ''\n}\n\nconst DefaultType = {\n toggle : 'boolean',\n parent : '(string|element)'\n}\n\nconst Event = {\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n SHOW : 'show',\n COLLAPSE : 'collapse',\n COLLAPSING : 'collapsing',\n COLLAPSED : 'collapsed'\n}\n\nconst Dimension = {\n WIDTH : 'width',\n HEIGHT : 'height'\n}\n\nconst Selector = {\n ACTIVES : '.show, .collapsing',\n DATA_TOGGLE : '[data-toggle=\"collapse\"]'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Collapse {\n constructor(element, config) {\n this._isTransitioning = false\n this._element = element\n this._config = this._getConfig(config)\n this._triggerArray = [].slice.call(document.querySelectorAll(\n `[data-toggle=\"collapse\"][href=\"#${element.id}\"],` +\n `[data-toggle=\"collapse\"][data-target=\"#${element.id}\"]`\n ))\n\n const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggleList.length; i < len; i++) {\n const elem = toggleList[i]\n const selector = Util.getSelectorFromElement(elem)\n const filterElement = [].slice.call(document.querySelectorAll(selector))\n .filter((foundElem) => foundElem === element)\n\n if (selector !== null && filterElement.length > 0) {\n this._selector = selector\n this._triggerArray.push(elem)\n }\n }\n\n this._parent = this._config.parent ? this._getParent() : null\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._element, this._triggerArray)\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle() {\n if ($(this._element).hasClass(ClassName.SHOW)) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning ||\n $(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n let actives\n let activesData\n\n if (this._parent) {\n actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))\n .filter((elem) => {\n if (typeof this._config.parent === 'string') {\n return elem.getAttribute('data-parent') === this._config.parent\n }\n\n return elem.classList.contains(ClassName.COLLAPSE)\n })\n\n if (actives.length === 0) {\n actives = null\n }\n }\n\n if (actives) {\n activesData = $(actives).not(this._selector).data(DATA_KEY)\n if (activesData && activesData._isTransitioning) {\n return\n }\n }\n\n const startEvent = $.Event(Event.SHOW)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n if (actives) {\n Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')\n if (!activesData) {\n $(actives).data(DATA_KEY, null)\n }\n }\n\n const dimension = this._getDimension()\n\n $(this._element)\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n\n this._element.style[dimension] = 0\n\n if (this._triggerArray.length) {\n $(this._triggerArray)\n .removeClass(ClassName.COLLAPSED)\n .attr('aria-expanded', true)\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .addClass(ClassName.SHOW)\n\n this._element.style[dimension] = ''\n\n this.setTransitioning(false)\n\n $(this._element).trigger(Event.SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning ||\n !$(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n const startEvent = $.Event(Event.HIDE)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n Util.reflow(this._element)\n\n $(this._element)\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW)\n\n const triggerArrayLength = this._triggerArray.length\n if (triggerArrayLength > 0) {\n for (let i = 0; i < triggerArrayLength; i++) {\n const trigger = this._triggerArray[i]\n const selector = Util.getSelectorFromElement(trigger)\n\n if (selector !== null) {\n const $elem = $([].slice.call(document.querySelectorAll(selector)))\n if (!$elem.hasClass(ClassName.SHOW)) {\n $(trigger).addClass(ClassName.COLLAPSED)\n .attr('aria-expanded', false)\n }\n }\n }\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n this.setTransitioning(false)\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .trigger(Event.HIDDEN)\n }\n\n this._element.style[dimension] = ''\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n }\n\n setTransitioning(isTransitioning) {\n this._isTransitioning = isTransitioning\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._parent = null\n this._element = null\n this._triggerArray = null\n this._isTransitioning = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n config.toggle = Boolean(config.toggle) // Coerce string values\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _getDimension() {\n const hasWidth = $(this._element).hasClass(Dimension.WIDTH)\n return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT\n }\n\n _getParent() {\n let parent\n\n if (Util.isElement(this._config.parent)) {\n parent = this._config.parent\n\n // It's a jQuery object\n if (typeof this._config.parent.jquery !== 'undefined') {\n parent = this._config.parent[0]\n }\n } else {\n parent = document.querySelector(this._config.parent)\n }\n\n const selector =\n `[data-toggle=\"collapse\"][data-parent=\"${this._config.parent}\"]`\n\n const children = [].slice.call(parent.querySelectorAll(selector))\n $(children).each((i, element) => {\n this._addAriaAndCollapsedClass(\n Collapse._getTargetFromElement(element),\n [element]\n )\n })\n\n return parent\n }\n\n _addAriaAndCollapsedClass(element, triggerArray) {\n const isOpen = $(element).hasClass(ClassName.SHOW)\n\n if (triggerArray.length) {\n $(triggerArray)\n .toggleClass(ClassName.COLLAPSED, !isOpen)\n .attr('aria-expanded', isOpen)\n }\n }\n\n // Static\n\n static _getTargetFromElement(element) {\n const selector = Util.getSelectorFromElement(element)\n return selector ? document.querySelector(selector) : null\n }\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $this = $(this)\n let data = $this.data(DATA_KEY)\n const _config = {\n ...Default,\n ...$this.data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data && _config.toggle && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n if (!data) {\n data = new Collapse(this, _config)\n $this.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.currentTarget.tagName === 'A') {\n event.preventDefault()\n }\n\n const $trigger = $(this)\n const selector = Util.getSelectorFromElement(this)\n const selectors = [].slice.call(document.querySelectorAll(selector))\n\n $(selectors).each(function () {\n const $target = $(this)\n const data = $target.data(DATA_KEY)\n const config = data ? 'toggle' : $trigger.data()\n Collapse._jQueryInterface.call($target, config)\n })\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Collapse._jQueryInterface\n$.fn[NAME].Constructor = Collapse\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Collapse._jQueryInterface\n}\n\nexport default Collapse\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'modal'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.modal'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n\nconst Default = {\n backdrop : true,\n keyboard : true,\n focus : true,\n show : true\n}\n\nconst DefaultType = {\n backdrop : '(boolean|string)',\n keyboard : 'boolean',\n focus : 'boolean',\n show : 'boolean'\n}\n\nconst Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n RESIZE : `resize${EVENT_KEY}`,\n CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,\n KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`,\n MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`,\n MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n SCROLLABLE : 'modal-dialog-scrollable',\n SCROLLBAR_MEASURER : 'modal-scrollbar-measure',\n BACKDROP : 'modal-backdrop',\n OPEN : 'modal-open',\n FADE : 'fade',\n SHOW : 'show'\n}\n\nconst Selector = {\n DIALOG : '.modal-dialog',\n MODAL_BODY : '.modal-body',\n DATA_TOGGLE : '[data-toggle=\"modal\"]',\n DATA_DISMISS : '[data-dismiss=\"modal\"]',\n FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n STICKY_CONTENT : '.sticky-top'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Modal {\n constructor(element, config) {\n this._config = this._getConfig(config)\n this._element = element\n this._dialog = element.querySelector(Selector.DIALOG)\n this._backdrop = null\n this._isShown = false\n this._isBodyOverflowing = false\n this._ignoreBackdropClick = false\n this._isTransitioning = false\n this._scrollbarWidth = 0\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isShown || this._isTransitioning) {\n return\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n this._isTransitioning = true\n }\n\n const showEvent = $.Event(Event.SHOW, {\n relatedTarget\n })\n\n $(this._element).trigger(showEvent)\n\n if (this._isShown || showEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = true\n\n this._checkScrollbar()\n this._setScrollbar()\n\n this._adjustDialog()\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(this._element).on(\n Event.CLICK_DISMISS,\n Selector.DATA_DISMISS,\n (event) => this.hide(event)\n )\n\n $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {\n $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {\n if ($(event.target).is(this._element)) {\n this._ignoreBackdropClick = true\n }\n })\n })\n\n this._showBackdrop(() => this._showElement(relatedTarget))\n }\n\n hide(event) {\n if (event) {\n event.preventDefault()\n }\n\n if (!this._isShown || this._isTransitioning) {\n return\n }\n\n const hideEvent = $.Event(Event.HIDE)\n\n $(this._element).trigger(hideEvent)\n\n if (!this._isShown || hideEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = false\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (transition) {\n this._isTransitioning = true\n }\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(document).off(Event.FOCUSIN)\n\n $(this._element).removeClass(ClassName.SHOW)\n\n $(this._element).off(Event.CLICK_DISMISS)\n $(this._dialog).off(Event.MOUSEDOWN_DISMISS)\n\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, (event) => this._hideModal(event))\n .emulateTransitionEnd(transitionDuration)\n } else {\n this._hideModal()\n }\n }\n\n dispose() {\n [window, this._element, this._dialog]\n .forEach((htmlElement) => $(htmlElement).off(EVENT_KEY))\n\n /**\n * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API`\n * Do not move `document` in `htmlElements` array\n * It will remove `Event.CLICK_DATA_API` event that should remain\n */\n $(document).off(Event.FOCUSIN)\n\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._element = null\n this._dialog = null\n this._backdrop = null\n this._isShown = null\n this._isBodyOverflowing = null\n this._ignoreBackdropClick = null\n this._isTransitioning = null\n this._scrollbarWidth = null\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _showElement(relatedTarget) {\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (!this._element.parentNode ||\n this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n // Don't move modal's DOM position\n document.body.appendChild(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.setAttribute('aria-modal', true)\n\n if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) {\n this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0\n } else {\n this._element.scrollTop = 0\n }\n\n if (transition) {\n Util.reflow(this._element)\n }\n\n $(this._element).addClass(ClassName.SHOW)\n\n if (this._config.focus) {\n this._enforceFocus()\n }\n\n const shownEvent = $.Event(Event.SHOWN, {\n relatedTarget\n })\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._element.focus()\n }\n this._isTransitioning = false\n $(this._element).trigger(shownEvent)\n }\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._dialog)\n\n $(this._dialog)\n .one(Util.TRANSITION_END, transitionComplete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n transitionComplete()\n }\n }\n\n _enforceFocus() {\n $(document)\n .off(Event.FOCUSIN) // Guard against infinite focus loop\n .on(Event.FOCUSIN, (event) => {\n if (document !== event.target &&\n this._element !== event.target &&\n $(this._element).has(event.target).length === 0) {\n this._element.focus()\n }\n })\n }\n\n _setEscapeEvent() {\n if (this._isShown && this._config.keyboard) {\n $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {\n if (event.which === ESCAPE_KEYCODE) {\n event.preventDefault()\n this.hide()\n }\n })\n } else if (!this._isShown) {\n $(this._element).off(Event.KEYDOWN_DISMISS)\n }\n }\n\n _setResizeEvent() {\n if (this._isShown) {\n $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))\n } else {\n $(window).off(Event.RESIZE)\n }\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._element.removeAttribute('aria-modal')\n this._isTransitioning = false\n this._showBackdrop(() => {\n $(document.body).removeClass(ClassName.OPEN)\n this._resetAdjustments()\n this._resetScrollbar()\n $(this._element).trigger(Event.HIDDEN)\n })\n }\n\n _removeBackdrop() {\n if (this._backdrop) {\n $(this._backdrop).remove()\n this._backdrop = null\n }\n }\n\n _showBackdrop(callback) {\n const animate = $(this._element).hasClass(ClassName.FADE)\n ? ClassName.FADE : ''\n\n if (this._isShown && this._config.backdrop) {\n this._backdrop = document.createElement('div')\n this._backdrop.className = ClassName.BACKDROP\n\n if (animate) {\n this._backdrop.classList.add(animate)\n }\n\n $(this._backdrop).appendTo(document.body)\n\n $(this._element).on(Event.CLICK_DISMISS, (event) => {\n if (this._ignoreBackdropClick) {\n this._ignoreBackdropClick = false\n return\n }\n if (event.target !== event.currentTarget) {\n return\n }\n if (this._config.backdrop === 'static') {\n this._element.focus()\n } else {\n this.hide()\n }\n })\n\n if (animate) {\n Util.reflow(this._backdrop)\n }\n\n $(this._backdrop).addClass(ClassName.SHOW)\n\n if (!callback) {\n return\n }\n\n if (!animate) {\n callback()\n return\n }\n\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callback)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else if (!this._isShown && this._backdrop) {\n $(this._backdrop).removeClass(ClassName.SHOW)\n\n const callbackRemove = () => {\n this._removeBackdrop()\n if (callback) {\n callback()\n }\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callbackRemove)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else {\n callbackRemove()\n }\n } else if (callback) {\n callback()\n }\n }\n\n // ----------------------------------------------------------------------\n // the following methods are used to handle overflowing modals\n // todo (fat): these should probably be refactored out of modal.js\n // ----------------------------------------------------------------------\n\n _adjustDialog() {\n const isModalOverflowing =\n this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!this._isBodyOverflowing && isModalOverflowing) {\n this._element.style.paddingLeft = `${this._scrollbarWidth}px`\n }\n\n if (this._isBodyOverflowing && !isModalOverflowing) {\n this._element.style.paddingRight = `${this._scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n _checkScrollbar() {\n const rect = document.body.getBoundingClientRect()\n this._isBodyOverflowing = rect.left + rect.right < window.innerWidth\n this._scrollbarWidth = this._getScrollbarWidth()\n }\n\n _setScrollbar() {\n if (this._isBodyOverflowing) {\n // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))\n\n // Adjust fixed content padding\n $(fixedContent).each((index, element) => {\n const actualPadding = element.style.paddingRight\n const calculatedPadding = $(element).css('padding-right')\n $(element)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n })\n\n // Adjust sticky content margin\n $(stickyContent).each((index, element) => {\n const actualMargin = element.style.marginRight\n const calculatedMargin = $(element).css('margin-right')\n $(element)\n .data('margin-right', actualMargin)\n .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)\n })\n\n // Adjust body padding\n const actualPadding = document.body.style.paddingRight\n const calculatedPadding = $(document.body).css('padding-right')\n $(document.body)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n }\n\n $(document.body).addClass(ClassName.OPEN)\n }\n\n _resetScrollbar() {\n // Restore fixed content padding\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n $(fixedContent).each((index, element) => {\n const padding = $(element).data('padding-right')\n $(element).removeData('padding-right')\n element.style.paddingRight = padding ? padding : ''\n })\n\n // Restore sticky content\n const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))\n $(elements).each((index, element) => {\n const margin = $(element).data('margin-right')\n if (typeof margin !== 'undefined') {\n $(element).css('margin-right', margin).removeData('margin-right')\n }\n })\n\n // Restore body padding\n const padding = $(document.body).data('padding-right')\n $(document.body).removeData('padding-right')\n document.body.style.paddingRight = padding ? padding : ''\n }\n\n _getScrollbarWidth() { // thx d.walsh\n const scrollDiv = document.createElement('div')\n scrollDiv.className = ClassName.SCROLLBAR_MEASURER\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n }\n\n // Static\n\n static _jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = {\n ...Default,\n ...$(this).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data) {\n data = new Modal(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config](relatedTarget)\n } else if (_config.show) {\n data.show(relatedTarget)\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n let target\n const selector = Util.getSelectorFromElement(this)\n\n if (selector) {\n target = document.querySelector(selector)\n }\n\n const config = $(target).data(DATA_KEY)\n ? 'toggle' : {\n ...$(target).data(),\n ...$(this).data()\n }\n\n if (this.tagName === 'A' || this.tagName === 'AREA') {\n event.preventDefault()\n }\n\n const $target = $(target).one(Event.SHOW, (showEvent) => {\n if (showEvent.isDefaultPrevented()) {\n // Only register focus restorer if modal will actually get shown\n return\n }\n\n $target.one(Event.HIDDEN, () => {\n if ($(this).is(':visible')) {\n this.focus()\n }\n })\n })\n\n Modal._jQueryInterface.call($(target), config, this)\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Modal._jQueryInterface\n$.fn[NAME].Constructor = Modal\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Modal._jQueryInterface\n}\n\nexport default Modal\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.3.1): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'scrollspy'\nconst VERSION = '4.3.1'\nconst DATA_KEY = 'bs.scrollspy'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Default = {\n offset : 10,\n method : 'auto',\n target : ''\n}\n\nconst DefaultType = {\n offset : 'number',\n method : 'string',\n target : '(string|element)'\n}\n\nconst Event = {\n ACTIVATE : `activate${EVENT_KEY}`,\n SCROLL : `scroll${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`\n}\n\nconst ClassName = {\n DROPDOWN_ITEM : 'dropdown-item',\n DROPDOWN_MENU : 'dropdown-menu',\n ACTIVE : 'active'\n}\n\nconst Selector = {\n DATA_SPY : '[data-spy=\"scroll\"]',\n ACTIVE : '.active',\n NAV_LIST_GROUP : '.nav, .list-group',\n NAV_LINKS : '.nav-link',\n NAV_ITEMS : '.nav-item',\n LIST_ITEMS : '.list-group-item',\n DROPDOWN : '.dropdown',\n DROPDOWN_ITEMS : '.dropdown-item',\n DROPDOWN_TOGGLE : '.dropdown-toggle'\n}\n\nconst OffsetMethod = {\n OFFSET : 'offset',\n POSITION : 'position'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass ScrollSpy {\n constructor(element, config) {\n this._element = element\n this._scrollElement = element.tagName === 'BODY' ? window : element\n this._config = this._getConfig(config)\n this._selector = `${this._config.target} ${Selector.NAV_LINKS},` +\n `${this._config.target} ${Selector.LIST_ITEMS},` +\n `${this._config.target} ${Selector.DROPDOWN_ITEMS}`\n this._offsets = []\n this._targets = []\n this._activeTarget = null\n this._scrollHeight = 0\n\n $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))\n\n this.refresh()\n this._process()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n refresh() {\n const autoMethod = this._scrollElement === this._scrollElement.window\n ? OffsetMethod.OFFSET : OffsetMethod.POSITION\n\n const offsetMethod = this._config.method === 'auto'\n ? autoMethod : this._config.method\n\n const offsetBase = offsetMethod === OffsetMethod.POSITION\n ? this._getScrollTop() : 0\n\n this._offsets = []\n this._targets = []\n\n this._scrollHeight = this._getScrollHeight()\n\n const targets = [].slice.call(document.querySelectorAll(this._selector))\n\n targets\n .map((element) => {\n let target\n const targetSelector = Util.getSelectorFromElement(element)\n\n if (targetSelector) {\n target = document.querySelector(targetSelector)\n }\n\n if (target) {\n const targetBCR = target.getBoundingClientRect()\n if (targetBCR.width || targetBCR.height) {\n // TODO (fat): remove sketch reliance on jQuery position/offset\n return [\n $(target)[offsetMethod]().top + offsetBase,\n targetSelector\n ]\n }\n }\n return null\n })\n .filter((item) => item)\n .sort((a, b) => a[0] - b[0])\n .forEach((item) => {\n this._offsets.push(item[0])\n this._targets.push(item[1])\n })\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._scrollElement).off(EVENT_KEY)\n\n this._element = null\n this._scrollElement = null\n this._config = null\n this._selector = null\n this._offsets = null\n this._targets = null\n this._activeTarget = null\n this._scrollHeight = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.target !== 'string') {\n let id = $(config.target).attr('id')\n if (!id) {\n id = Util.getUID(NAME)\n $(config.target).attr('id', id)\n }\n config.target = `#${id}`\n }\n\n Util.typeCheckConfig(NAME, config, DefaultType)\n\n return config\n }\n\n _getScrollTop() {\n return this._scrollElement === window\n ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop\n }\n\n _getScrollHeight() {\n return this._scrollElement.scrollHeight || Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n )\n }\n\n _getOffsetHeight() {\n return this._scrollElement === window\n ? window.innerHeight : this._scrollElement.getBoundingClientRect().height\n }\n\n _process() {\n const scrollTop = this._getScrollTop() + this._config.offset\n const scrollHeight = this._getScrollHeight()\n const maxScroll = this._config.offset +\n scrollHeight -\n this._getOffsetHeight()\n\n if (this._scrollHeight !== scrollHeight) {\n this.refresh()\n }\n\n if (scrollTop >= maxScroll) {\n const target = this._targets[this._targets.length - 1]\n\n if (this._activeTarget !== target) {\n this._activate(target)\n }\n return\n }\n\n if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n this._activeTarget = null\n this._clear()\n return\n }\n\n const offsetLength = this._offsets.length\n for (let i = offsetLength; i--;) {\n const isActiveTarget = this._activeTarget !== this._targets[i] &&\n scrollTop >= this._offsets[i] &&\n (typeof this._offsets[i + 1] === 'undefined' ||\n scrollTop < this._offsets[i + 1])\n\n if (isActiveTarget) {\n this._activate(this._targets[i])\n }\n }\n }\n\n _activate(target) {\n this._activeTarget = target\n\n this._clear()\n\n const queries = this._selector\n .split(',')\n .map((selector) => `${selector}[data-target=\"${target}\"],${selector}[href=\"${target}\"]`)\n\n const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))\n\n if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)\n $link.addClass(ClassName.ACTIVE)\n } else {\n // Set triggered link as active\n $link.addClass(ClassName.ACTIVE)\n // Set triggered links parents as active\n // With both