{"version":3,"sources":["node_modules/events/events.js","mod::system/js/net/requester.ts","mod::system/js/net/jsonrpc.ts","mod::utwente_base/node_modules/@webhare/dompack-carrousel/src/iscroll.modified.js","mod::utwente_base/node_modules/@webhare/dompack-carrousel/src/index.es","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/photoalbum/fullscreen-slideshow.ts","mod::utwente_base/webdesigns/ws2016/src/shared/domtemplate.ts","mod::utwente_base/node_modules/ev-emitter/ev-emitter.js","mod::utwente_base/node_modules/get-size/get-size.js","mod::utwente_base/node_modules/desandro-matches-selector/matches-selector.js","mod::utwente_base/node_modules/fizzy-ui-utils/utils.js","mod::utwente_base/node_modules/outlayer/item.js","mod::utwente_base/node_modules/outlayer/outlayer.js","mod::utwente_base/node_modules/masonry-layout/masonry.js","mod::system/js/wh/rpc.ts","mod::utwente_base/web/pub/ws2016/searsia.js","mod::utwente_base/web/pub/ws2016/searsiaconfig.ts","mod::consilio/js/internal/search.rpc.json","@webhare/frontend/src/init.ts","@webhare/env/src/init-browser.ts","mod::publisher/js/internal/polyfills/all.ts","mod::publisher/js/internal/polyfills/iterator-helpers.ts","mod::publisher/js/internal/polyfills/publisher-integration.ts","@webhare/frontend/src/gtm.ts","mod::publisher/js/analytics/gtm.ts","mod::publisher/js/analytics/consenthandler.ts","mod::utwente_base/src/nextpager/nextpager.ts","mod::publisher/js/analytics/geoip.ts","mod::system/js/dompack/extra/storage.ts","mod::system/js/dompack/extra/cookie.ts","mod::utwente_design/js/cookiebar/index.tsx","@webhare/frontend/src/frontend.ts","@webhare/frontend/src/auth.ts","@webhare/rpc/src/rpc.ts","@webhare/auth/src/shared.ts","mod::platform/js/concepts/frontend.ts","@webhare/frontend/src/authormode.ts","mod::consilio/js/pxl.ts","@webhare/frontend/src/pxl.ts","@webhare/frontend/src/analytics.ts","mod::utwente_base/webdesigns/ws2016/src/cobrowserchat/index.ts","mod::utwente_base/webdesigns/ws2016/src/shared/crm/index.ts","mod::utwente_design/js/crm/consenthandler.ts","mod::utwente_base/webdesigns/ws2016/src/shared/crm/usersettings.ts","mod::utwente_base/webdesigns/ws2016/src/shared/crm/referralinfo.ts","mod::utwente_design/js/crm/auth.ts","mod::wrd/js/auth.ts","mod::system/js/wh/integration.ts","mod::utwente_design/js/crm/networks.ts","mod::system/js/dompack/api/dialog.ts","mod::system/js/dompack/browserfix/focus.ts","mod::utwente_design/webfeatures/videoproviders/index.ts","mod::utwente_design/webfeatures/videoproviders/video.ts","mod::tollium/js/gettid.ts","mod::publisher/js/internal/rtd.lang.json","mod::utwente_design/theme/theme.ts","mod::system/js/dompack/components/dialog/index.ts","mod::utwente_base/webdesigns/ws2016/src/shared/dialog/index.tsx","mod::utwente_base/webdesigns/ws2016/src/shared/dialog/dialog.lang.json","mod::utwente_design/vendor/perfect-scrollbar-wh/src/lib/css.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/lib/dom.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/lib/class-names.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/lib/event-manager.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/process-scroll-diff.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/lib/util.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/update-geometry.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/handlers/click-rail.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/handlers/drag-thumb.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/handlers/keyboard.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/handlers/mouse-wheel.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/handlers/touch.js","mod::utwente_design/vendor/perfect-scrollbar-wh/src/index.js","mod::utwente_base/webdesigns/ws2016/src/rtd/index.tsx","mod::utwente_design/web/utdesign/fonts/univers-next-async.ts","mod::utwente_base/webdesigns/ws2016/src/shared/utforms/index.tsx","mod::utwente_base/webdesigns/ws2016/src/site.lang.json","mod::system/js/dompack/extra/merge.ts","mod::publisher/js/forms/internal/customvalidation.ts","mod::publisher/js/forms/internal/webharefields.tsx","mod::system/js/dompack/types/datetime.ts","mod::publisher/js/forms/fields/addressfield.ts","mod::publisher/js/forms/formbase.ts","@webhare/forms/src/registeredfield.ts","mod::publisher/js/forms/fields/arrayfield.ts","@webhare/forms/src/fieldmap.ts","@webhare/forms/src/address.ts","mod::publisher/js/forms/internal/datehelpers.ts","@webhare/forms/src/domsupport.ts","@webhare/forms/src/jsformelement.ts","mod::publisher/js/forms/rpc.ts","mod::publisher/js/forms/internal/emailvalidation.tsx","mod::publisher/js/forms/fields/captchafield.ts","mod::publisher/js/captcha/api.ts","mod::publisher/js/captcha/__captcha.lang.json","mod::publisher/js/forms/fields/upload.tsx","mod::publisher/js/forms/fields/fileeditbase.ts","mod::publisher/js/forms/internal/form.lang.json","mod::publisher/js/forms/fields/imgedit.ts","@webhare/forms/src/registration.ts","@webhare/forms/src/forms.ts","mod::publisher/js/forms/fields/datetime.tsx","mod::publisher/js/forms/internal/datepicker.tsx","mod::publisher/js/captcha/google-recaptcha.tsx","@webhare/forms/src/friendly-captcha.ts","mod::publisher/js/forms/index.ts","mod::publisher/js/forms/fields/rtd/index.ts","mod::publisher/js/forms/fields/rtd/embedvideo.ts","mod::system/js/dompack/components/pulldown/index.ts","mod::system/js/dompack/components/internal/selectlist.ts","mod::utwente_base/webdesigns/ws2016/src/shared/utforms/phone.tsx","mod::utwente_design/node_modules/slim-select/src/slim-select/classes.ts","mod::utwente_design/node_modules/slim-select/src/slim-select/helpers.ts","mod::utwente_design/node_modules/slim-select/src/slim-select/store.ts","mod::utwente_design/node_modules/slim-select/src/slim-select/render.ts","mod::utwente_design/node_modules/slim-select/src/slim-select/select.ts","mod::utwente_design/node_modules/slim-select/src/slim-select/settings.ts","mod::utwente_design/node_modules/slim-select/src/slim-select/index.ts","mod::utwente_design/js/utils/trigram.ts","mod::utwente_base/webdesigns/ws2016/src/shared/utforms/linkhandling.ts","mod::utwente_base/webdesigns/ws2016/src/theme/colorschemeanimation.tsx","mod::utwente_base/webdesigns/ws2016/src/shared/newwindow.ts","mod::utwente_base/webdesigns/ws2016/src/header/index.ts","mod::utwente_base/webdesigns/ws2016/src/components/promisexmlhttprequest.ts","mod::utwente_base/webdesigns/ws2016/src/shared/slideshow.ts","mod::utwente_base/webdesigns/ws2016/src/components/video.ts","mod::utwente_base/webdesigns/ws2016/src/components/swipedetect.ts","mod::utwente_base/webdesigns/ws2016/src/shared/wh.layout.autofit.ts","mod::utwente_base/webdesigns/ws2016/src/header/header_cta.ts","mod::utwente_base/webdesigns/ws2016/src/header/header_stickyctabar.ts","mod::utwente_base/webdesigns/ws2016/src/shared/deeplinks.tsx","mod::utwente_base/webdesigns/ws2016/src/components/smoothscroll.ts","mod::utwente_base/webdesigns/ws2016/src/components/scrolllistener.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/carrousel/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/photoalbum/index.ts","mod::utwente_base/node_modules/@webhare/dompack-justifiedcontentgrid/src/index.es","mod::utwente_base/webdesigns/ws2016/src/shared/hoversupport.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/slideshow/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/slideshow/dompack-carrousel-slideshow.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/progress/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/timeline/index.ts","mod::utwente_base/webdesigns/ws2016/src/filteredoverview/index.tsx","mod::utwente_base/node_modules/autocompleter/autocomplete.ts","mod::utwente_base/webdesigns/ws2016/src/components/autocompleter2/autocompleter.ts","mod::utwente_base/webdesigns/ws2016/src/filteredoverview/searchindex/index.tsx","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/timeline/dompack-masonry-update.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/timetable/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/timetable/components/popuppanel.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/timetable/whtimetable.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/managed-cta/index.tsx","mod::utwente_base/webdesigns/ws2016/src/shared/crm/managedctas.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/publicationslist/index.tsx","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/banner/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/linkspercategory_tabs/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/newsandevents/index.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/figures/index.ts","mod::utwente_base/webdesigns/ws2016/src/shared/layout-tools.ts","mod::utwente_base/webdesigns/ws2016/src/shared/smartlayout.ts","mod::utwente_base/webdesigns/ws2016/src/footer/index.ts","mod::utwente_base/webdesigns/ws2016/src/shared/showalllinks.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/index.ts","mod::utwente_base/webdesigns/ws2016/src/components/resizeobserver.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/widgetsholder/widgetsholder.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/widgetsholder/dompack-masonry.ts","mod::utwente_base/webfeatures/utwidgets/layout.ts","mod::utwente_base/webdesigns/ws2016/src/widgets/consentcheck.tsx","mod::utwente_base/webdesigns/ws2016/src/widgets/homepage/index.ts","mod::utwente_base/webfeatures/utcomponents/countdown/index.ts","mod::utwente_base/webfeatures/utwidgets/countdown/index.ts","mod::utwente_base/webfeatures/utwidgets/events/index.tsx","mod::utwente_base/webfeatures/utwidgets/faq/index.ts","mod::utwente_base/webdesigns/ws2016/src/components/carrouselcontent/index.ts","mod::utwente_base/webfeatures/utwidgets/imagewithcaption/index.tsx","mod::utwente_base/webfeatures/utwidgets/imagevideowithtext/index.tsx","mod::utwente_base/webfeatures/utwidgets/news/index.tsx","mod::utwente_base/webfeatures/utwidgets/quote/index.tsx","mod::utwente_design/js/ut-formatting.tsx","mod::utwente_base/webfeatures/utwidgets/soundcloud/soundcloud.tsx","mod::utwente_base/webfeatures/utwidgets/tablewithtabs/index.ts","mod::utwente_design/js/foldablecontent/index.tsx","mod::utwente_base/webfeatures/utwidgets/video/index.ts","mod::utwente_base/webdesigns/ws2016/src/components/preventzoomonfocus.js","mod::utwente_base/webdesigns/ws2016/src/shared/peopleimages/index.ts","mod::utwente_base/webdesigns/ws2016/src/shared/peopleimages/pirservice.rpc.json","mod::utwente_base/webdesigns/ws2016/src/shared/psa-chatbot.ts","mod::utwente_base/webfeatures/ws2021/header/header.tsx","mod::utwente_base/webfeatures/ws2021/shared/universe.tsx","mod::utwente_base/webfeatures/ws2021/navigation/navigation.tsx","mod::utwente_base/webdesigns/ws2016/src/shared/searchsheet/index.tsx","mod::utwente_base/webdesigns/ws2016/src/shared/searchsheet/searsiasuggest.tsx","mod::utwente_base/webdesigns/ws2016/src/shared/searchsheet/searsiatypes.tsx","mod::utwente_base/webdesigns/ws2016/src/shared/searchsheet/searsiawidgets.tsx","mod::utwente_base/webfeatures/ws2021/navigation/sitemenu.tsx","mod::utwente_base/js/promisetimeout.ts","mod::utwente_base/webfeatures/ws2021/navigation/langswitch.ts","mod::utwente_base/webfeatures/ws2021/shared/resizelistener.ts","mod::utwente_base/webfeatures/ws2021/main/index.ts","mod::utwente_design/js/wh-compatibility.ts","mod::utwente_base/webdesigns/ws2016/src/ws2016.ts","mod::utwente_base/webdesigns/ws2016/src/pages/newsevents/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/newsevents/formfilters.ts","mod::utwente_base/webdesigns/ws2016/src/pages/newsevents/index-new.ts","mod::utwente_base/webdesigns/ws2016/src/pages/toplevelhome/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/login/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/ufonds-donaties/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/meetings/index.ts","mod::system/js/dompack/types/text.ts","mod::utwente_base/webdesigns/ws2016/src/pages/people/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/medical/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/neoform/index.tsx","mod::utwente_base/webdesigns/ws2016/src/pages/tablewithfilter/index.tsx","mod::utwente_base/webdesigns/ws2016/src/pages/tablewithfilter/tablewithfilter.rpc.json","mod::utwente_base/webdesigns/ws2016/src/pages/filteredfolder/index.tsx","mod::utwente_base/webdesigns/ws2016/src/pages/itc-intranet/btor.ts","mod::utwente_base/webdesigns/ws2016/src/pages/itc-intranet/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/itc-forms/index.ts","mod::utwente_base/webdesigns/ws2016/src/pages/itc-search/index.tsx","mod::utwente_base/webdesigns/ws2016/src/pages/itc-projects/index.ts","mod::utwente_base/webdesigns/ws2016/src/components/osiris/index.tsx","mod::utwente_base/webdesigns/ws2016/src/notificationbar/index.ts","mod::utwente_base/webdesigns/ws2016/src/shared/edge-fullscreen.ts","mod::utwente_base/webdesigns/ws2016/src/shared/addthisevent/index.ts","mod::utwente_base/webdesigns/ws2016/src/shared/login/index.tsx","mod::utwente_base/webdesigns/ws2016/src/forms/recipientsfield.tsx","mod::utwente_base/webdesigns/ws2016/src/components/skiplinks/index.ts","mod::utwente_base/js/frontendauth.ts","mod::utwente_base/webdesigns/ws2016/src/site.tsx","mod::datacloud/webfeatures/datacloud-loader.ts","mod::utwente_courses/webfeatures/courses/index.tsx","mod::utwente_courses/webfeatures/courses/components/calendar/index.tsx","mod::utwente_courses/webfeatures/courses/components/detail/index.tsx","mod::utwente_courses/webfeatures/courses/coursefinder.lang.json","mod::utwente_courses/webfeatures/courses/pages/course/index.tsx","mod::utwente_courses/webfeatures/courses/pages/mycourses/index.ts","mod::utwente_courses/webfeatures/courses/components/dialogs/index.tsx","mod::utwente_education/webfeatures/studyfinder/index.tsx","mod::utwente_education/webfeatures/studyfinder/studyfinder.lang.json","mod::utwente_education/webfeatures/scholarshipfinder/index.ts","mod::utwente_education/webfeatures/widgets/transfer/index.tsx","mod::utwente_education/webfeatures/shared/services.rpc.json","mod::utwente_education/webfeatures/widgets/transfer/transfer.lang.json","mod::utwente_education/webfeatures/widgets/programmedetails/index.ts","mod::utwente_education/webfeatures/widgets/programmeheader/programmeheader.ts","mod::utwente_education/webfeatures/widgets/mastercareerprospects/index.ts","mod::utwente_education/webfeatures/widgets/relatedmasterprogrammes/index.ts","mod::utwente_education/webfeatures/widgets/studyinnumbers/index.ts","mod::utwente_education/webfeatures/widgets/cssstudies/index.ts","mod::utwente_education/webfeatures/widgets/specializations/index.ts","mod::utwente_jobs/webfeatures/vacanciespage/vacancywidget/index.tsx","mod::utwente_jobs/webfeatures/vacanciespage/vacancywidget/vacancies.rpc.json","mod::utwente_jobs/webfeatures/vacanciespage/index.ts","mod::utwente_ppp/webdesigns/shared/widgets/projectslist/index.ts","mod::utwente_voorlichting/js/shared/orgselect.tsx","mod::utwente_voorlichting/js/shared/internal/leads.rpc.json","mod::utwente_voorlichting/js/shared/shared_search.ts","mod::utwente_voorlichting/js/shared/institutes.ts","mod::utwente_voorlichting/webfeatures/cashpoint/index.tsx","mod::utwente_voorlichting/webfeatures/cashpoint/cashpointpage.lang.json","mod::utwente_base/webdesigns/ws2016/src/shared/crm/prefill.ts","mod::utwente_voorlichting/js/shared/forms.ts","mod::utwente_voorlichting/webfeatures/echeck/index.tsx","mod::utwente_voorlichting/webfeatures/opendagen/index.tsx","mod::utwente_voorlichting/webfeatures/opendagen/opendagen.lang.json","mod::utwente_voorlichting/webfeatures/opendays_v2/index.tsx","mod::utwente_voorlichting/webfeatures/opendays_v2/opendays_v2.lang.json","mod::utwente_voorlichting/webfeatures/leadswidgets/index.ts","mod::utwente_voorlichting/webfeatures/leadswidgets/brochurerequest/brochurerequest.ts","mod::utwente_voorlichting/webfeatures/leadswidgets/leadswidgets.rpc.json","mod::utwente_voorlichting/webfeatures/leadswidgets/stayuptodate/stayuptodate.ts","mod::utwente_voorlichting/webfeatures/scopemastercontact/index.ts","mod::utwente_voorlichting/webfeatures/tasterdays/index.tsx","mod::utwente_voorlichting/webfeatures/tasterdays/tasterdays.lang.json","mod::utwente_voorlichting/webfeatures/sirform/sirform.ts","mod::publisher/js/pwa/index.ts","mod::publisher/js/pwa/internal/debugmenu.tsx","mod::publisher/js/pwa/internal/settings.ts","node_modules/idb/build/index.js","mod::publisher/js/pwa/internal/maintenance.ts","mod::utwente_voorlichting/webfeatures/sirform/sirform.lang.json","mod::utwente_voorlichting/webfeatures/ws2016_voorlichting/activities/blockspage.ts","mod::utwente_voorlichting/webfeatures/ws2016_voorlichting/activities/activities.ts","mod::utwente_voorlichting/webfeatures/ws2016_voorlichting/activities/activitieslist.ts","mod::utwente_voorlichting/webfeatures/ws2016_voorlichting/components/toggle.ts","mod::utwente_voorlichting/webfeatures/ws2016_voorlichting/widgets/ctalinks/ctalinks.ts","mod::utwente_voorlichting/webfeatures/ws2016_voorlichting/ws2016_voorlichting.ts","/entrypoint.js"],"sourcesContent":["// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar R = typeof Reflect === 'object' ? Reflect : null\nvar ReflectApply = R && typeof R.apply === 'function'\n  ? R.apply\n  : function ReflectApply(target, receiver, args) {\n    return Function.prototype.apply.call(target, receiver, args);\n  }\n\nvar ReflectOwnKeys\nif (R && typeof R.ownKeys === 'function') {\n  ReflectOwnKeys = R.ownKeys\n} else if (Object.getOwnPropertySymbols) {\n  ReflectOwnKeys = function ReflectOwnKeys(target) {\n    return Object.getOwnPropertyNames(target)\n      .concat(Object.getOwnPropertySymbols(target));\n  };\n} else {\n  ReflectOwnKeys = function ReflectOwnKeys(target) {\n    return Object.getOwnPropertyNames(target);\n  };\n}\n\nfunction ProcessEmitWarning(warning) {\n  if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n  return value !== value;\n}\n\nfunction EventEmitter() {\n  EventEmitter.init.call(this);\n}\nmodule.exports = EventEmitter;\nmodule.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n  if (typeof listener !== 'function') {\n    throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n  }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n  enumerable: true,\n  get: function() {\n    return defaultMaxListeners;\n  },\n  set: function(arg) {\n    if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n      throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n    }\n    defaultMaxListeners = arg;\n  }\n});\n\nEventEmitter.init = function() {\n\n  if (this._events === undefined ||\n      this._events === Object.getPrototypeOf(this)._events) {\n    this._events = Object.create(null);\n    this._eventsCount = 0;\n  }\n\n  this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n  if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n    throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n  }\n  this._maxListeners = n;\n  return this;\n};\n\nfunction _getMaxListeners(that) {\n  if (that._maxListeners === undefined)\n    return EventEmitter.defaultMaxListeners;\n  return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n  return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n  var args = [];\n  for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n  var doError = (type === 'error');\n\n  var events = this._events;\n  if (events !== undefined)\n    doError = (doError && events.error === undefined);\n  else if (!doError)\n    return false;\n\n  // If there is no 'error' event listener then throw.\n  if (doError) {\n    var er;\n    if (args.length > 0)\n      er = args[0];\n    if (er instanceof Error) {\n      // Note: The comments on the `throw` lines are intentional, they show\n      // up in Node's output if this results in an unhandled exception.\n      throw er; // Unhandled 'error' event\n    }\n    // At least give some kind of context to the user\n    var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n    err.context = er;\n    throw err; // Unhandled 'error' event\n  }\n\n  var handler = events[type];\n\n  if (handler === undefined)\n    return false;\n\n  if (typeof handler === 'function') {\n    ReflectApply(handler, this, args);\n  } else {\n    var len = handler.length;\n    var listeners = arrayClone(handler, len);\n    for (var i = 0; i < len; ++i)\n      ReflectApply(listeners[i], this, args);\n  }\n\n  return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n  var m;\n  var events;\n  var existing;\n\n  checkListener(listener);\n\n  events = target._events;\n  if (events === undefined) {\n    events = target._events = Object.create(null);\n    target._eventsCount = 0;\n  } else {\n    // To avoid recursion in the case that type === \"newListener\"! Before\n    // adding it to the listeners, first emit \"newListener\".\n    if (events.newListener !== undefined) {\n      target.emit('newListener', type,\n                  listener.listener ? listener.listener : listener);\n\n      // Re-assign `events` because a newListener handler could have caused the\n      // this._events to be assigned to a new object\n      events = target._events;\n    }\n    existing = events[type];\n  }\n\n  if (existing === undefined) {\n    // Optimize the case of one listener. Don't need the extra array object.\n    existing = events[type] = listener;\n    ++target._eventsCount;\n  } else {\n    if (typeof existing === 'function') {\n      // Adding the second element, need to change to array.\n      existing = events[type] =\n        prepend ? [listener, existing] : [existing, listener];\n      // If we've already got an array, just append.\n    } else if (prepend) {\n      existing.unshift(listener);\n    } else {\n      existing.push(listener);\n    }\n\n    // Check for listener leak\n    m = _getMaxListeners(target);\n    if (m > 0 && existing.length > m && !existing.warned) {\n      existing.warned = true;\n      // No error code for this since it is a Warning\n      // eslint-disable-next-line no-restricted-syntax\n      var w = new Error('Possible EventEmitter memory leak detected. ' +\n                          existing.length + ' ' + String(type) + ' listeners ' +\n                          'added. Use emitter.setMaxListeners() to ' +\n                          'increase limit');\n      w.name = 'MaxListenersExceededWarning';\n      w.emitter = target;\n      w.type = type;\n      w.count = existing.length;\n      ProcessEmitWarning(w);\n    }\n  }\n\n  return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n  return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n    function prependListener(type, listener) {\n      return _addListener(this, type, listener, true);\n    };\n\nfunction onceWrapper() {\n  if (!this.fired) {\n    this.target.removeListener(this.type, this.wrapFn);\n    this.fired = true;\n    if (arguments.length === 0)\n      return this.listener.call(this.target);\n    return this.listener.apply(this.target, arguments);\n  }\n}\n\nfunction _onceWrap(target, type, listener) {\n  var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n  var wrapped = onceWrapper.bind(state);\n  wrapped.listener = listener;\n  state.wrapFn = wrapped;\n  return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n  checkListener(listener);\n  this.on(type, _onceWrap(this, type, listener));\n  return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n    function prependOnceListener(type, listener) {\n      checkListener(listener);\n      this.prependListener(type, _onceWrap(this, type, listener));\n      return this;\n    };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n    function removeListener(type, listener) {\n      var list, events, position, i, originalListener;\n\n      checkListener(listener);\n\n      events = this._events;\n      if (events === undefined)\n        return this;\n\n      list = events[type];\n      if (list === undefined)\n        return this;\n\n      if (list === listener || list.listener === listener) {\n        if (--this._eventsCount === 0)\n          this._events = Object.create(null);\n        else {\n          delete events[type];\n          if (events.removeListener)\n            this.emit('removeListener', type, list.listener || listener);\n        }\n      } else if (typeof list !== 'function') {\n        position = -1;\n\n        for (i = list.length - 1; i >= 0; i--) {\n          if (list[i] === listener || list[i].listener === listener) {\n            originalListener = list[i].listener;\n            position = i;\n            break;\n          }\n        }\n\n        if (position < 0)\n          return this;\n\n        if (position === 0)\n          list.shift();\n        else {\n          spliceOne(list, position);\n        }\n\n        if (list.length === 1)\n          events[type] = list[0];\n\n        if (events.removeListener !== undefined)\n          this.emit('removeListener', type, originalListener || listener);\n      }\n\n      return this;\n    };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n    function removeAllListeners(type) {\n      var listeners, events, i;\n\n      events = this._events;\n      if (events === undefined)\n        return this;\n\n      // not listening for removeListener, no need to emit\n      if (events.removeListener === undefined) {\n        if (arguments.length === 0) {\n          this._events = Object.create(null);\n          this._eventsCount = 0;\n        } else if (events[type] !== undefined) {\n          if (--this._eventsCount === 0)\n            this._events = Object.create(null);\n          else\n            delete events[type];\n        }\n        return this;\n      }\n\n      // emit removeListener for all listeners on all events\n      if (arguments.length === 0) {\n        var keys = Object.keys(events);\n        var key;\n        for (i = 0; i < keys.length; ++i) {\n          key = keys[i];\n          if (key === 'removeListener') continue;\n          this.removeAllListeners(key);\n        }\n        this.removeAllListeners('removeListener');\n        this._events = Object.create(null);\n        this._eventsCount = 0;\n        return this;\n      }\n\n      listeners = events[type];\n\n      if (typeof listeners === 'function') {\n        this.removeListener(type, listeners);\n      } else if (listeners !== undefined) {\n        // LIFO order\n        for (i = listeners.length - 1; i >= 0; i--) {\n          this.removeListener(type, listeners[i]);\n        }\n      }\n\n      return this;\n    };\n\nfunction _listeners(target, type, unwrap) {\n  var events = target._events;\n\n  if (events === undefined)\n    return [];\n\n  var evlistener = events[type];\n  if (evlistener === undefined)\n    return [];\n\n  if (typeof evlistener === 'function')\n    return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n  return unwrap ?\n    unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n  return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n  return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n  if (typeof emitter.listenerCount === 'function') {\n    return emitter.listenerCount(type);\n  } else {\n    return listenerCount.call(emitter, type);\n  }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n  var events = this._events;\n\n  if (events !== undefined) {\n    var evlistener = events[type];\n\n    if (typeof evlistener === 'function') {\n      return 1;\n    } else if (evlistener !== undefined) {\n      return evlistener.length;\n    }\n  }\n\n  return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n  return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n  var copy = new Array(n);\n  for (var i = 0; i < n; ++i)\n    copy[i] = arr[i];\n  return copy;\n}\n\nfunction spliceOne(list, index) {\n  for (; index + 1 < list.length; index++)\n    list[index] = list[index + 1];\n  list.pop();\n}\n\nfunction unwrapListeners(arr) {\n  var ret = new Array(arr.length);\n  for (var i = 0; i < ret.length; ++i) {\n    ret[i] = arr[i].listener || arr[i];\n  }\n  return ret;\n}\n\nfunction once(emitter, name) {\n  return new Promise(function (resolve, reject) {\n    function errorListener(err) {\n      emitter.removeListener(name, resolver);\n      reject(err);\n    }\n\n    function resolver() {\n      if (typeof emitter.removeListener === 'function') {\n        emitter.removeListener('error', errorListener);\n      }\n      resolve([].slice.call(arguments));\n    };\n\n    eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });\n    if (name !== 'error') {\n      addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });\n    }\n  });\n}\n\nfunction addErrorHandlerIfEventEmitter(emitter, handler, flags) {\n  if (typeof emitter.on === 'function') {\n    eventTargetAgnosticAddListener(emitter, 'error', handler, flags);\n  }\n}\n\nfunction eventTargetAgnosticAddListener(emitter, name, listener, flags) {\n  if (typeof emitter.on === 'function') {\n    if (flags.once) {\n      emitter.once(name, listener);\n    } else {\n      emitter.on(name, listener);\n    }\n  } else if (typeof emitter.addEventListener === 'function') {\n    // EventTarget does not have `error` event semantics like Node\n    // EventEmitters, we do not listen for `error` events here.\n    emitter.addEventListener(name, function wrapListener(arg) {\n      // IE does not have builtin `{ once: true }` support so we\n      // have to do it manually.\n      if (flags.once) {\n        emitter.removeEventListener(name, wrapListener);\n      }\n      listener(arg);\n    });\n  } else {\n    throw new TypeError('The \"emitter\" argument must be of type EventEmitter. Received type ' + typeof emitter);\n  }\n}\n","/* eslint-disable */\n/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\nimport * as dompack from 'dompack';\nconst EventEmitter = require('events');\n\nclass InternetRequester extends EventEmitter {\n  constructor(options) {\n    super();\n    if (!options)\n      options = {};\n    //Host url of event server\n    this.options = {\n      url: options.url || '',\n      log: Boolean(options.log || dompack.debugflags.rpc),\n      withcredentials: 'withCredentials' in options && options.withcredentials\n    };\n\n    // XMLHttpRequest\n    this.conn = null;\n\n    // used for estimating the server date\n    this.__date_server = null;\n    this.__date_client = null;\n    this.__date_diff = null;\n  }\n\n  destroy() {\n    this.stopCurrentRequest();\n    this.conn = null;\n  }\n\n  stopCurrentRequest() {\n    if (this.conn) {\n      this.conn.onreadystatechange = null;\n      this.conn.onloadend = null;\n\n      this.conn.abort();\n    }\n    if (this.jsoncheckinterval) {\n      clearTimeout(this.jsoncheckinterval);\n      this.jsoncheckinterval = null;\n    }\n  }\n\n  ensureConnection() {\n    if (!this.conn)\n      this.conn = new XMLHttpRequest();\n  }\n\n  startXMLHTTPRequest(method, url, body, options) {\n    this.ensureConnection();\n\n    const async = !options || !options.synchronous;\n\n    // Because aborting the connection may result in a readystatechange event (yes, we're looking at you, Titanium's\n    // TiNetworkHTTPClient...), we have to reset the have_response flag _after_ aborting the connection, so the response for\n    // the previous request isn't used for the new request\n\n    this.laststateevent = null; //make sure we don't accidentally cancel the previous request\n    this.conn.abort();\n    this.have_response = false;\n\n    this.conn.open(method.toUpperCase(), url, async);\n    if (options && options.headers)\n      Object.keys(options.headers).forEach(key => { this.conn.setRequestHeader(key, options.headers[key]); });\n\n    if (this.options.withcredentials)\n      this.conn.withCredentials = true;\n\n    this.conn.onreadystatechange = this.onStateChange.bind(this);\n    // Required for Firefox 12 (+firebug?), without it statechange to 4 doesn't seem to be fired sometimes\n    this.conn.onloadend = this.onStateChange.bind(this);\n    this.conn.onabort = this.onAbort.bind(this);\n\n    this.emit(\"requeststart\", { target: this });\n    this.conn.send(body);\n\n    if (!async)\n      this.onStateChange();\n  }\n\n  onAbort(event) {\n    if (this.laststateevent)\n      this.laststateevent.isaborted = true;\n  }\n\n  onStateChange(event) {\n    if (this.conn.readyState !== 4 || this.have_response)\n      return;\n\n    this.have_response = true;\n\n    const datestr = this.conn.getResponseHeader(\"date\");\n    if (datestr !== \"\") {\n      const parseddate = Date.parse(datestr);\n      this.__date_server = parseddate;\n      this.__date_client = new Date();\n      this.__date_diff = this.__date_server - this.__date_client;\n    }\n\n    const evt = {\n      target: this,\n      success: this.conn.status === 200,\n      internalerror: this.conn.status === 500,\n      message: this.conn.status,\n\n      responsetext: this.conn.responseText,\n      responsejson: null\n    };\n\n    //FIXME only decode JSON data if the mimetype specified it was JSON, and then log any errors\n    try {\n      evt.responsejson = JSON.parse(evt.responsetext);\n    } catch (e) {\n    }\n\n    this.laststateevent = evt;\n    this.emit(\"requestend\", evt);\n  }\n}\n\nmodule.exports = InternetRequester;\n","/* eslint-disable */\n/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\n/** @require: var JSONRPC = require('@mod-system/js/net/jsonrpc')\n*/\nconst InternetRequester = require('./requester');\nimport { isLive } from \"@webhare/env\";\nimport * as dompack from 'dompack';\n\nconst rpcscriptid = Math.floor(Math.random() * 1000);\n\nclass JSONRPC extends InternetRequester {\n  /** @short RPC status codes (defined as getter-only properties as long as we don't have static const properties) */\n  static get HTTP_ERROR() { return -1; } // Error connecting to the RPC server\n  static get JSON_ERROR() { return -2; } // The returned value could not be decoded into a JSON object\n  static get PROTOCOL_ERROR() { return -3; } // The return object did not contain an id, or the id did not match the request id\n  static get RPC_ERROR() { return -4; } // The RPC returned an error\n  static get OFFLINE_ERROR() { return -5; } // The application is not online (only returned if the onlineonly option was set)\n  static get TIMEOUT_ERROR() { return -6; } // The request could not be sent or was not answered before within the timeout set in the options\n  static get SERVER_ERROR() { return -7; } // The server encountered an internal error\n\n  constructor(options) {\n    super(options);\n    if (!options)\n      options = {};\n\n    this.lastid = 0;\n    this.requestqueue = [];\n    this.cachecounter = 0;\n    this.activerequest = null;\n    this.haveresponse = false;\n    //timeout after which we trigger a 'wait' action, eg a spinner\n    this.options.waittimeout = 'waittimeout' in options ? options.waittimeout : 500;\n    this.options.appendfunctionname = 'appendfunctionname' in options ? options.appendfunctionname : false;\n    this.waitcallback = null;\n    this.waittimeoutid = null;\n    this.waitingnow = false;\n\n    this.on(\"requestend\", this.onResponse.bind(this));\n  }\n\n  destroy() {\n    super.destroy();\n    this.requestqueue = [];\n    this.activerequest = null;\n\n    if (this.waittimeoutid) {\n      clearTimeout(this.waittimeoutid);\n      this.waittimeoutid = null;\n    }\n  }\n\n  promiseRequest(method, params, options) {\n    const deferred = Promise.withResolvers();\n    const req = this.request(method, params, deferred.resolve, (errorcode, errormsg, rpcid) => { deferred.reject(new Error(errormsg)); }, options);\n    deferred.promise.__jsonrpcinfo = { deferred, req };\n    return deferred.promise;\n  }\n  async(method, ...params) {\n    return this.promiseRequest(method, params);\n  }\n\n  _doAsyncAbort(promise, result, rejection) {\n    if (!promise.__jsonrpcinfo)\n      throw new Error(\"The promise is not an async JSONRPC request\");\n    if (!rejection)\n      promise.__jsonrpcinfo.deferred.resolve(result);\n    else\n      promise.__jsonrpcinfo.deferred.reject(rejection);\n    promise.__jsonrpcinfo.req.cancel();\n  }\n\n  rpcResolve(promise, result) {\n    this._doAsyncAbort(promise, result);\n  }\n  rpcReject(promise, rejection) {\n    this._doAsyncAbort(promise, null, rejection);\n  }\n\n\n  /**\n   * @short Queue an RPC request\n   * @param method The RPC method to call\n   * @param params Params for the RPC method\n   * @param callback The callback which is called, with:\n   *                 param status A JSONRPC. value\n   *                 param result The result object as sent by the RPC, or an error message string sent by the RPC, or an error\n   *                              message\n   *                 param id The request id\n   * @param options Options\n   * @param options.url The URL to connect to\n   * @param options.timeout Timeout in ms after which the request will fail (callback is called with ERROR_TIMEOUT error)\n   * @param options.waittimeout Timeout in ms after which the request will set waiting status to TRUE (via the waitCallback)\n   *                Set negative to not trigger waiting status.\n   * @return The request id\n   */\n  request(method, params, onsuccess, onfailure, options) {\n    if (!params || typeof params !== \"object\" || params.length === undefined)\n      throw new Error(\"The parameters passed to request must be an Array\");\n\n    const id = ++this.lastid;\n\n    let url;\n    if (options && options.url)\n      url = options.url + (options.appendfunctionname ? (options.url.match(/\\/$/) ? '' : '/') + method : '');\n    else if (this.options.url)\n      url = this.options.url + (this.options.appendfunctionname ? (this.options.url.match(/\\/$/) ? '' : '/') + method : '');\n    else\n      url = location.href; //we do not support appendfunctionname for self-posts\n\n    const timeout = Math.max((options && typeof options.timeout === \"number\") ? options.timeout : 0, 0);\n    const waittimeout = (options && typeof options.waittimeout === \"number\") ? options.waittimeout : this.options.waittimeout;\n    const synchronous = options && options.synchronous || false;\n    const errortrace = options && options.errortrace || null;\n\n    if (this.options.log)\n      console.log(\"JSONRPC request\", method, params, options, 'timeout:', timeout, 'waitTimeout:', waittimeout);\n\n    const request = new Request(this, id, method, params, url, timeout, waittimeout, onsuccess, onfailure, synchronous, errortrace);\n    if (this.options.log || !isLive)\n      request.stack = new Error().stack;\n\n    this.requestqueue.push(request);\n    if (this.options.log)\n      console.log(\"JSONRPC request is on queue\");\n    this.processNextRequest();\n    return request;\n  }\n\n  handleError(onfailure, errorcode, errormsg, rpcid) {\n    if (onfailure)\n      setTimeout(() => onfailure(errorcode, errormsg, rpcid), 0);\n\n    setTimeout(() => this.emit([\"error\", { target: this, errorcode: errorcode, errormessage: errormsg, rpcid: rpcid }]), 0);\n  }\n\n  //is a json request pending?\n  isRequestPending() {\n    return this.activerequest !== null || this.requestqueue.length;\n  }\n\n  //ADDME is it possible for the 'next' response to already be .delay/setTimeout() scheduled, racing against our cancel ?\n  __cancelRequest(id) {\n    if (typeof id !== 'number')\n      return;\n\n    if (this.activerequest === id) {\n      this.stopCurrentRequest();\n      this.activerequest = null;\n\n      const request = this.requestqueue.shift();\n      if (request.timeout && typeof request.timeout !== \"boolean\")\n        clearTimeout(request.timeout);\n\n      this.processNextRequest();\n    } else {\n      for (let i = 0; i < this.requestqueue.length; ++i)\n        if (this.requestqueue[i].id === id) {\n          this.requestqueue.splice(i, 1);\n          break;\n        }\n    }\n  }\n\n  processNextRequest() {\n    if (this.activerequest) {\n      if (this.options.log)\n        console.log(\"JSONRPC request #\" + this.activerequest + \" pending, not scheduling a new one yet\");\n      this.handleWaitTimeouts();\n      return;\n    }\n\n    let request = null;\n    while (!request) {\n      request = this.requestqueue[0];\n      if (!request) {\n        if (this.options.log)\n          console.log(\"JSONRPC request - processNextRequest, queue is empty\");\n        return;\n      }\n      if (request.timeout && typeof request.timeout === \"boolean\") {\n        this.requestqueue = this.requestqueue.filter(el => el !== request);\n        request = this.requestqueue[0];\n      }\n    }\n\n    this.activerequest = request.id;\n\n    if (request.timeout)\n      request.timeout = setTimeout(() => this.onTimeout(request), request.timeout);\n\n    if (this.options.log)\n      console.log(\"JSONRPC request #\" + request.id + \" offering for XMLHTTP\");\n    this.startXMLHTTPRequest(\n      \"post\",\n      request.url,\n      JSON.stringify(request.request),\n      {\n        headers: { \"Content-Type\": \"application/json; charset=utf-8\" },\n        synchronous: request.synchronous\n      });\n    this.handleWaitTimeouts();\n  }\n\n  onResponse(event) {\n    this.activerequest = null;\n\n    const request = this.requestqueue[0];\n    if (!request)\n      return;\n\n    this.requestqueue = this.requestqueue.slice(1);\n\n    if (request.timeout) {\n      if (typeof request.timeout === \"boolean\") {\n        this.processNextRequest();\n        return;\n      }\n      clearTimeout(request.timeout);\n    }\n\n    let status = -1;\n    let result = null;\n\n    if (!event.success) {\n      status = JSONRPC.HTTP_ERROR;\n      result = \"HTTP Error: \" + event.message;\n\n      if (event.internalerror) {\n        let json = null;\n        try {\n          json = event.responsejson;\n          let trace;\n          if (json && json.error && json.error.data) {\n            trace = json.error.data.trace || json.error.data.errors || json.error.data.list || [];\n\n            console.group();\n            const line = \"RPC #\" + rpcscriptid + \":\" + request.id + \" failed: \" + json.error.message;\n            console.warn(line);\n            if (request.errortrace)\n              request.errortrace.push(line);\n            trace.forEach(rec => {\n              if (rec.filename || rec.line) {\n                const line = rec.filename + '#' + rec.line + '#' + rec.col + (rec.func ? ' (' + rec.func + ')' : '');\n                console.warn(line);\n                if (request.errortrace)\n                  request.errortrace.push(line);\n              }\n            });\n            console.groupEnd();\n          }\n          status = JSONRPC.SERVER_ERROR;\n          result = json.error && `${json.error.message} from ${request.url}` || \"Unknown error\";\n        } catch (e) {\n        }\n      }\n    } else {\n      const json = event.responsejson;\n\n      if (!json) {\n        status = JSONRPC.JSON_ERROR;\n        result = \"Invalid JSON response\";\n      } else if (json.id === null || json.id !== request.id) {\n        status = JSONRPC.PROTOCOL_ERROR;\n        result = \"Protocol error: invalid id\";\n      } else if (json.error !== null) {\n        status = JSONRPC.RPC_ERROR;\n        result = json.error;\n        if (this.options.log)\n          console.log('RPC error:', result.message ? result.message : '*no message*');\n      } else if (\"result\" in json) {\n        status = 0;\n        result = json.result;\n      } else {\n        status = JSONRPC.PROTOCOL_ERROR;\n        result = \"Could not interpret response\";\n      }\n    }\n\n    this.processNextRequest();\n\n    if (this.options.log) {\n      console.log(\"JSONRPC request\", request.request.method, 'status:', status, 'time:', (new Date).getTime() - request.scheduled, 'ms, result:');\n      console.log(result);\n    }\n\n    /*\n    console.log({ serverdate: this.__date_server\n                , clientdate: this.__date_client\n                , diff: this.__date_diff\n                });\n    */\n    setTimeout(() => request.__completedCall(status, result, event), 0);\n  }\n\n  onTimeout(request) {\n    request.timeout = true;\n    if (this.activerequest === request.id) {\n      this.activerequest = null;\n      this.stopCurrentRequest();\n      this.processNextRequest();\n    }\n    this.handleError(request.onfailure, JSONRPC.TIMEOUT_ERROR, \"Timeout while waiting for response\", request.id);\n  }\n\n  onWaitTimeout() {\n    this.waittimeoutid = null;\n    this.handleWaitTimeouts();\n  }\n\n  handleWaitTimeouts() {\n    if (this.waittimeoutid) {\n      clearTimeout(this.waittimeoutid);\n      this.waittimeoutid = null;\n    }\n\n    if (!this.waitCallback)\n      return;\n\n    let waiting = false;\n    let nextTimeout = -1;\n\n    const now = (new Date).getTime();\n    for (let i = 0; i < this.requestqueue.length; ++i) {\n      const req = this.requestqueue[i];\n      if (req.waitTimeout >= 0) {\n        const waitLength = now - req.scheduled;\n\n        if (waitLength >= req.waitTimeout)\n          waiting = true;\n        else {\n          const toGo = req.waitTimeout - waitLength;\n          if (nextTimeout < 0 || nextTimeout > toGo)\n            nextTimeout = toGo;\n        }\n      }\n    }\n\n    if (this.waitingNow !== waiting) {\n      this.waitingNow = waiting;\n      setTimeout(() => this.waitCallback(waiting), 0);\n    }\n\n    if (nextTimeout >= 0)\n      this.waittimeoutid = setTimeout(() => this.onWaitTimeout(), nextTimeout);\n  }\n\n  getEstimatedServerTime() {\n    return new Date().getTime() + this.__date_diff;\n  }\n\n  /** @short estimate the server's datetime based on the known descrepancy between the date of an reponse from the server and the time on the client\n  */\n  getEstimatedServerDate() {\n    return new Date(this.getEstimatedServerTime());\n  }\n}\n\nclass Request //extends PreloadableAsset\n{\n  constructor(parent, id, method, params, url, timeout, waittimeout, onsuccess, onfailure, synchronous, errortrace) {\n    //    super();\n\n    this.cancelled = false;\n    this.stack = null;\n\n    if (parent.options.log)\n      console.log('req', this);\n    this.parent = parent;\n    this.id = id;\n    this.request = {\n      id: id,\n      method: method,\n      params: params || []\n    };\n    this.url = url;\n    this.onsuccess = onsuccess;\n    this.onfailure = onfailure;\n    this.timeout = timeout;\n    this.scheduled = new Date - 0;\n    this.waittimeout = waittimeout;\n    this.synchronous = synchronous;\n    this.errortrace = errortrace;\n\n    //this.startPreload();\n  }\n  onStartPreload() {\n\n  }\n  cancel() {\n    //we need to prevent a race when our parent invokes cancel(), but we actually had our __completedCall already queued up. if we still fire onsuccess/onfailure, our parent might think we completed the _next_ request our parent submitted\n    this.cancelled = true;\n    this.parent.__cancelRequest(this.id);\n  }\n\n  __completedCall(status, result, event) {\n    if (event.isaborted)\n      this.cancelled = true;\n\n    if (status === 0) {\n      if (this.onsuccess && !this.cancelled)\n        this.onsuccess(result);\n      //this.donePreload(true);\n    } else {\n      if (!this.cancelled) {\n        if (this.stack) {\n          console.log(\"Stack at calling point:\");\n          console.log(this.stack);\n        }\n        this.parent.handleError(this.onfailure, status, result, this.id);\n      }\n      //this.donePreload(false);\n    }\n  }\n}\n\nmodule.exports = JSONRPC;\n","/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */\n\n/*\n\n!!!!! For Chrome 55 (on Touch devices/Android) iScroll will use pointer events instead of touch events.\n      However this ONLY WORKS if the element has touch-action: none;\n\n\nModifications made:\n- options and code to allow for an endless scroll without iScroll performing any DOM/style interactions\n- tap event will pass the source (mouse or touch) of the event\n- patch from RByers from https://github.com/cubiq/iscroll/issues/1100 to fix scrolling on Android breaking\n\n*/\n\n(function (window, document, Math) {\nvar rAF = window.requestAnimationFrame  ||\n  window.webkitRequestAnimationFrame  ||\n  window.mozRequestAnimationFrame   ||\n  window.oRequestAnimationFrame   ||\n  window.msRequestAnimationFrame    ||\n  function (callback) { window.setTimeout(callback, 1000 / 60); };\n\nvar utils = (function () {\n  var me = {};\n\n  var _elementStyle = document.createElement('div').style;\n  var _vendor = (function () {\n    var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],\n      transform,\n      i = 0,\n      l = vendors.length;\n\n    for ( ; i < l; i++ ) {\n      transform = vendors[i] + 'ransform';\n      if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);\n    }\n\n    return false;\n  })();\n\n  function _prefixStyle (style) {\n    if ( _vendor === false ) return false;\n    if ( _vendor === '' ) return style;\n    return _vendor + style.charAt(0).toUpperCase() + style.substr(1);\n  }\n\n  me.getTime = Date.now || function getTime () { return new Date().getTime(); };\n\n  me.extend = function (target, obj) {\n    for ( var i in obj ) {\n      target[i] = obj[i];\n    }\n  };\n\n  me.addEvent = function (el, type, fn, capture) {\n    el.addEventListener(type, fn, !!capture);\n  };\n\n  me.removeEvent = function (el, type, fn, capture) {\n    el.removeEventListener(type, fn, !!capture);\n  };\n\n  me.prefixPointerEvent = function (pointerEvent) {\n    return window.MSPointerEvent ?\n      'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):\n      pointerEvent;\n  };\n\n  //(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration)\n  me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {\n    var distance = current - start,\n      speed = Math.abs(distance) / time,\n      destination,\n      duration;\n\n    deceleration = deceleration === undefined ? 0.0006 : deceleration;\n\n    destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );\n    duration = speed / deceleration;\n\n    if ( destination < lowerMargin ) {\n      destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;\n      distance = Math.abs(destination - current);\n      duration = distance / speed;\n    } else if ( destination > 0 ) {\n      destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;\n      distance = Math.abs(current) + destination;\n      duration = distance / speed;\n    }\n\n    return {\n      destination: Math.round(destination),\n      duration: duration\n    };\n  };\n\n  var _transform = _prefixStyle('transform');\n\n  me.extend(me, {\n    hasTransform: _transform !== false,\n    hasPerspective: _prefixStyle('perspective') in _elementStyle,\n    hasTouch: 'ontouchstart' in window,\n    hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed\n    hasTransition: _prefixStyle('transition') in _elementStyle\n  });\n\n  /*\n  This should find all Android browsers lower than build 535.19 (both stock browser and webview)\n  - galaxy S2 is ok\n    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`\n    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S3 is badAndroid (stock brower, webview)\n     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S4 is badAndroid (stock brower, webview)\n     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n   - galaxy S5 is OK\n     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n   - galaxy S6 is OK\n     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n  */\n  me.isBadAndroid = (function() {\n    var appVersion = window.navigator.appVersion;\n    // Android browser is not a chrome browser.\n    if (/Android/.test(appVersion) && !(/Chrome\\/\\d/.test(appVersion))) {\n      var safariVersion = appVersion.match(/Safari\\/(\\d+.\\d)/);\n      if(safariVersion && typeof safariVersion === \"object\" && safariVersion.length >= 2) {\n        return parseFloat(safariVersion[1]) < 535.19;\n      } else {\n        return true;\n      }\n    } else {\n      return false;\n    }\n  })();\n\n  me.extend(me.style = {}, {\n    transform: _transform,\n    transitionTimingFunction: _prefixStyle('transitionTimingFunction'),\n    transitionDuration: _prefixStyle('transitionDuration'),\n    transitionDelay: _prefixStyle('transitionDelay'),\n    transformOrigin: _prefixStyle('transformOrigin')\n  });\n\n  me.hasClass = function (e, c) {\n    var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\");\n    return re.test(e.className);\n  };\n\n  me.addClass = function (e, c) {\n    if ( me.hasClass(e, c) ) {\n      return;\n    }\n\n    var newclass = e.className.split(' ');\n    newclass.push(c);\n    e.className = newclass.join(' ');\n  };\n\n  me.removeClass = function (e, c) {\n    if ( !me.hasClass(e, c) ) {\n      return;\n    }\n\n    var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", 'g');\n    e.className = e.className.replace(re, ' ');\n  };\n\n  me.offset = function (el) {\n    var left = -el.offsetLeft,\n      top = -el.offsetTop;\n\n    // jshint -W084\n    while (el = el.offsetParent) {\n      left -= el.offsetLeft;\n      top -= el.offsetTop;\n    }\n    // jshint +W084\n\n    return {\n      left: left,\n      top: top\n    };\n  };\n\n  me.preventDefaultException = function (el, exceptions) {\n    for ( var i in exceptions ) {\n      if ( exceptions[i].test(el[i]) ) {\n        return true;\n      }\n    }\n\n    return false;\n  };\n\n  me.extend(me.eventType = {}, {\n    touchstart: 1,\n    touchmove: 1,\n    touchend: 1,\n\n    mousedown: 2,\n    mousemove: 2,\n    mouseup: 2,\n\n    pointerdown: 3,\n    pointermove: 3,\n    pointerup: 3,\n\n    MSPointerDown: 3,\n    MSPointerMove: 3,\n    MSPointerUp: 3\n  });\n\n  me.extend(me.ease = {}, {\n    quadratic: {\n      style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n      fn: function (k) {\n        return k * ( 2 - k );\n      }\n    },\n    circular: {\n      style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly \"circular\" but this looks better, it should be (0.075, 0.82, 0.165, 1)\n      fn: function (k) {\n        return Math.sqrt( 1 - ( --k * k ) );\n      }\n    },\n    back: {\n      style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',\n      fn: function (k) {\n        var b = 4;\n        return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;\n      }\n    },\n    bounce: {\n      style: '',\n      fn: function (k) {\n        if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {\n          return 7.5625 * k * k;\n        } else if ( k < ( 2 / 2.75 ) ) {\n          return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;\n        } else if ( k < ( 2.5 / 2.75 ) ) {\n          return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;\n        } else {\n          return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;\n        }\n      }\n    },\n    elastic: {\n      style: '',\n      fn: function (k) {\n        var f = 0.22,\n          e = 0.4;\n\n        if ( k === 0 ) { return 0; }\n        if ( k == 1 ) { return 1; }\n\n        return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );\n      }\n    }\n  });\n//touch: e.type == \"touchend\"\n  me.tap = function (e, eventName) {\n    var ev = document.createEvent('Event');\n    ev.initEvent(eventName, true, true);\n//    ev.initCustomEvent(eventName, true, true, { touch: e.type == \"touchend\", mouse: e.type == \"mouseup\" });\n    ev.pageX = e.pageX;\n    ev.pageY = e.pageY;\n\n    ev.tapbytouch = e.type == \"touchend\"; // NOTE: should use initCustomEvent instead and pass details??(does this work in every target browser?)\n    ev.tapbymouse = e.type == \"mouseup\";\n\n    e.target.dispatchEvent(ev);\n  };\n\n  me.click = function (e) {\n    var target = e.target,\n      ev;\n\n    if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {\n      // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent\n      // initMouseEvent is deprecated.\n      ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');\n      ev.initEvent('click', true, true);\n      ev.view = e.view || window;\n      ev.detail = 1;\n      ev.screenX = target.screenX || 0;\n      ev.screenY = target.screenY || 0;\n      ev.clientX = target.clientX || 0;\n      ev.clientY = target.clientY || 0;\n      ev.ctrlKey = !!e.ctrlKey;\n      ev.altKey = !!e.altKey;\n      ev.shiftKey = !!e.shiftKey;\n      ev.metaKey = !!e.metaKey;\n      ev.button = 0;\n      ev.relatedTarget = null;\n      ev._constructed = true;\n      target.dispatchEvent(ev);\n    }\n  };\n\n  return me;\n})();\nfunction IScroll (el, options) {\n  this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;\n  this.scroller = this.wrapper.children[0];\n  this.scrollerStyle = this.scroller.style;   // cache style for better performance\n\n  this.options = {\n\n    resizeScrollbars: true,\n\n    mouseWheelSpeed: 20,\n\n    snapThreshold: 0.334,\n\n// INSERT POINT: OPTIONS\n    disablePointer : !utils.hasPointer,\n    disableTouch : utils.hasPointer || !utils.hasTouch,\n    disableMouse : utils.hasPointer || utils.hasTouch,\n    startX: 0,\n    startY: 0,\n    scrollY: true,\n    directionLockThreshold: 5,\n    momentum: true,\n\n    bounce: true,\n    bounceTime: 600,\n    bounceEasing: '',\n\n    preventDefault: true,\n    preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },\n\n    HWCompositing: true,\n    useTransition: true,\n    useTransform: true,\n    bindToWrapper: typeof window.onmousedown === \"undefined\",\n\n    autoUpdatePosition: true, // ADDED by Mark\n    overrideMeasurements: false // ADDED by Mark\n  };\n\n  for ( var i in options ) {\n    this.options[i] = options[i];\n  }\n\n  // Normalize options\n  this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';\n\n  this.options.useTransition = utils.hasTransition && this.options.useTransition;\n  this.options.useTransform = utils.hasTransform && this.options.useTransform;\n\n  this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;\n  this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;\n\n  // If you want eventPassthrough I have to lock one of the axes\n  this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;\n  this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;\n\n  // With eventPassthrough we also need lockDirection mechanism\n  this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;\n  this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;\n\n  this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;\n\n  this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;\n\n  if ( this.options.tap === true ) {\n    this.options.tap = 'tap';\n  }\n\n  // https://github.com/cubiq/iscroll/issues/1029\n  if (!this.options.useTransition && !this.options.useTransform) {\n    if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {\n      this.scrollerStyle.position = \"relative\";\n    }\n  }\n\n  if ( this.options.shrinkScrollbars == 'scale' ) {\n    this.options.useTransition = false;\n  }\n\n  this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;\n\n// INSERT POINT: NORMALIZATION\n\n\n  // ADDED by Mark de Jong\n  if (options.overrideMeasurements)\n  {\n    this.wrapperWidth = options.wrapperWidth;\n    this.scrollerWidth = options.scrollerWidth;\n    this.maxScrollX = -options.maxScrollX;\n\n    this.hasHorizontalScroll  = options.scrollX && this.maxScrollX < 0;\n    this.hasVerticalScroll    = options.scrollY && this.maxScrollY < 0;\n\n    //console.log(\"overrideMeasurements\", this.hasHorizontalScroll, this.hasVerticalScroll);\n  }\n\n\n  // Some defaults\n  this.x = 0;\n  this.y = 0;\n  this.directionX = 0;\n  this.directionY = 0;\n  this._events = {};\n\n// INSERT POINT: DEFAULTS\n\n  this._init();\n  this.refresh();\n\n  this.scrollTo(this.options.startX, this.options.startY);\n  this.enable();\n}\n\nIScroll.prototype = {\n  version: '5.2.0',\n\n  _init: function () {\n    this._initEvents();\n\n    if ( this.options.scrollbars || this.options.indicators ) {\n      this._initIndicators();\n    }\n\n    if ( this.options.mouseWheel ) {\n      this._initWheel();\n    }\n\n    if ( this.options.snap ) {\n      this._initSnap();\n    }\n\n    if ( this.options.keyBindings ) {\n      this._initKeys();\n    }\n\n// INSERT POINT: _init\n\n  },\n\n  destroy: function () {\n    this._initEvents(true);\n    clearTimeout(this.resizeTimeout);\n    this.resizeTimeout = null;\n    this._execEvent('destroy');\n  },\n\n  _transitionEnd: function (e) {\n    if ( e.target != this.scroller || !this.isInTransition ) {\n      return;\n    }\n\n    this._transitionTime();\n    if ( !this.resetPosition(this.options.bounceTime) ) {\n      this.isInTransition = false;\n      this._execEvent('scrollEnd');\n    }\n  },\n\n  _start: function (e) {\n    // React to left mouse button only\n    if ( utils.eventType[e.type] != 1 ) {\n      // for button property\n      // http://unixpapa.com/js/mouse.html\n      var button;\n      if (!e.which) {\n        /* IE case */\n        button = (e.button < 2) ? 0 :\n                 ((e.button == 4) ? 1 : 2);\n      } else {\n        /* All others */\n        button = e.button;\n      }\n      if ( button !== 0 ) {\n        return;\n      }\n    }\n\n    if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {\n      return;\n    }\n\n    if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n      e.preventDefault();\n    }\n\n    var point = e.touches ? e.touches[0] : e,\n      pos;\n\n    this.initiated  = utils.eventType[e.type];\n    this.moved    = false;\n    this.distX    = 0;\n    this.distY    = 0;\n    this.directionX = 0;\n    this.directionY = 0;\n    this.directionLocked = 0;\n\n    this.startTime = utils.getTime();\n\n    if ( this.options.useTransition && this.isInTransition ) {\n      this._transitionTime();\n      this.isInTransition = false;\n      pos = this.getComputedPosition();\n      this._translate(Math.round(pos.x), Math.round(pos.y));\n      this._execEvent('scrollEnd');\n    } else if ( !this.options.useTransition && this.isAnimating ) {\n      this.isAnimating = false;\n      this._execEvent('scrollEnd');\n    }\n\n    this.startX    = this.x;\n    this.startY    = this.y;\n    this.absStartX = this.x;\n    this.absStartY = this.y;\n    this.pointX    = point.pageX;\n    this.pointY    = point.pageY;\n\n    this._execEvent('beforeScrollStart');\n  },\n\n  _move: function (e) {\n    if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n      return;\n    }\n\n    if ( this.options.preventDefault ) {  // increases performance on Android? TODO: check!\n      e.preventDefault();\n    }\n\n    var point   = e.touches ? e.touches[0] : e,\n      deltaX    = point.pageX - this.pointX,\n      deltaY    = point.pageY - this.pointY,\n      timestamp = utils.getTime(),\n      newX, newY,\n      absDistX, absDistY;\n\n    this.pointX   = point.pageX;\n    this.pointY   = point.pageY;\n\n    this.distX    += deltaX;\n    this.distY    += deltaY;\n    absDistX    = Math.abs(this.distX);\n    absDistY    = Math.abs(this.distY);\n\n    // We need to move at least 10 pixels for the scrolling to initiate\n    if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {\n      return;\n    }\n\n    // If you are scrolling in one direction lock the other\n    if ( !this.directionLocked && !this.options.freeScroll ) {\n      if ( absDistX > absDistY + this.options.directionLockThreshold ) {\n        this.directionLocked = 'h';   // lock horizontally\n      } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {\n        this.directionLocked = 'v';   // lock vertically\n      } else {\n        this.directionLocked = 'n';   // no lock\n      }\n    }\n\n    if ( this.directionLocked == 'h' ) {\n      if ( this.options.eventPassthrough == 'vertical' ) {\n        e.preventDefault();\n      } else if ( this.options.eventPassthrough == 'horizontal' ) {\n        this.initiated = false;\n        return;\n      }\n\n      deltaY = 0;\n    } else if ( this.directionLocked == 'v' ) {\n      if ( this.options.eventPassthrough == 'horizontal' ) {\n        e.preventDefault();\n      } else if ( this.options.eventPassthrough == 'vertical' ) {\n        this.initiated = false;\n        return;\n      }\n\n      deltaX = 0;\n    }\n\n    deltaX = this.hasHorizontalScroll ? deltaX : 0;\n    deltaY = this.hasVerticalScroll ? deltaY : 0;\n\n    newX = this.x + deltaX;\n    newY = this.y + deltaY;\n\n    // Slow down if outside of the boundaries\n    if ( newX > 0 || newX < this.maxScrollX ) {\n      newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;\n    }\n    if ( newY > 0 || newY < this.maxScrollY ) {\n      newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;\n    }\n\n    this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n    this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n    if ( !this.moved ) {\n      this._execEvent('scrollStart');\n    }\n\n    this.moved = true;\n\n    this._translate(newX, newY);\n\n/* REPLACE START: _move */\n\n    if ( timestamp - this.startTime > 300 ) {\n      this.startTime = timestamp;\n      this.startX = this.x;\n      this.startY = this.y;\n    }\n\n/* REPLACE END: _move */\n\n  },\n\n  _end: function (e) {\n    if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n      return;\n    }\n\n    if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n      e.preventDefault();\n    }\n\n    var point = e.changedTouches ? e.changedTouches[0] : e,\n      momentumX,\n      momentumY,\n      duration = utils.getTime() - this.startTime,\n      newX = Math.round(this.x),\n      newY = Math.round(this.y),\n      distanceX = Math.abs(newX - this.startX),\n      distanceY = Math.abs(newY - this.startY),\n      time = 0,\n      easing = '';\n\n    this.isInTransition = 0;\n    this.initiated = 0;\n    this.endTime = utils.getTime();\n\n    // reset if we are outside of the boundaries\n    if ( this.resetPosition(this.options.bounceTime) ) {\n      return;\n    }\n\n    this.scrollTo(newX, newY);  // ensures that the last position is rounded\n\n    // we scrolled less than 10 pixels\n    if ( !this.moved ) {\n      if ( this.options.tap ) {\n        utils.tap(e, this.options.tap);\n      }\n\n      if ( this.options.click ) {\n        utils.click(e);\n      }\n\n      this._execEvent('scrollCancel');\n      return;\n    }\n\n/*\nFIXME: FLICK GIVES US PROBLEMS --- MARK\n    if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {\n      this._execEvent('flick');\n      return;\n    }\n*/\n    // start momentum animation if needed\n    if ( this.options.momentum && duration < 300 ) {\n      momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };\n      momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };\n      newX = momentumX.destination;\n      newY = momentumY.destination;\n      time = Math.max(momentumX.duration, momentumY.duration);\n      this.isInTransition = 1;\n    }\n\n\n    if ( this.options.snap ) {\n      var snap = this._nearestSnap(newX, newY);\n      this.currentPage = snap;\n      time = this.options.snapSpeed || Math.max(\n          Math.max(\n            Math.min(Math.abs(newX - snap.x), 1000),\n            Math.min(Math.abs(newY - snap.y), 1000)\n          ), 300);\n      newX = snap.x;\n      newY = snap.y;\n\n      this.directionX = 0;\n      this.directionY = 0;\n      easing = this.options.bounceEasing;\n\n      //console.log(\"_end will snap to \", newX, newY);\n    }\n\n// INSERT POINT: _end\n\n    if ( newX != this.x || newY != this.y ) {\n      // change easing function when scroller goes out of the boundaries\n      if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {\n        easing = utils.ease.quadratic;\n      }\n\n      this.scrollTo(newX, newY, time, easing);\n      return;\n    }\n\n    this._execEvent('scrollEnd');\n  },\n\n  _resize: function () {\n    var that = this;\n\n    clearTimeout(this.resizeTimeout);\n\n    this.resizeTimeout = setTimeout(function () {\n      that.refresh();\n    }, this.options.resizePolling);\n  },\n\n  resetPosition: function (time) {\n    var x = this.x,\n      y = this.y;\n\n    time = time || 0;\n\n    if ( !this.hasHorizontalScroll || this.x > 0 ) {\n      x = 0;\n    } else if ( this.x < this.maxScrollX ) {\n      x = this.maxScrollX;\n    }\n\n    if ( !this.hasVerticalScroll || this.y > 0 ) {\n      y = 0;\n    } else if ( this.y < this.maxScrollY ) {\n      y = this.maxScrollY;\n    }\n\n    if ( x == this.x && y == this.y ) {\n      return false;\n    }\n\n    this.scrollTo(x, y, time, this.options.bounceEasing);\n\n    return true;\n  },\n\n  disable: function () {\n    /** Patch by RByers (21 dec 2016) **************************/\n    this.wrapper.style.touchAction='';\n\n    this.enabled = false;\n  },\n\n  enable: function () {\n\n    this.enabled = true;\n\n    /** Patch by RByers (21 dec 2016) **************************/\n    // https://github.com/cubiq/iscroll/issues/1100\n\n    var touchAction = 'none'\n    if ( this.options.eventPassthrough == 'vertical' ) {\n      touchAction = 'pan-y';\n    } else if ( this.options.eventPassthrough == 'horizontal' ) {\n      touchAction = 'pan-x';\n    }\n    this.wrapper.style.touchAction = touchAction;\n    if (touchAction != 'none') {\n      // add pinch-zoom support if the browser supports it, but if not (eg. Chrome <55) do nothing\n      this.wrapper.style.touchAction += ' pinch-zoom';\n    }\n    /***********************************************************/\n  },\n\n  refresh: function () {\n    var rf = this.wrapper.offsetHeight;   // Force reflow\n\n    this.wrapperWidth = this.wrapper.clientWidth;\n    this.wrapperHeight  = this.wrapper.clientHeight;\n\n/* REPLACE START: refresh */\n\n    if (!this.options.overrideMeasurements) // MARK\n    { // MARK\n      this.scrollerWidth  = this.scroller.offsetWidth;\n      this.scrollerHeight = this.scroller.offsetHeight;\n\n      this.maxScrollX   = this.wrapperWidth - this.scrollerWidth;\n      this.maxScrollY   = this.wrapperHeight - this.scrollerHeight;\n    } // MARK\n\n/* REPLACE END: refresh */\n\n    this.hasHorizontalScroll  = this.options.scrollX && this.maxScrollX < 0;\n    this.hasVerticalScroll    = this.options.scrollY && this.maxScrollY < 0;\n\n    if ( !this.hasHorizontalScroll ) {\n      this.maxScrollX = 0;\n      this.scrollerWidth = this.wrapperWidth;\n    }\n\n    if ( !this.hasVerticalScroll ) {\n      this.maxScrollY = 0;\n      this.scrollerHeight = this.wrapperHeight;\n    }\n\n    this.endTime = 0;\n    this.directionX = 0;\n    this.directionY = 0;\n\n    this.wrapperOffset = utils.offset(this.wrapper);\n\n    this._execEvent('refresh');\n\n    this.resetPosition();\n\n// INSERT POINT: _refresh\n\n  },\n\n  on: function (type, fn) {\n    if ( !this._events[type] ) {\n      this._events[type] = [];\n    }\n\n    this._events[type].push(fn);\n  },\n\n  off: function (type, fn) {\n    if ( !this._events[type] ) {\n      return;\n    }\n\n    var index = this._events[type].indexOf(fn);\n\n    if ( index > -1 ) {\n      this._events[type].splice(index, 1);\n    }\n  },\n\n  _execEvent: function (type) {\n    if ( !this._events[type] ) {\n      return;\n    }\n\n    var i = 0,\n      l = this._events[type].length;\n\n    if ( !l ) {\n      return;\n    }\n\n    for ( ; i < l; i++ ) {\n      this._events[type][i].apply(this, [].slice.call(arguments, 1));\n    }\n  },\n\n  scrollBy: function (x, y, time, easing) {\n    x = this.x + x;\n    y = this.y + y;\n    time = time || 0;\n\n    this.scrollTo(x, y, time, easing);\n  },\n\n  scrollTo: function (x, y, time, easing) {\n    this._execEvent('scrollStart'); // MARK\n\n\n// EXPERIMENTAL: a scrollTo (with no animation) while an animation is still running should override that animation..??\n    if (this.animframe) // MARK\n      cancelAnimationFrame(this.animframe); // MARK - Fixed multiple animate/scrollTo's fighting\n\n\n    easing = easing || utils.ease.circular;\n\n    this.isInTransition = this.options.useTransition && time > 0;\n    var transitionType = this.options.useTransition && easing.style;\n    if ( !time || transitionType ) {\n        if(transitionType) {\n          this._transitionTimingFunction(easing.style);\n          this._transitionTime(time);\n        }\n      this._translate(x, y);\n    } else {\n      this._animate(x, y, time, easing.fn);\n    }\n  },\n\n  scrollToElement: function (el, time, offsetX, offsetY, easing) {\n    el = el.nodeType ? el : this.scroller.querySelector(el);\n\n    if ( !el ) {\n      return;\n    }\n\n    var pos = utils.offset(el);\n\n    pos.left -= this.wrapperOffset.left;\n    pos.top  -= this.wrapperOffset.top;\n\n    // if offsetX/Y are true we center the element to the screen\n    if ( offsetX === true ) {\n      offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);\n    }\n    if ( offsetY === true ) {\n      offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);\n    }\n\n    pos.left -= offsetX || 0;\n    pos.top  -= offsetY || 0;\n\n    pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;\n    pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;\n\n    time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;\n\n    this.scrollTo(pos.left, pos.top, time, easing);\n  },\n\n  _transitionTime: function (time) {\n    if (this.options.autoUpdatePosition) // MARK\n      return; // MARK\n\n    if (!this.options.useTransition) {\n      return;\n    }\n    time = time || 0;\n    var durationProp = utils.style.transitionDuration;\n    if(!durationProp) {\n      return;\n    }\n\n    this.scrollerStyle[durationProp] = time + 'ms';\n\n    if ( !time && utils.isBadAndroid ) {\n      this.scrollerStyle[durationProp] = '0.0001ms';\n      // remove 0.0001ms\n      var self = this;\n      rAF(function() {\n        if(self.scrollerStyle[durationProp] === '0.0001ms') {\n          self.scrollerStyle[durationProp] = '0s';\n        }\n      });\n    }\n\n\n    if ( this.indicators ) {\n      for ( var i = this.indicators.length; i--; ) {\n        this.indicators[i].transitionTime(time);\n      }\n    }\n\n\n// INSERT POINT: _transitionTime\n\n  },\n\n  _transitionTimingFunction: function (easing) {\n    if (this.options.autoUpdatePosition) // MARK\n      return; // MARK\n\n    this.scrollerStyle[utils.style.transitionTimingFunction] = easing;\n\n\n    if ( this.indicators ) {\n      for ( var i = this.indicators.length; i--; ) {\n        this.indicators[i].transitionTimingFunction(easing);\n      }\n    }\n\n\n// INSERT POINT: _transitionTimingFunction\n\n  },\n\n  _translate: function (x, y) {\n\n    if (this.options.autoUpdatePosition) // MARK\n    { // MARK\n\n      if ( this.options.useTransform ) {\n\n  /* REPLACE START: _translate */\n\n        this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;\n\n  /* REPLACE END: _translate */\n\n      } else {\n        x = Math.round(x);\n        y = Math.round(y);\n        this.scrollerStyle.left = x + 'px';\n        this.scrollerStyle.top = y + 'px';\n      }\n\n    } // MARK\n\n    this.x = x;\n    this.y = y;\n\n  if ( this.indicators ) {\n    for ( var i = this.indicators.length; i--; ) {\n      this.indicators[i].updatePosition();\n    }\n  }\n\n\n// INSERT POINT: _translate\n\n  },\n\n  _initEvents: function (remove) {\n    var eventType = remove ? utils.removeEvent : utils.addEvent,\n      target = this.options.bindToWrapper ? this.wrapper : window;\n\nif (!this.options.overrideMeasurements) // MARK\n{\n    eventType(window, 'orientationchange', this);\n    eventType(window, 'resize', this);\n}\n\n    if ( this.options.click ) {\n      eventType(this.wrapper, 'click', this, true);\n    }\n\n    if ( !this.options.disableMouse ) {\n      eventType(this.wrapper, 'mousedown', this);\n      eventType(target, 'mousemove', this);\n      eventType(target, 'mousecancel', this);\n      eventType(target, 'mouseup', this);\n    }\n\n    if ( utils.hasPointer && !this.options.disablePointer ) {\n      eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);\n      eventType(target, utils.prefixPointerEvent('pointermove'), this);\n      eventType(target, utils.prefixPointerEvent('pointercancel'), this);\n      eventType(target, utils.prefixPointerEvent('pointerup'), this);\n    }\n\n    if ( utils.hasTouch && !this.options.disableTouch ) {\n      eventType(this.wrapper, 'touchstart', this);\n      eventType(target, 'touchmove', this);\n      eventType(target, 'touchcancel', this);\n      eventType(target, 'touchend', this);\n    }\n\n    eventType(this.scroller, 'transitionend', this);\n    eventType(this.scroller, 'webkitTransitionEnd', this);\n    //eventType(this.scroller, 'oTransitionEnd', this); // MARK: only used for Opera < 12.10\n    eventType(this.scroller, 'MSTransitionEnd', this);\n  },\n\n  getComputedPosition: function () {\n    var matrix = window.getComputedStyle(this.scroller, null),\n      x, y;\n\n    if ( this.options.useTransform ) {\n      matrix = matrix[utils.style.transform].split(')')[0].split(', ');\n      x = +(matrix[12] || matrix[4]);\n      y = +(matrix[13] || matrix[5]);\n    } else {\n      x = +matrix.left.replace(/[^-\\d.]/g, '');\n      y = +matrix.top.replace(/[^-\\d.]/g, '');\n    }\n\n    return { x: x, y: y };\n  },\n  _initIndicators: function () {\n    var interactive = this.options.interactiveScrollbars,\n      customStyle = typeof this.options.scrollbars != 'string',\n      indicators = [],\n      indicator;\n\n    var that = this;\n\n    this.indicators = [];\n\n    if ( this.options.scrollbars ) {\n      // Vertical scrollbar\n      if ( this.options.scrollY ) {\n        indicator = {\n          el: createDefaultScrollbar('v', interactive, this.options.scrollbars),\n          interactive: interactive,\n          defaultScrollbars: true,\n          customStyle: customStyle,\n          resize: this.options.resizeScrollbars,\n          shrink: this.options.shrinkScrollbars,\n          fade: this.options.fadeScrollbars,\n          listenX: false\n        };\n\n        this.wrapper.appendChild(indicator.el);\n        indicators.push(indicator);\n      }\n\n      // Horizontal scrollbar\n      if ( this.options.scrollX ) {\n        indicator = {\n          el: createDefaultScrollbar('h', interactive, this.options.scrollbars),\n          interactive: interactive,\n          defaultScrollbars: true,\n          customStyle: customStyle,\n          resize: this.options.resizeScrollbars,\n          shrink: this.options.shrinkScrollbars,\n          fade: this.options.fadeScrollbars,\n          listenY: false\n        };\n\n        this.wrapper.appendChild(indicator.el);\n        indicators.push(indicator);\n      }\n    }\n\n    if ( this.options.indicators ) {\n      // TODO: check concat compatibility\n      indicators = indicators.concat(this.options.indicators);\n    }\n\n    for ( var i = indicators.length; i--; ) {\n      this.indicators.push( new Indicator(this, indicators[i]) );\n    }\n\n    // TODO: check if we can use array.map (wide compatibility and performance issues)\n    function _indicatorsMap (fn) {\n      if (that.indicators) {\n        for ( var i = that.indicators.length; i--; ) {\n          fn.call(that.indicators[i]);\n        }\n      }\n    }\n\n    if ( this.options.fadeScrollbars ) {\n      this.on('scrollEnd', function () {\n        _indicatorsMap(function () {\n          this.fade();\n        });\n      });\n\n      this.on('scrollCancel', function () {\n        _indicatorsMap(function () {\n          this.fade();\n        });\n      });\n\n      this.on('scrollStart', function () {\n        _indicatorsMap(function () {\n          this.fade(1);\n        });\n      });\n\n      this.on('beforeScrollStart', function () {\n        _indicatorsMap(function () {\n          this.fade(1, true);\n        });\n      });\n    }\n\n\n    this.on('refresh', function () {\n      _indicatorsMap(function () {\n        this.refresh();\n      });\n    });\n\n    this.on('destroy', function () {\n      _indicatorsMap(function () {\n        this.destroy();\n      });\n\n      delete this.indicators;\n    });\n  },\n\n  _initWheel: function () {\n    utils.addEvent(this.wrapper, 'wheel', this); // Firefox 17+\n    utils.addEvent(this.wrapper, 'mousewheel', this); // Chrome, IE, Safari, Opera\n    utils.addEvent(this.wrapper, 'DOMMouseScroll', this); // FF1.0\n\n    this.on('destroy', function () {\n      clearTimeout(this.wheelTimeout);\n      this.wheelTimeout = null;\n      utils.removeEvent(this.wrapper, 'wheel', this);\n      utils.removeEvent(this.wrapper, 'mousewheel', this);\n      utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);\n    });\n  },\n\n  _wheel: function (e) {\n    if ( !this.enabled ) {\n      return;\n    }\n\n    e.preventDefault();\n\n    var wheelDeltaX, wheelDeltaY,\n      newX, newY,\n      that = this;\n\n    if ( this.wheelTimeout === undefined ) {\n      that._execEvent('scrollStart');\n    }\n\n    // Execute the scrollEnd event after 400ms the wheel stopped scrolling\n    clearTimeout(this.wheelTimeout);\n    this.wheelTimeout = setTimeout(function () {\n      if(!that.options.snap) {\n        that._execEvent('scrollEnd');\n      }\n      that.wheelTimeout = undefined;\n    }, 400);\n\n    if ( 'deltaX' in e ) {\n      if (e.deltaMode === 1) {\n        wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;\n        wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;\n      } else {\n// FIXME MARK: not using the mouseWheelSpeed here is a bug??\n        wheelDeltaX = -e.deltaX;\n        wheelDeltaY = -e.deltaY;\n      }\n    } else if ( 'wheelDeltaX' in e ) {\n      wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;\n      wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;\n    } else if ( 'wheelDelta' in e ) {\n      wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;\n    } else if ( 'detail' in e ) {\n      wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;\n    } else {\n      return;\n    }\n\n    wheelDeltaX *= this.options.invertWheelDirection;\n    wheelDeltaY *= this.options.invertWheelDirection;\n\n    if ( !this.hasVerticalScroll ) {\n      wheelDeltaX = wheelDeltaY;\n      wheelDeltaY = 0;\n    }\n\n    if ( this.options.snap ) {\n      newX = this.currentPage.pageX;\n      newY = this.currentPage.pageY;\n\n      if ( wheelDeltaX > 0 ) {\n        newX--;\n      } else if ( wheelDeltaX < 0 ) {\n        newX++;\n      }\n\n      if ( wheelDeltaY > 0 ) {\n        newY--;\n      } else if ( wheelDeltaY < 0 ) {\n        newY++;\n      }\n\n      this.goToPage(newX, newY);\n\n      return;\n    }\n\n    newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);\n    newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);\n\n    this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;\n    this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;\n\n    if ( newX > 0 ) {\n      newX = 0;\n    } else if ( newX < this.maxScrollX ) {\n      newX = this.maxScrollX;\n    }\n\n    if ( newY > 0 ) {\n      newY = 0;\n    } else if ( newY < this.maxScrollY ) {\n      newY = this.maxScrollY;\n    }\n\n    this.scrollTo(newX, newY, 0);\n\n// INSERT POINT: _wheel\n  },\n\n  _initSnap: function () {\n    this.currentPage = {};\n\n    if ( typeof this.options.snap == 'string' ) {\n      this.options.snap = this.scroller.querySelectorAll(this.options.snap);\n    }\n\n    this.on('refresh', function () {\n      var i = 0, l,\n        m = 0, n,\n        cx, cy,\n        x = 0, y,\n        stepX = this.options.snapStepX || this.wrapperWidth,\n        stepY = this.options.snapStepY || this.wrapperHeight,\n        el;\n\n      this.pages = [];\n\n      if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {\n        return;\n      }\n\n      if ( this.options.snap === true ) {\n        cx = Math.round( stepX / 2 );\n        cy = Math.round( stepY / 2 );\n\n        while ( x > -this.scrollerWidth ) {\n          this.pages[i] = [];\n          l = 0;\n          y = 0;\n\n          while ( y > -this.scrollerHeight ) {\n            this.pages[i][l] = {\n              x: Math.max(x, this.maxScrollX),\n              y: Math.max(y, this.maxScrollY),\n              width: stepX,\n              height: stepY,\n              cx: x - cx,\n              cy: y - cy\n            };\n\n            y -= stepY;\n            l++;\n          }\n\n          x -= stepX;\n          i++;\n        }\n      } else {\n        el = this.options.snap;\n        l = el.length;\n        n = -1;\n\n        for ( ; i < l; i++ ) {\n          if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {\n            m = 0;\n            n++;\n          }\n\n          if ( !this.pages[m] ) {\n            this.pages[m] = [];\n          }\n\n          x = Math.max(-el[i].offsetLeft, this.maxScrollX);\n          y = Math.max(-el[i].offsetTop, this.maxScrollY);\n          cx = x - Math.round(el[i].offsetWidth / 2);\n          cy = y - Math.round(el[i].offsetHeight / 2);\n\n          this.pages[m][n] = {\n            x: x,\n            y: y,\n            width: el[i].offsetWidth,\n            height: el[i].offsetHeight,\n            cx: cx,\n            cy: cy\n          };\n\n          if ( x > this.maxScrollX ) {\n            m++;\n          }\n        }\n      }\n\n      this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);\n\n      // Update snap threshold if needed\n      if ( this.options.snapThreshold % 1 === 0 ) {\n        this.snapThresholdX = this.options.snapThreshold;\n        this.snapThresholdY = this.options.snapThreshold;\n      } else {\n        this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);\n        this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);\n      }\n    });\n\n    this.on('flick', function () {\n      console.info(\"FLICK\");\n\n      var time = this.options.snapSpeed || Math.max(\n          Math.max(\n            Math.min(Math.abs(this.x - this.startX), 1000),\n            Math.min(Math.abs(this.y - this.startY), 1000)\n          ), 300);\n\n      this.goToPage(\n        this.currentPage.pageX + this.directionX,\n        this.currentPage.pageY + this.directionY,\n        time\n      );\n    });\n  },\n\n  _nearestSnap: function (x, y) {\n    // MARK ---\n    if (this.options.getNearestSnap)\n    {\n      var snap = this.options.getNearestSnap(x, y, this);\n      return snap;\n    }\n    // --------\n\n    if ( !this.pages.length ) {\n      return { x: 0, y: 0, pageX: 0, pageY: 0 };\n    }\n\n    var i = 0,\n      l = this.pages.length,\n      m = 0;\n\n    // Check if we exceeded the snap threshold\n    if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&\n      Math.abs(y - this.absStartY) < this.snapThresholdY ) {\n      return this.currentPage;\n    }\n\n    if ( x > 0 ) {\n      x = 0;\n    } else if ( x < this.maxScrollX ) {\n      x = this.maxScrollX;\n    }\n\n    if ( y > 0 ) {\n      y = 0;\n    } else if ( y < this.maxScrollY ) {\n      y = this.maxScrollY;\n    }\n\n    for ( ; i < l; i++ ) {\n      if ( x >= this.pages[i][0].cx ) {\n        x = this.pages[i][0].x;\n        break;\n      }\n    }\n\n    l = this.pages[i].length;\n\n    for ( ; m < l; m++ ) {\n      if ( y >= this.pages[0][m].cy ) {\n        y = this.pages[0][m].y;\n        break;\n      }\n    }\n\n    if ( i == this.currentPage.pageX ) {\n      i += this.directionX;\n\n      if ( i < 0 ) {\n        i = 0;\n      } else if ( i >= this.pages.length ) {\n        i = this.pages.length - 1;\n      }\n\n      x = this.pages[i][0].x;\n    }\n\n    if ( m == this.currentPage.pageY ) {\n      m += this.directionY;\n\n      if ( m < 0 ) {\n        m = 0;\n      } else if ( m >= this.pages[0].length ) {\n        m = this.pages[0].length - 1;\n      }\n\n      y = this.pages[0][m].y;\n    }\n\n    return {\n      x: x,\n      y: y,\n      pageX: i,\n      pageY: m\n    };\n  },\n\n  goToPage: function (x, y, time, easing) {\n    easing = easing || this.options.bounceEasing;\n\n    // MARK ---\n    if (this.options.getPage)\n    {\n      var page = this.options.getPage(x, y);\n      var posX = page.x;\n      var posY = page.y;\n\n      time = time === undefined ? this.options.snapSpeed || Math.max(\n        Math.max(\n          Math.min(Math.abs(posX - this.x), 1000),\n          Math.min(Math.abs(posY - this.y), 1000)\n        ), 300) : time;\n\n      this.currentPage = {\n        x: page.x,\n        y: page.y,\n        pageX: page.x,\n        pageY: page.y\n      };\n\n      this.scrollTo(posX, posY, time, easing);\n\n      return;\n    }\n    // --------\n\n\n    if ( x >= this.pages.length ) {\n      x = this.pages.length - 1;\n    } else if ( x < 0 ) {\n      x = 0;\n    }\n\n    if ( y >= this.pages[x].length ) {\n      y = this.pages[x].length - 1;\n    } else if ( y < 0 ) {\n      y = 0;\n    }\n\n    var posX = this.pages[x][y].x,\n      posY = this.pages[x][y].y;\n\n    time = time === undefined ? this.options.snapSpeed || Math.max(\n      Math.max(\n        Math.min(Math.abs(posX - this.x), 1000),\n        Math.min(Math.abs(posY - this.y), 1000)\n      ), 300) : time;\n\n    this.currentPage = {\n      x: posX,\n      y: posY,\n      pageX: x,\n      pageY: y\n    };\n\n    this.scrollTo(posX, posY, time, easing);\n  },\n\n  next: function (time, easing) {\n    var x = this.currentPage.pageX,\n      y = this.currentPage.pageY;\n\n    x++;\n\n    if ( x >= this.pages.length && this.hasVerticalScroll ) {\n      x = 0;\n      y++;\n    }\n\n    this.goToPage(x, y, time, easing);\n  },\n\n  prev: function (time, easing) {\n    var x = this.currentPage.pageX,\n      y = this.currentPage.pageY;\n\n    x--;\n\n    if ( x < 0 && this.hasVerticalScroll ) {\n      x = 0;\n      y--;\n    }\n\n    this.goToPage(x, y, time, easing);\n  },\n\n  _initKeys: function (e) {\n    // default key bindings\n    var keys = {\n      pageUp: 33,\n      pageDown: 34,\n      end: 35,\n      home: 36,\n      left: 37,\n      up: 38,\n      right: 39,\n      down: 40\n    };\n    var i;\n\n    // if you give me characters I give you keycode\n    if ( typeof this.options.keyBindings == 'object' ) {\n      for ( i in this.options.keyBindings ) {\n        if ( typeof this.options.keyBindings[i] == 'string' ) {\n          this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);\n        }\n      }\n    } else {\n      this.options.keyBindings = {};\n    }\n\n    for ( i in keys ) {\n      this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];\n    }\n\n    utils.addEvent(window, 'keydown', this);\n\n    this.on('destroy', function () {\n      utils.removeEvent(window, 'keydown', this);\n    });\n  },\n\n  _key: function (e) {\n    if ( !this.enabled ) {\n      return;\n    }\n\nconsole.log(this.tempid);\n\n    var snap = this.options.snap, // we are using this alot, better to cache it\n      newX = snap ? this.currentPage.pageX : this.x,\n      newY = snap ? this.currentPage.pageY : this.y,\n      now = utils.getTime(),\n      prevTime = this.keyTime || 0,\n      acceleration = 0.250,\n      pos;\n\n    if ( this.options.useTransition && this.isInTransition ) {\n      pos = this.getComputedPosition();\n\n      this._translate(Math.round(pos.x), Math.round(pos.y));\n      this.isInTransition = false;\n    }\n\n    this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;\n\n    switch ( e.keyCode ) {\n      case this.options.keyBindings.pageUp:\n        if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n          newX += snap ? 1 : this.wrapperWidth;\n        } else {\n          newY += snap ? 1 : this.wrapperHeight;\n        }\n        break;\n      case this.options.keyBindings.pageDown:\n        if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n          newX -= snap ? 1 : this.wrapperWidth;\n        } else {\n          newY -= snap ? 1 : this.wrapperHeight;\n        }\n        break;\n      case this.options.keyBindings.end:\n        newX = snap ? this.pages.length-1 : this.maxScrollX;\n        newY = snap ? this.pages[0].length-1 : this.maxScrollY;\n        break;\n      case this.options.keyBindings.home:\n        newX = 0;\n        newY = 0;\n        break;\n      case this.options.keyBindings.left:\n        newX += snap ? -1 : 5 + this.keyAcceleration>>0;\n        break;\n      case this.options.keyBindings.up:\n        newY += snap ? 1 : 5 + this.keyAcceleration>>0;\n        break;\n      case this.options.keyBindings.right:\n        newX -= snap ? -1 : 5 + this.keyAcceleration>>0;\n        break;\n      case this.options.keyBindings.down:\n        newY -= snap ? 1 : 5 + this.keyAcceleration>>0;\n        break;\n      default:\n        return;\n    }\n\n    if ( snap ) {\n      this.goToPage(newX, newY);\n      return;\n    }\n\n    if ( newX > 0 ) {\n      newX = 0;\n      this.keyAcceleration = 0;\n    } else if ( newX < this.maxScrollX ) {\n      newX = this.maxScrollX;\n      this.keyAcceleration = 0;\n    }\n\n    if ( newY > 0 ) {\n      newY = 0;\n      this.keyAcceleration = 0;\n    } else if ( newY < this.maxScrollY ) {\n      newY = this.maxScrollY;\n      this.keyAcceleration = 0;\n    }\n\n    this.scrollTo(newX, newY, 0);\n\n    this.keyTime = now;\n  },\n\n  _animate: function (destX, destY, duration, easingFn) {\n    var that = this,\n      startX = this.x,\n      startY = this.y,\n      startTime = utils.getTime(),\n      destTime = startTime + duration;\n\n//console.log(this.tempid, \"_animate\");\n\n    if (this.animframe) // MARK\n      cancelAnimationFrame(this.animframe); // MARK - Fixed multiple animate/scrollTo's fighting\n\n    function step () {\n//console.log(that.tempid, \"_animate / step\");\n\n      var now = utils.getTime(),\n        newX, newY,\n        easing;\n\n      if ( now >= destTime ) {\n\n//console.log(that.tempid, \"DESTTIME reached\");\n        that.isAnimating = false;\n        that._translate(destX, destY);\n\n        if ( !that.resetPosition(that.options.bounceTime) ) {\n          that._execEvent('scrollEnd');\n        }\n\n        return;\n      }\n\n      now = ( now - startTime ) / duration;\n      easing = easingFn(now);\n      newX = ( destX - startX ) * easing + startX;\n      newY = ( destY - startY ) * easing + startY;\n      that._translate(newX, newY);\n\n      if ( that.isAnimating ) {\n        //rAF(step);\n        that.animframe = rAF(step); // FIXME: Mark fixing multiple scrollTo's, last one ends at timing of first one\n      }\n    }\n\n    this.isAnimating = true;\n    step();\n  },\n  handleEvent: function (e) {\n    switch ( e.type ) {\n      case 'touchstart':\n      case 'pointerdown':\n      case 'MSPointerDown':\n      case 'mousedown':\n        this._start(e);\n        break;\n      case 'touchmove':\n      case 'pointermove':\n      case 'MSPointerMove':\n      case 'mousemove':\n        this._move(e);\n        break;\n      case 'touchend':\n      case 'pointerup':\n      case 'MSPointerUp':\n      case 'mouseup':\n      case 'touchcancel':\n      case 'pointercancel':\n      case 'MSPointerCancel':\n      case 'mousecancel':\n        this._end(e);\n        break;\n      case 'orientationchange':\n      case 'resize':\n        this._resize();\n        break;\n      case 'transitionend':\n      case 'webkitTransitionEnd':\n      //case 'oTransitionEnd': // MARK: only for Opera < 12.10\n      case 'MSTransitionEnd':\n        this._transitionEnd(e);\n        break;\n      case 'wheel':\n      case 'DOMMouseScroll':\n      case 'mousewheel':\n        this._wheel(e);\n        break;\n      case 'keydown':\n        this._key(e);\n        break;\n      case 'click':\n        if ( this.enabled && !e._constructed ) {\n          e.preventDefault();\n          e.stopPropagation();\n        }\n        break;\n    }\n  }\n};\nfunction createDefaultScrollbar (direction, interactive, type) {\n  var scrollbar = document.createElement('div'),\n    indicator = document.createElement('div');\n\n  if ( type === true ) {\n    scrollbar.style.cssText = 'position:absolute;z-index:9999';\n    indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';\n  }\n\n  indicator.className = 'iScrollIndicator';\n\n  if ( direction == 'h' ) {\n    if ( type === true ) {\n      scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';\n      indicator.style.height = '100%';\n    }\n    scrollbar.className = 'iScrollHorizontalScrollbar';\n  } else {\n    if ( type === true ) {\n      scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';\n      indicator.style.width = '100%';\n    }\n    scrollbar.className = 'iScrollVerticalScrollbar';\n  }\n\n  scrollbar.style.cssText += ';overflow:hidden';\n\n  if ( !interactive ) {\n    scrollbar.style.pointerEvents = 'none';\n  }\n\n  scrollbar.appendChild(indicator);\n\n  return scrollbar;\n}\n\nfunction Indicator (scroller, options) {\n  this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;\n  this.wrapperStyle = this.wrapper.style;\n  this.indicator = this.wrapper.children[0];\n  this.indicatorStyle = this.indicator.style;\n  this.scroller = scroller;\n\n  this.options = {\n    listenX: true,\n    listenY: true,\n    interactive: false,\n    resize: true,\n    defaultScrollbars: false,\n    shrink: false,\n    fade: false,\n    speedRatioX: 0,\n    speedRatioY: 0\n  };\n\n  for ( var i in options ) {\n    this.options[i] = options[i];\n  }\n\n  this.sizeRatioX = 1;\n  this.sizeRatioY = 1;\n  this.maxPosX = 0;\n  this.maxPosY = 0;\n\n  if ( this.options.interactive ) {\n    if ( !this.options.disableTouch ) {\n      utils.addEvent(this.indicator, 'touchstart', this);\n      utils.addEvent(window, 'touchend', this);\n    }\n    if ( !this.options.disablePointer ) {\n      utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n      utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);\n    }\n    if ( !this.options.disableMouse ) {\n      utils.addEvent(this.indicator, 'mousedown', this);\n      utils.addEvent(window, 'mouseup', this);\n    }\n  }\n\n  if ( this.options.fade ) {\n    this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;\n    var durationProp = utils.style.transitionDuration;\n    if(!durationProp) {\n      return;\n    }\n    this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';\n    // remove 0.0001ms\n    var self = this;\n    if(utils.isBadAndroid) {\n      rAF(function() {\n        if(self.wrapperStyle[durationProp] === '0.0001ms') {\n          self.wrapperStyle[durationProp] = '0s';\n        }\n      });\n    }\n    this.wrapperStyle.opacity = '0';\n  }\n}\n\nIndicator.prototype = {\n  handleEvent: function (e) {\n    switch ( e.type ) {\n      case 'touchstart':\n      case 'pointerdown':\n      case 'MSPointerDown':\n      case 'mousedown':\n        this._start(e);\n        break;\n      case 'touchmove':\n      case 'pointermove':\n      case 'MSPointerMove':\n      case 'mousemove':\n        this._move(e);\n        break;\n      case 'touchend':\n      case 'pointerup':\n      case 'MSPointerUp':\n      case 'mouseup':\n      case 'touchcancel':\n      case 'pointercancel':\n      case 'MSPointerCancel':\n      case 'mousecancel':\n        this._end(e);\n        break;\n    }\n  },\n\n  destroy: function () {\n    if ( this.options.fadeScrollbars ) {\n      clearTimeout(this.fadeTimeout);\n      this.fadeTimeout = null;\n    }\n    if ( this.options.interactive ) {\n      utils.removeEvent(this.indicator, 'touchstart', this);\n      utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n      utils.removeEvent(this.indicator, 'mousedown', this);\n\n      utils.removeEvent(window, 'touchmove', this);\n      utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n      utils.removeEvent(window, 'mousemove', this);\n\n      utils.removeEvent(window, 'touchend', this);\n      utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);\n      utils.removeEvent(window, 'mouseup', this);\n    }\n\n    if ( this.options.defaultScrollbars ) {\n      this.wrapper.parentNode.removeChild(this.wrapper);\n    }\n  },\n\n  _start: function (e) {\n    var point = e.touches ? e.touches[0] : e;\n\n    e.preventDefault();\n    e.stopPropagation();\n\n    this.transitionTime();\n\n    this.initiated = true;\n    this.moved = false;\n    this.lastPointX = point.pageX;\n    this.lastPointY = point.pageY;\n\n    this.startTime  = utils.getTime();\n\n    if ( !this.options.disableTouch ) {\n      utils.addEvent(window, 'touchmove', this);\n    }\n    if ( !this.options.disablePointer ) {\n      utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);\n    }\n    if ( !this.options.disableMouse ) {\n      utils.addEvent(window, 'mousemove', this);\n    }\n\n    this.scroller._execEvent('beforeScrollStart');\n  },\n\n  _move: function (e) {\n    var point = e.touches ? e.touches[0] : e,\n      deltaX, deltaY,\n      newX, newY,\n      timestamp = utils.getTime();\n\n    if ( !this.moved ) {\n      this.scroller._execEvent('scrollStart');\n    }\n\n    this.moved = true;\n\n    deltaX = point.pageX - this.lastPointX;\n    this.lastPointX = point.pageX;\n\n    deltaY = point.pageY - this.lastPointY;\n    this.lastPointY = point.pageY;\n\n    newX = this.x + deltaX;\n    newY = this.y + deltaY;\n\n    this._pos(newX, newY);\n\n// INSERT POINT: indicator._move\n\n    e.preventDefault();\n    e.stopPropagation();\n  },\n\n  _end: function (e) {\n    if ( !this.initiated ) {\n      return;\n    }\n\n    this.initiated = false;\n\n    e.preventDefault();\n    e.stopPropagation();\n\n    utils.removeEvent(window, 'touchmove', this);\n    utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n    utils.removeEvent(window, 'mousemove', this);\n\n    if ( this.scroller.options.snap ) {\n      var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); // MARK\n\n      var time = this.options.snapSpeed || Math.max(\n          Math.max(\n            Math.min(Math.abs(this.scroller.x - snap.x), 1000),\n            Math.min(Math.abs(this.scroller.y - snap.y), 1000)\n          ), 300);\n\n      if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {\n        this.scroller.directionX = 0;\n        this.scroller.directionY = 0;\n        this.scroller.currentPage = snap;\n        this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);\n      }\n    }\n\n    if ( this.moved ) {\n      this.scroller._execEvent('scrollEnd');\n    }\n  },\n\n  transitionTime: function (time) {\n    time = time || 0;\n    var durationProp = utils.style.transitionDuration;\n    if(!durationProp) {\n      return;\n    }\n\n    this.indicatorStyle[durationProp] = time + 'ms';\n\n    if ( !time && utils.isBadAndroid ) {\n      this.indicatorStyle[durationProp] = '0.0001ms';\n      // remove 0.0001ms\n      var self = this;\n      rAF(function() {\n        if(self.indicatorStyle[durationProp] === '0.0001ms') {\n          self.indicatorStyle[durationProp] = '0s';\n        }\n      });\n    }\n  },\n\n  transitionTimingFunction: function (easing) {\n    this.indicatorStyle[utils.style.transitionTimingFunction] = easing;\n  },\n\n  refresh: function () {\n    if (this.options.overrideMeasurements) // SPC\n      return; // SPC\n\n    this.transitionTime();\n\n    if ( this.options.listenX && !this.options.listenY ) {\n      this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';\n    } else if ( this.options.listenY && !this.options.listenX ) {\n      this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';\n    } else {\n      this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';\n    }\n\n    if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {\n      utils.addClass(this.wrapper, 'iScrollBothScrollbars');\n      utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');\n\n      if ( this.options.defaultScrollbars && this.options.customStyle ) {\n        if ( this.options.listenX ) {\n          this.wrapper.style.right = '8px';\n        } else {\n          this.wrapper.style.bottom = '8px';\n        }\n      }\n    } else {\n      utils.removeClass(this.wrapper, 'iScrollBothScrollbars');\n      utils.addClass(this.wrapper, 'iScrollLoneScrollbar');\n\n      if ( this.options.defaultScrollbars && this.options.customStyle ) {\n        if ( this.options.listenX ) {\n          this.wrapper.style.right = '2px';\n        } else {\n          this.wrapper.style.bottom = '2px';\n        }\n      }\n    }\n\n    var r = this.wrapper.offsetHeight;  // force refresh\n\n    if ( this.options.listenX ) {\n      this.wrapperWidth = this.wrapper.clientWidth;\n      if ( this.options.resize ) {\n        this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);\n        this.indicatorStyle.width = this.indicatorWidth + 'px';\n      } else {\n        this.indicatorWidth = this.indicator.clientWidth;\n      }\n\n      this.maxPosX = this.wrapperWidth - this.indicatorWidth;\n\n      if ( this.options.shrink == 'clip' ) {\n        this.minBoundaryX = -this.indicatorWidth + 8;\n        this.maxBoundaryX = this.wrapperWidth - 8;\n      } else {\n        this.minBoundaryX = 0;\n        this.maxBoundaryX = this.maxPosX;\n      }\n\n      this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));\n    }\n\n    if ( this.options.listenY ) {\n      this.wrapperHeight = this.wrapper.clientHeight;\n      if ( this.options.resize ) {\n        this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);\n        this.indicatorStyle.height = this.indicatorHeight + 'px';\n      } else {\n        this.indicatorHeight = this.indicator.clientHeight;\n      }\n\n      this.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\n      if ( this.options.shrink == 'clip' ) {\n        this.minBoundaryY = -this.indicatorHeight + 8;\n        this.maxBoundaryY = this.wrapperHeight - 8;\n      } else {\n        this.minBoundaryY = 0;\n        this.maxBoundaryY = this.maxPosY;\n      }\n\n      this.maxPosY = this.wrapperHeight - this.indicatorHeight;\n      this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));\n    }\n\n    this.updatePosition();\n  },\n\n  updatePosition: function () {\n    var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,\n      y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;\n\n    if ( !this.options.ignoreBoundaries ) {\n      if ( x < this.minBoundaryX ) {\n        if ( this.options.shrink == 'scale' ) {\n          this.width = Math.max(this.indicatorWidth + x, 8);\n          this.indicatorStyle.width = this.width + 'px';\n        }\n        x = this.minBoundaryX;\n      } else if ( x > this.maxBoundaryX ) {\n        if ( this.options.shrink == 'scale' ) {\n          this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);\n          this.indicatorStyle.width = this.width + 'px';\n          x = this.maxPosX + this.indicatorWidth - this.width;\n        } else {\n          x = this.maxBoundaryX;\n        }\n      } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {\n        this.width = this.indicatorWidth;\n        this.indicatorStyle.width = this.width + 'px';\n      }\n\n      if ( y < this.minBoundaryY ) {\n        if ( this.options.shrink == 'scale' ) {\n          this.height = Math.max(this.indicatorHeight + y * 3, 8);\n          this.indicatorStyle.height = this.height + 'px';\n        }\n        y = this.minBoundaryY;\n      } else if ( y > this.maxBoundaryY ) {\n        if ( this.options.shrink == 'scale' ) {\n          this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);\n          this.indicatorStyle.height = this.height + 'px';\n          y = this.maxPosY + this.indicatorHeight - this.height;\n        } else {\n          y = this.maxBoundaryY;\n        }\n      } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {\n        this.height = this.indicatorHeight;\n        this.indicatorStyle.height = this.height + 'px';\n      }\n    }\n\n    this.x = x;\n    this.y = y;\n\n    if ( this.scroller.options.useTransform ) {\n      this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;\n    } else {\n      this.indicatorStyle.left = x + 'px';\n      this.indicatorStyle.top = y + 'px';\n    }\n  },\n\n  _pos: function (x, y) {\n    if ( x < 0 ) {\n      x = 0;\n    } else if ( x > this.maxPosX ) {\n      x = this.maxPosX;\n    }\n\n    if ( y < 0 ) {\n      y = 0;\n    } else if ( y > this.maxPosY ) {\n      y = this.maxPosY;\n    }\n\n    x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;\n    y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;\n\n    this.scroller.scrollTo(x, y);\n  },\n\n  fade: function (val, hold) {\n    if ( hold && !this.visible ) {\n      return;\n    }\n\n    clearTimeout(this.fadeTimeout);\n    this.fadeTimeout = null;\n\n    var time = val ? 250 : 500,\n      delay = val ? 0 : 300;\n\n    val = val ? '1' : '0';\n\n    this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';\n\n    this.fadeTimeout = setTimeout((function (val) {\n      this.wrapperStyle.opacity = val;\n      this.visible = +val;\n    }).bind(this, val), delay);\n  }\n};\n\nIScroll.utils = utils;\n\nif ( typeof module != 'undefined' && module.exports ) {\n  module.exports = IScroll;\n} else if ( typeof define == 'function' && define.amd ) {\n        define( function () { return IScroll; } );\n} else {\n  window.IScroll = IScroll;\n}\n\n})(window, document, Math);\n","import * as dompack from \"dompack\";\nimport IScroll from \"./iscroll.modified\";\n\nlet tempid = 0;\n\n\nif (!window.__spc_carrousels)\n  window.__spc_carrousels = [];\n\nexport default class SpellcoderCarrousel\n{\n  /*\n  Variables used internally:\n      options\n      node\n      nodes.viewport\n      nodes.content\n      nodes.btn_prev\n      nodes.btn_next\n      items\n      items[].node\n      items[].width\n      items[].height\n      items[].left\n      items[].right\n      items[].usecount - at every animation frame the count is started at 0. It's used to deteremine which index to use in nodecopies.\n      items[].nodecopies - the original carrousel__cell and it's clones. when more clones are needed to fill up the carrousel's viewport, a clone is added on-the-fly.\n\n      items_onscreen - list of nodes in use. used to match after drawing all caroussel-cell's which nodes from the previous animation frame aren't used anymore and must be moved offscreen.\n\n      visiblenodes - rendering information that can be used outside the class for special effects\n\n      scrollleft - the virtual scroll left we internally work with\n      width_content - the size of the content (which will be repeated)\n      width_viewport\n      largestslideheight\n\n      slide_virtualstartidx\n      slide_offset\n\n      activeslideidx\n      activeslidenode\n      alignedslideidx\n      alignedslidenode - the (copy of the) slide which is active\n      alignedslidevirtualidx\n\n      paused // not implemented yet\n  */\n  constructor(node, options)\n  {\n    // DEBUG\n    window.__spc_carrousels.push(this);\n\n    tempid++;\n    this.tempid = tempid;\n\n    // for debugging\n    this.logprefix = \"name\" in options ? \"[SPC/CARROUSEL/\"+options.name+\"]\"\n                                       : \"[SPC/CARROUSEL #\" + this.tempid + \"]\";\n\n    if (!node)\n    {\n      console.error(\"SpellcoderCarrousel got null as node.\");\n      return;\n    }\n\n    var domoptions = dompack.getJSONAttribute(node, \"data-carrousel-options\");\n\n    this.options = Object.assign(\n            { // layout  -----------------------------------------------------------------------\n              gap:                20\n            , slidewidth:         0 // if set, the fixed width (in px) will be used instead of the measures width\n            , height:             0 // to override the automatic height based on slide height\n                                    // (auto slide height doesn't take things like box-shadow's into account and so the overflow: hidden; meant to prevent page overflow will cut off the box-shadows)\n            , updateviewportheight: true // Update the height of our viewport based on the specified height option or height of the slides.\n                                        // Set to TRUE of we want to resize to the slides or our parent have no fixed height\n                                        // Set to FALSE in case our parent has a fixed height which we want to fill (often in an inline/in-the-page slideshow)\n\n            // padding around the content space in which the active slide is positioned\n            , paddingLeft:        0\n            , paddingRight:       0\n\n            /*\n            \"viewport_left\"   - active slide will be at the far left, regardless of paddingLeft\n            \"viewport_middle\" - center the cell in the full space used by the carrousel\n            \"viewport_right\"  - !! not implemented yet\n\n            \"left\" - left\n            \"middle\" - center the cell in the content space (between the paddingLeft and paddingRight)\n            \"right\" - !! not implemented yet\n            */\n            , activeslidealignment:  \"left\"\n            , vertical_align:        \"top\" // \"top\", \"middle\", \"bottom\"\n\n\n            // scroll behaviour -----------------------------------------------------------------\n            , interactable:        true // allow drag, keyboard interaction etc... (if you use multiple carrousels and one is the main)\n            , useiscroll:          true // if false, no scroll animation is performed and no dragging is possible\n            , draggable:           true\n            , snap:                true\n            , blockscrolloncontentleft: false\n            , scroll_deceleration: 0.004 // default of iScroll is 0.0006\n\n\n            // content --------------------------------------------------------------------------\n            , items:                 \"\" // nodeList or string(selectors)\n            , renderinfo:            null\n            , masonry_renderinfo:    [] // renderinfo from Spellcoder Masonry, to turn a Masonry into an Carrousel\n            , contentnode:           null // node in which to place newly clones nodes. for easy grouping (destroying/fade effects)\n\n            , buttonprevious:        null\n            , buttonnext:            null\n            , slideskip:             1\n\n\n            // layout overrides ---------------------------------------------------------------\n            // (use at own risk)\n\n            , contentwidth:          null // amount of pixels after which the content will be repeated\n\n\n            // behaviour ----------------------------------------------------------------------\n\n            , nextSlideDelay:     5000  // ADDME\n            , transitionDuration: 750\n\n            /** allow mouse/touch events to pass, so vertical scrolling keeps working\n               downside is that dragging may cause selections. */\n            , eventPassthrough:   true\n\n            , initialslide:        0       // set to \"none\" to start a left 0 of the original content\n            , activateslidewithclick: true // when clicking on a cell, make it the active slide\n\n            , keyboardnavigation:  true\n\n            , randomizeslides:    false // set to true to randomize the slides on initialization\n\n            /** In case cases you might want to first setup stuff.. or prevent getting a callback before getting the returnvalue of new Carrousel..\n                If this is the case set autodraw_firstframe to false and call drawFrame();\n            */\n            , autodraw_firstframe: true\n\n            , debugoptions:       false // show computer carrousel and iScroll options\n            , debugslides:        false // show debug info in slides\n            , debugdimensions:    false // show debug information on the calculated slides and carrousel dimensions\n            , debugdraw:          false // show debug information on drawing/animation\n\n            , delayfirstframe:    false\n\n            // hooks & internal ---------------------------------------------------------------\n            , ondrawframe:        null // hook to call when a frame is drawn (this is done in an animationframe, usually when the scroll position has changed or an update has been forced)\n            // optimalizations\n            , items_positions_ordered: true // when using as a slideshow, simple horizontal carrousel all images can be placed after eachother and drawing can end upon the first item which is outside the viewport\n                                            // Set this to false if using the carrousel for arbitrary positioned content (for example an masonry)\n            }, domoptions, options);\n\n    this.node = node;\n\n    this.nodes =\n            { dragarea:   this.getSelfOrChild(node, \"carrousel__dragarea\")\n            , viewport:   this.getSelfOrChild(node, \"carrousel__viewport\") // positioning container for items + focus element for keyboard navigation\n            , content:    this.options.contentnode    ? this.options.contentnode : this.getSelfOrChild(node, \"carrousel__content\") // for easy grouping of all items (easy deletion/replacing), falls back to viewport if not existant.. all copies of content will be thrown into this container.\n            , btn_prev:   this.options.buttonprevious ? this.options.buttonprevious : this.getSelfOrChild(node, \"carrousel__previous\")\n            , btn_next:   this.options.buttonnext     ? this.options.buttonnext     : this.getSelfOrChild(node, \"carrousel__next\")\n            };\n\n    //this._addToLog(\"Initialized while document readyState is \" + document.readyState);\n\n    if (this.options.debugoptions)\n    {\n      console.groupCollapsed(this.logprefix);\n      console.log(\"Computed options\", this.options);\n      console.groupEnd();\n    }\n\n    if (!this.nodes.dragarea)\n      this.nodes.dragarea = this.node;\n\n    if (!this.nodes.viewport)\n      this.nodes.viewport = this.node;\n\n    if (!this.nodes.content)\n      this.nodes.content = this.nodes.viewport;\n\n    this.nodes.viewport.tabIndex = -1;\n    this.nodes.viewport.addEventListener(\"keydown\", this.onKeyPress.bind(this));\n\n    this.items = []; // the original slides/carousel-cells\n    this.items_onscreen = [];\n    this.visiblenodes = []; // ADDME: rendering information\n\n    this.scrollleft = 0;\n    this.width_viewport = 0;\n    this.width_content = 0;\n    this.largestslideheight = 0;\n\n    // variables to allow navigation to work during an active scroll\n    // (otherwise we have to freeze the navigation buttons until each previous/next action has completed)\n    this.slide_virtualstartidx = -1; // from which slide we started to slide. used to determine the direction of the scroll.\n    this.slide_offset = 0; // how many items to slide during the current scroll action\n\n    this.activeslideidx = this.options.initialslide;\n    this.activeslidenode = null;\n\n    this.alignedslide = null;\n    this.alignedslideidx = this.options.initialslide;\n    //this.alignedslidevirtualidx = 0;\n    this.alignedslidenode = null;\n\n    this.animationframe = null;\n\n    this.finishedinit = false; // if our content width is 0 we have to delay until this changes\n\n    //this.paused = false;\n\n    if (\"renderinfo\" in options)\n    {\n      this.importRenderInfo(options.renderinfo);\n    }\n    else if (\"masonry_renderinfo\" in options)\n    {\n      this.importSlidesFromMasonry(options.masonry_renderinfo);\n    }\n    else if (\"items\" in options)\n    {\n      if (typeof(options.items) == \"string\") // assume a selector string\n      {\n        console.log(\"items is a selector string\"); // debug\n        let nodes = node.querySelectorAll(options.items);\n        if (nodes.length == 0)\n        {\n          console.warn(\"No slides specified for the carrousel.\");\n          return;\n        }\n\n        this.setSlides(nodes);\n      }\n      else if(options.items instanceof NodeList || options.items instanceof Array)\n      {\n        console.log(\"items is a NodeList\"); // debug\n        this.setSlides(options.items);\n      }\n    }\n    else\n    {\n      let nodes = node.querySelectorAll(\".carrousel__cell\");\n      if (nodes.length == 0)\n      {\n        console.warn(\"No slides specified for the carrousel.\");\n        return;\n      }\n\n      this.setSlides(nodes);\n    }\n\n    if (this.options.contentwidth) // override any calculated (or imported from renderinfo) content width\n      this.width_content = this.options.contentwidth;\n\n    this.__determineContainerWidth();\n\n    this.virtualwidth = 2147483645;\n\n    if (this.options.blockscrolloncontentleft)\n      this.scrollleft = 0; // endless scroll to the right\n    else\n      this.scrollleft = Math.round(this.virtualwidth / 2); // endless scroll to all sides\n\n    this.attemptFinishInit();\n  }\n\n  attemptFinishInit()\n  {\n    if (this.width_content == 0)\n    {\n      console.info(\"Carrousel\", this.options.name, \"cancelled init (content width is 0)\");\n      return;\n    }\n    else\n      console.info(\"Carrousel\", this.options.name, \"is finishing init\");\n\n    let initialx = this.scrollleft;\n\n    if (this.options.initialslide != \"none\")\n    {\n      initialx = this.__getLeftForSlide(this.options.initialslide);\n      if (isNaN(initialx))\n        console.error(\"Cannot determine initial X position. (internal slides info corrupt?)\");\n    }\n    else\n    {\n      //initialx = this.__getContentScrollToVirtualScroll(this.scrollleft);\n      initialx = this.scrollleft - this.scrollleft % this.width_content; // round down to the nearest 0 in content position\n    }\n\n    if (this.options.useiscroll)\n    {\n      let iscrollsettings =\n          { useTransition: false // this would request computed style\n          , tap: true\n          , eventPassthrough: this.options.eventPassthrough\n\n          , deceleration: this.options.scroll_deceleration\n\n          , autoUpdatePosition: false // OVERRIDE\n          , overrideMeasurements: true // OVERRIDE\n\n          , wrapperWidth:  this.width_viewport // don't care // FIXME: care because this influences the momentum\n          , scrollerWidth: 0 // don't care\n\n          , maxScrollX:    this.virtualwidth\n          , startX:        -initialx\n\n          , scrollX: true\n          , scrollY: false\n\n          , snap:           this.options.snap\n          //, snapStepX: this.options.slidewidth\n          , getNearestSnap: this.getNearestSnap.bind(this)\n          , getPage:        this.getPage.bind(this)\n\n          , mouseWheel:     false\n          // mouseWheel disabled, because with mouse as input it's usually very jerky\n          //, mouseWheel:     this.options.interactable && this.options.mouseWheel\n          //mouseWheelSpeed: 20\n/*\n          , disableMouse:   !this.options.interactable\n          , disablePointer: !this.options.interactable\n          , disableTouch:   !this.options.interactable\n*/\n          , name:           \"\" // for debugging purposes\n          };\n\n      if (this.options.debugoptions)\n        console.log(iscrollsettings);\n\n      this.iscroll = new IScroll(this.nodes.dragarea, iscrollsettings);\n      this.iscroll.tempid = this.options.name + \"-iscroll\"; // debug\n\n      this.iscroll.on(\"scrollEnd\", this.onScrollEnd.bind(this));\n\n      if (!this.options.interactable || !this.options.draggable)\n        this.iscroll.disable();\n\n      this.prevtime = -1;\n\n      if (this.nodes.btn_prev)\n      {\n        // FIXME: if within viewport AND using iscroll ??\n//        if (dompack.closest(this.nodes.btn_prev, \".carrousel__viewport\")) // FIXME: look for this.nodes.viewport instead\n//          this.nodes.btn_prev.addEventListener(\"tap\", this.__onPreviousSlideClick.bind(this));\n//        else\n          this.nodes.btn_prev.addEventListener(\"click\", this.__onPreviousSlideClick.bind(this));\n      }\n\n      if (this.nodes.btn_next)\n      {\n//        if (dompack.closest(this.nodes.btn_next, \".carrousel__viewport\")) // FIXME: look for this.nodes.viewport instead\n//          this.nodes.btn_next.addEventListener(\"tap\", this.__onNextSlideClick.bind(this));\n//        else\n          this.nodes.btn_next.addEventListener(\"click\", this.__onNextSlideClick.bind(this));\n      }\n\n      this.nodes.viewport.addEventListener(\"tap\", this.__detectCellTap.bind(this));\n    }\n    else\n    {\n      this.scrollleft = 0;\n      this.scrollleft_next = initialx;\n    }\n\n    this.finishedinit = true;\n\n    if (!this.options.delayfirstframe)\n      this.onAnimFrame(0, true);    \n  }\n\n  destroy()\n  {\n    // prevent eventlisteners keeping iscroll and us alive\n    // (and triggering our onanimframe)\n    this.iscroll.destroy();\n    cancelAnimationFrame(this.animationframe);\n\n    let idx = window.__spc_carrousels.indexOf(this);\n    window.__spc_carrousels.splice(idx, 1);\n\n    /*\n    destroy references\n\n    for(let item of this.items)\n    {\n      for (let node of item.nodecopies)\n        delete node.__iteminfo // remove reference from node to it's rendering/item info object within our carrousel\n\n      item.nodecopies = null;\n    }\n    */\n\n    //this.dead = true;\n  }\n\n  getSelfOrChild(node, classname)\n  {\n    if (node.classList.contains(classname))\n      return node;\n    else\n      return node.querySelector(\".\"+classname);\n  }\n\n  setOptions(options)\n  {\n    //var need_slides_refresh = false;\n    //need_slides_refresh = (\"gap\" in options && gap != this.options.gap);\n\n    Object.assign(this.options, options);\n\n    //if (need_slides_refresh)\n    //  this.__refreshSlidesLayout();\n  }\n\n  onAnimFrame(timestamp, force)\n  {\n//console.log(\"onAnimFrame\", timestamp, force, this.iscroll.x);\n\n    window.cancelAnimationFrame(this.animationframe);\n    this.animationframe = null;\n\n    var dpr = window.devicePixelRatio;\n    if (!dpr)\n      dpr = 1; // fallback for IE10\n\n    var currentpos;\n    if (this.options.useiscroll)\n    {\n      if (isNaN(this.iscroll.x)) // FIXME: find the cause and remove\n      {\n        //console.error(\"ISCROLL's x position is not a number!\");\n        //currentpos = 0;\n        return;\n      }\n      currentpos = -Math.round(this.iscroll.x * dpr) / dpr;\n    }\n    else\n      currentpos = Math.round(this.scrollleft_next * dpr) / dpr;\n\n    if (force || this.scrollleft != currentpos)\n    {\n//       console.log(\"Scrolling:\", this.iscroll.x, dpr, currentpos);\n\n      //console.log(force, this.scrollleft, currentpos);\n\n      this.scrollleft = currentpos;\n      this.__redraw_slides(true);\n    }\n    else\n    {\n      if (this.options.ondrawframe)\n      {\n        var scrollleft = this.scrollleft % this.width_content;\n        //var visible_left = scrollleft;\n        //var visible_right = visible_left + this.width_viewport;\n        this.options.ondrawframe.bind(this)(\n                { scrollleft:   this.scrollleft // scrollposition in the virtual (almost endless) space\n                , contentleft:  scrollleft // scrollposition in the content (xpos in the content where we start in our container)\n                , contentwidth: this.width_content\n                , draw:         false // not drawing\n                });\n      }\n    }\n\n    // schedule the next frame\n    // (!! don't move this to the start of the function, this might create a race condition)\n    if (!this.animationframe)\n      this.animationframe = requestAnimationFrame(this.onAnimFrame.bind(this));\n  }\n\n  /** @short scroll to the x position in the virtual space\n  */\n  scrollTo(newx, animate)\n  {\n    //console.log(this.options.name+\".scrollTo\", newx, animate);\n\n    if (this.options.useiscroll)\n      this.iscroll.scrollTo(-newx, 0, animate ? this.options.transitionDuration : 0);\n    else\n    {\n      console.info(this.options.name + \" no iscroll\");\n      this.scrollleft_next = newx;\n      this.__redraw_slides(true);\n    }\n  }\n\n  scrollBy(offsetx, animate)\n  {\n    //console.log(this.options.name+\".scrollBy\", offsetx, animate);\n\n    if (this.options.useiscroll)\n    {\n      //this.iscroll.scrollTo(-(this.scrollleft + offsetx), 0, animate ? this.options.transitionDuration : 0);\n\n      // We apply the offset to iScroll's internal X since that one hasn't been rounded,\n      // allowing us to scroll with subpixel position (even though we position at whole pixels)\n      this.iscroll.scrollTo(this.iscroll.x - offsetx, 0, animate ? this.options.transitionDuration : 0);\n    }\n    else\n    {\n      console.info(this.options.name + \" no iscroll\");\n      this.scrollleft_next += newx;\n      this.__redraw_slides(true);\n    }\n  }\n\n  /** @short scroll to the (nearest copy of the) content x position\n  */\n  scrollToContent(newx, forward, animate)\n  {\n    let xfloor = Math.floor(this.scrollleft / this.width_content) * this.width_content;\n    let xceil = xfloor + this.width_content;\n\n    if (forward)\n      this.scrollTo(xceil, animate);\n    else\n      this.scrollTo(xfloor, animate);\n  }\n\n  /** @short slide to (a copy of the) specified slide\n  */\n  jumpToSlide(idx, animate, forward)\n  {\n    if (idx >= this.items.length)\n    {\n      console.error(\"Slide #\"+idx+\" doesn't exist.\");\n      return;\n    }\n\n    this.activeslideidx = idx; // FIXME: should we do this here?\n\n    var newx = this.__getLeftForSlide(idx, forward);\n    this.iscroll.scrollTo(-newx, 0, animate ? this.options.transitionDuration : 0);\n  }\n\n  /** @short slide to the virtual slide\n  */\n  jumpToVirtualSlide(virtualidx)\n  {\n    if (virtualidx < 0)\n    {\n      console.error(\"Negative virtual slide idx not supported.\")\n      return;\n    }\n    // ADDME: should we set this.activeslideidx ?\n\n    var newx = this.__getVirtualLeftForSlide(virtualidx);\n    this.iscroll.scrollTo(-newx, 0, this.options.transitionDuration);\n  }\n\n  previousSlide()\n  {\n    if (this.slide_virtualstartidx == -1)\n    {\n      //console.info(\"Restart slide_virtualstartidx\");\n      this.slide_virtualstartidx = this.alignedslidevirtualidx;\n    }\n\n    this.slide_offset -= this.options.slideskip;\n\n    //console.log(\"previousSlide to \", this.slide_virtualstartidx, \"+\", this.slide_offset, \"=\", this.slide_virtualstartidx + this.slide_offset);\n\n    this.jumpToVirtualSlide(this.slide_virtualstartidx + this.slide_offset, true);\n  }\n\n  nextSlide()\n  {\n    if (this.slide_virtualstartidx == -1)\n    {\n      //console.info(\"Restart slide_virtualstartidx\");\n      this.slide_virtualstartidx = this.alignedslidevirtualidx;\n    }\n\n    this.slide_offset += this.options.slideskip;\n\n    if (this.options.name == \"videos\")\n      console.log(\"nextSlide to \", this.slide_virtualstartidx, \"+\", this.slide_offset, \"=\", this.slide_virtualstartidx + this.slide_offset);\n\n    this.jumpToVirtualSlide(this.slide_virtualstartidx + this.slide_offset, true);\n  }\n\n  onScrollEnd()\n  {\n    //console.info(\"onScrollEnd\");\n    this.slide_virtualstartidx = -1;\n    this.slide_offset = 0;\n  }\n\n\n  __determineContainerWidth()\n  {\n    this.width_viewport = this.nodes.viewport.clientWidth;\n\n    if (this.options.debugdimensions)\n      console.log(this.logprefix, \"New carrousel width_viewport is \", this.width_viewport)\n\n    if (this.width_viewport == 0)\n      console.warn(\"clientWidth of carrousel viewport is 0.\");\n  }\n\n  refresh()\n  {\n    this.__determineContainerWidth();\n//    if (this.width_viewport == 0)\n//      return; // nothing to draw\n\n    this.jumpToSlide(this.alignedslideidx, false) // heractiveer deze regel\n\n    this.__redraw_slides(true);\n\n    // reset keyboard navigation information\n    this.slide_virtualstartidx = -1;\n    this.slide_offset = 0;\n  }\n\n  drawFrame()\n  {\n    this.__redraw_slides(true);\n  }\n\n  // PRIVATE //////////////////////////////////////////////////////////////////////////////////\n\n\n\n  importRenderInfo(renderinfo)\n  {\n    this.width_content = renderinfo.width;\n    this.largestslideheight = renderinfo.height; // renderinfo.height; ... TEMP workaround FIXME\n\n//console.info(\"importLayoutArray\", items.length);\n\n    for (let item of renderinfo.items)\n    {\n      // enrich with some internal data\n      item.usecount = 0;\n      item.nodecopies = [item.node];\n\n      this.items_onscreen.push(item.node); // push so refresh() will move these out of view if needed\n\n      item.node.__iteminfo = item;\n    }\n\n    this.items = renderinfo.items;\n\n    this.__relayoutViewport();\n  }\n\n  // @short import items from a Spellcoder Masonry\n  //        Items imported this way aren't placed side by side, but their left position is copied.\n  //        The top style property will be left untouched.\n  importSlidesFromMasonry(renderinfo)\n  {\n    //console.log(renderinfo);\n    if (renderinfo.width == 0)\n    {\n      console.error(\"Cannot import data from masonry, it's width is reported to be 0.\")\n      return;\n    }\n\n    this.width_content = renderinfo.width;\n    this.largestslideheight = renderinfo.height; // renderinfo.height; ... TEMP workaround FIXME\n\n    /*\n    renderinfo.items[] =\n        col: 0\n        cols: 1\n        height: 100\n        left:0\n        node:div.projectview__project\n        top:0\n        width:469\n    */\n\n    for (let item of renderinfo.items)\n    {\n      var iteminfo =\n        { node:       item.node\n        , width:      item.width\n        , width_real: item.width\n        , height:     item.height\n        , left:       item.left\n        , right:      item.left + item.width\n        , usecount:   0\n        , nodecopies: [item.node]\n        };\n      this.items.push(iteminfo);\n      this.items_onscreen.push(item.node); // push so refresh() will move these out of view if needed\n\nitem.node.style.left = \"0\";\n      item.node.__iteminfo = iteminfo;\n    }\n\n    if (this.options.randomizeslides)\n      this._randomizeSlides();\n\n    this.__relayoutViewport();\n  }\n\n//TEST\n  // FIXME: if used again remove all old slides from the DOM ?\n  setSlides(nodes)\n  {\n    if (this.options.debugdimensions)\n      console.info(this.logprefix, \"setSlides\")\n\n    let posx = 0;\n    let largestheight = 0;\n    this.width_content = 0;\n\n    var fixedslidewidth = Math.round(this.options.slidewidth);\n\n    for (let node of nodes)\n    {\n      var width = node.offsetWidth;\n      var height = node.offsetHeight;\n\n      if (height > largestheight)\n        largestheight = height;\n\n      var positionwidth = fixedslidewidth > 0 ? fixedslidewidth : width;\n\n      var iteminfo =\n        { node:       node\n        , width:      positionwidth\n        , width_real: width\n        , height:     height\n\n        , left:       posx\n        , right:      posx + positionwidth\n\n        , usecount:   0      // how many times this slide is shown in the current drawn frame\n        , nodecopies: [node] // cache of all copies of the slide (including the original node)\n        };\n\n      if (fixedslidewidth > 0)\n        iteminfo.left += (positionwidth - width) / 2;\n\n      this.items.push(iteminfo);\n\n      this.items_onscreen.push(node); // push so refresh() will move these out of view if needed\n\n      posx += positionwidth + this.options.gap;\n\n      this.width_content += positionwidth + this.options.gap;\n\n      node.__iteminfo = iteminfo;\n    }\n\n    if (this.options.randomizeslides)\n      this._randomizeSlides();\n\n    this.largestslideheight = largestheight;\n\n    if (this.options.debugdimensions)\n      this._logSlides();\n\n    this.__relayoutViewport();\n  }\n\n  _randomizeSlides()\n  {\n    for (let i = this.items.length - 1; i > 0; --i)\n    {\n      let j = Math.floor(Math.random() * (i + 1));\n\n      let tmp = this.items[i];\n      this.items[i] = this.items[j];\n      this.items[j] = tmp;\n\n      tmp = this.items_onscreen[i];\n      this.items_onscreen[i] = this.items_onscreen[j];\n      this.items_onscreen[j] = tmp;\n    }\n  }\n\n  _addToLog(msg)\n  {\n    console.info(this.logprefix + \" \" + msg);\n  }\n\n  _logSlides()\n  {\n    if (this.options.debugdimensions)\n    {\n      this._addToLog(\"largest slide height is \" + this.largestslideheight);\n      for (let item of this.items)\n        this._addToLog(\"slide is \"+item.width+\"x\"+item.height);\n    }\n  }\n\n  /** @short call when dimension of slides have changes\n  */\n  relayoutSlides()\n  {\n    if (this.options.debugdimensions)\n      console.info(this.logprefix, \"relayoutSlides\")\n\n    let posx = 0;\n    let largestheight = 0;\n    let width_content = 0;\n\n    var fixedslidewidth = Math.round(this.options.slidewidth);\n\n    for (var idx = 0; idx < this.items.length; idx++)\n    {\n      var iteminfo = this.items[idx];\n      //console.log(\"Before\", iteminfo);\n\n      var width = iteminfo.node.offsetWidth;\n      var height = iteminfo.node.offsetHeight;\n\n      if (height > largestheight)\n        largestheight = height;\n\n      var positionwidth = fixedslidewidth > 0 ? fixedslidewidth : width;\n\n      iteminfo.width = positionwidth;\n      iteminfo.width_real = width\n      iteminfo.height = height;\n      iteminfo.left = posx;\n      iteminfo.right = posx + positionwidth;\n      //console.log(\"After\", iteminfo);\n\n      if (fixedslidewidth > 0)\n        iteminfo.left += (positionwidth - width) / 2;\n\n      posx += positionwidth + this.options.gap;\n\n      width_content += positionwidth + this.options.gap;\n    }\n\n    // FIXME: for now everything will get messed up if this.width_content is 0\n    //        so bail here and pages in which a carrousel temporary gets hidden\n    //        will stay working correctly\n    if (width_content == 0)\n    {\n      console.error(\"Content width is 0\");\n      return;\n    }\n\n    this.width_content = width_content;\n    this.largestslideheight = largestheight;\n\n    if (this.options.debugdimensions)\n      this._logSlides();\n\n    this.__relayoutViewport();\n\n    if (!this.finishedinit)\n      this.attemptFinishInit();\n  }\n\n  __relayoutViewport()\n  {\n    this.width_viewport = this.nodes.viewport.clientWidth;\n\n    let newheight = 0;\n    if (this.options.height)\n    {\n      newheight = this.options.height;\n    }\n    else\n    {\n      if (this.options.debugdimensions)\n        console.info(\"No options.height set, using the largestslideheight\");\n\n      newheight = this.largestslideheight;\n    }\n\n    if (this.options.debugdimensions)\n      console.log(\"__relayoutViewport reads width (\", this.width_viewport, \") and sets viewport height to\", newheight);\n\n    if (this.options.updateviewportheight)\n      this.nodes.viewport.style.height = newheight + \"px\";\n  }\n\n  // PRIVATE - UI interaction //////////////////////////////////////////////////////////////////\n\n  onKeyPress(evt)\n  {\n    //if (this.options.debug)\n    //  console.log(evt.keyCode, this.options.interactable, this.options.keyboardnavigation);\n\n    if (!this.options.interactable || !this.options.keyboardnavigation)\n      return;\n\n    switch (evt.keyCode)\n    {\n      case 37: // left arrow\n      {\n        evt.preventDefault();\n        evt.stopPropagation();\n        this.previousSlide();\n        break;\n      }\n\n      case 39: // right arrow\n      {\n        evt.preventDefault();\n        evt.stopPropagation();\n        this.nextSlide();\n        break;\n      }\n\n      case 27: // escape\n      {\n        evt.preventDefault();\n        evt.stopPropagation();\n        dompack.dispatchCustomEvent( this.node\n                                   , \"wh:closeslideshow\"\n                                   , { bubbles:    false // FIXME: or would we ever want this to be true?\n                                     , cancelable: false\n                                     , detail:     { carrousel:          this // for access if no reference was kept or if our event gets dispatched for 'new Carrousel' has returned \"this\".\n                                                   }\n                                     });\n        break;\n      }\n    }\n  }\n\n  __onPreviousSlideClick(evt)\n  {\n    evt.preventDefault();\n    evt.stopPropagation();\n    this.previousSlide(evt);\n  }\n\n  __onNextSlideClick(evt)\n  {\n    evt.preventDefault();\n    evt.stopPropagation();\n\n/*\nSometimes if eventPassThrough is set to true we get double events? (but only in fullscreen slideshow mode?)\n\n    var time = new Date().getTime();\n\n    console.info(\"__onNextSlideClick\", time - this.prevtime);\n\n    if (time - this.prevtime < 200)\n    {\n      console.log(\"again??\");\n      return;\n    }\n    if (time == this.prevtime)\n    {\n      console.warn(\"OI\");\n      return;\n    }\n    this.prevtime = time;\n*/\n//console.trace();\n    this.nextSlide(evt);\n  }\n\n  __detectCellTap(evt)\n  {\n    if (!this.options.activateslidewithclick)\n      return;\n\n    // lookup this node\n    var carrouselcell = dompack.closest(evt.target, \".carrousel__cell\");\n    if (!carrouselcell)\n      return;\n\n    var idx = this.items.indexOf(carrouselcell.__iteminfo);\n\n    if (idx == this.activeslideidx)\n      return; // whe're already in view\n\n    console.info(this.items[idx]); // DEBUG\n\n    var viewport_rect = this.nodes.viewport.getBoundingClientRect();\n    var clickpos = evt.pageX - viewport_rect.left;\n\n    // Whether the content is left or right of the position where the active slide appears\n    // determines whether we scroll forward or backward.\n    var forward = false;\n    switch(this.options.activeslidealignment)\n    {\n      case \"\":\n      case \"viewport_left\":\n          forward = true;\n          break;\n\n      case \"viewport_middle\":\n          forward = clickpos > this.width_viewport / 2;\n          break;\n\n      case \"left\":\n          forward = clickpos > this.options.paddingLeft;\n          break;\n\n      case \"middle\":\n          var contentareawidth = this.width_viewport - this.options.paddingLeft - this.options.paddingRight;\n          var middlex = contentareawidth / 2 + this.options.paddingLeft;\n          forward = clickpos > middlex;\n          break;\n    }\n\n    //console.log(\"Tapped at x position \" + clickpos + \", will now scroll \" + (forward ? \"forward\" : \"backward\"));\n\n    //console.log(evt);\n\n    this.jumpToSlide(idx, true, forward);\n  }\n\n\n  __getVirtualLeftForSlide(virtualidx)\n  {\n    var items = this.items.length;\n    var idx = virtualidx % items;\n    var pages = Math.floor(virtualidx / items);\n    //console.warn(virtualidx, pages, idx);\n\n    var left = (pages * this.width_content) + this.__getActivationCenterForSlide(idx);\n    //console.log(\"__getVirtualLeftForSlide\", pages, \"*\", this.width_content, \"+\", this.__getActivationCenterForSlide(idx));\n\n    return left;\n  }\n\n\n  __getActivationCenterForSlide(idx)\n  {\n    var wanted_left_within_content = this.items[idx].left;\n    switch(this.options.activeslidealignment)\n    {\n      case \"\":\n      case \"viewport_left\":\n          break;\n\n      case \"viewport_middle\":\n          wanted_left_within_content -= (this.width_viewport - this.items[idx].width_real) / 2;\n          break;\n\n      case \"left\":\n          wanted_left_within_content -= this.options.paddingLeft;\n          break;\n\n      case \"middle\":\n          var contentareawidth = this.width_viewport - this.options.paddingLeft - this.options.paddingRight;\n          //console.log(\"middle contentareawidth\", contentareawidth, this.options.paddingLeft, this.options.paddingRight);\n          wanted_left_within_content -= (contentareawidth - this.items[idx].width_real) / 2 + this.options.paddingLeft;\n          break;\n    }\n    return wanted_left_within_content;\n  }\n\n  __getLeftForSlide(idx, forward)\n  {\n    //var orig_idx = idx; // DEBUG\n\n    // get the real item index\n    var idx_neg = idx < 0;\n    var pages;\n    if (idx < 0)\n    {\n      idx++;\n      idx = (this.items.length-1) - (-idx % this.items.length);\n      pages = -Math.floor(-idx % this.items.length);\n    }\n    else\n    {\n      idx = idx % this.items.length;\n      pages = Math.floor(idx / this.items.length);\n    }\n\n    var wanted_left_within_content = this.__getActivationCenterForSlide(idx);\n    console.info(\"wanted_left_within_content\", wanted_left_within_content);\n\n    var left = this.scrollleft + wanted_left_within_content - (this.scrollleft % this.width_content);\n\n    if (forward && left < this.scrollleft)\n      left += this.width_content;\n    else if (!forward && left > this.scrollleft)\n      left -= this.width_content;\n\n    return left;\n  }\n\n  // NOTE: not finished\n  __getContentScrollToVirtualScroll(wanted_left_within_content, forward)\n  {\n// ADDME: forward\n    return this.scrollleft - this.scrollleft % this.width_content + wanted_left_within_content;\n  }\n\n\n  /** @short\n      @param x the page number\n\n      TEST:\n      ctest.iscroll.goToPage(12, 0)\n  */\n  getPage(pageX, pageY)\n  {\n    console.info(\"getPage\");\n\n    if (pageX < 0)\n    {\n      console.error(\"pageX should not be negative.\");\n      pageX = -pageX;\n    }\n\n    var repeatedcontent = Math.floor(pageX / this.items.length);\n    var itemidx = pageX % this.items.length;\n\n    console.log(\"iScroll pageX\", pageX, \"is actually contentrepetition\", repeatedcontent, \" slide #\"+itemidx);\n\n    var val =\n        { x:     - ((repeatedcontent * this.width_content) + this.items[itemidx].left)\n        , y:     0\n        , pageX: pageX //-Math.floor(x / this.width_content)\n        , pageY: pageY\n        };\n\n    console.info(\"getPage\", pageX, \" returns \", val);\n\n    return val;\n  }\n\n// iScroll.currentPage = nearest snap\n\n  getNearestSnap(x, y, iScroll)\n  {\n/*\n    if (this.options.snapto == \"contentstart\")\n    {\n      // (same calculation as in scrollToContent)\n      let xfloor = Math.floor(this.scrollleft / this.width_content) * this.width_content;\n      let xceil = xfloor + this.width_content;\n\n      let distance_to_previous_contentstart = xceil - this.scrollleft;\n      let distance_to_next_contentstart = this.scrollleft - xfloor;\n      let closest = distance_to_next_contentstart < distance_to_previous_contentstart ? xceil : xfloor;\n\n      console.log(this.scrollleft, xfloor, xceil);\n      console.log(distance_to_previous_contentstart, distance_to_next_contentstart, closest);\n\n      var val =\n          { x:     -closest\n          , y:     0\n          , pageX: 1\n          , pageY: 0\n          }\n      return val;\n    }\n*/\n    console.info(\"getNearestSnap\");\n\n    x = -x;\n    this.__redraw_slides(false, x);\n    var renderinfo = this.renderinfo; // renderinfo for this __redraw_slides or the previous one (if render failed due to viewport being 0 wide)\n/*    \n\n    // if we aren't visible (width is 0) we don't ret renderinfo\n    return { x: -this.scrollleft\n           , y: 0\n           , pageX: \n           }\n*/\n\n    //console.log(renderinfo);\n    var val =\n         {// x:     -this.__getLeftForSlide(renderinfo.newactiveslidevirtualidx)\n           x:     -this.__getVirtualLeftForSlide(renderinfo.newactiveslidevirtualidx)\n         , y:     0\n         , pageX: renderinfo.newactiveslidevirtualidx\n         , pageY: 0\n\n         //, _carr_contentrepeat: Math.floor(x / this.width_content)\n         //, _carr_slideidx:      nearestslideidx\n         };\n\n    //console.log(\"getNearestSnap\", val);\n\n    return val;\n  }\n\n  __getActivationX()\n  {\n    var activation_x = 0;//\n    switch(this.options.activeslidealignment)\n    {\n      case \"\":\n      case \"viewport_left\":\n          break;\n\n      case \"viewport_middle\":\n          activation_x = this.width_viewport / 2;\n          break;\n\n      case \"left\":\n          activation_x = this.options.paddingLeft;\n          break;\n\n      case \"middle\":\n          var contentareawidth = this.width_viewport - this.options.paddingLeft - this.options.paddingRight;\n          //console.log(\"middle contentareawidth\", contentareawidth, this.options.paddingLeft, this.options.paddingRight);\n          activation_x = contentareawidth / 2 + this.options.paddingLeft;\n          break;\n    }\n    return activation_x;\n  }\n\n\n  __redraw_slides(draw, override_scrollleft)\n  {\n    if (this.width_viewport == 0 || this.width_content == 0)\n    {\n      //console.error(\"cannot draw, width is 0\");\n      return;\n    }\n\n    if (isNaN(this.scrollleft)) // this should not happen anymore?\n    {\n      console.error(\"scrolleft is NaN\");\n      return;\n    }\n\n    // virtual positions\n    // Our scrolleft must be a round number to prevent blurring\n    // (which will be especially visible when scrolling has ended)\n    var absolute_scrollleft = (override_scrollleft ? override_scrollleft : this.scrollleft);\n    var scrollleft = absolute_scrollleft % this.width_content;\n    var visible_left = scrollleft;\n    var visible_right = visible_left + this.width_viewport;\n\n    if (this.options.ondrawframe && draw)\n      this.options.ondrawframe.bind(this)({ scrollleft:   absolute_scrollleft // scrollposition in the virtual (almost endless) space\n                               , contentleft:  scrollleft // scrollposition in the content (xpos in the content where we start in our container)\n                               , contentwidth: this.width_content\n                               , draw:         true // not drawing\n                               });\n\n\n    if (this.items.length == 0)\n    {\n      //console.warn(\"No slides to draw.\");\n      return;\n    }\n\n\n    var activation_x = this.__getActivationX();\n\n    //console.log(scrollleft, this.options.activeslidealignment, this.width_content, activation_x);\n\n\n    var new_items_onscreen = [];\n    this.visiblenodes = [];\n\n    var items_visible = 0;\n    var itemcount = this.items.length;\n    var draw_itemidx = 0; //first_idx;\n\n    if (this.options.debugdraw)\n    {\n      console.log( \"__redraw_slides()\"\n                 , { scrollleft:     scrollleft\n                   , content_offset: scrollleft\n\n                   , width_content:  this.width_content\n\n                   , visible_left: visible_left\n                   , visible_right: visible_right\n                   });\n    }\n\n\n    // reset the usage counter for each item\n    for (var idx = 0; idx < this.items.length; idx++)\n      this.items[idx].usecount = 0;\n\n    var offsetleft = 0;\n\n    var newactiveslideidx = -1;\n    var newactivenode = null;\n    var newactiveslidevirtualidx = null;\n    var newactiveslide_dist = -1;\n\n    var virtualslideidx = Math.floor( absolute_scrollleft / this.width_content) * this.items.length;\n\n    while(items_visible < 1000) // FIXME: arbitrary workaround to prevent a loop when all items have width 0\n    {\n\nif (items_visible == 999)\n{\n      console.log( \"__redraw_slides() overflow\"\n                 , { absolute_scrollleft: absolute_scrollleft\n                   , scrollleft:     scrollleft\n                   , width_content:  this.width_content\n\n                   , visible_left: visible_left\n                   , visible_right: visible_right\n\n                   , activation_x: activation_x\n\n                   , virtualslideidx: virtualslideidx\n                   });\n}\n\n\n      var item = this.items[draw_itemidx];\n\n//      console.log((item.left + offsetleft) + \" to \" + (item.right + offsetleft));\n\n      if (item.right + offsetleft < visible_left)\n      {\n        // Prepare for the next potential item to draw\n        draw_itemidx++;\n        virtualslideidx++;\n        if (draw_itemidx == itemcount)\n        {\n          draw_itemidx = 0;\n          offsetleft += this.width_content;\n        }\n        continue;\n      }\n\n      // for simple side-by-side scrollers (like a slideshow) we can assume all items after the first out-of-view item is also out-of-view\n      let outofview = item.left + offsetleft > visible_right;\n      if (outofview && this.options.items_positions_ordered)\n        break; // whe are done. whe've gone beyond the visible edge of the viewport.\n      // else !!! FIXME: implement detecting all items in the content being out of view.... or we only stop at our 1000 items cutoff point.\n\n      if (!outofview)\n      {\n        var left_in_viewport = item.left + offsetleft - scrollleft;\n\n        // idx in the \"infinite\" space - calculated to return for debug/render inspection\n        //var virtualslideidx = Math.floor(scrollleft + offsetleft + left_in_viewport) / this.width_content * this.items.length + draw_itemidx); // virtual world idx\n\n        // DRAW ---------------------------------------------------------------------\n        if (draw)\n        {\n          var use_node;\n          if (item.usecount < item.nodecopies.length)\n          {\n            // we can reuse a node\n            use_node = item.nodecopies[item.usecount];\n          }\n          else\n          {\n            // create a new copy of the slide to use\n            use_node = item.node.cloneNode(true);\n            use_node.__iteminfo = item;\n            item.nodecopies.push(use_node);\n            this.nodes.content.appendChild(use_node);\n          }\n\n          // store data which might be usefull when handling events (clicks) in content within a slide\n          use_node._wh_carrouseldata = { slideidx:        draw_itemidx\n                                       , virtualslideidx: virtualslideidx\n                                       };\n  /*\n          if (this.options.debugslides)\n          {\n            var titlenode = item.node.querySelector(\".carrousel__cell-title\");\n            if (titlenode)\n            {\n              // show the virtual slide idx and the idx of the real slide being drawn\n              titlenode.innerText = virtualslideidx + \" / \" + draw_itemidx;\n            }\n          }\n  */\n\n          var centerwithinheight = this.options.height ? this.options.height : this.largestslideheight;\n\n          var offsety = 0;\n          if (this.options.vertical_align == \"middle\")\n            offsety = Math.round(centerwithinheight - item.height) / 2; // FIXME: retina positioning\n          else if (this.options.vertical_align == \"bottom\")\n            offsety = Math.round(centerwithinheight - item.height);\n\n          let transform = \"translate3D(\"+left_in_viewport+\"px,\"+offsety+\"px,0)\";\n\n          if (item.scale)\n            transform += \" scale(\"+item.scale+\")\";\n\n          //use_node.style.webkitTransform = transform; // FIXME: reenable for iOS 8\n          use_node.style.transform = transform;\n\n          // FIXME: This should NOT be done here, implement a callback or event which passes the node which are or will become visible\n          //        and let the fsslideshow code handle this.\n          var imagecontainer = use_node.querySelector(\".carrousel__cell-image\");\n          if (imagecontainer)\n            imagecontainer.style.backgroundImage = \"\"; // FIXME: too specific to use here?? used to allow loading the bgimage from a class/id\n\n    //      console.log(\"Drawing item #\" + draw_itemidx + \" using copy #\" + item.usecount + \" at left: \" + left_in_viewport + \"px\");\n    //      console.log(use_node);\n\n          new_items_onscreen.push(use_node);\n          item.usecount++;\n        }\n        // --------------------------------------------------------------------------\n\n\n        // The slide closest to the activation area will be picked as the alignemnt slide\n        var leftdist = Math.abs(activation_x - left_in_viewport);\n       // var rightdist = Math.abs(activation_x - (left_in_viewport + item.width + this.options.gap/2))\n        var dist = leftdist;// > rightdist ? rightdist : leftdist;\n\n        // ADDME: work-in-progress to collect rendering information to do extra effects in code outside this library\n        this.visiblenodes.push(\n              { x: left_in_viewport\n              , y: offsety\n              , width: item.width\n              , height: item.height\n              });\n\n        if (newactiveslide_dist == -1 || dist < newactiveslide_dist)\n        {\n          //console.log(\"actsl\", virtualslideidx);\n          newactiveslideidx = draw_itemidx;\n          newactivenode = use_node;\n          newactiveslidevirtualidx = virtualslideidx;\n          newactiveslide_dist = dist;\n        }\n      } // if not out of view\n\n\n      // Prepare for the next potential item to draw\n      draw_itemidx++;\n      virtualslideidx++;\n      if (draw_itemidx == itemcount)\n      {\n        draw_itemidx = 0;\n        offsetleft += this.width_content;\n      }\n\n      items_visible++;\n    } // while\n\n    //console.log(items_visible, \"slides visible.\");\n\n    if (items_visible == 0)\n    {\n      //console.error(\"No items to draw??\");\n      return;\n    }\n\n//console.log(\"Old onscreen assets\", this.items_onscreen);\n//console.log(\"New onscreen assets\", new_items_onscreen);\n\n    if (draw)\n    {\n      // remove previously used, but now unused sprites from the view\n      // NOTE: we cannot use visibility or display for this, on iOS this will flush caches and making\n      //       a sprite reappear would cause flicker and stuttering.\n      for (var idx = 0; idx < this.items_onscreen.length; idx++)\n      {\n        var asset = this.items_onscreen[idx];\n        if (new_items_onscreen.indexOf(asset) == -1)\n        {\n          asset.style.webkitTransform = \"translate3D(-50000px,0,0)\";\n          asset.style.transform = \"translate3D(-50000px,0,0)\";\n        }\n      }\n\n      this.items_onscreen = new_items_onscreen;\n\n/*\nif (this.options.name == \"videos\")\n  console.log( \"This frame:\\n\"\n             , \"newactiveslideidx\",        newactiveslideidx, \"\\n\"\n             , \"newactiveslidevirtualidx\", newactiveslidevirtualidx, \"\\n\"\n             , \"slide_virtualstartidx\",    this.slide_virtualstartidx\n             );\n*/\n\n/*\nconsole.log(\"ACTIVE SLIDE\", { current:   this.alignedslidevirtualidx\n                            , new:       newactiveslideidx\n                            , carrousel: this.options.name\n\n                            , node_aligned: this.alignedslidenode\n                            , node_alignnew: newactivenode\n                            });\n*/\n      if (newactiveslideidx > -1)\n      {\n        if (this.alignedslidenode != newactivenode) //newactiveslidevirtualidx != this.alignedslidevirtualidx)\n        {\n          //console.log(\"Distance of active slide to activity-center: \", newactiveslide_dist, newactiveslidevirtualidx);\n          //console.log(\"Activate slide set to \", newactiveslideidx);\n          this.__setActiveSlide(item, newactiveslideidx, newactivenode, newactiveslidevirtualidx);\n        }\n\n        //console.info(\"virtualslideidx-active\", virtualslideidx);\n        this.alignedslideidx = newactiveslideidx;\n        this.alignedslidevirtualidx = newactiveslidevirtualidx;\n      }\n    }\n\n    this.renderinfo =\n           { newactiveslideidx: newactiveslideidx\n           , newactivenode:     newactivenode\n           , newactiveslidevirtualidx: newactiveslidevirtualidx\n           , newactiveslide_dist:      newactiveslide_dist\n           , width_viewport:           this.width_viewport\n           , width_content:            this.width_content\n           };\n\n    return this.renderinfo;\n  } // end of refresh()\n\n\n  __setActiveSlide(item, newactiveslideidx, newactivenode, virtualslideidx)\n  {\n    //console.log(\"Firing wh:activeslidechange\");\n\n    if (this.options.name == \"videos\")\n      console.log(\"New active slide\", newactiveslideidx, newactivenode, \"prev\", this.alignedslidenode);\n\n    if (this.alignedslidenode != newactivenode)\n    {\n      if (this.alignedslidenode)\n        this.alignedslidenode.classList.remove(\"carrousel__cell--aligned\");\n\n      newactivenode.classList.add(\"carrousel__cell--aligned\");\n    }\n\n    // FIXME: although the node getting the class has changed, the actual (original) slide may still be the same\n    dompack.dispatchCustomEvent( this.node\n                               , \"wh:activeslidechange\"\n                               , { bubbles:    false // FIXME: or would we ever want this to be true?\n                                 , cancelable: false\n                                 , detail:     { carrousel:          this // for access if no reference was kept or if our event gets dispatched for 'new Carrousel' has returned \"this\".\n                                               , previousactive:     this.alignedslide\n                                               , previousactiveidx:  this.alignedslideidx\n                                               , previousactivenode: this.alignedslidenode\n                                               , nextactive:         item\n                                               , nextactiveidx:      newactiveslideidx\n                                               , nextactivenode:     newactivenode\n                                               }\n                                 });\n\n    this.activeslide = item;\n    this.alignedslidenode = newactivenode;\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n///////////////////////////////////////////////////////////////////////////////////\n//\n//  Fullscreen slideshow\n//\n\nimport * as dompack from \"dompack\";\nimport Carrousel from \"@webhare/dompack-carrousel\";\n\n\nlet __active_photoviewer = null;\nlet __active_fsslideshow_container = null;\nlet __old_scrolly = 0;\nlet __initialized = false;\n\nfunction refreshFullScreenSlideshow(viewer) {\n  if (viewer.node.clientHeight == 0)\n    return;\n\n  resizeImagesToFitInViewport(viewer.node);\n\n  const options = getDefaultSlideshowOptions();\n  //console.log(\"Slideshow options\", options);\n\n  viewer.setOptions(options);\n  viewer.relayoutSlides();\n  viewer.refresh();\n}\n\n\nfunction resizeActivePhotoviewer() {\n  if (!__active_fsslideshow_container)\n    return;\n\n  if (__active_photoviewer) {\n    console.log(\"update active photoviewer\");\n    refreshFullScreenSlideshow(__active_photoviewer);\n  } else {\n    resizeImagesToFitInViewport(__active_fsslideshow_container);\n  }\n}\n\nfunction doActivateSlideshowByHash(hash) {\n  // we only use the ID part, since we assume the title may change more often than the (whfs/whfssetting)id of an image\n  // (people add titles after first publication of the page, they correct spelling errors)\n  const parts = hash.split(\"-\");\n  const imageid = parts[0]; // assume ID-title\n\n  console.info(\"doActivateSlideshowByHash\", hash);\n\n  // for items with <id>-title make sure to have - at the end so for example 1337 won't be a match when imageid is 133\n  let cell = document.querySelector('.carrousel__cell[data-hash^=\"' + imageid + '-\"]');\n\n  // for items with no title we only have <id>\n  if (!cell)\n    cell = document.querySelector('.carrousel__cell[data-hash=\"' + imageid + '\"]');\n\n  console.info('.carrousel__cell[data-hash=\"' + imageid + ']');\n\n  if (!cell)\n    return;\n\n  // find the first slideshow which has this hash\n  const slideshow = cell.closest(\".photoalbumwidget__slideshow\");\n\n  // lookup the index of the image we have to show\n  const all_items = slideshow.querySelectorAll(\".carrousel__cell\");\n  const itemidx = Array.from(all_items).indexOf(cell);\n\n  ___doActivateSlideshow(slideshow, itemidx);\n}\n\nfunction doActivateSlideshow(instanceid, itemidx) {\n  const containerid = instanceid + \"-slideshow\";\n  const slideshowcontainer = document.getElementById(containerid);\n  if (!slideshowcontainer) {\n    console.error(\"Cannot find slideshow container \", containerid);\n    return;\n  }\n\n  ___doActivateSlideshow(slideshowcontainer, itemidx);\n}\n\nfunction ___doActivateSlideshow(slideshowcontainer, itemidx) {\n  const use_carrousel = slideshowcontainer.hasAttribute(\"data-carrousel-options\");\n\n  if (!__initialized) {\n    window.addEventListener(\"resize\", resizeActivePhotoviewer);\n    __initialized = true;\n  }\n\n  __old_scrolly = document.body.scrollTop || document.documentElement.scrollTop;\n\n\n  document.body.appendChild(slideshowcontainer);\n\n  const carrouselcontainer = slideshowcontainer; //.querySelector(\".carrousel\");\n  carrouselcontainer.addEventListener(\"wh:activeslidechange\", onActiveSlideChange);\n  carrouselcontainer.addEventListener(\"wh:closeslideshow\", doCloseFullscreenSlideshow);\n\n  // FULLSCREEN\n  slideshowcontainer.classList.add(\"html__fullscreenelement\");\n  document.documentElement.classList.add(\"html--onlyfullscreenelement\");\n  slideshowcontainer.classList.add(\"prepare\"); // measure + pre-animation phase\n\n  //console.info(\"Fullscreen carrousel\", options);\n\n  const options = getDefaultSlideshowOptions();\n  resizeImagesToFitInViewport(carrouselcontainer); //carr.node);\n\n  //console.log(\"Slideshow options\", options);\n\n  let carr = carrouselcontainer.__carrousel;\n\n  //if (carr.node.clientHeight == 0)\n  if (carrouselcontainer.clientHeight == 0)\n    console.error(\"Failed to resize fullscreen slideshow.\");\n\n\n\n  if (use_carrousel) {\n    if (!carr) {\n      options.initialslide = itemidx;\n\n      carr = new Carrousel(carrouselcontainer, options);\n\n      // The carrousel must handle the click/taps!!\n      carr.node.addEventListener(\"tap\", detectButtonTaps);\n\n      carrouselcontainer.__carrousel = carr;\n    } else {\n      carr.setOptions(options);\n      carr.relayoutSlides();\n      carr.jumpToSlide(itemidx);\n    }\n\n    carr.drawFrame(); // be sure to have the first frame ready before settings 'visible'\n  } else {\n    slideshowcontainer.addEventListener(\"click\", detectButtonTaps);\n\n    // allow loading of the image\n    const slidenodes = slideshowcontainer.querySelectorAll(\".carrousel__cell-image\");\n    for (const node of slidenodes)\n      node.style.backgroundImage = \"\";\n  }\n\n  document.clientWidth; // Force reflow so the .visible will trigger an transition\n\n  slideshowcontainer.classList.add(\"visible\");\n\n  if (use_carrousel) {\n    // Set focus for keyboard navigation\n    carr.nodes.viewport.focus(); // FIXME: private node info\n  }\n\n  document.body.scrollTop = 0;\n  document.documentElement.scrollTop = 0;\n\n  if (use_carrousel)\n    __active_photoviewer = carrouselcontainer.__carrousel;\n\n  __active_fsslideshow_container = slideshowcontainer;\n}\n\nfunction doCloseFullscreenSlideshow() {\n  const fsscontainer = __active_fsslideshow_container;\n  fsscontainer.classList.remove(\"prepare\");\n  fsscontainer.classList.remove(\"active\");\n\n  // Exit FULLSCREEN\n  fsscontainer.classList.remove(\"html__fullscreenelement\");\n  document.documentElement.classList.remove(\"html--onlyfullscreenelement\");\n\n  // WS2016 specific\n  const headeranim = document.querySelector(\".header__universe\");\n  if (headeranim)\n    headeranim.style.display = \"block\";\n\n  window.scrollTo(0, __old_scrolly);\n\n  __active_photoviewer = null;\n  __active_fsslideshow_container = null;\n\n  history.replaceState(undefined, undefined, \".\");\n}\n\nfunction detectButtonTaps(evt) {\n  const buttonnode = evt.target.closest(\".fsslideshow__button\");\n  if (!buttonnode)\n    return;\n\n  if (buttonnode.classList.contains(\"fsslideshow__close\"))\n    doCloseFullscreenSlideshow();\n}\n\nfunction onActiveSlideChange(evt) {\n  //console.info(evt.detail);\n\n  const slideshowcontainer = evt.target.closest(\".fsslideshow\");\n  const titlenode = slideshowcontainer.querySelector(\".fsslideshow__title\");\n  const downloadbutton = slideshowcontainer.querySelector(\".fsslideshow__download\");\n\n  const carrousel = slideshowcontainer.querySelector(\".carrousel\").__carrousel;\n  const slidenode = evt.detail.nextactivenode;\n\n  // FIXME: carrousel.items.length ... is this evil or allowed?\n  titlenode.textContent = (evt.detail.nextactiveidx + 1) + \"/\" + evt.detail.carrousel.items.length + \" \" + evt.detail.nextactivenode.getAttribute(\"data-title\");\n  downloadbutton.href = slidenode.getAttribute(\"data-download\");\n  downloadbutton.setAttribute(\"download\", slidenode.getAttribute(\"data-filename\"));\n\n  const urlhash = slidenode.getAttribute(\"data-hash\");\n  history.replaceState(undefined, undefined, \"#fsviewer-\" + urlhash);\n}\n\nfunction getDefaultSlideshowOptions() {\n  const viewport_width = window.innerWidth;\n  const viewport_height = window.innerHeight;\n  return {\n    activeslidealignment: \"middle\",\n    vertical_align: \"middle\",\n    gap: viewport_width / 20,\n    slidewidth: viewport_width, //* 0.75\n\n    height: viewport_height, // center within the full height (if we use auto height the box-shadow get's cut off by overflow: hidden;)\n\n    autodraw_firstframe: false,\n\n    // because we are fullscreen we don't need to worry about blocking vertical dragging\n    // of the page on touch devices. We rather prevent dragging causing selections(with mouse)\n    // or unintentionally scrolling the background.\n    eventPassthrough: false\n  };\n}\n\nfunction resizeImagesToFitInViewport(carrouselcontainer) {\n  let viewport_width;\n  let viewport_height;\n\n  getComputedStyle(carrouselcontainer); // Force size calculation\n  const rect = carrouselcontainer.getBoundingClientRect();\n  viewport_width = rect.width;\n  viewport_height = rect.height;\n\n  const maximagewidth = viewport_width * 0.75;\n  const maximageheight = viewport_height - 130;\n\n  let dpr = window.devicePixelRatio;\n  if (!dpr)\n    dpr = 1; // fallback for IE10\n\n  const images = carrouselcontainer.querySelectorAll(\".carrousel__cell-image\");\n  //for (var idx = 0; idx < carrouselcontainer.__carrousel.items.length; idx++)\n  for (let idx = 0; idx < images.length; idx++) {\n    const image = images[idx];\n\n    const orig_w = parseInt(image.getAttribute(\"data-width\"));\n    const orig_h = parseInt(image.getAttribute(\"data-height\"));\n\n    const max_w_stretch = maximagewidth / orig_w;\n    const max_h_stretch = maximageheight / orig_h;\n    const stretch = max_w_stretch < max_h_stretch ? max_w_stretch : max_h_stretch;\n\n    const img_w = Math.round(orig_w * stretch * dpr) / dpr;\n    const img_h = Math.round(orig_h * stretch * dpr) / dpr;\n\n    //console.log(image, orig_w+\"x\"+orig_h, img_w+\"x\"+img_h);\n\n    image.style.width = img_w + \"px\";\n    image.style.height = img_h + \"px\";\n  }\n}\n\n\n\ndompack.register(\".fsslideshow\", (node, idx) => {\n  if (idx != 0)\n    return;\n\n  let hash = window.location.hash;\n\n  if (hash != \"\")\n    hash = hash.substr(1);\n\n  if (hash.substr(0, 9) == \"fsviewer-\") {\n    doActivateSlideshowByHash(hash.substr(9));\n  }\n});\n\n\nmodule.exports = { doActivateSlideshow: doActivateSlideshow };\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n/** @require: var domtemplate = require('@mod-utwente_base/webdesigns/ws2016/src/shared/domtemplate');\n*/\nimport * as dompack from 'dompack';\nimport * as whintegration from '@mod-system/js/wh/integration';\n\nfunction setTextWithLinefeeds(node, message) {\n  message.split(\"\\n\").forEach(function (line, idx) {\n    if (idx == 0) {\n      node.textContent = line;\n    } else {\n      node.appendChild(dompack.create(\"br\"));\n      node.appendChild(document.createTextNode(line));\n    }\n  });\n}\n\n// IE compatibility code\n\nfunction cloneDeep(node, appendto) {\n  for (node = node.firstChild; node; node = node.nextSibling) {\n    const clone = node.cloneNode(false);\n    cloneDeep(node, clone);\n    appendto.appendChild(clone);\n  }\n}\n\nfunction getContent() {\n  const frag = this.ownerDocument.createDocumentFragment();\n  cloneDeep(this, frag);\n  return frag;\n}\n\nfunction iterateNode(data, node) {\n  const list = data[node.getAttribute('data-template-iterate')];\n  node.removeAttribute('data-template-iterate');\n\n  const copies = [];\n  Array.from(list).forEach(function (item) {\n    const copy = node.cloneNode(true);\n    expandNode(item, copy);\n    while (copy.firstChild) {\n      copies.push(copy.firstChild);\n      copy.removeChild(copy.firstChild);\n    }\n  });\n  node.replaceChildren();\n  copies.forEach(copy => node.appendChild(copy));\n}\nfunction repeatNode(data, node, isrepeat) {\n  const list = data[node.getAttribute('data-template-repeat')];\n  node.removeAttribute('data-template-repeat');\n\n  Array.from(list).forEach(function (item) {\n    const copy = node.cloneNode(true);\n    expandNode(item, copy);\n    node.parentNode.insertBefore(copy, node);\n  });\n  node.parentNode.removeChild(node);\n}\n\nfunction decodeSets(instr, data) {\n  if (instr === \"this\")\n    return data;\n  if (typeof instr === \"string\")\n    return data[instr];\n\n  const retval = {};\n  Object.keys(instr).forEach(key => {\n    const subval = decodeSets(instr[key], data);\n    if (subval == undefined)\n      return;\n    retval[key] = subval;\n  });\n  return retval;\n}\n\nfunction expandTemplateContent(clonednode, data, __originalbasenode) //originalbasenode is not an official parameter\n{\n  if (!(\"rangestart\" in clonednode)) //receiving direct node\n  {\n    if (dompack.debugflags.tpl)\n      console.log(\"[tpl] Instantiating node\", __originalbasenode || clonednode, \"with\", data);\n    expandNode(data, clonednode);\n  } else {\n    let next;\n    if (dompack.debugflags.tpl)\n      if (__originalbasenode)\n        console.log(\"[tpl] Instantiating node\", __originalbasenode, \"with\", data);\n      else if (clonednode.rangelimit)\n        console.log(\"[tpl] Instantiating range [\", clonednode.rangestart, \"-\", clonednode.rangelimit, \"[ with\", data);\n      else\n        console.log(\"[tpl] Instantiating range [\", clonednode.rangestart, \"...] with\", data);\n\n    for (let node = clonednode.rangestart; node && node != clonednode.rangelimit; node = next) {\n      next = node.nextSibling;\n      expandNode(data, node);\n    }\n  }\n}\nfunction expandNode(data, node) {\n  if (node.hasAttribute) {\n    //note, repeat runs BEFORE all other handlers, so a data-template-set combined with repeat refers to the iterated data, with iterate to the current data.\n    if (node.hasAttribute('data-template-repeat')) {\n      repeatNode(data, node);\n      return;\n    }\n    if (node.hasAttribute('data-template-set')) {\n      const instructions = dompack.getJSONAttribute(node, \"data-template-set\");\n      const toset = decodeSets(instructions, data);\n      if (toset.textContentBR) //apply with linefeeds\n      {\n        setTextWithLinefeeds(node, toset.textContentBR + '');//force to string incase of number\n        delete toset.textContentBR;\n      }\n      ['style', 'dataset'].forEach(deepkey => {\n        if (toset[deepkey]) {\n          Object.assign(node[deepkey], toset[deepkey]);\n          delete toset[deepkey];\n        }\n      });\n      Object.assign(node, toset); //FIXME moo dependency!\n      node.removeAttribute(\"data-template-set\");\n    }\n    if (node.hasAttribute('data-template-if')) {\n      const tocheck = node.getAttribute(\"data-template-if\").split(\" \");\n      // If field is prefixed with \"!\", the field should NOT be present/filled\n      if (tocheck.some(function (field) {\n        return field && ((field[0] != \"!\" && !data[field])\n          || (field[0] == \"!\" && data[field.substr(1)]));\n      })) {\n        node.parentNode.removeChild(node);\n        return;\n      } else\n        node.removeAttribute(\"data-template-if\");\n    }\n    if (node.hasAttribute('data-template-store'))\n      throw new Error(\"data-template-store is no longer supported\");\n    if (node.hasAttribute('data-template-iterate'))\n      iterateNode(data, node);\n  }\n\n  let subnode = node.firstChild;\n  while (subnode) {\n    const nextnode = subnode.nextSibling;\n    expandNode(data, subnode);\n    subnode = nextnode;\n  }\n\n  if (node.hasAttribute && node.parentNode && node.hasAttribute('data-template-flatten')) {\n    while (node.firstChild)\n      node.parentNode.insertBefore(node.firstChild, node);\n    node.parentNode.removeChild(node);\n  }\n}\nfunction importTemplate(doc, templatenode) {\n  //ADDME: Use getContent directly if the polyfill hasn't been called yet (domready race)\n  let content = templatenode.content;\n  if (!content)\n    content = getContent.apply(templatenode);\n  return doc.importNode(content, true);\n}\nfunction instantiateTemplate(templatenode, data) {\n  const fragment = templatenode.ownerDocument.importNode(templatenode.content, true);\n  expandTemplateContent({ rangestart: fragment.firstChild }, data, templatenode); //pass the original node for easier debugging\n  return fragment;\n}\nfunction expandTemplate(templatenode, data, options) {\n  if (data instanceof Array) //ADDME create one big fragment and insert in one chunk\n  {\n    data.forEach(el => expandTemplate(templatenode, el, options));\n    return;\n  }\n\n  const clone = templatenode.content.cloneNode(true);\n  let toinform = null;\n  let range;\n  if (options && options.injectinto) {\n    beforemarker = options.injectinto.lastChild;\n    options.injectinto.appendChild(clone);\n    toinform = options.injectinto;\n    range = {\n      rangestart: beforemarker ? beforemarker.nextSibling : options.injectinto.firstChild,\n      rangelimit: beforemarker\n    };\n  } else {\n    var beforemarker = templatenode.previousSibling;\n    templatenode.parentNode.insertBefore(clone, templatenode);\n    toinform = templatenode.parentNode;\n    range = {\n      rangestart: beforemarker ? beforemarker.nextSibling : templatenode.parentNode.firstChild,\n      rangelimit: templatenode\n    };\n  }\n\n  expandTemplateContent(range, data);\n\n  dompack.dispatchCustomEvent(toinform, \"wh:template-expandedchild\", //replaceablecomponents listens for this\n    {\n      bubbles: false,\n      cancelable: true\n    });\n}\n\nmodule.exports = {\n  importTemplate: importTemplate,\n  expandTemplate: expandTemplate,\n  expandTemplateContent: expandTemplateContent,\n  instantiate: instantiateTemplate\n};\n","/**\n * EvEmitter v1.1.0\n * Lil' event emitter\n * MIT License\n */\n\n/* jshint unused: true, undef: true, strict: true */\n\n( function( global, factory ) {\n  // universal module definition\n  /* jshint strict: false */ /* globals define, module, window */\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD - RequireJS\n    define( factory );\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS - Browserify, Webpack\n    module.exports = factory();\n  } else {\n    // Browser globals\n    global.EvEmitter = factory();\n  }\n\n}( typeof window != 'undefined' ? window : this, function() {\n\n\"use strict\";\n\nfunction EvEmitter() {}\n\nvar proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n  if ( !eventName || !listener ) {\n    return;\n  }\n  // set events hash\n  var events = this._events = this._events || {};\n  // set listeners array\n  var listeners = events[ eventName ] = events[ eventName ] || [];\n  // only add once\n  if ( listeners.indexOf( listener ) == -1 ) {\n    listeners.push( listener );\n  }\n\n  return this;\n};\n\nproto.once = function( eventName, listener ) {\n  if ( !eventName || !listener ) {\n    return;\n  }\n  // add event\n  this.on( eventName, listener );\n  // set once flag\n  // set onceEvents hash\n  var onceEvents = this._onceEvents = this._onceEvents || {};\n  // set onceListeners object\n  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n  // set flag\n  onceListeners[ listener ] = true;\n\n  return this;\n};\n\nproto.off = function( eventName, listener ) {\n  var listeners = this._events && this._events[ eventName ];\n  if ( !listeners || !listeners.length ) {\n    return;\n  }\n  var index = listeners.indexOf( listener );\n  if ( index != -1 ) {\n    listeners.splice( index, 1 );\n  }\n\n  return this;\n};\n\nproto.emitEvent = function( eventName, args ) {\n  var listeners = this._events && this._events[ eventName ];\n  if ( !listeners || !listeners.length ) {\n    return;\n  }\n  // copy over to avoid interference if .off() in listener\n  listeners = listeners.slice(0);\n  args = args || [];\n  // once stuff\n  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n  for ( var i=0; i < listeners.length; i++ ) {\n    var listener = listeners[i]\n    var isOnce = onceListeners && onceListeners[ listener ];\n    if ( isOnce ) {\n      // remove listener\n      // remove before trigger to prevent recursion\n      this.off( eventName, listener );\n      // unset once flag\n      delete onceListeners[ listener ];\n    }\n    // trigger listener\n    listener.apply( this, args );\n  }\n\n  return this;\n};\n\nproto.allOff = function() {\n  delete this._events;\n  delete this._onceEvents;\n};\n\nreturn EvEmitter;\n\n}));\n","/*!\n * getSize v2.0.3\n * measure size of elements\n * MIT license\n */\n\n/* jshint browser: true, strict: true, undef: true, unused: true */\n/* globals console: false */\n\n( function( window, factory ) {\n  /* jshint strict: false */ /* globals define, module */\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD\n    define( factory );\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory();\n  } else {\n    // browser global\n    window.getSize = factory();\n  }\n\n})( window, function factory() {\n'use strict';\n\n// -------------------------- helpers -------------------------- //\n\n// get a number from a string, not a percentage\nfunction getStyleSize( value ) {\n  var num = parseFloat( value );\n  // not a percent like '100%', and a number\n  var isValid = value.indexOf('%') == -1 && !isNaN( num );\n  return isValid && num;\n}\n\nfunction noop() {}\n\nvar logError = typeof console == 'undefined' ? noop :\n  function( message ) {\n    console.error( message );\n  };\n\n// -------------------------- measurements -------------------------- //\n\nvar measurements = [\n  'paddingLeft',\n  'paddingRight',\n  'paddingTop',\n  'paddingBottom',\n  'marginLeft',\n  'marginRight',\n  'marginTop',\n  'marginBottom',\n  'borderLeftWidth',\n  'borderRightWidth',\n  'borderTopWidth',\n  'borderBottomWidth'\n];\n\nvar measurementsLength = measurements.length;\n\nfunction getZeroSize() {\n  var size = {\n    width: 0,\n    height: 0,\n    innerWidth: 0,\n    innerHeight: 0,\n    outerWidth: 0,\n    outerHeight: 0\n  };\n  for ( var i=0; i < measurementsLength; i++ ) {\n    var measurement = measurements[i];\n    size[ measurement ] = 0;\n  }\n  return size;\n}\n\n// -------------------------- getStyle -------------------------- //\n\n/**\n * getStyle, get style of element, check for Firefox bug\n * https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n */\nfunction getStyle( elem ) {\n  var style = getComputedStyle( elem );\n  if ( !style ) {\n    logError( 'Style returned ' + style +\n      '. Are you running this code in a hidden iframe on Firefox? ' +\n      'See https://bit.ly/getsizebug1' );\n  }\n  return style;\n}\n\n// -------------------------- setup -------------------------- //\n\nvar isSetup = false;\n\nvar isBoxSizeOuter;\n\n/**\n * setup\n * check isBoxSizerOuter\n * do on first getSize() rather than on page load for Firefox bug\n */\nfunction setup() {\n  // setup once\n  if ( isSetup ) {\n    return;\n  }\n  isSetup = true;\n\n  // -------------------------- box sizing -------------------------- //\n\n  /**\n   * Chrome & Safari measure the outer-width on style.width on border-box elems\n   * IE11 & Firefox<29 measures the inner-width\n   */\n  var div = document.createElement('div');\n  div.style.width = '200px';\n  div.style.padding = '1px 2px 3px 4px';\n  div.style.borderStyle = 'solid';\n  div.style.borderWidth = '1px 2px 3px 4px';\n  div.style.boxSizing = 'border-box';\n\n  var body = document.body || document.documentElement;\n  body.appendChild( div );\n  var style = getStyle( div );\n  // round value for browser zoom. desandro/masonry#928\n  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;\n  getSize.isBoxSizeOuter = isBoxSizeOuter;\n\n  body.removeChild( div );\n}\n\n// -------------------------- getSize -------------------------- //\n\nfunction getSize( elem ) {\n  setup();\n\n  // use querySeletor if elem is string\n  if ( typeof elem == 'string' ) {\n    elem = document.querySelector( elem );\n  }\n\n  // do not proceed on non-objects\n  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {\n    return;\n  }\n\n  var style = getStyle( elem );\n\n  // if hidden, everything is 0\n  if ( style.display == 'none' ) {\n    return getZeroSize();\n  }\n\n  var size = {};\n  size.width = elem.offsetWidth;\n  size.height = elem.offsetHeight;\n\n  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';\n\n  // get all measurements\n  for ( var i=0; i < measurementsLength; i++ ) {\n    var measurement = measurements[i];\n    var value = style[ measurement ];\n    var num = parseFloat( value );\n    // any 'auto', 'medium' value will be 0\n    size[ measurement ] = !isNaN( num ) ? num : 0;\n  }\n\n  var paddingWidth = size.paddingLeft + size.paddingRight;\n  var paddingHeight = size.paddingTop + size.paddingBottom;\n  var marginWidth = size.marginLeft + size.marginRight;\n  var marginHeight = size.marginTop + size.marginBottom;\n  var borderWidth = size.borderLeftWidth + size.borderRightWidth;\n  var borderHeight = size.borderTopWidth + size.borderBottomWidth;\n\n  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;\n\n  // overwrite width and height if we can get it from style\n  var styleWidth = getStyleSize( style.width );\n  if ( styleWidth !== false ) {\n    size.width = styleWidth +\n      // add padding and border unless it's already including it\n      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );\n  }\n\n  var styleHeight = getStyleSize( style.height );\n  if ( styleHeight !== false ) {\n    size.height = styleHeight +\n      // add padding and border unless it's already including it\n      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );\n  }\n\n  size.innerWidth = size.width - ( paddingWidth + borderWidth );\n  size.innerHeight = size.height - ( paddingHeight + borderHeight );\n\n  size.outerWidth = size.width + marginWidth;\n  size.outerHeight = size.height + marginHeight;\n\n  return size;\n}\n\nreturn getSize;\n\n});\n","/**\n * matchesSelector v2.0.2\n * matchesSelector( element, '.selector' )\n * MIT license\n */\n\n/*jshint browser: true, strict: true, undef: true, unused: true */\n\n( function( window, factory ) {\n  /*global define: false, module: false */\n  'use strict';\n  // universal module definition\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD\n    define( factory );\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory();\n  } else {\n    // browser global\n    window.matchesSelector = factory();\n  }\n\n}( window, function factory() {\n  'use strict';\n\n  var matchesMethod = ( function() {\n    var ElemProto = window.Element.prototype;\n    // check for the standard method name first\n    if ( ElemProto.matches ) {\n      return 'matches';\n    }\n    // check un-prefixed\n    if ( ElemProto.matchesSelector ) {\n      return 'matchesSelector';\n    }\n    // check vendor prefixes\n    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];\n\n    for ( var i=0; i < prefixes.length; i++ ) {\n      var prefix = prefixes[i];\n      var method = prefix + 'MatchesSelector';\n      if ( ElemProto[ method ] ) {\n        return method;\n      }\n    }\n  })();\n\n  return function matchesSelector( elem, selector ) {\n    return elem[ matchesMethod ]( selector );\n  };\n\n}));\n","/**\n * Fizzy UI utils v2.0.7\n * MIT license\n */\n\n/*jshint browser: true, undef: true, unused: true, strict: true */\n\n( function( window, factory ) {\n  // universal module definition\n  /*jshint strict: false */ /*globals define, module, require */\n\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD\n    define( [\n      'desandro-matches-selector/matches-selector'\n    ], function( matchesSelector ) {\n      return factory( window, matchesSelector );\n    });\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory(\n      window,\n      require('desandro-matches-selector')\n    );\n  } else {\n    // browser global\n    window.fizzyUIUtils = factory(\n      window,\n      window.matchesSelector\n    );\n  }\n\n}( window, function factory( window, matchesSelector ) {\n\n'use strict';\n\nvar utils = {};\n\n// ----- extend ----- //\n\n// extends objects\nutils.extend = function( a, b ) {\n  for ( var prop in b ) {\n    a[ prop ] = b[ prop ];\n  }\n  return a;\n};\n\n// ----- modulo ----- //\n\nutils.modulo = function( num, div ) {\n  return ( ( num % div ) + div ) % div;\n};\n\n// ----- makeArray ----- //\n\nvar arraySlice = Array.prototype.slice;\n\n// turn element or nodeList into an array\nutils.makeArray = function( obj ) {\n  if ( Array.isArray( obj ) ) {\n    // use object if already an array\n    return obj;\n  }\n  // return empty array if undefined or null. #6\n  if ( obj === null || obj === undefined ) {\n    return [];\n  }\n\n  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n  if ( isArrayLike ) {\n    // convert nodeList to array\n    return arraySlice.call( obj );\n  }\n\n  // array of single index\n  return [ obj ];\n};\n\n// ----- removeFrom ----- //\n\nutils.removeFrom = function( ary, obj ) {\n  var index = ary.indexOf( obj );\n  if ( index != -1 ) {\n    ary.splice( index, 1 );\n  }\n};\n\n// ----- getParent ----- //\n\nutils.getParent = function( elem, selector ) {\n  while ( elem.parentNode && elem != document.body ) {\n    elem = elem.parentNode;\n    if ( matchesSelector( elem, selector ) ) {\n      return elem;\n    }\n  }\n};\n\n// ----- getQueryElement ----- //\n\n// use element as selector string\nutils.getQueryElement = function( elem ) {\n  if ( typeof elem == 'string' ) {\n    return document.querySelector( elem );\n  }\n  return elem;\n};\n\n// ----- handleEvent ----- //\n\n// enable .ontype to trigger from .addEventListener( elem, 'type' )\nutils.handleEvent = function( event ) {\n  var method = 'on' + event.type;\n  if ( this[ method ] ) {\n    this[ method ]( event );\n  }\n};\n\n// ----- filterFindElements ----- //\n\nutils.filterFindElements = function( elems, selector ) {\n  // make array of elems\n  elems = utils.makeArray( elems );\n  var ffElems = [];\n\n  elems.forEach( function( elem ) {\n    // check that elem is an actual element\n    if ( !( elem instanceof HTMLElement ) ) {\n      return;\n    }\n    // add elem if no selector\n    if ( !selector ) {\n      ffElems.push( elem );\n      return;\n    }\n    // filter & find items if we have a selector\n    // filter\n    if ( matchesSelector( elem, selector ) ) {\n      ffElems.push( elem );\n    }\n    // find children\n    var childElems = elem.querySelectorAll( selector );\n    // concat childElems to filterFound array\n    for ( var i=0; i < childElems.length; i++ ) {\n      ffElems.push( childElems[i] );\n    }\n  });\n\n  return ffElems;\n};\n\n// ----- debounceMethod ----- //\n\nutils.debounceMethod = function( _class, methodName, threshold ) {\n  threshold = threshold || 100;\n  // original method\n  var method = _class.prototype[ methodName ];\n  var timeoutName = methodName + 'Timeout';\n\n  _class.prototype[ methodName ] = function() {\n    var timeout = this[ timeoutName ];\n    clearTimeout( timeout );\n\n    var args = arguments;\n    var _this = this;\n    this[ timeoutName ] = setTimeout( function() {\n      method.apply( _this, args );\n      delete _this[ timeoutName ];\n    }, threshold );\n  };\n};\n\n// ----- docReady ----- //\n\nutils.docReady = function( callback ) {\n  var readyState = document.readyState;\n  if ( readyState == 'complete' || readyState == 'interactive' ) {\n    // do async to allow for other scripts to run. metafizzy/flickity#441\n    setTimeout( callback );\n  } else {\n    document.addEventListener( 'DOMContentLoaded', callback );\n  }\n};\n\n// ----- htmlInit ----- //\n\n// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/\nutils.toDashed = function( str ) {\n  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {\n    return $1 + '-' + $2;\n  }).toLowerCase();\n};\n\nvar console = window.console;\n/**\n * allow user to initialize classes via [data-namespace] or .js-namespace class\n * htmlInit( Widget, 'widgetName' )\n * options are parsed from data-namespace-options\n */\nutils.htmlInit = function( WidgetClass, namespace ) {\n  utils.docReady( function() {\n    var dashedNamespace = utils.toDashed( namespace );\n    var dataAttr = 'data-' + dashedNamespace;\n    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );\n    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );\n    var elems = utils.makeArray( dataAttrElems )\n      .concat( utils.makeArray( jsDashElems ) );\n    var dataOptionsAttr = dataAttr + '-options';\n    var jQuery = window.jQuery;\n\n    elems.forEach( function( elem ) {\n      var attr = elem.getAttribute( dataAttr ) ||\n        elem.getAttribute( dataOptionsAttr );\n      var options;\n      try {\n        options = attr && JSON.parse( attr );\n      } catch ( error ) {\n        // log error, do not initialize\n        if ( console ) {\n          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +\n          ': ' + error );\n        }\n        return;\n      }\n      // initialize\n      var instance = new WidgetClass( elem, options );\n      // make available via $().data('namespace')\n      if ( jQuery ) {\n        jQuery.data( elem, namespace, instance );\n      }\n    });\n\n  });\n};\n\n// -----  ----- //\n\nreturn utils;\n\n}));\n","/**\n * Outlayer Item\n */\n\n( function( window, factory ) {\n  // universal module definition\n  /* jshint strict: false */ /* globals define, module, require */\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD - RequireJS\n    define( [\n        'ev-emitter/ev-emitter',\n        'get-size/get-size'\n      ],\n      factory\n    );\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS - Browserify, Webpack\n    module.exports = factory(\n      require('ev-emitter'),\n      require('get-size')\n    );\n  } else {\n    // browser global\n    window.Outlayer = {};\n    window.Outlayer.Item = factory(\n      window.EvEmitter,\n      window.getSize\n    );\n  }\n\n}( window, function factory( EvEmitter, getSize ) {\n'use strict';\n\n// ----- helpers ----- //\n\nfunction isEmptyObj( obj ) {\n  for ( var prop in obj ) {\n    return false;\n  }\n  prop = null;\n  return true;\n}\n\n// -------------------------- CSS3 support -------------------------- //\n\n\nvar docElemStyle = document.documentElement.style;\n\nvar transitionProperty = typeof docElemStyle.transition == 'string' ?\n  'transition' : 'WebkitTransition';\nvar transformProperty = typeof docElemStyle.transform == 'string' ?\n  'transform' : 'WebkitTransform';\n\nvar transitionEndEvent = {\n  WebkitTransition: 'webkitTransitionEnd',\n  transition: 'transitionend'\n}[ transitionProperty ];\n\n// cache all vendor properties that could have vendor prefix\nvar vendorProperties = {\n  transform: transformProperty,\n  transition: transitionProperty,\n  transitionDuration: transitionProperty + 'Duration',\n  transitionProperty: transitionProperty + 'Property',\n  transitionDelay: transitionProperty + 'Delay'\n};\n\n// -------------------------- Item -------------------------- //\n\nfunction Item( element, layout ) {\n  if ( !element ) {\n    return;\n  }\n\n  this.element = element;\n  // parent layout class, i.e. Masonry, Isotope, or Packery\n  this.layout = layout;\n  this.position = {\n    x: 0,\n    y: 0\n  };\n\n  this._create();\n}\n\n// inherit EvEmitter\nvar proto = Item.prototype = Object.create( EvEmitter.prototype );\nproto.constructor = Item;\n\nproto._create = function() {\n  // transition objects\n  this._transn = {\n    ingProperties: {},\n    clean: {},\n    onEnd: {}\n  };\n\n  this.css({\n    position: 'absolute'\n  });\n};\n\n// trigger specified handler for event type\nproto.handleEvent = function( event ) {\n  var method = 'on' + event.type;\n  if ( this[ method ] ) {\n    this[ method ]( event );\n  }\n};\n\nproto.getSize = function() {\n  this.size = getSize( this.element );\n};\n\n/**\n * apply CSS styles to element\n * @param {Object} style\n */\nproto.css = function( style ) {\n  var elemStyle = this.element.style;\n\n  for ( var prop in style ) {\n    // use vendor property if available\n    var supportedProp = vendorProperties[ prop ] || prop;\n    elemStyle[ supportedProp ] = style[ prop ];\n  }\n};\n\n // measure position, and sets it\nproto.getPosition = function() {\n  var style = getComputedStyle( this.element );\n  var isOriginLeft = this.layout._getOption('originLeft');\n  var isOriginTop = this.layout._getOption('originTop');\n  var xValue = style[ isOriginLeft ? 'left' : 'right' ];\n  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];\n  var x = parseFloat( xValue );\n  var y = parseFloat( yValue );\n  // convert percent to pixels\n  var layoutSize = this.layout.size;\n  if ( xValue.indexOf('%') != -1 ) {\n    x = ( x / 100 ) * layoutSize.width;\n  }\n  if ( yValue.indexOf('%') != -1 ) {\n    y = ( y / 100 ) * layoutSize.height;\n  }\n  // clean up 'auto' or other non-integer values\n  x = isNaN( x ) ? 0 : x;\n  y = isNaN( y ) ? 0 : y;\n  // remove padding from measurement\n  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;\n  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;\n\n  this.position.x = x;\n  this.position.y = y;\n};\n\n// set settled position, apply padding\nproto.layoutPosition = function() {\n  var layoutSize = this.layout.size;\n  var style = {};\n  var isOriginLeft = this.layout._getOption('originLeft');\n  var isOriginTop = this.layout._getOption('originTop');\n\n  // x\n  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';\n  var xProperty = isOriginLeft ? 'left' : 'right';\n  var xResetProperty = isOriginLeft ? 'right' : 'left';\n\n  var x = this.position.x + layoutSize[ xPadding ];\n  // set in percentage or pixels\n  style[ xProperty ] = this.getXValue( x );\n  // reset other property\n  style[ xResetProperty ] = '';\n\n  // y\n  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';\n  var yProperty = isOriginTop ? 'top' : 'bottom';\n  var yResetProperty = isOriginTop ? 'bottom' : 'top';\n\n  var y = this.position.y + layoutSize[ yPadding ];\n  // set in percentage or pixels\n  style[ yProperty ] = this.getYValue( y );\n  // reset other property\n  style[ yResetProperty ] = '';\n\n  this.css( style );\n  this.emitEvent( 'layout', [ this ] );\n};\n\nproto.getXValue = function( x ) {\n  var isHorizontal = this.layout._getOption('horizontal');\n  return this.layout.options.percentPosition && !isHorizontal ?\n    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';\n};\n\nproto.getYValue = function( y ) {\n  var isHorizontal = this.layout._getOption('horizontal');\n  return this.layout.options.percentPosition && isHorizontal ?\n    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';\n};\n\nproto._transitionTo = function( x, y ) {\n  this.getPosition();\n  // get current x & y from top/left\n  var curX = this.position.x;\n  var curY = this.position.y;\n\n  var didNotMove = x == this.position.x && y == this.position.y;\n\n  // save end position\n  this.setPosition( x, y );\n\n  // if did not move and not transitioning, just go to layout\n  if ( didNotMove && !this.isTransitioning ) {\n    this.layoutPosition();\n    return;\n  }\n\n  var transX = x - curX;\n  var transY = y - curY;\n  var transitionStyle = {};\n  transitionStyle.transform = this.getTranslate( transX, transY );\n\n  this.transition({\n    to: transitionStyle,\n    onTransitionEnd: {\n      transform: this.layoutPosition\n    },\n    isCleaning: true\n  });\n};\n\nproto.getTranslate = function( x, y ) {\n  // flip cooridinates if origin on right or bottom\n  var isOriginLeft = this.layout._getOption('originLeft');\n  var isOriginTop = this.layout._getOption('originTop');\n  x = isOriginLeft ? x : -x;\n  y = isOriginTop ? y : -y;\n  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';\n};\n\n// non transition + transform support\nproto.goTo = function( x, y ) {\n  this.setPosition( x, y );\n  this.layoutPosition();\n};\n\nproto.moveTo = proto._transitionTo;\n\nproto.setPosition = function( x, y ) {\n  this.position.x = parseFloat( x );\n  this.position.y = parseFloat( y );\n};\n\n// ----- transition ----- //\n\n/**\n * @param {Object} style - CSS\n * @param {Function} onTransitionEnd\n */\n\n// non transition, just trigger callback\nproto._nonTransition = function( args ) {\n  this.css( args.to );\n  if ( args.isCleaning ) {\n    this._removeStyles( args.to );\n  }\n  for ( var prop in args.onTransitionEnd ) {\n    args.onTransitionEnd[ prop ].call( this );\n  }\n};\n\n/**\n * proper transition\n * @param {Object} args - arguments\n *   @param {Object} to - style to transition to\n *   @param {Object} from - style to start transition from\n *   @param {Boolean} isCleaning - removes transition styles after transition\n *   @param {Function} onTransitionEnd - callback\n */\nproto.transition = function( args ) {\n  // redirect to nonTransition if no transition duration\n  if ( !parseFloat( this.layout.options.transitionDuration ) ) {\n    this._nonTransition( args );\n    return;\n  }\n\n  var _transition = this._transn;\n  // keep track of onTransitionEnd callback by css property\n  for ( var prop in args.onTransitionEnd ) {\n    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];\n  }\n  // keep track of properties that are transitioning\n  for ( prop in args.to ) {\n    _transition.ingProperties[ prop ] = true;\n    // keep track of properties to clean up when transition is done\n    if ( args.isCleaning ) {\n      _transition.clean[ prop ] = true;\n    }\n  }\n\n  // set from styles\n  if ( args.from ) {\n    this.css( args.from );\n    // force redraw. http://blog.alexmaccaw.com/css-transitions\n    var h = this.element.offsetHeight;\n    // hack for JSHint to hush about unused var\n    h = null;\n  }\n  // enable transition\n  this.enableTransition( args.to );\n  // set styles that are transitioning\n  this.css( args.to );\n\n  this.isTransitioning = true;\n\n};\n\n// dash before all cap letters, including first for\n// WebkitTransform => -webkit-transform\nfunction toDashedAll( str ) {\n  return str.replace( /([A-Z])/g, function( $1 ) {\n    return '-' + $1.toLowerCase();\n  });\n}\n\nvar transitionProps = 'opacity,' + toDashedAll( transformProperty );\n\nproto.enableTransition = function(/* style */) {\n  // HACK changing transitionProperty during a transition\n  // will cause transition to jump\n  if ( this.isTransitioning ) {\n    return;\n  }\n\n  // make `transition: foo, bar, baz` from style object\n  // HACK un-comment this when enableTransition can work\n  // while a transition is happening\n  // var transitionValues = [];\n  // for ( var prop in style ) {\n  //   // dash-ify camelCased properties like WebkitTransition\n  //   prop = vendorProperties[ prop ] || prop;\n  //   transitionValues.push( toDashedAll( prop ) );\n  // }\n  // munge number to millisecond, to match stagger\n  var duration = this.layout.options.transitionDuration;\n  duration = typeof duration == 'number' ? duration + 'ms' : duration;\n  // enable transition styles\n  this.css({\n    transitionProperty: transitionProps,\n    transitionDuration: duration,\n    transitionDelay: this.staggerDelay || 0\n  });\n  // listen for transition end event\n  this.element.addEventListener( transitionEndEvent, this, false );\n};\n\n// ----- events ----- //\n\nproto.onwebkitTransitionEnd = function( event ) {\n  this.ontransitionend( event );\n};\n\nproto.onotransitionend = function( event ) {\n  this.ontransitionend( event );\n};\n\n// properties that I munge to make my life easier\nvar dashedVendorProperties = {\n  '-webkit-transform': 'transform'\n};\n\nproto.ontransitionend = function( event ) {\n  // disregard bubbled events from children\n  if ( event.target !== this.element ) {\n    return;\n  }\n  var _transition = this._transn;\n  // get property name of transitioned property, convert to prefix-free\n  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;\n\n  // remove property that has completed transitioning\n  delete _transition.ingProperties[ propertyName ];\n  // check if any properties are still transitioning\n  if ( isEmptyObj( _transition.ingProperties ) ) {\n    // all properties have completed transitioning\n    this.disableTransition();\n  }\n  // clean style\n  if ( propertyName in _transition.clean ) {\n    // clean up style\n    this.element.style[ event.propertyName ] = '';\n    delete _transition.clean[ propertyName ];\n  }\n  // trigger onTransitionEnd callback\n  if ( propertyName in _transition.onEnd ) {\n    var onTransitionEnd = _transition.onEnd[ propertyName ];\n    onTransitionEnd.call( this );\n    delete _transition.onEnd[ propertyName ];\n  }\n\n  this.emitEvent( 'transitionEnd', [ this ] );\n};\n\nproto.disableTransition = function() {\n  this.removeTransitionStyles();\n  this.element.removeEventListener( transitionEndEvent, this, false );\n  this.isTransitioning = false;\n};\n\n/**\n * removes style property from element\n * @param {Object} style\n**/\nproto._removeStyles = function( style ) {\n  // clean up transition styles\n  var cleanStyle = {};\n  for ( var prop in style ) {\n    cleanStyle[ prop ] = '';\n  }\n  this.css( cleanStyle );\n};\n\nvar cleanTransitionStyle = {\n  transitionProperty: '',\n  transitionDuration: '',\n  transitionDelay: ''\n};\n\nproto.removeTransitionStyles = function() {\n  // remove transition\n  this.css( cleanTransitionStyle );\n};\n\n// ----- stagger ----- //\n\nproto.stagger = function( delay ) {\n  delay = isNaN( delay ) ? 0 : delay;\n  this.staggerDelay = delay + 'ms';\n};\n\n// ----- show/hide/remove ----- //\n\n// remove element from DOM\nproto.removeElem = function() {\n  this.element.parentNode.removeChild( this.element );\n  // remove display: none\n  this.css({ display: '' });\n  this.emitEvent( 'remove', [ this ] );\n};\n\nproto.remove = function() {\n  // just remove element if no transition support or no transition\n  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {\n    this.removeElem();\n    return;\n  }\n\n  // start transition\n  this.once( 'transitionEnd', function() {\n    this.removeElem();\n  });\n  this.hide();\n};\n\nproto.reveal = function() {\n  delete this.isHidden;\n  // remove display: none\n  this.css({ display: '' });\n\n  var options = this.layout.options;\n\n  var onTransitionEnd = {};\n  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');\n  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;\n\n  this.transition({\n    from: options.hiddenStyle,\n    to: options.visibleStyle,\n    isCleaning: true,\n    onTransitionEnd: onTransitionEnd\n  });\n};\n\nproto.onRevealTransitionEnd = function() {\n  // check if still visible\n  // during transition, item may have been hidden\n  if ( !this.isHidden ) {\n    this.emitEvent('reveal');\n  }\n};\n\n/**\n * get style property use for hide/reveal transition end\n * @param {String} styleProperty - hiddenStyle/visibleStyle\n * @returns {String}\n */\nproto.getHideRevealTransitionEndProperty = function( styleProperty ) {\n  var optionStyle = this.layout.options[ styleProperty ];\n  // use opacity\n  if ( optionStyle.opacity ) {\n    return 'opacity';\n  }\n  // get first property\n  for ( var prop in optionStyle ) {\n    return prop;\n  }\n};\n\nproto.hide = function() {\n  // set flag\n  this.isHidden = true;\n  // remove display: none\n  this.css({ display: '' });\n\n  var options = this.layout.options;\n\n  var onTransitionEnd = {};\n  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');\n  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;\n\n  this.transition({\n    from: options.visibleStyle,\n    to: options.hiddenStyle,\n    // keep hidden stuff hidden\n    isCleaning: true,\n    onTransitionEnd: onTransitionEnd\n  });\n};\n\nproto.onHideTransitionEnd = function() {\n  // check if still hidden\n  // during transition, item may have been un-hidden\n  if ( this.isHidden ) {\n    this.css({ display: 'none' });\n    this.emitEvent('hide');\n  }\n};\n\nproto.destroy = function() {\n  this.css({\n    position: '',\n    left: '',\n    right: '',\n    top: '',\n    bottom: '',\n    transition: '',\n    transform: ''\n  });\n};\n\nreturn Item;\n\n}));\n","/*!\n * Outlayer v2.1.1\n * the brains and guts of a layout library\n * MIT license\n */\n\n( function( window, factory ) {\n  'use strict';\n  // universal module definition\n  /* jshint strict: false */ /* globals define, module, require */\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD - RequireJS\n    define( [\n        'ev-emitter/ev-emitter',\n        'get-size/get-size',\n        'fizzy-ui-utils/utils',\n        './item'\n      ],\n      function( EvEmitter, getSize, utils, Item ) {\n        return factory( window, EvEmitter, getSize, utils, Item);\n      }\n    );\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS - Browserify, Webpack\n    module.exports = factory(\n      window,\n      require('ev-emitter'),\n      require('get-size'),\n      require('fizzy-ui-utils'),\n      require('./item')\n    );\n  } else {\n    // browser global\n    window.Outlayer = factory(\n      window,\n      window.EvEmitter,\n      window.getSize,\n      window.fizzyUIUtils,\n      window.Outlayer.Item\n    );\n  }\n\n}( window, function factory( window, EvEmitter, getSize, utils, Item ) {\n'use strict';\n\n// ----- vars ----- //\n\nvar console = window.console;\nvar jQuery = window.jQuery;\nvar noop = function() {};\n\n// -------------------------- Outlayer -------------------------- //\n\n// globally unique identifiers\nvar GUID = 0;\n// internal store of all Outlayer intances\nvar instances = {};\n\n\n/**\n * @param {Element, String} element\n * @param {Object} options\n * @constructor\n */\nfunction Outlayer( element, options ) {\n  var queryElement = utils.getQueryElement( element );\n  if ( !queryElement ) {\n    if ( console ) {\n      console.error( 'Bad element for ' + this.constructor.namespace +\n        ': ' + ( queryElement || element ) );\n    }\n    return;\n  }\n  this.element = queryElement;\n  // add jQuery\n  if ( jQuery ) {\n    this.$element = jQuery( this.element );\n  }\n\n  // options\n  this.options = utils.extend( {}, this.constructor.defaults );\n  this.option( options );\n\n  // add id for Outlayer.getFromElement\n  var id = ++GUID;\n  this.element.outlayerGUID = id; // expando\n  instances[ id ] = this; // associate via id\n\n  // kick it off\n  this._create();\n\n  var isInitLayout = this._getOption('initLayout');\n  if ( isInitLayout ) {\n    this.layout();\n  }\n}\n\n// settings are for internal use only\nOutlayer.namespace = 'outlayer';\nOutlayer.Item = Item;\n\n// default options\nOutlayer.defaults = {\n  containerStyle: {\n    position: 'relative'\n  },\n  initLayout: true,\n  originLeft: true,\n  originTop: true,\n  resize: true,\n  resizeContainer: true,\n  // item options\n  transitionDuration: '0.4s',\n  hiddenStyle: {\n    opacity: 0,\n    transform: 'scale(0.001)'\n  },\n  visibleStyle: {\n    opacity: 1,\n    transform: 'scale(1)'\n  }\n};\n\nvar proto = Outlayer.prototype;\n// inherit EvEmitter\nutils.extend( proto, EvEmitter.prototype );\n\n/**\n * set options\n * @param {Object} opts\n */\nproto.option = function( opts ) {\n  utils.extend( this.options, opts );\n};\n\n/**\n * get backwards compatible option value, check old name\n */\nproto._getOption = function( option ) {\n  var oldOption = this.constructor.compatOptions[ option ];\n  return oldOption && this.options[ oldOption ] !== undefined ?\n    this.options[ oldOption ] : this.options[ option ];\n};\n\nOutlayer.compatOptions = {\n  // currentName: oldName\n  initLayout: 'isInitLayout',\n  horizontal: 'isHorizontal',\n  layoutInstant: 'isLayoutInstant',\n  originLeft: 'isOriginLeft',\n  originTop: 'isOriginTop',\n  resize: 'isResizeBound',\n  resizeContainer: 'isResizingContainer'\n};\n\nproto._create = function() {\n  // get items from children\n  this.reloadItems();\n  // elements that affect layout, but are not laid out\n  this.stamps = [];\n  this.stamp( this.options.stamp );\n  // set container style\n  utils.extend( this.element.style, this.options.containerStyle );\n\n  // bind resize method\n  var canBindResize = this._getOption('resize');\n  if ( canBindResize ) {\n    this.bindResize();\n  }\n};\n\n// goes through all children again and gets bricks in proper order\nproto.reloadItems = function() {\n  // collection of item elements\n  this.items = this._itemize( this.element.children );\n};\n\n\n/**\n * turn elements into Outlayer.Items to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - collection of new Outlayer Items\n */\nproto._itemize = function( elems ) {\n\n  var itemElems = this._filterFindItemElements( elems );\n  var Item = this.constructor.Item;\n\n  // create new Outlayer Items for collection\n  var items = [];\n  for ( var i=0; i < itemElems.length; i++ ) {\n    var elem = itemElems[i];\n    var item = new Item( elem, this );\n    items.push( item );\n  }\n\n  return items;\n};\n\n/**\n * get item elements to be used in layout\n * @param {Array or NodeList or HTMLElement} elems\n * @returns {Array} items - item elements\n */\nproto._filterFindItemElements = function( elems ) {\n  return utils.filterFindElements( elems, this.options.itemSelector );\n};\n\n/**\n * getter method for getting item elements\n * @returns {Array} elems - collection of item elements\n */\nproto.getItemElements = function() {\n  return this.items.map( function( item ) {\n    return item.element;\n  });\n};\n\n// ----- init & layout ----- //\n\n/**\n * lays out all items\n */\nproto.layout = function() {\n  this._resetLayout();\n  this._manageStamps();\n\n  // don't animate first layout\n  var layoutInstant = this._getOption('layoutInstant');\n  var isInstant = layoutInstant !== undefined ?\n    layoutInstant : !this._isLayoutInited;\n  this.layoutItems( this.items, isInstant );\n\n  // flag for initalized\n  this._isLayoutInited = true;\n};\n\n// _init is alias for layout\nproto._init = proto.layout;\n\n/**\n * logic before any new layout\n */\nproto._resetLayout = function() {\n  this.getSize();\n};\n\n\nproto.getSize = function() {\n  this.size = getSize( this.element );\n};\n\n/**\n * get measurement from option, for columnWidth, rowHeight, gutter\n * if option is String -> get element from selector string, & get size of element\n * if option is Element -> get size of element\n * else use option as a number\n *\n * @param {String} measurement\n * @param {String} size - width or height\n * @private\n */\nproto._getMeasurement = function( measurement, size ) {\n  var option = this.options[ measurement ];\n  var elem;\n  if ( !option ) {\n    // default to 0\n    this[ measurement ] = 0;\n  } else {\n    // use option as an element\n    if ( typeof option == 'string' ) {\n      elem = this.element.querySelector( option );\n    } else if ( option instanceof HTMLElement ) {\n      elem = option;\n    }\n    // use size of element, if element\n    this[ measurement ] = elem ? getSize( elem )[ size ] : option;\n  }\n};\n\n/**\n * layout a collection of item elements\n * @api public\n */\nproto.layoutItems = function( items, isInstant ) {\n  items = this._getItemsForLayout( items );\n\n  this._layoutItems( items, isInstant );\n\n  this._postLayout();\n};\n\n/**\n * get the items to be laid out\n * you may want to skip over some items\n * @param {Array} items\n * @returns {Array} items\n */\nproto._getItemsForLayout = function( items ) {\n  return items.filter( function( item ) {\n    return !item.isIgnored;\n  });\n};\n\n/**\n * layout items\n * @param {Array} items\n * @param {Boolean} isInstant\n */\nproto._layoutItems = function( items, isInstant ) {\n  this._emitCompleteOnItems( 'layout', items );\n\n  if ( !items || !items.length ) {\n    // no items, emit event with empty array\n    return;\n  }\n\n  var queue = [];\n\n  items.forEach( function( item ) {\n    // get x/y object from method\n    var position = this._getItemLayoutPosition( item );\n    // enqueue\n    position.item = item;\n    position.isInstant = isInstant || item.isLayoutInstant;\n    queue.push( position );\n  }, this );\n\n  this._processLayoutQueue( queue );\n};\n\n/**\n * get item layout position\n * @param {Outlayer.Item} item\n * @returns {Object} x and y position\n */\nproto._getItemLayoutPosition = function( /* item */ ) {\n  return {\n    x: 0,\n    y: 0\n  };\n};\n\n/**\n * iterate over array and position each item\n * Reason being - separating this logic prevents 'layout invalidation'\n * thx @paul_irish\n * @param {Array} queue\n */\nproto._processLayoutQueue = function( queue ) {\n  this.updateStagger();\n  queue.forEach( function( obj, i ) {\n    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );\n  }, this );\n};\n\n// set stagger from option in milliseconds number\nproto.updateStagger = function() {\n  var stagger = this.options.stagger;\n  if ( stagger === null || stagger === undefined ) {\n    this.stagger = 0;\n    return;\n  }\n  this.stagger = getMilliseconds( stagger );\n  return this.stagger;\n};\n\n/**\n * Sets position of item in DOM\n * @param {Outlayer.Item} item\n * @param {Number} x - horizontal position\n * @param {Number} y - vertical position\n * @param {Boolean} isInstant - disables transitions\n */\nproto._positionItem = function( item, x, y, isInstant, i ) {\n  if ( isInstant ) {\n    // if not transition, just set CSS\n    item.goTo( x, y );\n  } else {\n    item.stagger( i * this.stagger );\n    item.moveTo( x, y );\n  }\n};\n\n/**\n * Any logic you want to do after each layout,\n * i.e. size the container\n */\nproto._postLayout = function() {\n  this.resizeContainer();\n};\n\nproto.resizeContainer = function() {\n  var isResizingContainer = this._getOption('resizeContainer');\n  if ( !isResizingContainer ) {\n    return;\n  }\n  var size = this._getContainerSize();\n  if ( size ) {\n    this._setContainerMeasure( size.width, true );\n    this._setContainerMeasure( size.height, false );\n  }\n};\n\n/**\n * Sets width or height of container if returned\n * @returns {Object} size\n *   @param {Number} width\n *   @param {Number} height\n */\nproto._getContainerSize = noop;\n\n/**\n * @param {Number} measure - size of width or height\n * @param {Boolean} isWidth\n */\nproto._setContainerMeasure = function( measure, isWidth ) {\n  if ( measure === undefined ) {\n    return;\n  }\n\n  var elemSize = this.size;\n  // add padding and border width if border box\n  if ( elemSize.isBorderBox ) {\n    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +\n      elemSize.borderLeftWidth + elemSize.borderRightWidth :\n      elemSize.paddingBottom + elemSize.paddingTop +\n      elemSize.borderTopWidth + elemSize.borderBottomWidth;\n  }\n\n  measure = Math.max( measure, 0 );\n  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';\n};\n\n/**\n * emit eventComplete on a collection of items events\n * @param {String} eventName\n * @param {Array} items - Outlayer.Items\n */\nproto._emitCompleteOnItems = function( eventName, items ) {\n  var _this = this;\n  function onComplete() {\n    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );\n  }\n\n  var count = items.length;\n  if ( !items || !count ) {\n    onComplete();\n    return;\n  }\n\n  var doneCount = 0;\n  function tick() {\n    doneCount++;\n    if ( doneCount == count ) {\n      onComplete();\n    }\n  }\n\n  // bind callback\n  items.forEach( function( item ) {\n    item.once( eventName, tick );\n  });\n};\n\n/**\n * emits events via EvEmitter and jQuery events\n * @param {String} type - name of event\n * @param {Event} event - original event\n * @param {Array} args - extra arguments\n */\nproto.dispatchEvent = function( type, event, args ) {\n  // add original event to arguments\n  var emitArgs = event ? [ event ].concat( args ) : args;\n  this.emitEvent( type, emitArgs );\n\n  if ( jQuery ) {\n    // set this.$element\n    this.$element = this.$element || jQuery( this.element );\n    if ( event ) {\n      // create jQuery event\n      var $event = jQuery.Event( event );\n      $event.type = type;\n      this.$element.trigger( $event, args );\n    } else {\n      // just trigger with type if no event available\n      this.$element.trigger( type, args );\n    }\n  }\n};\n\n// -------------------------- ignore & stamps -------------------------- //\n\n\n/**\n * keep item in collection, but do not lay it out\n * ignored items do not get skipped in layout\n * @param {Element} elem\n */\nproto.ignore = function( elem ) {\n  var item = this.getItem( elem );\n  if ( item ) {\n    item.isIgnored = true;\n  }\n};\n\n/**\n * return item to layout collection\n * @param {Element} elem\n */\nproto.unignore = function( elem ) {\n  var item = this.getItem( elem );\n  if ( item ) {\n    delete item.isIgnored;\n  }\n};\n\n/**\n * adds elements to stamps\n * @param {NodeList, Array, Element, or String} elems\n */\nproto.stamp = function( elems ) {\n  elems = this._find( elems );\n  if ( !elems ) {\n    return;\n  }\n\n  this.stamps = this.stamps.concat( elems );\n  // ignore\n  elems.forEach( this.ignore, this );\n};\n\n/**\n * removes elements to stamps\n * @param {NodeList, Array, or Element} elems\n */\nproto.unstamp = function( elems ) {\n  elems = this._find( elems );\n  if ( !elems ){\n    return;\n  }\n\n  elems.forEach( function( elem ) {\n    // filter out removed stamp elements\n    utils.removeFrom( this.stamps, elem );\n    this.unignore( elem );\n  }, this );\n};\n\n/**\n * finds child elements\n * @param {NodeList, Array, Element, or String} elems\n * @returns {Array} elems\n */\nproto._find = function( elems ) {\n  if ( !elems ) {\n    return;\n  }\n  // if string, use argument as selector string\n  if ( typeof elems == 'string' ) {\n    elems = this.element.querySelectorAll( elems );\n  }\n  elems = utils.makeArray( elems );\n  return elems;\n};\n\nproto._manageStamps = function() {\n  if ( !this.stamps || !this.stamps.length ) {\n    return;\n  }\n\n  this._getBoundingRect();\n\n  this.stamps.forEach( this._manageStamp, this );\n};\n\n// update boundingLeft / Top\nproto._getBoundingRect = function() {\n  // get bounding rect for container element\n  var boundingRect = this.element.getBoundingClientRect();\n  var size = this.size;\n  this._boundingRect = {\n    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,\n    top: boundingRect.top + size.paddingTop + size.borderTopWidth,\n    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),\n    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )\n  };\n};\n\n/**\n * @param {Element} stamp\n**/\nproto._manageStamp = noop;\n\n/**\n * get x/y position of element relative to container element\n * @param {Element} elem\n * @returns {Object} offset - has left, top, right, bottom\n */\nproto._getElementOffset = function( elem ) {\n  var boundingRect = elem.getBoundingClientRect();\n  var thisRect = this._boundingRect;\n  var size = getSize( elem );\n  var offset = {\n    left: boundingRect.left - thisRect.left - size.marginLeft,\n    top: boundingRect.top - thisRect.top - size.marginTop,\n    right: thisRect.right - boundingRect.right - size.marginRight,\n    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom\n  };\n  return offset;\n};\n\n// -------------------------- resize -------------------------- //\n\n// enable event handlers for listeners\n// i.e. resize -> onresize\nproto.handleEvent = utils.handleEvent;\n\n/**\n * Bind layout to window resizing\n */\nproto.bindResize = function() {\n  window.addEventListener( 'resize', this );\n  this.isResizeBound = true;\n};\n\n/**\n * Unbind layout to window resizing\n */\nproto.unbindResize = function() {\n  window.removeEventListener( 'resize', this );\n  this.isResizeBound = false;\n};\n\nproto.onresize = function() {\n  this.resize();\n};\n\nutils.debounceMethod( Outlayer, 'onresize', 100 );\n\nproto.resize = function() {\n  // don't trigger if size did not change\n  // or if resize was unbound. See #9\n  if ( !this.isResizeBound || !this.needsResizeLayout() ) {\n    return;\n  }\n\n  this.layout();\n};\n\n/**\n * check if layout is needed post layout\n * @returns Boolean\n */\nproto.needsResizeLayout = function() {\n  var size = getSize( this.element );\n  // check that this.size and size are there\n  // IE8 triggers resize on body size change, so they might not be\n  var hasSizes = this.size && size;\n  return hasSizes && size.innerWidth !== this.size.innerWidth;\n};\n\n// -------------------------- methods -------------------------- //\n\n/**\n * add items to Outlayer instance\n * @param {Array or NodeList or Element} elems\n * @returns {Array} items - Outlayer.Items\n**/\nproto.addItems = function( elems ) {\n  var items = this._itemize( elems );\n  // add items to collection\n  if ( items.length ) {\n    this.items = this.items.concat( items );\n  }\n  return items;\n};\n\n/**\n * Layout newly-appended item elements\n * @param {Array or NodeList or Element} elems\n */\nproto.appended = function( elems ) {\n  var items = this.addItems( elems );\n  if ( !items.length ) {\n    return;\n  }\n  // layout and reveal just the new items\n  this.layoutItems( items, true );\n  this.reveal( items );\n};\n\n/**\n * Layout prepended elements\n * @param {Array or NodeList or Element} elems\n */\nproto.prepended = function( elems ) {\n  var items = this._itemize( elems );\n  if ( !items.length ) {\n    return;\n  }\n  // add items to beginning of collection\n  var previousItems = this.items.slice(0);\n  this.items = items.concat( previousItems );\n  // start new layout\n  this._resetLayout();\n  this._manageStamps();\n  // layout new stuff without transition\n  this.layoutItems( items, true );\n  this.reveal( items );\n  // layout previous items\n  this.layoutItems( previousItems );\n};\n\n/**\n * reveal a collection of items\n * @param {Array of Outlayer.Items} items\n */\nproto.reveal = function( items ) {\n  this._emitCompleteOnItems( 'reveal', items );\n  if ( !items || !items.length ) {\n    return;\n  }\n  var stagger = this.updateStagger();\n  items.forEach( function( item, i ) {\n    item.stagger( i * stagger );\n    item.reveal();\n  });\n};\n\n/**\n * hide a collection of items\n * @param {Array of Outlayer.Items} items\n */\nproto.hide = function( items ) {\n  this._emitCompleteOnItems( 'hide', items );\n  if ( !items || !items.length ) {\n    return;\n  }\n  var stagger = this.updateStagger();\n  items.forEach( function( item, i ) {\n    item.stagger( i * stagger );\n    item.hide();\n  });\n};\n\n/**\n * reveal item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nproto.revealItemElements = function( elems ) {\n  var items = this.getItems( elems );\n  this.reveal( items );\n};\n\n/**\n * hide item elements\n * @param {Array}, {Element}, {NodeList} items\n */\nproto.hideItemElements = function( elems ) {\n  var items = this.getItems( elems );\n  this.hide( items );\n};\n\n/**\n * get Outlayer.Item, given an Element\n * @param {Element} elem\n * @param {Function} callback\n * @returns {Outlayer.Item} item\n */\nproto.getItem = function( elem ) {\n  // loop through items to get the one that matches\n  for ( var i=0; i < this.items.length; i++ ) {\n    var item = this.items[i];\n    if ( item.element == elem ) {\n      // return item\n      return item;\n    }\n  }\n};\n\n/**\n * get collection of Outlayer.Items, given Elements\n * @param {Array} elems\n * @returns {Array} items - Outlayer.Items\n */\nproto.getItems = function( elems ) {\n  elems = utils.makeArray( elems );\n  var items = [];\n  elems.forEach( function( elem ) {\n    var item = this.getItem( elem );\n    if ( item ) {\n      items.push( item );\n    }\n  }, this );\n\n  return items;\n};\n\n/**\n * remove element(s) from instance and DOM\n * @param {Array or NodeList or Element} elems\n */\nproto.remove = function( elems ) {\n  var removeItems = this.getItems( elems );\n\n  this._emitCompleteOnItems( 'remove', removeItems );\n\n  // bail if no items to remove\n  if ( !removeItems || !removeItems.length ) {\n    return;\n  }\n\n  removeItems.forEach( function( item ) {\n    item.remove();\n    // remove item from collection\n    utils.removeFrom( this.items, item );\n  }, this );\n};\n\n// ----- destroy ----- //\n\n// remove and disable Outlayer instance\nproto.destroy = function() {\n  // clean up dynamic styles\n  var style = this.element.style;\n  style.height = '';\n  style.position = '';\n  style.width = '';\n  // destroy items\n  this.items.forEach( function( item ) {\n    item.destroy();\n  });\n\n  this.unbindResize();\n\n  var id = this.element.outlayerGUID;\n  delete instances[ id ]; // remove reference to instance by id\n  delete this.element.outlayerGUID;\n  // remove data for jQuery\n  if ( jQuery ) {\n    jQuery.removeData( this.element, this.constructor.namespace );\n  }\n\n};\n\n// -------------------------- data -------------------------- //\n\n/**\n * get Outlayer instance from element\n * @param {Element} elem\n * @returns {Outlayer}\n */\nOutlayer.data = function( elem ) {\n  elem = utils.getQueryElement( elem );\n  var id = elem && elem.outlayerGUID;\n  return id && instances[ id ];\n};\n\n\n// -------------------------- create Outlayer class -------------------------- //\n\n/**\n * create a layout class\n * @param {String} namespace\n */\nOutlayer.create = function( namespace, options ) {\n  // sub-class Outlayer\n  var Layout = subclass( Outlayer );\n  // apply new options and compatOptions\n  Layout.defaults = utils.extend( {}, Outlayer.defaults );\n  utils.extend( Layout.defaults, options );\n  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );\n\n  Layout.namespace = namespace;\n\n  Layout.data = Outlayer.data;\n\n  // sub-class Item\n  Layout.Item = subclass( Item );\n\n  // -------------------------- declarative -------------------------- //\n\n  utils.htmlInit( Layout, namespace );\n\n  // -------------------------- jQuery bridge -------------------------- //\n\n  // make into jQuery plugin\n  if ( jQuery && jQuery.bridget ) {\n    jQuery.bridget( namespace, Layout );\n  }\n\n  return Layout;\n};\n\nfunction subclass( Parent ) {\n  function SubClass() {\n    Parent.apply( this, arguments );\n  }\n\n  SubClass.prototype = Object.create( Parent.prototype );\n  SubClass.prototype.constructor = SubClass;\n\n  return SubClass;\n}\n\n// ----- helpers ----- //\n\n// how many milliseconds are in each unit\nvar msUnits = {\n  ms: 1,\n  s: 1000\n};\n\n// munge time-like parameter into millisecond number\n// '0.4s' -> 40\nfunction getMilliseconds( time ) {\n  if ( typeof time == 'number' ) {\n    return time;\n  }\n  var matches = time.match( /(^\\d*\\.?\\d*)(\\w*)/ );\n  var num = matches && matches[1];\n  var unit = matches && matches[2];\n  if ( !num.length ) {\n    return 0;\n  }\n  num = parseFloat( num );\n  var mult = msUnits[ unit ] || 1;\n  return num * mult;\n}\n\n// ----- fin ----- //\n\n// back in global\nOutlayer.Item = Item;\n\nreturn Outlayer;\n\n}));\n","/*!\n * Masonry v4.2.1\n * Cascading grid layout library\n * https://masonry.desandro.com\n * MIT License\n * by David DeSandro\n */\n\n( function( window, factory ) {\n  // universal module definition\n  /* jshint strict: false */ /*globals define, module, require */\n  if ( typeof define == 'function' && define.amd ) {\n    // AMD\n    define( [\n        'outlayer/outlayer',\n        'get-size/get-size'\n      ],\n      factory );\n  } else if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory(\n      require('outlayer'),\n      require('get-size')\n    );\n  } else {\n    // browser global\n    window.Masonry = factory(\n      window.Outlayer,\n      window.getSize\n    );\n  }\n\n}( window, function factory( Outlayer, getSize ) {\n\n'use strict';\n\n// -------------------------- masonryDefinition -------------------------- //\n\n  // create an Outlayer layout class\n  var Masonry = Outlayer.create('masonry');\n  // isFitWidth -> fitWidth\n  Masonry.compatOptions.fitWidth = 'isFitWidth';\n\n  var proto = Masonry.prototype;\n\n  proto._resetLayout = function() {\n    this.getSize();\n    this._getMeasurement( 'columnWidth', 'outerWidth' );\n    this._getMeasurement( 'gutter', 'outerWidth' );\n    this.measureColumns();\n\n    // reset column Y\n    this.colYs = [];\n    for ( var i=0; i < this.cols; i++ ) {\n      this.colYs.push( 0 );\n    }\n\n    this.maxY = 0;\n    this.horizontalColIndex = 0;\n  };\n\n  proto.measureColumns = function() {\n    this.getContainerWidth();\n    // if columnWidth is 0, default to outerWidth of first item\n    if ( !this.columnWidth ) {\n      var firstItem = this.items[0];\n      var firstItemElem = firstItem && firstItem.element;\n      // columnWidth fall back to item of first element\n      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||\n        // if first elem has no width, default to size of container\n        this.containerWidth;\n    }\n\n    var columnWidth = this.columnWidth += this.gutter;\n\n    // calculate columns\n    var containerWidth = this.containerWidth + this.gutter;\n    var cols = containerWidth / columnWidth;\n    // fix rounding errors, typically with gutters\n    var excess = columnWidth - containerWidth % columnWidth;\n    // if overshoot is less than a pixel, round up, otherwise floor it\n    var mathMethod = excess && excess < 1 ? 'round' : 'floor';\n    cols = Math[ mathMethod ]( cols );\n    this.cols = Math.max( cols, 1 );\n  };\n\n  proto.getContainerWidth = function() {\n    // container is parent if fit width\n    var isFitWidth = this._getOption('fitWidth');\n    var container = isFitWidth ? this.element.parentNode : this.element;\n    // check that this.size and size are there\n    // IE8 triggers resize on body size change, so they might not be\n    var size = getSize( container );\n    this.containerWidth = size && size.innerWidth;\n  };\n\n  proto._getItemLayoutPosition = function( item ) {\n    item.getSize();\n    // how many columns does this brick span\n    var remainder = item.size.outerWidth % this.columnWidth;\n    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';\n    // round if off by 1 pixel, otherwise use ceil\n    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );\n    colSpan = Math.min( colSpan, this.cols );\n    // use horizontal or top column position\n    var colPosMethod = this.options.horizontalOrder ?\n      '_getHorizontalColPosition' : '_getTopColPosition';\n    var colPosition = this[ colPosMethod ]( colSpan, item );\n    // position the brick\n    var position = {\n      x: this.columnWidth * colPosition.col,\n      y: colPosition.y\n    };\n    // apply setHeight to necessary columns\n    var setHeight = colPosition.y + item.size.outerHeight;\n    var setMax = colSpan + colPosition.col;\n    for ( var i = colPosition.col; i < setMax; i++ ) {\n      this.colYs[i] = setHeight;\n    }\n\n    return position;\n  };\n\n  proto._getTopColPosition = function( colSpan ) {\n    var colGroup = this._getTopColGroup( colSpan );\n    // get the minimum Y value from the columns\n    var minimumY = Math.min.apply( Math, colGroup );\n\n    return {\n      col: colGroup.indexOf( minimumY ),\n      y: minimumY,\n    };\n  };\n\n  /**\n   * @param {Number} colSpan - number of columns the element spans\n   * @returns {Array} colGroup\n   */\n  proto._getTopColGroup = function( colSpan ) {\n    if ( colSpan < 2 ) {\n      // if brick spans only one column, use all the column Ys\n      return this.colYs;\n    }\n\n    var colGroup = [];\n    // how many different places could this brick fit horizontally\n    var groupCount = this.cols + 1 - colSpan;\n    // for each group potential horizontal position\n    for ( var i = 0; i < groupCount; i++ ) {\n      colGroup[i] = this._getColGroupY( i, colSpan );\n    }\n    return colGroup;\n  };\n\n  proto._getColGroupY = function( col, colSpan ) {\n    if ( colSpan < 2 ) {\n      return this.colYs[ col ];\n    }\n    // make an array of colY values for that one group\n    var groupColYs = this.colYs.slice( col, col + colSpan );\n    // and get the max value of the array\n    return Math.max.apply( Math, groupColYs );\n  };\n\n  // get column position based on horizontal index. #873\n  proto._getHorizontalColPosition = function( colSpan, item ) {\n    var col = this.horizontalColIndex % this.cols;\n    var isOver = colSpan > 1 && col + colSpan > this.cols;\n    // shift to next row if item can't fit on current row\n    col = isOver ? 0 : col;\n    // don't let zero-size items take up space\n    var hasSize = item.size.outerWidth && item.size.outerHeight;\n    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;\n\n    return {\n      col: col,\n      y: this._getColGroupY( col, colSpan ),\n    };\n  };\n\n  proto._manageStamp = function( stamp ) {\n    var stampSize = getSize( stamp );\n    var offset = this._getElementOffset( stamp );\n    // get the columns that this stamp affects\n    var isOriginLeft = this._getOption('originLeft');\n    var firstX = isOriginLeft ? offset.left : offset.right;\n    var lastX = firstX + stampSize.outerWidth;\n    var firstCol = Math.floor( firstX / this.columnWidth );\n    firstCol = Math.max( 0, firstCol );\n    var lastCol = Math.floor( lastX / this.columnWidth );\n    // lastCol should not go over if multiple of columnWidth #425\n    lastCol -= lastX % this.columnWidth ? 0 : 1;\n    lastCol = Math.min( this.cols - 1, lastCol );\n    // set colYs to bottom of the stamp\n\n    var isOriginTop = this._getOption('originTop');\n    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +\n      stampSize.outerHeight;\n    for ( var i = firstCol; i <= lastCol; i++ ) {\n      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );\n    }\n  };\n\n  proto._getContainerSize = function() {\n    this.maxY = Math.max.apply( Math, this.colYs );\n    var size = {\n      height: this.maxY\n    };\n\n    if ( this._getOption('fitWidth') ) {\n      size.width = this._getContainerFitWidth();\n    }\n\n    return size;\n  };\n\n  proto._getContainerFitWidth = function() {\n    var unusedCols = 0;\n    // count unused columns\n    var i = this.cols;\n    while ( --i ) {\n      if ( this.colYs[i] !== 0 ) {\n        break;\n      }\n      unusedCols++;\n    }\n    // fit container to columns that have been used\n    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;\n  };\n\n  proto.needsResizeLayout = function() {\n    var previousWidth = this.containerWidth;\n    this.getContainerWidth();\n    return previousWidth != this.containerWidth;\n  };\n\n  return Masonry;\n\n}));\n","/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\nimport * as dompack from 'dompack';\n\n//just number RPCs globally instead of per server, makes debug ouput more useful\nlet globalseqnr = 1;\n\nfunction getDebugAppend() {\n  const urldebugvar = window.location.href.match(new RegExp('[?&#]wh-debug=([^&#?]*)'));\n  return urldebugvar ? '?wh-debug=' + urldebugvar[1] : '';\n}\n\n/* this is the followup for net/jsonrpc.es - we can hopefully clear net/ someday\n   and move net/eventserver to wh/eventserver.es then */\n\nclass ControlledCall {\n  abortcontroller = new AbortController;\n  timeout;\n  _callurl;\n  _fetchoptions;\n  promise: Promise<unknown>;\n  timedout = false;\n  aborted = false;\n  legacyresolve;\n\n  constructor(public client, method, stack, id, public options, callurl, fetchoptions) {\n    // if(options.timeout || options.signal) //as long as rpcResolve exists, we'll ALWAYS need to setup a controller\n    {\n      fetchoptions.signal = this.abortcontroller.signal;\n\n      if (options.timeout > 0) {\n        this.timeout = options.timeout;\n        setTimeout(() => this._handleTimeout(), options.timeout);\n      }\n      if (options.signal) {\n        options.signal.addEventListener(\"abort\", () => this._abort());\n      }\n    }\n\n    this._callurl = callurl;\n    this._fetchoptions = fetchoptions;\n\n    const fetchpromise = fetch(this._callurl, this._fetchoptions);\n    this.promise = this._completeCall(method, stack, id, fetchpromise);\n    this.promise.__jsonrpcinfo = this;\n  }\n  _handleTimeout() {\n    this.timedout = true;\n    this.abortcontroller.abort();\n  }\n  _abort() {\n    this.aborted = true;\n    this.abortcontroller.abort();\n  }\n  _legacyResolve(resolution) {\n    this.legacyresolve = resolution;\n    this.abortcontroller.abort();\n  }\n  async _completeCall(method, stack, id, fetchpromise) {\n    let response;\n    try {\n      while (true) { //loop for 429\n        response = await fetchpromise;\n        if (response.status === 429 && !(\"retry429\" in this.options && !this.options.retry429) && response.headers.get(\"Retry-After\")) {\n          const retryafter = parseInt(response.headers.get(\"Retry-After\"));\n          if (this.options.debug)\n            console.warn(`[rpc] We are being throttled (429 Too Many Requests) - retrying after ${retryafter} seconds`);\n\n          await new Promise(resolve => setTimeout(resolve, retryafter * 1000));\n          fetchpromise = fetch(this._callurl, this._fetchoptions);\n          continue;\n        }\n        break;\n      }\n    } catch (exception) {\n      if (this.options.debug)\n        console.log(`[rpc] #${id} Exception invoking '${method}'`, exception);\n\n      if (this.aborted)\n        throw new Error(`RPC Aborted`);\n      else if (this.timedout)\n        throw new Error(`RPC Timeout: timeout was set to ${this.timeout} milliseconds`);\n      else if (this.legacyresolve && this.legacyresolve.resolve)\n        return this.legacyresolve.resolve;\n      else\n        throw new Error(`RPC Failed: exception: ` + exception);\n    }\n\n    let jsonresponse;\n    try {\n      jsonresponse = await response.json();\n      if (this.options.debug)\n        console.log(`[rpc] #${id} Received response to '${method}'`, jsonresponse);\n    } catch (exception) {\n      if (this.options.debug)\n        console.warn(`[rpc] #${id} Response was not valid JSON`, exception);\n    }\n\n    if (!jsonresponse)\n      throw new Error(\"RPC Failed: Invalid JSON/RPC response received\");\n\n    if (jsonresponse && jsonresponse.error) {\n      this.client._tryLogError(stack, jsonresponse.error);\n      throw new Error(\"RPC Error: \" + (jsonresponse.error.message || \"Unknown error\"));\n    }\n\n    if (response.status === 200 && jsonresponse && jsonresponse.id !== id)\n      throw new Error(\"RPC Failed: Invalid JSON/RPC response received\");\n\n    if (this.options.wrapresult) {\n      return {\n        status: response.status,\n        result: jsonresponse.result || null,\n        error: jsonresponse.error || null,\n        retryafter: response.headers.get(\"Retry-After\") ? parseInt(response.headers.get(\"Retry-After\")) : null\n      };\n    }\n\n    return jsonresponse.result;\n  }\n}\n\n/** Invokes (WebHare) JSON/RPC\n    @param url - URL to invoke (leave empty or pass no parameters at all to callback to the current page)\n    options.timeout Default timeout for all calls\n    options.debug Debug (Follows 'rpc' debugflag if not explicity specified)\n    @deprecated Switch to \\@webhare/jsonrpc */\nexport default class RPCClient {\n  options;\n  url: string;\n  addfunctionname;\n  urlappend;\n  constructor(url: string, options?) {\n    this.options = {\n      timeout: 0,\n      debug: dompack.debugflags.rpc,\n      ...options\n    };\n\n    let whservicematch;\n    if (url) {\n      whservicematch = url.match(/^([a-z0-9_]+):([a-z0-9_]+)$/);\n      if (whservicematch)\n        this.url = `${location.origin}/wh_services/${whservicematch[1]}/${whservicematch[2]}`;\n      else\n        this.url = url;\n    } else {\n      this.url = location.href;  //invoke ourselves directly if no path specified\n    }\n\n    //if shorthand syntax is used, we know we're talking to our local webhare. add function names and the profiling flag if needed\n    this.addfunctionname = this.options.addfunctionname !== undefined ? this.options.addfunctionname : Boolean(whservicematch);\n    this.urlappend = this.options.urlappend !== undefined ? this.options.urlappend : whservicematch ? getDebugAppend() : \"\";\n  }\n\n  setOptions(options) {\n    this.options = { ...this.options, ...options };\n  }\n\n  _handleLegacyRPCResolve(promise, result) {\n    if (!promise.__jsonrpcinfo)\n      throw new Error(\"The promise is not an async JSONRPC request\");\n    promise.__jsonrpcinfo._legacyResolve({ resolve: result });\n  }\n\n  _tryLogError(stack, error) {\n    const trace = error.data ? (error.data.trace || error.data.list || []) : [];\n\n    console.group();\n    console.warn(\"RPC failed:\", error.message);\n    trace.forEach(rec => {\n      if (rec.filename || rec.line) {\n        const line = rec.filename + '#' + rec.line + '#' + rec.col + (rec.func ? ' (' + rec.func + ')' : '');\n        console.log(line);\n      }\n    });\n    if (stack) {\n      console.warn(\"Stack at calling point\");\n      console.log(stack);\n    }\n    console.groupEnd();\n  }\n\n  invoke(...params: unknown[]) {\n    let options;\n    if (typeof params[0] === \"object\")\n      options = { ...this.options, ...params.shift() };\n    else\n      options = this.options;\n\n    const method = params.shift();\n\n    //build the URL, add profiling and function parameters where needed\n    let callurl = this.url;\n    if (this.addfunctionname) //simplifies log analysis, ignored by the server\n      callurl += `/${method}`;\n    callurl += this.urlappend;\n\n    const id = ++globalseqnr;\n    let stack;\n\n    if (options.debug) {\n      stack = new Error().stack;\n      console.log(`[rpc] #${id} Invoking '${method}'`, params, callurl);\n    }\n\n    const fetchoptions = {\n      method: \"POST\",\n      credentials: 'same-origin', //this is the default since 2017-08-25, but Edge pre-18 is still around and will fail here\n      headers: {\n        \"Accept\": \"application/json\",\n        \"Content-Type\": \"application/json; charset=utf-8\"\n      },\n      body: JSON.stringify(\n        {\n          id: id,\n          method: method,\n          params: params || []\n        }),\n      keepalive: Boolean(options.keepalive)\n    };\n\n    return new ControlledCall(this, method, stack, id, options, callurl, fetchoptions).promise;\n  }\n}\n\nclass JSONRPCService { //originally generated inline by the rpcloader.ts\n  rpcclient;\n\n  static get HTTP_ERROR() { return -1; } // Error connecting to the RPC server\n  static get JSON_ERROR() { return -2; } // The returned value could not be decoded into a JSON object\n  static get PROTOCOL_ERROR() { return -3; } // The return object did not contain an id, or the id did not match the request id\n  static get RPC_ERROR() { return -4; } // The RPC returned an error\n  static get OFFLINE_ERROR() { return -5; } // The application is not online (only returned if the onlineonly option was set)\n  static get TIMEOUT_ERROR() { return -6; } // The request could not be sent or was not answered before within the timeout set in the options\n  static get SERVER_ERROR() { return -7; } // The server encountered an internal error\n\n  constructor(service: string) {\n    this.rpcclient = new RPCClient(service);\n  }\n\n  rpcResolve(promise: Promise<unknown>, result: unknown) {\n    this.rpcclient._handleLegacyRPCResolve(promise, result);\n  }\n  invoke(...args: unknown[]) {\n    return this.rpcclient.invoke(...args);\n  }\n}\n\nclass JSONRPCServiceProxy {\n  get(target: JSONRPCService, prop: string, receiver: unknown) {\n    if (prop in target)\n      return Reflect.get(target, prop, receiver);\n    //it's a call, turn into an invoke\n    return (...args: unknown[]) => target.invoke(prop, ...args);\n  }\n}\n\nexport function createService(name: string) {\n  const service = new JSONRPCService(name);\n  return new Proxy(service, new JSONRPCServiceProxy);\n}\n","//this file MUST keep its .js extension!\n\n/*\n * Copyright 2017 Searsia\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Searsia Library v1.2.0:\n *\n *   The web page should first call searsia.initClient(template) and then\n *   searsia.searchFederated(params, callback), see: exampleclient.js\n *   Syntax checked with: standard (https://standardjs.com)\n */\n\n/*\n * Modifications by WebHare:\n * - Prepare for usage as module by exporting the searsia object\n * - Support relative urls, interpret relative to Searsia\n * - Use fetch instead of XMLHttpRequest for better redirection control\n * - Encode amp _before_ encoding lt and gt in noHTMLelement\n *\n * Usage:\n *\n *   import searsia from \"searsia\";\n *   searsia.initClient(template);\n *   searsia.searchFederated(params, callback);\n */\n\n'use strict'\n\nvar searsia = (function () {\n  var SEARSIAVERSION = 'v1.2.0'\n  var globalId = null\n  var globalApiTemplate = null\n  var globalMother = null\n\n  /* replace JQuery $.ajax() */\n\n  async function searsiaAjax (ajaxObject) {\n    let url = ajaxObject.url;\n    const success = ajaxObject.success;\n    const error = ajaxObject.error;\n    //ADDME: timeout support (using AbortController?)\n    //const timeout = ajaxObject.timeout;\n    const dataType = ajaxObject.dataType;\n\n    const options = {\n      credentials: 'same-origin',\n      redirect: 'follow'\n    };\n\n    let response;\n    for (let tries = 0; tries < 3; ++tries) {\n      // For testing purposes only, replace www.webhare-test.utsp.utwente.nl with serviceportal.webhare-test.utsp.utwente.nl\n      // (the actual service portal will run at www, but the test... version runs at serviceportal...)\n      url = url.replace(\"//www.webhare-test.utsp.utwente.nl/\", \"//serviceportal.webhare-test.utsp.utwente.nl/\");\n\n      try {\n        response = await fetch(url, options);\n        if (response.status === 200) {\n          if (response.redirected)\n          {\n            url = response.url;\n            continue;\n          }\n          try {\n            const data = dataType === 'json' ? await response.json() : null;\n            success(data);\n            return;\n          } catch(decodeError) {\n            error(response, null, decodeError.message);\n            return;\n          }\n        } else {\n          let message = response.statusText;\n          if (!message) {\n            message = 'Not available';\n          }\n          error(response, null, message);\n          return;\n        }\n      } catch (connectError) {\n        error(response, null, 'Connection error');\n        return;\n      }\n    }\n    error(response, null, 'Max tries exceeded');\n  }\n\n  /* Basic local storage functions */\n\n  function clearLocalStorage () {\n    try {\n      Object.keys(localStorage).filter(function(key){return key.substr(0,8)=='searsia-'}).forEach(function(key){localStorage.removeItem(key)});\n    } catch (ignore) { }\n  }\n\n  function setLocalStorage (field, value) {\n    if (value != null) {\n      try {\n        window.localStorage['searsia-' + field] = value\n      } catch (ignore) { }\n    }\n  }\n\n  function deleteLocalStorage (field) {\n    try {\n      window.localStorage['searsia-' + field] = null\n    } catch (ignore) { }\n  }\n\n  function getLocalStorage (field) {\n    var value = null\n    try {\n      value = window.localStorage['searsia-' + field]\n    } catch (ignore) { }\n    return value\n  }\n\n  function existsLocalStorage (field) {\n    var value = false\n    try {\n      value = window.localStorage.hasOwnProperty('searsia-' + field)\n    } catch (ignore) { }\n    return value\n  }\n\n  /* Special storage functions -- fallback to local variables */\n\n  function setMother (motherObject) {\n    globalMother = motherObject // global\n    setLocalStorage('mother', JSON.stringify(motherObject))\n    if (motherObject.id != null) {\n      globalId = motherObject.id // global\n    } else {\n      globalId = 'searsia'\n    }\n    setLocalStorage('id', globalId)\n  }\n\n  function getMother () {\n    var motherJson\n    if (globalMother != null) { // global\n      return globalMother\n    }\n    motherJson = getLocalStorage('mother')\n    if (motherJson) {\n      return JSON.parse(motherJson)\n    }\n    return null\n  }\n\n  function setApiTemplate (template) {\n    globalApiTemplate = template // global\n    setLocalStorage('apitemplate', template)\n  }\n\n  function getApiTemplate () {\n    if (globalApiTemplate != null) { // global\n      return globalApiTemplate\n    }\n    return getLocalStorage('apitemplate')\n  }\n\n  /* there is no setId(), instead: see setMother() */\n  function getId () {\n    if (globalId != null) {\n      return globalId\n    } else {\n      return getLocalStorage('id')\n    }\n  }\n\n  function setLocalResource (resource) {\n    var id = getId()\n    if (id != null) {\n      setLocalStorage(id + '/' + resource.id, JSON.stringify(resource))\n    }\n  }\n\n  function getLocalResource (rid) {\n    var json\n    var id = getId()\n    if (id == null) {\n      return null\n    }\n    json = getLocalStorage(id + '/' + rid)\n    if (json) {\n      return JSON.parse(json)\n    }\n    return null\n  }\n\n  function existsLocalResource (rid) {\n    var id = getId()\n    if (id == null) {\n      return false\n    }\n    return existsLocalStorage(id + '/' + rid)\n  }\n\n  function deleteLocalResource (rid) {\n    var id = getId()\n    if (id != null) {\n      deleteLocalStorage(id + '/' + rid)\n    }\n  }\n\n  /* Template: only works on Searsia Server templates */\n  function fillUrlTemplate (template, query, page, resourceId, resulttype) {\n    if(template[0]=='/') //it's origin-relative, so copy origin from the api template.\n      template = getApiTemplate().split(\"/\").slice(0,3).join('/') + template;\n\n    var start, end, ext\n    var json = '.json'\n    if (resourceId) {\n      start = template.lastIndexOf('/')\n      end = template.indexOf('?')\n      if (start > 4 && end > start) {\n        if (template.substring(start + 1, end).indexOf(json) !== -1) {\n          ext = json\n        } else {\n          ext = ''\n        }\n        template = template.substring(0, start + 1) + resourceId + ext + template.substring(end, template.length)\n      }\n    }\n    if (page == null) {\n      page = 1\n    }\n    if (resulttype == null) {\n      resulttype = ''\n    }\n    template = template.replace(/\\{q\\??\\}/g, query)\n    template = template.replace(/\\{searchTerms\\??\\}/g, query)\n    template = template.replace(/\\{startPage\\??\\}/, page)\n    template = template.replace(/\\{resultType\\??\\}/, resulttype)\n    return template.replace(/\\{[A-Za-z]+\\?\\}/g, '') // remove all optional\n  }\n\n  function addToHits (hits, hit) {\n    var i\n    var newIndex = hits.length\n    var TOP = 100\n    if (newIndex < TOP || hit.score > hits[TOP - 1].score) {\n      if (newIndex < TOP) { newIndex += 1 }\n      i = newIndex - 1\n      while (i > 0 && hits[i - 1].score < hit.score) {\n        hits[i] = hits[i - 1]\n        i -= 1\n      }\n      hits[i] = hit\n    }\n  }\n\n  function normalizeText (text) {\n    return text.toLowerCase().replace(new RegExp('[^a-z0-9]+', 'g'), ' ').replace(new RegExp('^ +| +$', 'g'), '')\n  }\n\n  function noHTMLattribute (text) {\n    text = text.replace(/&/g, '&amp;')\n    text = text.replace(/\"/g, '&#34;')\n    return text\n  }\n\n  function noHTMLelement (text) {\n    text = text.replace(/&/g, '&amp;')\n    text = text.replace(/</g, '&lt;')\n    text = text.replace(/>/g, '&gt;')\n    return text\n  }\n\n  function scoreText (text, queryTerms) {\n    var i, j, len\n    var textTerms\n    var score = 0.0\n    textTerms = normalizeText(text).split(/ +/)\n    for (i = 0; i < queryTerms.length; i += 1) { // TODO: Really? Nested loop??\n      len = textTerms.length\n      if (len > 1000) { len = 1000 } // Only check first 1000 words\n      j = 0\n      while (j < len) {\n        if (queryTerms[i] === textTerms[j]) {\n          score += 1.0\n          j = len // one occurrence per query term\n        }\n        j += 1\n      }\n    }\n    return score\n  }\n\n  function restrictStart (someText, start, size) { // size must be > 3\n    var i, j\n    var prefix = ''\n    var postfix = ''\n    if (someText != null && someText.length > size) {\n      if (start < 0) { start = 0 }\n      if (start > 2) {\n        i = someText.indexOf(' ', start - 1)\n        if (i === -1) { i = start } else { i += 1 }\n        prefix = '... '\n      } else {\n        i = 0\n      }\n      if (start + size < someText.length) {\n        j = someText.lastIndexOf(' ', start + size)\n        if (j === -1) { j = start + size - 3 }\n        postfix = ' ...'\n      } else {\n        j = start + size\n      }\n      someText = prefix + someText.substr(i, j - i) + postfix\n    }\n    return someText\n  }\n\n  function matchingSnippets (hits, queryTerms) { // TODO for queries length > 2\n    var i, j, k, description, first, second\n    for (i = 0; i < hits.length; i += 1) {\n      first = -1\n      second = -1\n      if (queryTerms.length < 2) { first = 0 } // Take first part of description for query length 1\n      if (hits[i].description != null) {\n        description = hits[i].description.toLowerCase()\n        j = 0\n        while (j < queryTerms.length) {\n          if (first === -1) {\n            first = description.indexOf(queryTerms[j])\n          } else if (second === -1) {\n            k = first - 120\n            if (k < 0) { k = 0 }\n            second = description.indexOf(queryTerms[j], k)\n            if (second === -1) {\n              second = description.indexOf(queryTerms[j])\n            }\n          }\n          j += 1\n        }\n        if (first === -1) { first = 0 }\n        if (second === -1) { second = 0 }\n        if (first > second) {\n          k = first\n          first = second\n          second = k\n        }\n        if (second - first < 120) {\n          description = restrictStart(hits[i].description, first - 40, 192)\n        } else {\n          description = restrictStart(hits[i].description, first - 40, 92)\n          description += restrictStart(hits[i].description, second - 40, 92)\n        }\n        hits[i].description = description\n      }\n    }\n  }\n\n  /**\n   *  Computes maxscore of hits\n   *  If rerank === true: rerank and select those that match the query\n   *  Used if mother has \"rerank\"\n   */\n  function scoreAllHits (data, query, rerank) {\n    var queryTerms, queryLen, hit, score, maxscore, tscore\n    var newHits = []\n    var nrOfTopHits = 0\n    var i = 0\n    query = normalizeText(printableQuery(query))\n    queryTerms = query.split(/ +/).sort(function (a, b) { return b.length - a.length }) // TODO: Split might not work for all character encodings\n    queryLen = queryTerms.length\n    newHits = []\n    maxscore = 0\n    while (i < data.hits.length) {\n      hit = data.hits[i]\n      score = 0\n      tscore = 0\n      if (hit.title != null) {\n        tscore = scoreText(hit.title, queryTerms)\n      }\n      if (tscore === 0 && hit.url != null) {\n        tscore = scoreText(hit.url, queryTerms) / 1.1\n      }\n      if (tscore < queryLen && hit.description != null) {\n        score = scoreText(hit.description, queryTerms)\n      }\n      if (tscore * 1.1 > score) { // title boost\n        score = tscore * 1.1\n      } else {\n        score += tscore / 10\n      }\n      if (score > 0) {\n        if (score >= queryLen) { nrOfTopHits += 1 }\n        hit.score = score\n        addToHits(newHits, hit) // TODO: only if rerank?\n        if (score > maxscore) { maxscore = score }\n      }\n      if (nrOfTopHits >= 100) { break }\n      i += 1\n    }\n    if (rerank) {\n      matchingSnippets(newHits, queryTerms)\n      data.hits = newHits\n    }\n    return maxscore\n  }\n\n  function correctUrl (absUrl, relUrl) {\n    if (relUrl.match(/^https?:\\/\\//) || relUrl.match(/^\\/\\//)) {\n      return relUrl\n    }\n    if (absUrl == null) {\n      return null\n    }\n    if (relUrl.match(/^\\//)) {\n      return absUrl.replace(/([a-z])\\/.*$/, '$1') + relUrl\n    }\n    return absUrl.replace(/\\/[^/]+$/, '/') + relUrl\n  }\n\n  function getHost (url) {\n    if (!url) {\n      return null\n    }\n    var match = url.match(/:\\/\\/(www\\.)?(.[^/:]+)/)\n    if (match == null) {\n      return null\n    }\n    return match[2]\n  }\n\n  function urlParameters () {\n    var i, values\n    var params = { q: '', r: '', p: '', t: '' }\n    var paramString = window.location.search.substring(1)\n    var parts = paramString.split('&')\n    for (i = 0; i < parts.length; i += 1) {\n      values = parts[i].split('=')\n      if (values[0] === 'q') {\n        params.q = values[1]\n        params.q = params.q.replace(/%3C.*?%3E/g, '') // no HTML\n        params.q = params.q.replace(/%3C|%3E/g, '')\n        params.q = params.q.replace(/^\\++|\\++$/g, '') // no leading and trailing spaces\n      } else if (values[0] === 'r') {\n        params.r = values[1]\n      } else if (values[0] === 'p') {\n        params.p = values[1]\n      } else if (values[0] === 't') {\n        params.t = values[1]\n      }\n    }\n    return params\n  }\n\n  /* takes a url parameter query and returns a human readable query */\n  function printableQuery (query) {\n    query = query.replace(/\\+/g, ' ')\n    query = decodeURIComponent(query)\n    return noHTMLelement(query)\n  }\n\n  /* takes a url parameter query and returns a query for an HTML form */\n  function formQuery (query) {\n    query = printableQuery(query)\n    query = query.replace(/&amp;/g, '&')\n    return query\n  }\n\n  /* takes a human readable query and turns it into an urlencoded query */\n  function encodedQuery (text) {\n    text = encodeURIComponent(text)\n    text = text.replace(/%20/g, '+')\n    return text\n  }\n\n  /*\n   * This function is a mutable data type brain cracker:\n   * That is, we purposely change the values of data and\n   * resource here...\n   */\n  function inferMissingData (data, query, resulttype, rank) {\n    var i, hit, resource, rhost\n    var typeImages = true\n    var typeSmall = true\n    var typeFull = false\n    var typeTitleOnly = true\n    var count = data.hits.length - 1\n    var prior = null\n    var maxScore = 10\n\n    if (count >= maxScore) {\n      maxScore = count + 1\n    }\n    resource = data.resource\n    prior = Number(resource.prior)\n    if (isNaN(prior) || prior == null) { prior = 0.0 }\n\n    if (resource.urltemplate != null) {\n      rhost = getHost(resource.urltemplate)\n    }\n    for (i = count; i >= 0; i -= 1) {\n      hit = data.hits[i]\n      if (hit.title == null) { // everything *must* have a title\n        hit.title = 'Title'\n        console.log('WARNING: result without title')\n      } else {\n        hit.title = noHTMLelement(hit.title)\n      }\n      hit.score = 1 / Math.sqrt(rank) - i / maxScore\n      if (hit.score < 0.001) {\n        hit.score = 0.001\n      }\n      if (hit.url == null) {\n        if (resource.urltemplate != null) {\n          hit.url = fillUrlTemplate(resource.urltemplate, encodedQuery(hit.title), 1, '', resulttype)\n        } else {\n          hit.url = fillUrlTemplate('?q={searchTerms}&t={resultType?}', encodedQuery(hit.title), null, null, resulttype)\n        }\n      } else {\n        if (resource.urltemplate) {\n          hit.url = correctUrl(resource.urltemplate, hit.url)\n        } else {\n          hit.url = correctUrl(resource.apitemplate, hit.url)\n        }\n        if (rhost == null || rhost !== getHost(hit.url)) {\n          typeFull = true\n        }\n        hit.url = noHTMLelement(hit.url)\n      }\n      if (hit.description != null) {\n        hit.description = noHTMLelement(hit.description)\n        typeTitleOnly = false\n      }\n      if (hit.image != null) {\n        hit.image = noHTMLattribute(correctUrl(resource.urltemplate, hit.image))\n        typeTitleOnly = false\n      }\n      if (hit.favicon == null && resource.favicon != null) {\n        hit.favicon = resource.favicon\n      }\n      if (hit.favicon != null) {\n        hit.favicon = noHTMLattribute(hit.favicon)\n      }\n      if (hit.tags == null || hit.tags.indexOf('small') === -1) {\n        typeSmall = false\n      }\n      if (hit.tags == null || hit.tags.indexOf('image') === -1) {\n        typeImages = false\n      }\n    }\n    if (typeImages) {\n      resource.type = 'images'\n    } else if (typeSmall || typeTitleOnly) {\n      resource.type = 'small'\n    } else if (typeFull) {\n      resource.type = 'full'\n    } else {\n      resource.type = 'web'\n    }\n  }\n\n  function returnResults (query, resulttype, sessionid, data, rank, olddata, callbackSearch) {\n    var newscore, oldscore\n    var liveResults = true\n    var count = 0\n    if (data.resource && data.resource.apitemplate) { // TODO: why apitemplate necessary?\n      setLocalResource(data.resource)\n    }\n    if (data.hits && data.hits.length) {\n      count = data.hits.length // TODO: also includes 'rid'-only results from searsia engines\n      newscore = scoreAllHits(data, query, false)\n      oldscore = scoreAllHits(olddata, query, true)\n    }\n    if (count === 0 || oldscore - 0.5 > newscore) { // use old data if olddata is clearly better\n      data = olddata\n      liveResults = false\n      count = data.hits.length\n    }\n    if (count > 0) {\n      inferMissingData(data, query, resulttype, rank)\n      callbackSearch({\n        'searsia': SEARSIAVERSION,\n        'status': 'hits',\n        'sessionid': sessionid,\n        'resource': data.resource,\n        'hits': data.hits,\n        'rank': rank,\n        'query': query,\n        'live': liveResults })\n    }\n  }\n\n  function queryResources (query, resulttype, sessionid, data, callbackSearch) {\n    var pending = 0 // will be used by checkEmpty() and getResults()\n\n    function checkEmpty (sessionid, callbackSearch) {\n      if (pending === 0) {\n        callbackSearch({ 'searsia': SEARSIAVERSION, 'sessionid': sessionid, 'status': 'done' })\n      }\n    }\n\n    function getResults (query, resulttype, sessionid, rid, rank, olddata, callbackSearch) {\n      var template = getApiTemplate()\n      if (template == null) {\n        callbackSearch({\n          'searsia': SEARSIAVERSION,\n          'status': 'error',\n          'sessionid': sessionid,\n          'resource': { 'id': rid },\n          'message': 'No API template found.' })\n      } else {\n        pending += 1\n        searsiaAjax({\n          url: fillUrlTemplate(template, query, 1, rid, resulttype),\n          success: function (data) {\n            returnResults(query, resulttype, sessionid, data, rank, olddata, callbackSearch)\n            pending -= 1\n            checkEmpty(sessionid, callbackSearch)\n          },\n          error: function (xhr, options, err) {\n            if (xhr && xhr.status === 410) {\n              deleteLocalResource(rid)\n            } else {\n              returnResults(query, resulttype, sessionid, olddata, rank, olddata, callbackSearch)\n            }\n            console.log('WARNING: ' + rid + ' unavailable.')\n            pending -= 1\n            checkEmpty(sessionid, callbackSearch)\n          },\n          timeout: 12000,\n          dataType: 'json'\n        })\n      }\n    }\n\n    var rid, hits, olddata\n    var i = 0\n    var rank = 1\n    var done = []\n    var resource = data.resource\n    if (resource != null) {\n      setMother(resource)\n      if (resource.rerank != null) {\n        scoreAllHits(data, query, true)\n      }\n    } else {\n      resource = getMother()\n    }\n    callbackSearch({ 'searsia': SEARSIAVERSION, 'status': 'start', 'sessionid': sessionid, 'resource': resource })\n    hits = data.hits\n    if (hits == null || hits.length === 0) {\n      callbackSearch({ 'searsia': SEARSIAVERSION, 'status': 'done', 'sessionid': sessionid })\n      return\n    }\n    while (i < hits.length) {\n      rid = hits[i].rid\n      if (rid == null) { // a result that is not from another resource\n        if (data.resource != null && data.resource.urltemplate != null) {\n          hits[i].url = correctUrl(data.resource.urltemplate, hits[i].url)\n        }\n        callbackSearch({\n          'searsia': SEARSIAVERSION,\n          'hits': [ hits[i] ],\n          'query': query,\n          'status': 'hits',\n          'sessionid': sessionid,\n          'rank': rank })\n        rank += 1\n      } else if (done[rid] !== 1) {\n        olddata = { hits: [] }\n        if (existsLocalResource(rid)) {\n          olddata.resource = getLocalResource(rid)\n          while (i < hits.length && hits[i].rid === rid) {\n            if (hits[i].title != null && hits[i].title !== '' && // too many exceptions?\n                            (hits[i].url != null || olddata.resource.urltemplate != null) &&\n                            (hits[i].foundBefore == null || Date.now() - new Date(hits[i].foundBefore).getTime() < 1209600000)) { // 1209600000 is 2 weeks in ms\n              olddata.hits.push(hits[i])\n            }\n            i += 1\n          }\n          i -= 1 // otherwise we miss one\n        } else {\n          olddata.resource = { id: rid } // TODO: get it?\n        }\n        getResults(query, resulttype, sessionid, rid, rank, olddata, callbackSearch)\n        done[rid] = 1\n        rank += 1\n      }\n      i += 1\n    }\n  }\n\n  /**\n   * Generates a random identifier compliant with the uuid(v4) spec.\n   * The randomness of this number is based on Math.random(), which might not\n   * be a guaranteed RNG.\n   * @returns {string} the uuid string\n   */\n  function generateUUID () {\n    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,\n      function (c) {\n        var r = Math.random() * 16 | 0; var v = c === 'x' ? r : (r & 0x3 | 0x8)\n        return v.toString(16)\n      })\n  }\n\n  function searchFederated (params, callbackSearch) {\n    var url, query, page\n    var resulttype = null\n    var template = getApiTemplate()\n    var sessionid = generateUUID()\n    if (template == null) {\n      callbackSearch({ 'status': 'error', 'error': 'First initialize with searsia.initClient(apiTemplate)' })\n      return\n    }\n    if (params.q == null || params.q === '') {\n      callbackSearch({ 'status': 'error', 'sessionid': sessionid, 'error': 'No query.' })\n      return\n    }\n    if (params.q.length > 150) {\n      callbackSearch({ 'status': 'error', 'sessionid': sessionid, 'error': 'Query too long.' })\n      return\n    }\n    query = encodedQuery(params.q)\n    if (params.p == null) {\n      page = 1\n    } else {\n      page = params.p\n    }\n    if (params.t) {\n      resulttype = params.t\n    }\n    url = fillUrlTemplate(template, query, page, null, resulttype)\n    searsiaAjax({\n      url: url,\n      success: function (data) { queryResources(query, resulttype, sessionid, data, callbackSearch) },\n      error: function (xhr, options, error) {\n        console.log('ERROR: ' + error)\n        callbackSearch({ 'status': 'error', 'sessionid': sessionid, 'error': 'Temporarily out of order. Please try again later.' })\n      },\n      timeout: 10000,\n      dataType: 'json'\n    })\n    return sessionid\n  }\n\n  /* connect to mother and return definition */\n  function connectToServer (callbackConnect) {\n    var template = getApiTemplate()\n    if (template == null) {\n      callbackConnect({ 'status': 'error', 'error': 'If you see this then searsiaclient needs to be initialized with searsia.initClient(apiTemplate)' })\n    } else {\n      searsiaAjax({\n        url: fillUrlTemplate(template, '', '', null, null),\n        success: function (data) {\n          if (data.resource != null) {\n            data.status = 'connect'\n            setMother(data.resource)\n          }\n          callbackConnect(data)\n        },\n        error: function (xhr, options, error) {\n          console.log('ERROR: ' + error)\n          callbackConnect({ 'status': 'error', 'error': error })\n        },\n        timeout: 10000,\n        dataType: 'json'\n      })\n    }\n  }\n\n  /* sets the apiTemplate. If not new, return mother from storage */\n  function initClient (template) {\n    var originalTemplate = getApiTemplate()\n    var motherObject = null\n    if (template !== originalTemplate) {\n      clearLocalStorage()\n      setApiTemplate(template)\n    } else {\n      motherObject = getMother()\n    }\n    if (motherObject) {\n      return { 'resource': motherObject }\n    } else {\n      return null\n    }\n  }\n\n  return {\n    urlParameters: function () {\n      return urlParameters()\n    },\n    printableQuery: function (query) {\n      return printableQuery(query)\n    },\n    formQuery: function (query) {\n      return formQuery(query)\n    },\n    encodedQuery: function (query) {\n      return encodedQuery(query)\n    },\n    correctUrl: function (absUrl, relUrl) {\n      return correctUrl(absUrl, relUrl)\n    },\n    fillUrlTemplate: function (template, query, page, resourceId, resultType) {\n      return fillUrlTemplate(template, query, page, resourceId, resultType)\n    },\n    initClient: function (template) {\n      return initClient(template)\n    },\n    connectToServer: function (callbackConnect) {\n      connectToServer(callbackConnect)\n    },\n    searchFederated: function (params, callbackSearch) {\n      return searchFederated(params, callbackSearch)\n    }\n  }\n})()\n\nif (typeof module != \"undefined\")\n  module.exports = searsia;\n","const MIN_SUGGEST_LENGTH = 3; // Min number of characters for suggestions\nconst NUM_SUGGESTIONS = 5; // Max number of suggestions to show\nconst NUM_RELATED = 5; // Max number of related searches to show\n\n// Sources that aren't mapped here (e.g. 'googlecustom') are shown as 'plain' results\nconst SEARSIA_SOURCES =\n{\n  \"alsosearched\": { type: \"related\" },\n  \"alumni\": { type: \"news\" },\n  \"beeldbank\": { type: \"image\" },\n  \"bussen\": { type: \"pubtrans\", group: \"bus\" },\n  \"courses\": { type: \"courses\" },\n  \"cultuur\": { type: \"event\" },\n  \"didyoumean\": { type: \"didyoumean\" },\n  \"essays\": { type: \"publication\" },\n  \"evenementen\": { type: \"event\" },\n  \"facebook\": { type: \"news\" },\n  \"flickr\": { type: \"image\" },\n  \"forecast\": { type: \"weather\", group: \"weather\" },\n  \"instagram\": { type: \"image\" },\n  \"maps\": { type: \"location\" },\n  \"nieuws\": { type: \"news\" },\n  \"people\": { type: \"people\" },\n  \"publications\": { type: \"publication\" },\n  \"serviceportal\": { type: \"serviceportal\" },\n  \"treinen\": { type: \"pubtrans\", group: \"train\" },\n  \"utoday\": { type: \"news\" },\n  \"vimeo\": { type: \"video\" },\n  \"youtube\": { type: \"video\" }\n};\n\n// Duplicate URL's from these sources are deduplicated in the order they are listed here (e.g. if a URL is returned by both\n// the 'people' and 'googlecustom' sources, only the 'people' result is kept)\nconst SEARSIA_DUPLICATE_RESOURCES =\n  [\"courses\", \"evenementen\", \"googlecustom\", \"nieuws\", \"people\", \"serviceportal\"];\n\n// These words are filtered out of the user's query\nconst QUERY_STOPWORDS =\n{\n  \"nl\": [\n    \"de\", \"een\", \"en\", \"het\", \"of\",\n    \"a\", \"an\", \"and\", \"or\", \"the\"\n  ],\n  \"en\": [\"a\", \"an\", \"and\", \"or\", \"the\"]\n};\n\nif (typeof module !== \"undefined\") {\n  module.exports.MIN_SUGGEST_LENGTH = MIN_SUGGEST_LENGTH;\n  module.exports.NUM_SUGGESTIONS = NUM_SUGGESTIONS;\n  module.exports.NUM_RELATED = NUM_RELATED;\n  module.exports.SEARSIA_SOURCES = SEARSIA_SOURCES;\n  module.exports.SEARSIA_DUPLICATE_RESOURCES = SEARSIA_DUPLICATE_RESOURCES;\n  module.exports.QUERY_STOPWORDS = QUERY_STOPWORDS;\n}\n","// Auto-generated RPC interface from /opt/wh/whtree/modules/consilio/js/internal/search.rpc.json\nvar RPCClient = require(\"@mod-system/js/wh/rpc\").default;\nvar request = exports.rpcclient = new RPCClient(\"consilio:search\");\nexports.rpcResolve = function (promise, result) { request._handleLegacyRPCResolve(promise, result) };\nexports.invoke = function () { return request.invoke.apply(request,Array.prototype.slice.call(arguments)); }\n\nObject.defineProperty(module.exports, \"HTTP_ERROR\", { get: function () { return JSONRPC.HTTP_ERROR; }});\nObject.defineProperty(module.exports, \"JSON_ERROR\", { get: function () { return JSONRPC.JSON_ERROR; }});\nObject.defineProperty(module.exports, \"PROTOCOL_ERROR\", { get: function () { return JSONRPC.PROTOCOL_ERROR; }});\nObject.defineProperty(module.exports, \"RPC_ERROR\", { get: function () { return JSONRPC.RPC_ERROR; }});\nObject.defineProperty(module.exports, \"OFFLINE_ERROR\", { get: function () { return JSONRPC.OFFLINE_ERROR; }});\nObject.defineProperty(module.exports, \"TIMEOUT_ERROR\", { get: function () { return JSONRPC.TIMEOUT_ERROR; }});\nObject.defineProperty(module.exports, \"SERVER_ERROR\", { get: function () { return JSONRPC.SERVER_ERROR; }});\n\n// Adding dependency: '/opt/wh/whtree/modules/consilio/lib/internal/rpc_search.whlib'\n\nexports.suggest = exports.Suggest = /*RECORD*/function (/*RECORD*/ source, /*STRING*/ query, /*RECORD*/ options)\n{\nreturn request.invoke.apply(request,[\"Suggest\"].concat(Array.prototype.slice.call(arguments)));\n}\n","/* frontend-config parses the wh-config object in the browser and mocks any missing data. @webhare/env does not actually expose this config, @webhare/frontend does\n   The frontend configuration is built in the SiteResponse's 'frontendConfig' member */\n\nimport type { DTAPStage } from \"@webhare/env/src/concepts\";\nimport { debugFlags, initEnv } from \"@webhare/env/src/envbackend\";\nimport { getBrowserDebugFlags } from \"@webhare/env/src/init-browser\";\nimport type { FrontendDataTypes } from \"@webhare/frontend\";\n\n\n/** The format of the <script id=\"wh-config\"> object  */\nexport interface WHConfigScriptData {\n  ///Plugins may add keys at this level\n  [key: string]: unknown;\n\n  //NOTE: existing frontend code doesn't expect site/obj to ever be null. not sure if 'object' provides the best interface or whether we need some sort of 'unknown but an existing object'\n  /** Page (targetobject) specific settings */\n  obj: { [key: string]: unknown };\n  /** Site specific settings */\n  site: { [key: string]: unknown };\n\n  /** Numeric server version number (eg 5.02.24 = 50224)\n   *  @deprecated Interpreting numbers (or version strings) is dangerous. Feature flags/testing or limiting your entire module to compatible versions is safer\n  */\n  server: number;\n  /** Root URL of this site */\n  siteRoot: string;\n  /** @deprecated Use `document.documentElement.lang` instead */\n  locale: never;\n}\n\n//names fields can still have when not yet republished\nexport interface WHConfigScriptData_OldPublishFields {\n  islive: boolean;\n  dtapstage: DTAPStage;\n  siteroot: string;\n}\n\n//fallback names with deprecation warnings\nexport interface WHConfigScriptData_LegacyFields {\n  /** @deprecated Use dtapStage in WH5.4+ */\n  islive: boolean;\n  /** @deprecated Use `dtapStage` from \"\\@webhare/env\"; in WH5.4+ */\n  dtapstage: DTAPStage;\n  /** @deprecated Use `getSiteRoot` from \"\\@webhare/frontend\"; in WH5.7+ */\n  siteroot: string;\n}\n\ntype Configured = Partial<WHConfigScriptData & WHConfigScriptData_OldPublishFields & { dtapStage?: DTAPStage }>;\nlet config: Configured | undefined;\nlet siteroot;\nlet dtapStage: DTAPStage = \"production\";\n\n//if document is undefined, we're serverside or in a worker\nconst whconfigel = typeof document !== \"undefined\" ? document.querySelector('script#wh-config') : null;\nif (whconfigel?.textContent) {\n  config = JSON.parse(whconfigel.textContent) as Configured;\n\n  //Fallbacks for pages last published with WH5.3 *and* pages published from HareScript which still emit lowercase props\n  siteroot = config.siteRoot ?? config.siteroot;\n  dtapStage = config.dtapstage ?? config.dtapStage ?? dtapStage;\n}\n\ninitEnv(dtapStage, '/');\n\nif (typeof location !== \"undefined\")\n  for (const flag of getBrowserDebugFlags('wh-debug'))\n    debugFlags[flag] = true;\n\n\n/** @deprecated frontendConfig has been deprecated. Switch to the getFrontendData system */\n// Make sure we have obj/site as some sort of object, to prevent crashes on naive 'if ($wh.config.obj.x)' tests'\nexport const frontendConfig = {\n  server: 0,\n  ...config,\n  obj: config?.obj || {},\n  site: config?.site || {},\n  siteRoot: siteroot,\n  //deprecated variables:\n  dtapstage: dtapStage,\n  islive: ([\"production\", \"acceptance\"]).includes(dtapStage!),\n  siteroot\n} as WHConfigScriptData & WHConfigScriptData_LegacyFields; //in a future version we can either obsolete or even drop '& WHConfigScriptData_LegacyFields' and validation will fail without breaking existing JS code\n\n\n//NOTE: These APIs need to live in init.ts so eg gtm.ts can access us without triggering a CSS reset through frontend.ts. When frontend.ts stops auto-resetting we might move it back\n\nexport function getFrontendData<Type extends keyof FrontendDataTypes>(type: Type, options: { allowMissing: true }): FrontendDataTypes[Type] | null;\nexport function getFrontendData<Type extends keyof FrontendDataTypes>(type: Type, options?: { allowMissing: boolean }): FrontendDataTypes[Type];\n\n/** Get data exported by the response\n * @typeParam Type - The type of data to get\n * @param dataObject - The data object of data to get\n * @param allowMissing - If true, return null if the data object is missing. Otherwise throw an error\n * @example\n```\n  declare module \"@webhare/frontend\" {\n    interface FrontendDataTypes {\n      \"mymodule:type\": {\n        test: number;\n      };\n    }\n  }\n\n  const data = getFrontendData(\"mymodule:type\");\n```\n*/\nexport function getFrontendData<Type extends keyof FrontendDataTypes>(dataObject: Type, { allowMissing = false } = {}): FrontendDataTypes[Type] | null {\n  const retval = config?.[dataObject] as FrontendDataTypes[Type];\n  if (!retval)\n    if (allowMissing)\n      return null;\n    else\n      throw new Error(`Missing frontend data object: ${dataObject}`);\n\n  return retval;\n}\n\n/** Get the current site root\n *\n * @returns The site root URL (ending with a slash)\n*/\nexport function getSiteRoot() { //now an API to improve treeshaking\n  return frontendConfig.siteRoot;\n}\n","\n//Note that @webhare/env does not invoke this API itself. In WebHare @webhare/frontend/src/init uses this to initialize\nexport function getBrowserDebugFlags(varname: string): string[] {\n  const flags = [];\n  const urldebugvar = new URL(location.href).searchParams.get(varname);\n  if (urldebugvar)\n    flags.push(...urldebugvar.split(','));\n\n  //not importing getCookie to solve some import ordering issues\n  if (typeof document !== \"undefined\") { //'document' is undefined in a worker but assetpacks compiled for a ServiceWorker will also load us\n    const debugcookie = document.cookie.match(`(?:^|;)\\\\s*${varname}=([^;]*)`); //TODO escape varname\n    if (debugcookie) {\n      const debugcookievalue = decodeURIComponent(debugcookie[1]);\n      if (debugcookievalue)\n        flags.push(... (debugcookievalue.split('.').filter(flag => !flag.startsWith('sig='))));\n    }\n  }\n\n  return flags;\n}\n","import \"@webhare/tsrun/src/polyfills\";\nimport \"./iterator-helpers\";\nimport \"./publisher-integration\";\n","/* eslint-disable @typescript-eslint/array-type */\n/* eslint-disable @typescript-eslint/no-loop-func */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-this-alias */\n\n/* Iterator polyfills (https://caniuse.com/?search=iterator) - stage 4 ES but not in all browsers yet\n   Based on https://github.com/alkihis/iterator-polyfill/tree/master but we removed all the AsyncIterator\n   stuff as that's still stage 2 AND not implemented in TypeScript (as of 5.6)\n\n   We're ignoring a few linting/any issues as we really don't care to maintain this much\n   Fixed an issue with .some - reported as https://github.com/alkihis/iterator-polyfill/issues/6\n*/\n\n(function () {\n  // polyfill already applied / proposal implemented\n  if ('Iterator' in globalThis) {\n    return;\n  }\n\n  // Polyfill for Iterator\n  const IteratorPrototype = {};\n\n  const ArrayIteratorPrototype = Object.getPrototypeOf([][Symbol.iterator]());\n  const OriginalIteratorPrototype = Object.getPrototypeOf(ArrayIteratorPrototype);\n\n  Object.setPrototypeOf(OriginalIteratorPrototype, IteratorPrototype);\n\n  Object.defineProperties(IteratorPrototype, {\n    [Symbol.iterator]: {\n      value() {\n        return this;\n      }\n    },\n    map: {\n      *value<T, R>(callback: (value: T) => R): Generator<any, any, any> {\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = callback(value.value);\n          const next_value = yield real_value;\n          value = it.next(next_value);\n        }\n\n        return value.value;\n      },\n    },\n    filter: {\n      *value<T>(callback: (value: T) => boolean): Generator<any, any, any> {\n        const it = this;\n        let value = it.next();\n        let next_value;\n\n        while (!value.done) {\n          const real_value = value.value;\n          if (callback(real_value)) {\n            next_value = yield real_value;\n            value = it.next(next_value);\n          } else {\n            value = it.next(next_value);\n          }\n        }\n\n        return value.value;\n      },\n    },\n    find: {\n      value<T>(callback: (value: boolean) => T) {\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (callback(real_value))\n            return real_value;\n\n          value = it.next();\n        }\n      }\n    },\n    every: {\n      value<T>(callback: (value: T) => boolean) {\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (!callback(real_value))\n            return false;\n\n          value = it.next();\n        }\n\n        return true;\n      }\n    },\n    some: {\n      value<T>(callback: (value: T) => boolean) {\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (callback(real_value)) {\n            it.return();\n            return true;\n          }\n\n          value = it.next();\n        }\n\n        return false;\n      }\n    },\n    toArray: {\n      value(max_count = Infinity) {\n        const values = [];\n\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (max_count <= 0)\n            return values;\n\n          values.push(real_value);\n\n          if (max_count !== Infinity)\n            max_count--;\n\n          value = it.next();\n        }\n\n        return values;\n      }\n    },\n    take: {\n      *value(limit: number): Generator<any, any, any> {\n        limit = Number(limit);\n        if (limit < 0)\n          throw new RangeError('Invalid limit.');\n\n        const it = this;\n        let value = it.next();\n        let remaining = limit;\n        let next_value;\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (remaining <= 0)\n            return;\n\n          next_value = yield real_value;\n          value = it.next(next_value);\n          remaining--;\n        }\n\n        return value.value;\n      },\n    },\n    drop: {\n      *value(limit: number): Generator<any, any, any> {\n        limit = Number(limit);\n        if (limit < 0)\n          throw new RangeError('Invalid limit.');\n\n        const it = this;\n        let value = it.next();\n        let remaining = limit;\n        let next_value;\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (remaining > 0) {\n            value = it.next(next_value);\n            remaining--;\n            continue;\n          }\n\n          next_value = yield real_value;\n          value = it.next(next_value);\n        }\n\n        return value.value;\n      },\n    },\n    asIndexedPairs: {\n      *value(): Generator<any, any, any> {\n        const it = this;\n        let value = it.next();\n        let index = 0;\n\n        while (!value.done) {\n          const real_value = value.value;\n          const next_value = yield [index, real_value];\n          value = it.next(next_value);\n          index++;\n        }\n\n        return value.value;\n      }\n    },\n    flatMap: {\n      *value<T, R extends object>(mapper: (value: T) => IterableIterator<R> | R): Generator<any, any, any> {\n        if (typeof mapper !== 'function') {\n          throw new TypeError('Mapper must be a function.');\n        }\n\n        const it = this;\n        let value = it.next();\n        let next_value;\n\n        while (!value.done) {\n          const real_value = value.value;\n          const mapped = mapper(real_value);\n\n          if (Symbol.iterator in mapped) {\n            // @ts-ignore -- copied from original\n            next_value = yield* mapped[Symbol.iterator]();\n          } else {\n            next_value = yield mapped;\n          }\n\n          value = it.next(next_value);\n        }\n\n        return value.value;\n      },\n    },\n    reduce: {\n      value<T, V>(reducer: (acc: V, value: T) => V, initial_value?: V) {\n        let acc = initial_value;\n\n        const it = this;\n        if (acc === undefined) {\n          acc = it.next().value;\n        }\n\n        let value = it.next();\n        while (!value.done) {\n          const real_value = value.value;\n\n          acc = reducer(acc!, real_value);\n\n          value = it.next();\n        }\n\n        return acc;\n      }\n    },\n    forEach: {\n      value<T>(callback: (value: T) => any) {\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          callback(real_value);\n\n          value = it.next();\n        }\n      }\n    },\n    [Symbol.toStringTag]: {\n      value: 'IteratorPrototype'\n    },\n\n    /* OUTSIDE PROPOSAL */\n    count: {\n      value() {\n        let count = 0;\n\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          count++;\n          value = it.next();\n        }\n\n        return count;\n      },\n    },\n    join: {\n      value(string: string) {\n        let final = '';\n        let first = true;\n\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (first) {\n            first = false;\n            final += real_value;\n          } else {\n            final += string + real_value;\n          }\n\n          value = it.next();\n        }\n\n        return final;\n      }\n    },\n    chain: {\n      *value<I>(...iterables: IterableIterator<I>[]) {\n        yield* this;\n\n        for (const it of iterables) {\n          yield* it;\n        }\n      }\n    },\n    zip: {\n      *value<T, O>(...others: IterableIterator<O>[]): Iterator<(T | O)[]> {\n        const it_array = [this, ...others].map((e: any) => Symbol.iterator in e ? e[Symbol.iterator]() : e as Iterator<T | O>);\n        let values = it_array.map(e => e.next());\n        let next_value: any;\n\n        while (values.every(e => !e.done)) {\n          next_value = yield values.map(e => e.value);\n          values = it_array.map(e => e.next(next_value));\n        }\n      },\n    },\n    takeWhile: {\n      *value<T>(callback: (value: T) => boolean): Generator<any, any, any> {\n        const it = this;\n        let value = it.next();\n        let next_value;\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (callback(real_value))\n            next_value = yield real_value;\n          else\n            return;\n\n          value = it.next(next_value);\n        }\n\n        return value.value;\n      }\n    },\n    dropWhile: {\n      *value<T>(callback: (value: T) => boolean): Generator<any, any, any> {\n        const it = this;\n        let value = it.next();\n        let next_value;\n        let finished = false;\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (!finished && callback(real_value)) {\n            value = it.next(next_value);\n            continue;\n          }\n\n          finished = true;\n          next_value = yield real_value;\n\n          value = it.next(next_value);\n        }\n\n        return value.value;\n      }\n    },\n    fuse: {\n      *value(): Generator<any, any, any> {\n        const it = this;\n        let value = it.next();\n        let next_value;\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (real_value !== undefined && real_value !== null)\n            next_value = yield real_value;\n          else\n            return;\n\n          value = it.next(next_value);\n        }\n\n        return value.value;\n      }\n    },\n    partition: {\n      value<T>(callback: (value: T) => boolean) {\n        const partition1 = [], partition2 = [];\n\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (callback(real_value))\n            partition1.push(real_value);\n          else\n            partition2.push(real_value);\n\n          value = it.next();\n        }\n\n        return [partition1, partition2];\n      },\n    },\n    findIndex: {\n      value<T>(callback: (value: T) => boolean) {\n        const it = this;\n        let i = 0;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (callback(real_value))\n            return i;\n\n          value = it.next();\n          i++;\n        }\n\n        return -1;\n      }\n    },\n    max: {\n      value() {\n        let max = -Infinity;\n\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (max < real_value)\n            max = real_value;\n\n          value = it.next();\n        }\n\n        return max;\n      },\n    },\n    min: {\n      value() {\n        let min = Infinity;\n\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n\n          if (min > real_value)\n            min = real_value;\n\n          value = it.next();\n        }\n\n        return min;\n      },\n    },\n    cycle: {\n      *value(): Generator<any, any, any> {\n        const values = [];\n\n        const it = this;\n        let value = it.next();\n\n        while (!value.done) {\n          const real_value = value.value;\n          values.push(real_value);\n\n          const next_value = yield real_value;\n          value = it.next(next_value);\n        }\n\n        while (true) {\n          yield* values;\n        }\n      },\n    },\n  });\n\n  //iterator.from from https://github.com/rauschma/iterator-helpers-polyfill/\n\n  function isObject(value: unknown) {\n    if (value === null) return false;\n    const t = typeof value;\n    return t === 'object' || t === 'function';\n  }\n\n  function GetIteratorFlattenable<T>(obj: Record<symbol, any>): T {\n    if (!isObject(obj)) {\n      throw new TypeError();\n    }\n    const method = obj[Symbol.iterator];\n    let iterator = undefined;\n    if (typeof method !== 'function') {\n      iterator = obj;\n    } else {\n      iterator = method.call(obj);\n    }\n    if (!isObject(iterator)) {\n      throw new TypeError();\n    }\n    return iterator;\n  }\n\n  if (!('Iterator' in globalThis)) {\n    const Iterator = function Iterator() { };\n\n    Iterator.prototype = IteratorPrototype;\n\n    // @ts-expect-error We're still missing From in this poyfill\n    (globalThis).Iterator = Iterator;\n  }\n\n\n  //----- Static method -----\n  // Must be done after Iterator.prototype was set up,\n  // so that `extends Iterator` works below\n\n  class WrappedIterator<T, TReturn = any, TNext = undefined> extends Iterator<T, TReturn, TNext> {\n    #iterator;\n    constructor(iterator: Iterator<T, TReturn, TNext>) {\n      super();\n      this.#iterator = iterator;\n    }\n    override next(...args: [] | [TNext]): any {\n      return this.#iterator.next(...args);\n    }\n    // `async` helps with line (*)\n    override return(value?: TReturn | PromiseLike<TReturn>): any {\n      const returnMethod = this.#iterator.return;\n      if (returnMethod === undefined) {\n        return { done: true, value: value as any }; // (*)\n      }\n      return returnMethod.call(this.#iterator);\n    }\n  }\n\n  function Iterator_from<T>(value: any) {\n    const iterator = GetIteratorFlattenable<Iterator<T>>(value);\n    if (iterator instanceof Iterator) {\n      return iterator;\n    }\n    // `iterator´ does not support the new API – wrap it so that it does\n    return new WrappedIterator(iterator);\n  }\n\n  Object.defineProperty(\n    Iterator, 'from',\n    {\n      writable: true,\n      enumerable: false,\n      configurable: true,\n      value: Iterator_from,\n    }\n  );\n})();\n","import { isHTMLElement } from \"@webhare/dompack\";\nimport type { CMSConfig } from \"@mod-system/js/internal/generation/gen_misc_ts\";\n\nlet config: CMSConfig | undefined;\n\nfunction forwardPublisherNavigation(event: Event) {\n  /* we watch for clicks.. as we only want to update the Publisher's selection for user triggered actions (otherwise we'd\n     start navigation in response to JS or internal link autoredirects) */\n  if (!isHTMLElement(event.target) || !config?.interfaceServers)\n    return;\n\n  const navaction = event.target.closest<HTMLAnchorElement>('a[href]');\n  if (!navaction)\n    return;\n\n  const desturl = navaction.href;\n  if (desturl.split('#')[0] !== location.href.split('#')[0]) { //it's actual navigation...\n    for (const origin of config.interfaceServers) {\n      try {\n        window.top?.postMessage({ type: \"webhare-navigation\", location: desturl }, origin);\n      } catch (ignore) {\n        //ignore crossdomain errors\n      }\n    }\n  }\n}\n\nasync function configureForCMS() {\n  try {\n    const res = await fetch(\"/.wh/ea/config/cms.json\");\n    config = await res.json();\n  } catch (e) {\n    console.log(\"Failed to get CMS configuration\", e);\n    return;\n  }\n  window.addEventListener(\"click\", forwardPublisherNavigation);\n}\n\nif (typeof window !== \"undefined\" && window !== window.top) { //if we're in an iframe, we may be running in WebHare and need to forward navigation events\n  //we have no way to detect whether we're in a WebHare iframe or a 3rd party iframe. assume it's webhare and grab the interface servers\n  void configureForCMS();\n}\n","import { qSA } from \"@webhare/dompack\";\nimport { debugFlags } from \"@webhare/env\";\nimport type { FormAnalyticsEvent } from \"@webhare/forms\";\nimport type { DataLayerEntry } from \"./gtm-types\";\n\ndeclare global {\n  interface Window {\n    dataLayer: DataLayerEntry[];\n  }\n}\n\n//ADDME if we ever figure out a bundler trick to flush this command to the top of all imports/loads, that would be great (we could consider *ALWAYS* putting this in the generated startup code, or we'd need to do a tree pre-walk to see if gtm.es is loaded anywhere)\nwindow.dataLayer ||= [];\nlet lastSeen: DataLayerEntry | undefined;\n\nfunction showDataLayerUpdates() {\n  if (typeof window.dataLayer === 'undefined')\n    return; //not set up (yet?)\n\n  if (debugFlags.anl)\n    window.dataLayer.slice(window.dataLayer.indexOf(lastSeen!) + 1).forEach(entry => console.log(\"[anl] dataLayer.push:\", entry));\n\n  lastSeen = window.dataLayer[window.dataLayer.length - 1];\n}\n\n/** Push to the dataLayer\n * @param vars - The variables to push\n * @param options - Options for the push\n *   timeout Time before any eventCallback is forcibly called (default 200ms)\n*/\nexport function pushToDataLayer(vars: DataLayerEntry, options?: { timeout?: number }) {\n  if (vars.eventCallback) { //we'll wrap the callback into a promise to ensure it's only invoked once\n    const savecallback = vars.eventCallback;\n    let newcallback: () => void;\n    void (new Promise<void>(resolve => newcallback = resolve)).then(() => savecallback());\n    setTimeout(() => newcallback, options?.timeout || 200);\n  }\n\n  window.dataLayer.push(vars);\n  showDataLayerUpdates();\n}\n\nfunction collectFormValues(formnode: HTMLFormElement): Record<string, unknown> {\n  const donefields: Record<string, boolean> = {};\n  const outdata: Record<string, unknown> = {};\n\n  const multifields = qSA<HTMLInputElement>(formnode, 'input[type=radio], input[type=checkbox]');\n  for (const multifield of multifields) {\n    if (!multifield.name || donefields[multifield.name])\n      continue; //we did this one\n\n    donefields[multifield.name] = true;\n\n    let idx = 0;\n    const values = [];\n    const labels = [];\n    const checkboxes = multifields.filter(node => node.name === multifield.name);\n\n    for (const node of checkboxes.filter(cbox => cbox.checked)) {\n      const keyname = 'form_' + multifield.name + (idx ? '_' + idx : '');\n      let labelsfornode = node.dataset.gtmTag || qSA(`label[for=\"${CSS.escape(node.id)}\"]`).map(labelnode => labelnode.textContent).filter(labelnode => Boolean(labelnode)).join(' ');\n      labelsfornode = labelsfornode.trim(); //TODO normalize whitespace\n      outdata[keyname] = node.value;\n      outdata[keyname + '_label'] = labelsfornode;\n\n      ++idx;\n      values.push(node.value);\n      labels.push(labelsfornode);\n    }\n\n    if (values.length) {\n      const allkeyname = 'form_' + multifield.name + '_all';\n      outdata[allkeyname] = values.join(';');\n      outdata[allkeyname + '_label'] = labels.join(';');\n    }\n  }\n\n  for (const field of formnode.querySelectorAll<HTMLSelectElement | HTMLInputElement>('input:not([type=radio]):not([type=checkbox]),select,textarea')) {\n    if (!field.name || donefields[field.name])\n      continue;\n\n    donefields[field.name] = true;\n\n    const val = field.value;\n    outdata['form_' + field.name] = val;\n    if (field.matches('select')) {\n      const opt = (field as HTMLSelectElement).options[(field as HTMLSelectElement).selectedIndex];\n      if (opt)\n        outdata['form_' + field.name + '_label'] = opt.dataset.gtmTag || opt.textContent;\n    }\n  }\n  return outdata;\n}\n\n/** Setup the dataLayer */\nlet didinit: boolean | undefined;\nexport function setupGTM() {\n  if (!didinit) {\n    didinit = true;\n    if (debugFlags.anl)\n      setInterval(showDataLayerUpdates, 100);\n  }\n}\n\n/** Setup dataLayer events for form analytics events\n * @param options - Options for the form analytics setup\n     - `eventPrefix`. Prefix to use. Default is `wh-platform:form_` but existing integrations may (also) require `publisher:form`\n*/\nexport function setupFormAnalyticsForGTM(options?: { eventPrefix: string }): void {\n  setupGTM(); //ensurse the GTM basics are installed\n\n  addEventListener(\"wh:form-analytics\", (e: FormAnalyticsEvent) => {\n    //we use the same prefixing as pxl events would\n    const entry: DataLayerEntry = {\n      event: `${options?.eventPrefix || \"platform:form_\"}${e.detail.event}`\n    };\n\n    for (const [key, val] of Object.entries(e.detail))\n      if (key !== \"event\" && [\"string\", \"number\", \"boolean\"].includes(typeof val))\n        entry[`formmeta_${key}`] = val;\n\n    const form = e.target as HTMLFormElement | undefined;\n    if (form?.dataset.gtmSubmit) {\n      //When set, we push both the form: variable in gtmSubmit and the current form field avlues\n      Object.assign(entry, JSON.parse(form.dataset.gtmSubmit));\n      Object.assign(entry, collectFormValues(form));\n    }\n\n    pushToDataLayer(entry);\n  });\n}\n\nfunction processClickDataLayerTags(event: MouseEvent) {\n  const entry: Record<string, unknown> = {};\n\n  for (let node = event.target as HTMLElement | undefined | null; node; node = node?.parentElement)\n    for (const attr of node.attributes)\n      if (attr.nodeName.startsWith(\"data-wh-datalayer-onclick-\")) {\n        const key = attr.nodeName.substring(26);\n        if (key !== \"__proto__\" && !(key in entry)) //as we're working upwards, don't overwrite already set keys\n          entry[key] = attr.nodeValue || \"\";\n      } else if (attr.nodeName === \"data-wh-datalayer-onclick\") { //JSON setter\n        const data = JSON.parse(attr.nodeValue!);\n        for (const [key, value] of Object.entries(data))\n          if (key !== \"__proto__\" && !(key in entry)) //as we're working upwards, don't overwrite already set keys\n            entry[key] = value;\n      }\n\n  if (Object.keys(entry).length)\n    pushToDataLayer(entry as DataLayerEntry);\n}\n\n/** Setup support for data-wh-datalayer-onclick-xxx=\"yyy\" attributes. When clicking an element with these attributes the JSON from the attribute and all parents are merged together and pushed to the dataLayer  */\nexport function setupDataLayerTags() {\n  //we capture so we can also simply set variables for any existing GTM handlers\n  window.addEventListener(\"click\", processClickDataLayerTags, { capture: true });\n}\n","/* import '@mod-publisher/js/analytics/gtm';\n   enables ?wh-debug=anl support for GTM calls and implements non-script integration methods */\nimport { pushToDataLayer, setupGTM } from \"@webhare/frontend/src/gtm\";\nimport type { DataLayerEntry } from \"@webhare/frontend/src/gtm-types\";\nimport * as dompack from '@webhare/dompack';\nimport { debugFlags } from '@webhare/env';\nimport { loadScript } from '@webhare/dompack';\nimport { onConsentChange, type ConsentSettings } from \"./consenthandler\";\n\n//NOTE: Do *NOT* load @webhare/frontend or we enforce the new CSS reset!\nimport { getFrontendData } from '@webhare/frontend/src/init';\n\ndeclare global {\n  interface Window {\n    __gtmformsubmit: undefined | 1; //used by dev module for a sanity check\n  }\n}\n\nconst gtmsettings = getFrontendData(\"socialite:gtm\", { allowMissing: true });\nlet didinit: undefined | true;\n\n/* Send variables to the data layer */\nexport function setVariables(vars: DataLayerEntry & { event?: never }) {\n  if (vars.event)\n    throw new Error(\"An 'event' is not a a variable. use sendEvent for events\");\n  pushToDataLayer(vars);\n}\n\n/** Send an event to the data layer. Returns a promise that will resolve when the event is sent, or after a timeout of 200ms\n * @param event - The event name to send. If null, doesn't actually set an event but just sets the variables\n * @param vars - The variables to send with the event\n * @returns A promise that resolves when the event is sent or after a timeout of 200ms\n*/\nexport function sendEvent(event: string | null, vars: DataLayerEntry & { event?: never } = {}) {\n  const defer = Promise.withResolvers();\n  try {\n    if (event)\n      pushToDataLayer({ event: event, eventCallback: () => defer.resolve(false), ...vars });\n    else\n      pushToDataLayer(vars);\n  } catch (e) {\n  }\n  window.setTimeout(() => defer.resolve(true), event ? 200 : 0);\n  return defer.promise;\n}\n\nfunction processGTMPluginInstruction(node: HTMLElement) {\n  const topush = node.getAttribute(\"push\");\n  if (topush)\n    window.dataLayer.push(...JSON.parse(topush));\n}\n\nexport async function init() {\n  if (didinit || !gtmsettings) //even though we check for gtmsettings being available before init(), we may be invoked externally by manual launchers\n    return false;\n\n  didinit = true;\n  window.dataLayer.push({ 'gtm.start': Date.now() });\n\n  //give other event handlers a chance to run and add their events\n  await new Promise(resolve => window.setTimeout(resolve, 1));\n  window.dataLayer.push({ event: 'gtm.js' });\n\n  if (gtmsettings.h && !debugFlags.sne) { //self hosting\n    //ADDME taking whintegration.config.designcdnroot would be nice, but it's current format is pretty unusable\n    const src = \"/.se/gtm.\" + gtmsettings.a.substr(4).toLowerCase() + \".js\";\n    try {\n      await loadScript(src);\n      return; //done!\n    } catch (e) {\n      console.warn(\"Cannot load local GTM version at \", src);\n      //fallback to loading GTM's version\n    }\n  }\n  const gtmsrc = (gtmsettings.s ?? \"https://www.googletagmanager.com/gtm.js\") + \"?id=\" + gtmsettings.a;\n  await loadScript(gtmsrc);\n}\n\nexport function initOnConsent() {\n  if (!(gtmsettings && gtmsettings.a && gtmsettings.m))\n    console.error(\"<gtm/> tag must be configured with launch=manual to support initOnConsent\");\n\n  onConsentChange((consentsettings: ConsentSettings) => {\n    const consentsetting = consentsettings.consent?.length ? consentsettings.consent.join(' ') : \"denied\";\n    window.dataLayer.push({ \"wh.consent\": consentsetting, \"event\": \"wh-consentchange\" });\n    void init();\n  });\n}\n\nexport function configureGTMFormSubmit(opts: { eventname: string }) {\n  //STUB to remove sometime after WH5.7 - this used to setup the wh-formevents behavior\n}\n\ndompack.register(\"wh-socialite-gtm\", processGTMPluginInstruction);\n\nif (gtmsettings?.a && !gtmsettings?.m) //account is set, manual is not set\n  void init();\n\nwindow.__gtmformsubmit = 1; //allow us to validate we're installed - ADDME compile only in dev mode\n\n//unconditionally invoked if you use the 'old' import\nsetupGTM();\n","import * as dompack from '@webhare/dompack';\nimport { navigateTo } from '@webhare/env';\nimport { debugFlags } from '@webhare/env/src/envbackend';\n\ndeclare global {\n  interface Window {\n    whResetConsent: () => void;\n  }\n  interface GlobalEventHandlersEventMap {\n    \"wh:consent-changed\": CustomEvent<ConsentSettings>;\n  }\n}\n\nexport interface SetupConsentOptions {\n  /** Domain to which to bind the cookie, can be at most one level higher (eg '.example.net' for 'www.example.net') */\n  cookiedomain?: string;\n  /** Duration to store or extend the consent, in days. Defaults to 365 */\n  cookieduration?: number;\n  /** The consent tags which are active by default (only use this for anonymous tracking and functional cookies) */\n  defaultconsent?: string[];\n}\n\ninterface ConsentStatus {\n  /** Version (2) */\n  v: 2;\n  //** Consent options */\n  c?: string[];\n  /** Last consent change (ISO8601 date) */\n  lc?: string;\n}\n\nlet consentstatus: ConsentStatus | null;\nlet cookiename: string | undefined;\nlet consentoptions: SetupConsentOptions | undefined;\n\nexport type ConsentSettings = {\n  isdefault: true;\n  consent: string[];\n} | {\n  isdefault: false;\n  consent: string[] | undefined; //we've explicitly defined no consent-yet-given as 'undefined' (TODO was this a good idea?)\n};\n\n/** Setup the consent handler\n    @param usecookiename - Name of the cookie. Should be identical for all sites sharing this consent, set to empty string if you store consent externally\n    @param consentrequester - Function to invoke if consent is unknown to eg trigger a cookie bar. This function will be immediately registered for invocation through dompack.onDomReady\n*/\nexport function setup(usecookiename: string, consentrequester?: () => void, options?: SetupConsentOptions) {\n  if (typeof usecookiename !== 'string')\n    throw new Error(\"Cookiename must be of type 'string'\");\n  if (debugFlags.cst)\n    console.log(`[cst] consenthandler initialized. cookiename: '${usecookiename}'`);\n\n  cookiename = usecookiename;\n  consentoptions = {\n    cookieduration: 365,\n    defaultconsent: [],\n    ...options\n  };\n\n  if (consentrequester)\n    try {\n      consentstatus = JSON.parse(dompack.getCookie(cookiename)!);\n      if (debugFlags.cst)\n        console.log(`[cst] initial consent state:`, consentstatus);\n    } catch (ignore) {\n    }\n\n  if (!consentstatus || typeof consentstatus !== \"object\" || consentstatus.v !== 2 || typeof consentstatus.c !== \"object\")\n    consentstatus = { v: 2 };\n\n  if (!(\"c\" in consentstatus)) { //simple consent flag\n    if (consentrequester)\n      dompack.onDomReady(consentrequester); //run the request function, but only on domready! it's a safe assumption it should be delayed...\n  } else {\n    storeConsent(); //renew the status\n  }\n  updateConsent();\n}\n\n//Test for consent\nexport function hasConsent(consentsetting: string) {\n  if (consentsetting === undefined) //generic consent check\n    throw new Error(\"hasConsent required a string argument\");\n\n  const details = getConsentDetail();\n  if (!details // setup() not called yet?\n    || !details.consent) // no consent has been given and no defaults are available consent will be undefined?\n    return undefined;\n\n  return details.consent.includes(consentsetting);\n}\n\n//Set simple consent\nexport function setConsent(newsetting: string[]) {\n  if (cookiename === undefined)\n    throw new Error(\"Invoke consenthandler.setup before modifying consent state!\");\n  if (typeof newsetting !== \"object\" || !Array.isArray(newsetting))\n    throw new Error(\"Expecting an array in call to setConsent\");\n\n  // Check if there are some consents being revoked\n  const details = getConsentDetail(); // get current list of consent tags, including implicit (default) consent\n  let consent_revoked = false;\n  if (details?.consent) { // if no explicit or default consent, the consent field is undefined\n    for (const tag of details.consent) {\n      if (!newsetting.includes(tag))\n        consent_revoked = true;\n    }\n  }\n\n  if (!consentstatus)\n    throw new Error(`Attempting to change consent status before invoking consenthandler.setup`);\n\n  consentstatus.c = newsetting.sort();//ensure stable order\n  consentstatus.lc = (new Date()).toISOString();\n\n  storeConsent();\n\n  // Revoked consent may need a reload to take effect.\n  // This is because it's not worth the effort for most websites to implement on-the-fly disabling\n  // of functionality. It might even be impossible if 3rd party scripts are already loaded.\n  if (consent_revoked) {\n    console.log(\"[cst] Reloading to handle revoked consent\");\n    navigateTo({ type: \"reload\" });\n  }\n\n  updateConsent();\n}\n\n/** Get a list of consents and whether they are defaults (or explicitly set)\n    @returns consent: list all consents\n            isdefault: if true then the consents are implicit/defaults (not consent explicitly given by the user)\n*/\nfunction getConsentDetail(): ConsentSettings | null {\n  if (!consentstatus) // setup() did not run yet\n    return null;\n\n  if (!(\"c\" in consentstatus)) { // consent not set yet\n    if (consentoptions?.defaultconsent && consentoptions?.defaultconsent.length > 0)\n      return { consent: consentoptions!.defaultconsent!, isdefault: true }; // use fallback consent\n    else\n      return { consent: undefined, isdefault: false }; // no consent given yet (expected to return undefined for consent)\n  }\n\n  return {\n    consent: consentstatus.c,\n    isdefault: false\n  };\n}\n\nexport function onConsent(type: string, callback: (cs: ConsentSettings) => void) {\n  window.addEventListener(\"wh:consent-changed\", evt => {\n    if (evt.detail.consent?.includes(type))\n      callback(evt.detail);\n  });\n\n  const details = getConsentDetail();\n\n  if (details && details.consent && details.consent.includes(type)) {//already missed it, so invoke\n    if (debugFlags.cst)\n      console.log(\"[anl] Invoking callback\", details);\n    callback(details);\n  }\n}\n\n//Register callback for content changes\nexport function onConsentChange(callback: (cs: ConsentSettings) => void): void {\n  window.addEventListener(\"wh:consent-changed\", evt => callback(evt.detail));\n\n  const details = getConsentDetail();\n\n  if (details) { //already missed it, so invoke\n    if (debugFlags.cst)\n      console.log(\"[cst] Invoking callback\", details);\n    callback(details);\n  }\n}\n\nfunction updateConsentOverlays() {\n  const overlays = dompack.qSA(\".wh-requireconsent__overlay\");\n  const consent = getConsentDetail()!.consent; //we are only scheduled when details are set (but we reread them as they may change)\n\n  if (debugFlags.cst)\n    console.log(`[cst] update ${overlays.length} consent overlay(s). ${consent ? `consent: ${consent.length ? consent.join(', ') : \"<none>\"}` : \"<undefined>\"}`);\n\n  overlays.forEach(overlay => {\n    const parent = overlay.closest<HTMLElement>(\".wh-requireconsent\");\n    if (parent && parent.dataset.whConsentRequired)\n      overlay.hidden = consent?.includes(parent.dataset.whConsentRequired) || false;\n  });\n}\n\nfunction updateConsent() { //update in DOM, GTM, etc\n  const details = getConsentDetail();\n\n  if (!details // setup() not called yet?\n    || !details.consent) { // no consent has been given and no defaults are available consent will be undefined?\n    document.documentElement.dataset.whConsent = \"unknown\"; // unknown - no explicit or explicit (options.defaultconsent) consent\n    return;\n  }\n\n  document.documentElement.dataset.whConsent = details.consent.length ? details.consent.join(\" \") : \"denied\";\n\n  if (debugFlags.cst)\n    console.log(\"[cst] Firing wh:consent-changed with\", details);\n\n  dompack.dispatchCustomEvent(window, \"wh:consent-changed\", { bubbles: false, cancelable: false, detail: details });\n  dompack.onDomReady(updateConsentOverlays);\n}\n\nfunction storeConsent() {\n  if (cookiename)\n    dompack.setCookie(cookiename, JSON.stringify(consentstatus), { duration: consentoptions!.cookieduration, domain: consentoptions!.cookiedomain });\n}\n\nwindow.whResetConsent = function () {\n  if (cookiename === undefined)\n    throw new Error(\"Consent handler not setup\");\n  else if (!cookiename)\n    throw new Error(\"Consent handler is not handling storage\");\n\n  dompack.deleteCookie(cookiename);\n  console.log(\"Reloading for whResetConsent\");\n  navigateTo({ type: \"reload\" });\n};\n","import * as dompack from 'dompack';\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport { getFrontendData, sendPxl } from '@webhare/frontend';\nimport { debugFlags } from '@webhare/env';\n\nconst samplerate = 1;\n\ndeclare module \"@webhare/frontend\" {\n  interface FrontendDataTypes {\n    \"utwente_base:nextpager\": {\n      predictions: string[];\n    };\n  }\n}\n\nasync function fetchPredictions() {\n  for (const prediction of getFrontendData(\"utwente_base:nextpager\", { allowMissing: true })?.predictions || [])\n    await fetch(prediction, { mode: 'no-cors' });\n}\n\nasync function logReferrerIfNeeded() {\n  if (!document.documentElement.lang.startsWith('en')) //only interested in international content\n    return;\n\n  const alwaysoptin = debugFlags[\"ut-performance-optin\"];\n  const usesamplerate = alwaysoptin ? 1 : samplerate;\n  if (Math.random() > usesamplerate)\n    return;\n\n  const country = await crm.requestGeoIP();\n  if (country === 'NL' && !alwaysoptin)\n    return;\n\n  if (document.referrer && document.referrer.startsWith(location.origin)) //internal referrer, we want to track these for better preloading\n    sendPxl<void>(\"utwente_base:internal_referrer\");\n}\n\nvoid logReferrerIfNeeded();\n\nif (document.documentElement.lang.startsWith('en')) //only prefetching international content\n  dompack.onDomReady(() => window.setTimeout(() => void fetchPredictions(), 5000));\n","import { createClient } from '@webhare/jsonrpc-client';\n\nlet requestbarrier: Promise<void> | undefined; //TODO replace with serialize (or wait until we have it as a decorator)\n\ninterface GetIPInfoOptions {\n  /** Language code in which you want the country name */\n  countrylang?: string;\n  /** How long to trust the previously cached result in days (default: 7) */\n  cachedays?: number;\n}\n\ninterface PublisherRPCCLient {\n  getIPInfo(options: { countrylang?: string }): Promise<{ country: string; countryname?: string }>;\n}\n\nasync function getIPInfoIntoCache(options?: GetIPInfoOptions) {\n  const reqoptions = { countrylang: options?.countrylang };\n  const result = await createClient<PublisherRPCCLient>(\"publisher:rpc\").getIPInfo(reqoptions);\n  let geoinfo = {\n    countrycode: result ? result.country : \"\",\n    creationdate: Date.now(),\n  };\n  if (result && options?.countrylang)\n    geoinfo = { ...geoinfo, [\"countrylang_\" + options.countrylang]: result.countryname };\n\n  localStorage.setItem(\"_wh.geoinfo\", JSON.stringify(geoinfo));\n  return geoinfo;\n}\n\nexport async function getIPInfo(options?: { countrylang: string }): Promise<{ countrycode: string; countryname: string } | null>;\nexport async function getIPInfo(options?: GetIPInfoOptions): Promise<{ countrycode: string; countryname?: string } | null>;\n\n/** Get geoip fields\n    @returns Object with country code and possible name, null if unknown */\nexport async function getIPInfo(options?: GetIPInfoOptions): Promise<{ countrycode: string; countryname?: string } | null> {\n  //TODO return more than country name and code once we need it.\n\n  const finaloptions = {\n    cachedays: 7,\n    countrylang: \"\",\n    ...options\n  };\n\n  if (requestbarrier)\n    await requestbarrier; //first let parallel requests complete and set _wh.geoinfo\n\n  const barrier = Promise.withResolvers<void>();\n  requestbarrier = barrier.promise;\n\n  let geoinfo;\n  try {\n    let curgeoinfotext = localStorage.getItem(\"_wh.geoinfo\");\n\n    if (!curgeoinfotext) { //test local storage\n      localStorage.setItem(\"_wh.geoinfo\", JSON.stringify({ dummy: \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" }));\n      curgeoinfotext = localStorage.getItem(\"_wh.geoinfo\") || '';\n    }\n    geoinfo = JSON.parse(curgeoinfotext);\n  } catch (e) {\n    console.error(e);\n    barrier.resolve();\n    return null; //localstorage is broken\n  }\n\n  let refetch = false;\n\n  if (!geoinfo.creationdate || (geoinfo.creationdate + finaloptions.cachedays * 86400 * 1000) <= Date.now()) //is answer still valid?\n    refetch = true;\n  else if (finaloptions.countrylang && geoinfo.countrycode && !((\"countrylang_\" + finaloptions.countrylang) in geoinfo))\n    refetch = true;   //If the countrylang isn't requested.. OR we have it... OR we don't have it because we didn't even have the country figured out in the cached call... we can continue\n\n  if (refetch)\n    geoinfo = await getIPInfoIntoCache(options);\n\n  barrier.resolve();\n\n  if (geoinfo && geoinfo.countrycode) {\n    const retval: { countrycode: string; countryname?: string } = { countrycode: geoinfo.countrycode };\n    if (finaloptions.countrylang)\n      retval.countryname = geoinfo[\"countrylang_\" + finaloptions.countrylang];\n\n    return retval;\n  }\n\n  return null;\n}\n\n/** Get the current country code\n    @returns Promise resolving to 2-letter countrycode, or null if unknown */\nexport async function getCountryCode(options?: GetIPInfoOptions) {\n  const data = await getIPInfo(options);\n  return data ? data.countrycode : null;\n}\n","import * as storage from \"@webhare/dompack/src/storage\";\n\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const getCookie = storage.getCookie;\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const setCookie = storage.setCookie;\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const deleteCookie = storage.deleteCookie;\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const listCookies = storage.listCookies;\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const getLocal = storage.getLocal;\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const setLocal = storage.setLocal;\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const getSession = storage.getSession;\n/** @deprecated Import \\@webhare/dompack for storage APIs */\nexport const setSession = storage.setSession;\n","import { getCookie, setCookie, listCookies, deleteCookie } from \"@webhare/dompack\";\n/** @deprecated Use \\@webhare/dompack listCookies */\nexport const list = listCookies;\n/** @deprecated Use \\@webhare/dompack getCookie */\nexport const read = getCookie;\n/** @deprecated Use \\@webhare/dompack setCookie */\nexport const write = setCookie;\n/** @deprecated Use \\@webhare/dompack deleteCookie */\nexport const remove = deleteCookie;\n","import * as dompack from \"@webhare/dompack\";\nimport \"./cookiebar.scss\";\nimport { throwError } from \"@webhare/std\";\nimport * as consenthandler from '@mod-publisher/js/analytics/consenthandler';\nimport { pushToDataLayer } from \"@webhare/frontend\";\n\n//cookiedomain should be toplevel domain to make sure utwente.nl doesn't overwrite lower cookies\nconst cookiedomain = '.' + (document.domain.split('.').slice(location.host.match(/webhare.(nl|dev)$/) ? 1 : -2).join('.'));\n\ninterface CookieSettings {\n  c: boolean;\n  v?: 1;\n  lc?: string;\n  isset?: boolean;\n}\n\nfunction getLangCode(): \"en\" | \"nl\" | \"de\" {\n  const lang = ((document.documentElement.lang || \"\").split('-')[0].toLowerCase());\n  return [\"nl\", \"de\"].includes(lang) ? lang as \"nl\" | \"de\" : \"en\";\n}\n\nclass UtwenteCookies {\n  _consent = false;\n  cookieName = \"utwente__avgconsent\";\n  /** @deprecated some old code still checks this to see if AVG rules are in effect yet */\n  readonly avg = true as const;\n\n  constructor() {\n  }\n\n  reset(): void {\n    dompack.deleteCookie(this.cookieName, { domain: cookiedomain });\n    dompack.setLocal(\"utwente-design:cookiebar-variant\", null);\n    location.reload();\n  }\n  info(): void {\n    console.log(\"[utwente-avg-api] Cookiedomain = \" + cookiedomain);\n    console.log(\"[utwente-avg-api] Prefs = \" + JSON.stringify(utwenteCookies._getPrefs()));\n    console.log(\"[utwente-avg-api] Settings = \" + JSON.stringify({ consent: utwenteCookies._consent }));\n  }\n\n  private getNewTexts(): {\n    privacylink: string;\n    cookielink: string;\n    accept: string;\n    reject: string;\n  } {\n    const link = \"https://\" + (location.host.match(/webhare.nl$/) ? 'utwente' : 'www') + cookiedomain;\n    switch (getLangCode()) {\n      case \"nl\":\n        return {\n          privacylink: 'https://www.utwente.nl/over-de-website/',\n          cookielink: 'https://www.utwente.nl/over-de-website/cookies/',\n          accept: \"Accepteren\",\n          reject: \"Weigeren\"\n        };\n      case \"de\":\n        return {\n          privacylink: 'https://www.utwente.nl/de/ueber-unsere-webseite/',\n          cookielink: link + '/de/cookies/',\n          accept: \"Zustimmen\",\n          reject: \"Ablehnen\"\n        };\n      default:\n        return {\n          privacylink: 'https://www.utwente.nl/en/about-our-website/',\n          cookielink: link + '/en/cookies/',\n          accept: \"Accept\",\n          reject: \"Reject\"\n        };\n    }\n  }\n\n  private getNewContent(cookielink: string, privacylink: string) {\n    switch (getLangCode()) {\n      case 'nl':\n        return [\n          <h2>Cookies</h2>,\n          <p>We gebruiken cookies en vergelijkbare technologieën en verwerken je persoonlijke gegevens (bijv. IP-adres) voor gepersonaliseerde content, advertenties en voor media integraties van externe aanbieders.\n            Voor het gebruiken en analyseren van de website plaatsen wij altijd functionele en strikt analytische cookies. De gegevensverwerking voor niet-functionele en niet-analytische cookies vereist jouw toestemming.\n            Voor meer informatie over het gebruik van je gegevens, bezoek onze <a href={privacylink}>privacyverklaring</a> of ons <a href={cookielink}>cookiebeleid</a>.</p>\n        ];\n      case 'de':\n        return [\n          <h2>Cookies</h2>,\n          <p>Wir verwenden Cookies und ähnliche Technologien und verarbeiten deine personenbezogenen Daten (z.B. IP-Adresse) für personalisierte Inhalte, Werbung und die Einbindung von Drittanbieter-Medien.\n            Funktionale und strikt analytische Cookies werden immer gesetzt. Für nicht notwendige und nicht analytische Cookies benötigen wir deine Einwilligung. Weitere Informationen findest du in\n            unserer <a href={privacylink}>Datenschutzerklärung</a> oder unseren <a href={cookielink}>Cookie-Richtlinien</a>.</p>\n        ];\n      case 'en':\n        return [\n          <h2>Cookies</h2>,\n          <p>We use cookies and similar technologies to process your personal data (e.g. IP address) for personalised content, ads and third-party media integrations. Functional and strictly analytical cookies are always set.\n            Non-essential and non-analytical cookies require your permission. For more details, see our <a href={privacylink}>privacy statement</a> or <a href={cookielink}>cookie policy</a>.</p>\n        ];\n    }\n  }\n\n  _showBar(): void {\n    const reject = () => {\n      utwenteCookies._setPrefs({ c: false });\n      d.close();\n    };\n    const accept = () => {\n      utwenteCookies._setPrefs({ c: true });\n      d.close();\n    };\n    const texts = this.getNewTexts();\n    const buttons = [\n      <button type=\"button\" class=\"wh-form__button\" onClick={reject}>{texts.reject}</button>,\n      <button type=\"button\" class=\"wh-form__button\" onClick={accept}>{texts.accept}</button>\n    ];\n\n    const d: HTMLDialogElement = <dialog data-nosnippet class=\"utwente-cookiedialog\">\n      {this.getNewContent(texts.cookielink, texts.privacylink)}\n      <div class=\"utwente-cookiedialog__buttons\">{buttons}</div>\n    </dialog>;\n\n    document.body.appendChild(d);\n    d.showModal();\n    (document.activeElement as HTMLElement)?.blur?.(); //prevent focus ring, https://gitlab.webhare.com/utwente/utwente_base/-/issues/2414#note_211171\n  }\n\n  _getPrefs(): CookieSettings {\n    try {\n      let prefs = JSON.parse(dompack.getCookie(this.cookieName) || '{}') as CookieSettings;\n      //@ts-expect-error This type violation is how we detect Ghostery etc setting broken/blocked cookies. https://gitlab.webhare.com/utwente/utwente_base/-/issues/2414#note_211588\n      if (prefs?.v === \"1\") {\n        this.cookieName = \"utwente__cookieprefs\"; //new cookie name\n        prefs = JSON.parse(dompack.getCookie(this.cookieName) || '{}') as CookieSettings;\n      }\n      if (prefs.v === 1)\n        return { ...prefs, isset: true };\n    } catch (e) {\n      console.log(\"Error parsing cookie\", e);\n    }\n\n    return {\n      isset: false, //nothing recorded yet\n      c: false\n    };\n  }\n  _handlePrefs(prefs: CookieSettings, { ischange = false }) {\n    utwenteCookies._consent = Boolean(prefs.c);\n    try {\n      //we always fire this event as soon as we have cookie information, geoversity needs this trigger. https://gitlab.webhare.com/utwente/utwente_base/-/issues/2414#note_228507\n      const vars = { utwenteAnalytics: true, utwenteConsent: utwenteCookies._consent };\n      pushToDataLayer({ event: \"utwente.cookiesettings\", ...vars });\n      if (ischange)\n        pushToDataLayer({ event: \"utwente.cookieconsent\", ...vars });\n\n      document.documentElement.classList[utwenteCookies._consent ? \"add\" : \"remove\"](\"utwente--consent\");\n\n      const evt = document.createEvent(\"HTMLEvents\");\n      evt.initEvent(\"wh:consent-change\", true, false);\n      document.dispatchEvent(evt);\n    } catch (e) {\n      console.error(e);\n    }\n  }\n  _setCookie(newsettings: CookieSettings) {\n    const setting = JSON.stringify(newsettings);\n    const expires = new Date(Date.now() + 86400 * 365 * 1000);\n    dompack.setCookie(this.cookieName, setting, { domain: cookiedomain, expires, sameSite: \"None\", secure: true });\n  }\n  _setPrefs(newprefs: { c?: boolean }) {\n    const curprefs = this._getPrefs();\n    const newsettings: CookieSettings = {\n      c: newprefs.c ?? curprefs.c,\n      v: 1,\n      lc: (new Date).toUTCString(),\n    };\n\n    utwenteCookies._setCookie(newsettings);\n    newsettings.isset = true;\n    utwenteCookies._handlePrefs(newsettings, { ischange: true });\n  }\n\n  setup(): void {\n    //get the current cookie\n    const prefs = utwenteCookies._getPrefs();\n    utwenteCookies._handlePrefs(prefs, { ischange: false });\n\n    if (prefs.isset) {\n      utwenteCookies._setCookie(prefs); //prefs already set - refresh lifetime\n    } else {\n      if (document.documentElement.classList.contains(\"utwente--nocookiebar\")  //page opting out of cookiebar (medewerkers portal embedded news)\n        || document.documentElement.classList.contains(\"wh-isstaticdownload\")\n        || document.documentElement.classList.contains(\"wh-widgetpreview\")\n        || location.host.match(/utchallenge.nl$/)  //they're no longer compatible\n        || window.top !== window.self) //running in a frame - we normally don't permit this it must be a CI test or internal use, hide the cookiebar\n        return;\n\n      utwenteCookies._showBar();\n    }\n  }\n  _save(): void {\n    const c = document.querySelector<HTMLInputElement>(\"#utwenteCookiesConsent\")?.checked || false;\n    this._setPrefs({ c });\n  }\n  _accept(): void { //NOTE still used externally!\n    this.acceptMarketingCookies();\n  }\n  acceptMarketingCookies(): void { // invoked when activated by a consent layer\n    this._setPrefs({ c: true });\n  }\n  getConsent(): boolean {\n    return utwenteCookies._consent;\n  }\n  getAnalytics(): boolean {\n    return true;\n  }\n  getCookieSettingsLink() {\n    return this.getNewTexts().cookielink;\n  }\n  getExplicitAnalytics(): boolean {\n    return true;\n  }\n}\n\nconst utwenteCookies = new UtwenteCookies;\n\nexport function setupCookieWidget(form: HTMLFormElement): void {\n  const thirdparty = form.elements.namedItem(\"thirdparty\") as HTMLInputElement ?? throwError(\"Missing checkbox named 'thirdparty' in cookie settings form\");\n\n  thirdparty.checked = utwenteCookies.getConsent();\n\n  thirdparty.addEventListener(\"change\", ev => {\n    utwenteCookies._setPrefs({ c: thirdparty.checked });\n  });\n\n  form.inert = false; //activate!\n}\n\nexport function setupConsentHandlerForUtwente(): void {\n  //Link cookie api to consent handler\n  function syncConsent() {\n    const consent: string[] = [];\n    if (utwenteCookies.getConsent())\n      consent.push('marketing');\n    if (utwenteCookies.getAnalytics())\n      consent.push('analytics');\n    consenthandler.setConsent(consent);\n  }\n\n  consenthandler.setup(''); //setup consent handler in listening mode\n  window.addEventListener(\"wh:consent-change\", syncConsent);\n  syncConsent();\n\n  dompack.register<HTMLInputElement>(\".utwente__marketing__checkbox\", node => node.addEventListener(\"change\", function () {\n    //accepting marketing cookies\n    if (node.checked)\n      utwenteCookies._setPrefs({ c: true });\n  }));\n}\n\ndompack.onDomReady(() => utwenteCookies.setup());\n\nwindow.utwenteSetConsent = (__ignored: boolean, thirdparty: boolean) => utwenteCookies._setPrefs({ c: thirdparty });\nwindow.utwenteResetCookies = () => utwenteCookies.reset();\n\nexport default utwenteCookies;\n","/* To verify tree shaking viability, try:\n   whcd\n   cd whtree\n   echo 'import \"@webhare/frontend\"' | node_modules/.bin/esbuild --loader:.css=empty --tsconfig=tsconfig.json --bundle --minify\n*/\n\n// This gets TypeScript to refer to us by our @webhare/... name in auto imports:\ndeclare module \"@webhare/frontend\" {\n}\n\nimport { onDomReady } from \"@webhare/dompack\";\nimport \"../styling/reset.css\"; // Reset CSS - this will be dropped somewhere post WH5.6!\nexport { frontendConfig, getFrontendData, getSiteRoot } from \"./init\";\nexport { startSSOLogin, login, setupWRDAuth, isLoggedIn, logout, getUserInfo, setupWebHareSSOTrigger } from \"./auth\";\nexport { loadAssetPack, setupAuthorMode, type AuthorModeOptions } from \"./authormode\";\nexport { setPxlOptions, sendPxl, getPxlUserId, getPxlSessionId, setupFormAnalytics, type PxlData } from \"./pxl\";\nexport { getRemoteIPAddress, getGeoIPInfo, type GetIPInfoOptions, type GeoIPInfoResult } from \"./analytics\";\nexport { setupGTM, setupFormAnalyticsForGTM, pushToDataLayer, setupDataLayerTags } from \"./gtm\";\nexport { setupLinksInNewWindow, type LinkOpenOptions } from \"./linkhandler\";\n\nexport type * from \"./gtm-types\";\n\n// we shouldn't deprecate navigateTo exported from frontend. in fact it makes more sense to export it from frontend than env as it's browser-only\nexport { navigateTo } from \"@webhare/env\";\n\n/** Registry for data we receive from the backend */\nexport interface FrontendDataTypes {\n}\n\n/** Registry for expected PXL formats */\nexport interface PxlDataTypes {\n}\n\n/** Test whether the current page is being iframed in the WebHare test framework */\nexport function isInTestFramework(): boolean {\n  if (window.top !== window) { //in a frame\n    try {\n      if ((window.top as { __testframework?: unknown })?.__testframework)\n        return true;//we're inside a testframe, pretend to be the parent\n    } catch (ignore) {\n    }\n  }\n  return false;\n}\n\nfunction postRenderChecks() {\n  const log = document.getElementById(\"wh-console-log\");\n  if (log) {\n    const logtext = atob(log.textContent || \"\");\n    console.group(\"[etr] Server-side console output\");\n    console.log(logtext);\n    console.groupEnd();\n  }\n}\n\nonDomReady(postRenderChecks);\n","import { createClient } from \"@webhare/jsonrpc-client\";\nimport { type NavigateInstruction, navigateTo } from \"@webhare/env\";\nimport * as dompack from '@webhare/dompack';\nimport type { LoginOptions } from \"@webhare/auth/src/identity\";\nimport { rpc } from \"@webhare/rpc/src/rpc\";\n\n//NOTE: Do *NOT* load @webhare/frontend or we enforce the new CSS reset!\nimport { getFrontendData } from '@webhare/frontend/src/init';\nimport { PublicCookieSuffix, type LoginErrorCode, type LoginResult, type LoginTweaks } from \"@webhare/auth/src/shared\";\nimport { parseTyped } from \"@webhare/std\";\nimport type WRDAuthenticationProvider from \"@mod-wrd/js/auth\";\n\n/** WRDAuth configuration */\nexport interface WRDAuthOptions {\n  /** Callback that is invoked after a succesful login. If not set the page will be reloaded. */\n  onLogin?: () => Promise<void> | void;\n}\n\nexport interface PublicAuthData {\n  expiresMs: number;\n  userInfo?: object | null;\n  persistent?: boolean;\n}\n\ndeclare module \"@webhare/frontend\" {\n  interface FrontendDataTypes {\n    \"wrd:auth\": {\n      /** WRDAuth cookiename (used to store userinfo and expiry) */\n      cookiename: string;\n    };\n  }\n}\n\ndeclare global {\n  interface Window {\n    $wh$legacyAuthProvider: WRDAuthenticationProvider;\n    triggerWebHareSSO?: (tag: string, options?: SSOLoginOptions) => Promise<void>;\n  }\n}\n\n/** Current authoptions. undefined if setupWRDAuth hasn't been invoked yet */\nlet authOptions: WRDAuthOptions | undefined;\n\n/** Get current login cookie. If empty, wrdauth is not initialized here */\nfunction getCookieName(): string | null {\n  const settings = getFrontendData(\"wrd:auth\", { allowMissing: true });\n  return settings?.cookiename || null;\n}\n\nfunction getAuthLocalData(): PublicAuthData | null {\n  const c = getCookieName();\n  if (!c)\n    return null;\n\n  try {\n    return parseTyped(dompack.getCookie(c + PublicCookieSuffix)!) as PublicAuthData;\n  } catch {\n    return null;\n  }\n}\n\nasync function submitLoginForm(node: HTMLFormElement, event: SubmitEvent) {\n  if (node.propWhFormhandler)\n    return; //already handled by publisher forms so we'll defer to that\n  dompack.stop(event);\n\n  const username = (node.elements.namedItem(\"login\") as HTMLInputElement)?.value;\n  const password = (node.elements.namedItem(\"password\") as HTMLInputElement)?.value;\n  const site = (node.elements.namedItem(\"site\") as HTMLInputElement)?.value || undefined;\n  const returnto = (node.elements.namedItem(\"returnto\") as HTMLInputElement)?.value || undefined;\n  const persistentlogin = (node.elements.namedItem(\"persistent\") as HTMLInputElement)?.checked;\n  if (!login || !password)\n    throw new Error(`submitLoginForm: required elements login/password not set or missing`);\n\n  using lock = dompack.flagUIBusy({ modal: true });\n  void (lock);\n\n  const loginresult = await login(username, password, {\n    persistent: persistentlogin,\n    site,\n    returnTo: returnto ? new URL(returnto, location.href).toString() : location.href.split('#')[0]\n  });\n  if (loginresult.loggedIn) {\n    refreshLoginStatus();\n    if (loginresult.navigateTo.type === \"redirect\" && loginresult.navigateTo.url.split('#')[0] === location.href.split('#')[0]  //stay on same page\n      && authOptions?.onLogin) {\n\n      if (loginresult.navigateTo.url.includes('#')) //execute any #hash instruction\n        history.replaceState(null, \"\", loginresult.navigateTo.url.substring(loginresult.navigateTo.url.indexOf('#')));\n\n      await authOptions.onLogin();\n    } else {\n      //Reload the page to get the new login status - TODO put this behind a 'login state change' event and allow users to cancel it if they can deal with login/logout on-page\n      console.log(\"Post login redirect\", loginresult.navigateTo);\n      navigateTo(loginresult.navigateTo);\n    }\n  } else if (\"navigateTo\" in loginresult) {\n    console.log(\"Login incomplete, redirecting to\", loginresult.navigateTo);\n    navigateTo(loginresult.navigateTo);\n  } else\n    failLogin(loginresult.error ?? loginresult.code, { code: loginresult.code, data: \"\" }, node); //FIXME restore the code & data members from old wrdauth\n}\n\nfunction refreshLoginStatus() {\n  const loggedIn = isLoggedIn();\n  document.documentElement.classList.toggle(\"wh-wrdauth--isloggedin\", loggedIn);\n\n  window.$wh$legacyAuthProvider?.refresh();\n}\n\n/** Return whether a user's currently logged in */\nexport function isLoggedIn(): boolean {\n  return (getAuthLocalData()?.expiresMs || 0) > Date.now();\n}\n\n/** Setup WRDAuth frontend integration */\nexport function setupWRDAuth(options?: WRDAuthOptions) {\n  if (authOptions)\n    throw new Error(`Duplicate setupWRDAuth call`);\n\n  authOptions = { ...options };\n\n  dompack.register<HTMLFormElement>('form.wh-wrdauth__loginform,form.wh-wrdauth-login__form', node => {\n    node.setAttribute(\"data-wh-wrdauth-attached\", \"\");\n    dompack.addDocEventListener(node, \"submit\", evt => submitLoginForm(node, evt));\n  });\n  dompack.register('.wh-wrdauth__logout', node => {\n    function handleLogoutClick(event: Event) {\n      dompack.stop(event);\n\n      //letting rejections escape - our trigger is generally setup in HTML so there's nothing to catch but uncaught rejection handlers anyway\n      if (node instanceof HTMLAnchorElement && node.href && node.href.split('#')[0] !== location.href.split('#')[0]) { //logout link sending you elsewhere\n        void doLogout().then(() => {\n          console.log(\"Logout complete, redirecting to\", node.href);\n          navigateTo({ type: \"redirect\", url: node.href });\n        });\n      } else {\n        void logout(); //TODO what if the logout only changed the anchor? but what's the usecase for that?\n      }\n    }\n\n    dompack.addDocEventListener(node, \"click\", event => handleLogoutClick(event));\n  });\n\n  dompack.onDomReady(() => {\n    if (\"$wh$wrdauth\" in window) {\n      console.error(\"Both setupWRDAuth from @webhare/frontend and @mod-wrd/js/auth are present in this page. Mixing these is not supported!\");\n    }\n  });\n\n  refreshLoginStatus();\n}\n\nfunction failLogin(message: string, response: { code: LoginErrorCode; data: string }, form: HTMLFormElement) {\n  const evtdetail = {\n    message: message,\n    code: response.code,\n    data: response.data\n  };\n\n  const cancelled = !dompack.dispatchCustomEvent(form || document.documentElement, \"wh:wrdauth-loginfailed\", { bubbles: true, cancelable: true, detail: evtdetail });\n  if (!cancelled) {\n    //TODO depending on error we may need to change a different field?\n    const loginfield = dompack.qR<HTMLInputElement>(form, \"input[name=password]\");\n    loginfield.setCustomValidity(message);\n    // loginfield.reportValidity(); //this actually blocks wh-form error handling from showing the error in-page when so desired\n    loginfield.focus();\n  }\n}\n\n/** Retrieve userinfo if set by onFrontendUserInfo in your WRDAuth customizer */\nexport function getUserInfo<T extends object = object>(): T | null {\n  return isLoggedIn() ? getAuthLocalData()?.userInfo as T | null : null;\n}\n\nfunction getLoginTweaks(): LoginTweaks {\n  const tweaks: LoginTweaks = {};\n\n  const urlvars = new URL(location.href);\n  if (urlvars.searchParams.has(\"wrdauth_limit_expiry\"))\n    tweaks.limitExpiry = parseInt(urlvars.searchParams.get(\"wrdauth_limit_expiry\") || '0') || undefined;\n\n  const lang = document.documentElement.getAttribute(\"lang\");\n  if (lang)\n    tweaks.lang = lang;\n\n  return tweaks;\n}\n\n/** Implements the common username/password flows */\nexport async function login(username: string, password: string, options: LoginOptions = {}): Promise<LoginResult> {\n  const cookieName = getCookieName();\n  if (!cookieName)\n    throw new Error(\"WRDAuth not initialized, please call setupWRDAuth first and ensure this page has a <wrdauth> rule\");\n\n  const result = await rpc(\"platform:authservice\").login(username, password, cookieName, dompack.getBrowser().triplet, { ...options, ...getLoginTweaks() });\n  if (result.loggedIn && !getAuthLocalData())\n    throw new Error(\"Login succeeded but no auth data was set in the cookie\");\n\n  return result;\n}\n\n/** Execute and verify cookie clearance to prepare for logging out */\nasync function doLogout() {\n  const cookieName = getCookieName();\n  if (!cookieName)\n    throw new Error(\"WRDAuth not initialized, please call setupWRDAuth first and ensure this page has a <wrdauth> rule\");\n\n  await rpc(\"platform:authservice\").logout(cookieName, dompack.getBrowser().triplet);\n\n  if (getAuthLocalData())\n    throw new Error(\"Logged out but we still have auth data in the cookie\");\n}\n\n/** Logout the current user */\nexport async function logout() {\n  await doLogout();\n  console.log(\"Reloading to process the new logged out status\");\n  navigateTo({ type: \"reload\" }); //TODO put this behind a 'login state change' event\n}\n\nexport interface MyService {\n  startLogin2(urlpath: string, tag: string, options: { passive?: boolean }): Promise<NavigateInstruction>;\n}\n\ninterface SSOLoginOptions {\n  passive?: boolean;\n}\n\nexport async function startSSOLogin(tag: string, options?: SSOLoginOptions): Promise<void> {\n  const client = createClient<MyService>(\"wrd:auth\");\n\n  //Launch SSO login for the current page.\n  //TODO also pass getLoginTweaks() at least to OIDC logins as soon as we've ported this to authservice\n  navigateTo(await client.startLogin2(location.pathname + location.search + location.hash, tag, { passive: options?.passive }));\n}\n\n/** Configure WebHare external auth buttons (even hidden ones) to listen for bookmarklet login requests */\nexport function setupWebHareSSOTrigger(): void {\n  window.triggerWebHareSSO = startSSOLogin;\n}\n","// This gets TypeScript to refer to us by our @webhare/... name in auto imports:\ndeclare module \"@webhare/rpc\" {\n  export interface KnownRPCServices {\n    /* Filled by generated services.ts files */\n  }\n}\n\nimport { debugFlags, backendBase } from \"@webhare/env\";\nimport { type StackTrace, parseTrace, prependStackTrace, type PromisifyFunctionReturnType } from \"@webhare/js-api-tools\";\nimport { omit, parseTyped, stringify } from \"@webhare/std\";\n\n//Preload interface definitions. To solve this cleaner we would have to do some sort of auto-inject but how to robustly do that accross IDEs/Tscs ?\n\n//@ts-ignore Ignore if it doesn't exist\nimport type { } from \"@mod-platform/generated/ts/services.ts\";\n//@ts-ignore Ignore if it doesn't exist\nimport type { } from \"wh:ts/services.ts\";\n\nfunction isAbsolute(url: string) {\n  return url.startsWith(\"http:\") || url.startsWith(\"https:\");\n}\n\nfunction getBaseURL() {\n  if (!backendBase)\n    throw new Error(`You must set the baseUrl option when using the RPC Client outside Webhare`);\n  return isAbsolute(backendBase) ? backendBase : new URL(backendBase, location.origin);\n}\n\nexport interface RPCClientOptions {\n  /** Custom request update. Use to eg. set keepalive or add debug variables to the URL */\n  onBeforeRequest?: (url: URL, requestInit: RequestInit & { headers: Headers }) => void;\n  /** Response callback. Use this if you need to capture details on the incoming respones. May be invoked multiple times per request, eg due to 429 errors! */\n  onResponse?: (response: Response) => void;\n  /** Call timeout */\n  timeout?: number;\n  /** Abort signal to cancel the RPC */\n  signal?: AbortSignal;\n  /** Retry on 429 */\n  retry429?: boolean;\n  /** Silent - do not log errors */\n  silent?: boolean;\n  /** Debug (Follows 'rpc' debugflag if not explicity specified) */\n  debug?: boolean;\n  /** Headers to submit (Eg Authorization) */\n  headers?: Record<string, string>;\n  /** Base URL for service paths */\n  baseUrl?: string;\n}\n\n/** RPC Response format */\nexport type RPCResponse = ({\n  /** Result. Not present if the function didn't return anything */\n  result?: unknown;\n} | {\n  /** Error message */\n  error: string;\n  /** Captured stack trace (if 'etr' debugFlag is set) */\n  trace?: StackTrace;\n}) & {\n  /** Captured console log entries (if 'etr' debugFlag is set) */\n  consoleLog?: Array<{\n    //TODO this is Serialized<ConsoleLogItem[]> - should probably rename it to SerializedToJSON and move to std or env ?\n    /** Date when console function was called */\n    when: string;\n    /** `console` method that was called (eg 'log') */\n    method: string;\n    /** Logged data */\n    data: string;\n    /** Location of caller */\n    location?: {\n      filename: string;\n      line: number;\n      col: number;\n      func: string;\n    };\n    /** Codecontext */\n    codeContextId?: string;\n  }>;\n};\n\nclass ControlledCall {\n  client: RPCClient;\n  options: RPCClientOptions;\n  abortcontroller?: AbortController;\n  timeout?: number;\n  _callurl: string;\n  _fetchoptions: RequestInit;\n  promise: Promise<unknown>;\n  timedout?: boolean;\n  aborted?: boolean;\n\n  constructor(client: RPCClient, method: string, stack: StackTrace | null, options: RPCClientOptions, callurl: URL, fetchoptions: RequestInit) {\n    this.client = client;\n    this.options = options;\n\n    if (options.timeout || options.signal) {\n      this.abortcontroller = new AbortController;\n      fetchoptions.signal = this.abortcontroller.signal;\n\n      if (options.timeout && options.timeout > 0) {\n        this.timeout = options.timeout;\n        setTimeout(() => this._handleTimeout(), options.timeout);\n      }\n      if (options.signal) {\n        options.signal.addEventListener(\"abort\", () => this._abort());\n      }\n    }\n\n    this._callurl = callurl.toString();\n    this._fetchoptions = fetchoptions;\n\n    const fetchpromise = fetch(this._callurl, this._fetchoptions);\n    this.promise = this._completeCall(method, stack, fetchpromise) as Promise<unknown>;\n  }\n  _handleTimeout() {\n    this.timedout = true;\n    this.abortcontroller?.abort();\n  }\n  _abort() {\n    this.aborted = true;\n    this.abortcontroller?.abort();\n  }\n\n  async _completeCall(method: string, requestStack: StackTrace | null, fetchpromise: Promise<Response>) {\n    let response;\n    for (; ;) { //loop to handle \"429 Conflict\"s\n      try { //we should only guard the fetch call and specifically *not* the onResponse callback\n        response = await fetchpromise;\n      } catch (exception) {\n        if (this.client.debug)\n          console.log(`[rpc] Exception invoking '${method}'`, exception);\n\n        if (this.aborted)\n          throw new Error(`RPC Aborted`);\n        else if (this.timedout)\n          throw new Error(`RPC Timeout: timeout was set to ${this.timeout} milliseconds`);\n        else\n          throw new Error(`RPC Failed: exception: ` + exception);\n      }\n\n      this.options.onResponse?.(response); //allow hooks to capture headers\n\n      if (response.status === 429 && !(\"retry429\" in this.options && !this.options.retry429) && response.headers.get(\"Retry-After\")) {\n        const retryafter = parseInt(response.headers.get(\"Retry-After\") || \"\");\n        if (this.client.debug)\n          console.warn(`[rpc] We are being throttled (429 Too Many Requests) - retrying after ${retryafter} seconds`);\n\n        await new Promise(resolve => setTimeout(resolve, retryafter * 1000));\n        fetchpromise = fetch(this._callurl, this._fetchoptions);\n        continue;\n      }\n      break;\n    }\n\n    let jsonresponse: RPCResponse;\n    try {\n      jsonresponse = parseTyped(await response.text());\n      if (jsonresponse.consoleLog) {\n        for (const logitem of jsonresponse.consoleLog) {\n          //should we log 'when'? it's getting more and more noisy then though....\n          //TODO should we match the remote's method (after validating) or just keep everything at 'log' ?\n          console.log(`[remote:${logitem.method}] ${logitem.location ? `${logitem.location.filename.split(\"/\").at(-1)}:${logitem.location.line}: ` : ''}${logitem.data}`);\n        }\n      }\n\n      if (this.client.debug)\n        console.log(`[rpc] Received response to '${method}'`, omit(jsonresponse, [\"consoleLog\", \"trace\"]));\n    } catch (exception) {\n      if (this.client.debug)\n        console.warn(`[rpc] Response was not valid JSON`, exception);\n      throw new Error(\"RPC Failed: Invalid response received\", { cause: exception });\n    }\n\n    if (\"error\" in jsonresponse) {\n      const err = new Error(`RPC Error: ${jsonresponse.error}`);\n      if (jsonresponse.trace) {\n        try {\n          prependStackTrace(err, jsonresponse.trace);\n        } catch (err2) {\n          //ignore stacktrace manipulation error\n        }\n      }\n\n      if (this.options.debug) {\n        console.group();\n        console.warn(\"RPC failed:\", err);\n        if (requestStack) {\n          console.warn(\"Stack at calling point\");\n          console.log(requestStack);\n        }\n        console.groupEnd();\n      }\n\n      throw err;\n    }\n\n    return jsonresponse.result;\n  }\n}\n\nclass RPCClient {\n  readonly url: string;\n  options: RPCClientOptions;\n\n  constructor(url: string, options?: RPCClientOptions) {\n    this.url = url;\n    this.options = {\n      timeout: 0,\n      debug: false,\n      ...options\n    };\n  }\n\n  get debug() {\n    return this.options.debug || debugFlags.rpc;\n  }\n\n  _tryLogError(requestStack: StackTrace | null, error: Error) {\n  }\n\n  invoke(method: string, params: unknown[]) {\n    //build the URL, add profiling and function parameters where needed\n    //We'll delay the baseurl calculation until the first call to allow for the backendBase to be set up\n    const callurl = isAbsolute(this.url) ? new URL(this.url + method) : new URL(this.url + method, this.options.baseUrl || getBaseURL());\n\n    let requestStack: StackTrace | null = null;\n\n    const fetchoptions: RequestInit & { headers: Headers } = {\n      method: \"POST\",\n      headers: new Headers({\n        \"Accept\": \"application/json\",\n        \"Content-Type\": \"application/json; charset=utf-8\",\n        ...this.options.headers\n      }),\n      body: stringify(params, { typed: true }),\n    };\n\n    if (typeof location !== \"undefined\")\n      callurl.searchParams.set(\"pathname\", location.pathname);\n\n    if (this.debug) {\n      requestStack = parseTrace(new Error);\n      console.log(`[rpc] Invoking '${method}'`, params);\n    }\n\n    this.options.onBeforeRequest?.(callurl, fetchoptions);\n    return new ControlledCall(this, method, requestStack, this.options, callurl, fetchoptions).promise;\n  }\n}\n\ntype ServiceBase<T> = {\n  withOptions(options: RPCClientOptions): T & ServiceBase<T>;\n};\n\nclass ServiceProxy<Service extends keyof KnownRPCServices | object> {\n  client: RPCClient;\n\n  constructor(client: RPCClient) {\n    this.client = client;\n  }\n\n  get(target: object, prop: string, receiver: unknown) {\n    if ([\"then\", \"catch\", \"finally\"].includes(prop)) //do not appear like our object is a promise\n      return undefined;\n\n    if (prop === 'withOptions') { //create a withOptions function\n      return (options: RPCClientOptions) => {\n        const newoptions = {\n          ...this.client.options,\n          ...options,\n          headers: { ...this.client.options.headers, ...options.headers }\n        };\n        return rpc(this.client.url as (Service extends keyof KnownRPCServices ? Service : string), newoptions);\n      };\n    }\n\n    return (...args: unknown[]) => this.client.invoke(prop, args);\n  }\n}\n\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- need any to not worry about the actual first arg\ntype OmitFirstArg<F> = F extends (x: any, ...args: infer P) => infer R ? (...args: P) => R : never;\n\nexport type OmitRPCContextArgs<ServiceType> = {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- need any to not worry about the actual first arg\n  [K in keyof ServiceType as ServiceType[K] extends (...a: any) => any ? K : never]: ServiceType[K] extends (...a: any[]) => void ? OmitFirstArg<ServiceType[K]> : never;\n};\n\n/** Creates an async version of the functions in a class, removes context parameters\n * @typeParam ServiceType - Type definition of the service class that implements this service.\n*/\ntype ConvertToRPCInterface<ServiceType> = {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- using any is needed for this type definition\n  [K in keyof ServiceType as ServiceType[K] extends (...a: any) => any ? K : never]: ServiceType[K] extends (...a: any[]) => void ? PromisifyFunctionReturnType<ServiceType[K]> : never;\n};\n\ntype ExtractInterface<Service extends object> = ConvertToRPCInterface<Service> & ServiceBase<ConvertToRPCInterface<Service>>;\n\n/** Get the client interface type as would be returned by createClient\n * @typeParam Service - either the `module:service` name or the interface to implement. If you want to pass the implementation's type you should wrap it into `OmitRPCContextArgs`.\n*/\nexport type GetRPCClientInterface<Service extends (keyof KnownRPCServices) | object> = Service extends keyof KnownRPCServices ? ExtractInterface<OmitRPCContextArgs<KnownRPCServices[Service]>> : Service extends object ? ExtractInterface<Service> : never;\n\n/** Create a WebHare RPC client\n  @param service - URL (https://<ORIGIN>/.wh/rpc/module/service/) or service name (module:service) to invoke\n*/\nexport function rpc<Service extends keyof KnownRPCServices>(service: Service extends keyof KnownRPCServices ? Service : string, options?: RPCClientOptions): GetRPCClientInterface<Service>;\nexport function rpc<Service extends object>(service: Service extends keyof KnownRPCServices ? Service : string, options?: RPCClientOptions): GetRPCClientInterface<Service>;\n\nexport function rpc<Service extends keyof KnownRPCServices | object>(service: Service extends keyof KnownRPCServices ? Service : string, options?: RPCClientOptions): GetRPCClientInterface<Service> {\n  //NOTE: needed the separate overloads to get Intellisense to list the known services for createRPClient's first argument\n\n  if (!service)\n    throw new Error(`You must specify either a WebHare rpcService name or a full URL`);\n\n  const servicematch = service.match(/^([a-z0-9_]+):([a-z0-9_]+)$/);\n  if (servicematch)\n    service = `/.wh/rpc/${servicematch[1]}/${servicematch[2]}/` as (Service extends keyof KnownRPCServices ? Service : string);\n  else if (!service.endsWith('/'))\n    throw new Error(`Service URL must end in a slash`);\n\n  const rpcclient = new RPCClient(service, options);\n  return new Proxy({}, new ServiceProxy<GetRPCClientInterface<Service>>(rpcclient)) as GetRPCClientInterface<Service>;\n}\n","import type { NavigateInstruction } from \"@webhare/env\";\n\n/** Login failure reasons that can also be used by custom isLoginDenied checks */\nexport type LoginErrorCode = \"internal-error\" | \"incorrect-login-password\" | \"incorrect-email-password\" | \"account-disabled\" | \"unknown-account\" | \"require-external-login\";\n\n/** Login reasons that require further client side work but are not errors per-se */\nexport type LoginIncompleteCode = \"totp\" | \"incomplete-account\";\n\nexport type LoginTweaks = {\n  /** Limit session duration (development servers only) */\n  limitExpiry?: number;\n  /** Language code */\n  lang?: string;\n};\n\nexport type LoginResult = {\n  loggedIn: boolean;\n  navigateTo: NavigateInstruction;\n} | {\n  loggedIn: false;\n  code: LoginErrorCode;\n  error?: string;\n};\n\nexport type LogoutResult = { success: true } | {\n  error: string;\n  code: LoginErrorCode | LoginIncompleteCode;\n};\n\nexport const PublicCookieSuffix = \"_publicauthdata\";\n\n/* APIs and types shared between the client and server */\nexport function getCompleteAccountNavigation(token: string, pathname: string): NavigateInstruction {\n  return {\n    type: \"redirect\", //TODO or use a \"form\" too? went for a session now as an excursion to followup GET pages is much more likely in this procedure than with totp\n    url: \"/.wh/common/authpages/?wrd_pwdaction=completeaccount&token=\" + encodeURIComponent(token || '') + \"&pathname=\" + encodeURIComponent(pathname)\n  };\n}\n","/* @mod-platform/js/concepts/ is for constants, concepts, simple support APIs, but heavily shared stuff\n   that we can't find a place for (yet) in the jssdk\n\n  this file holds stuff needed to run or build the frontend */\n\nexport type DevModuleInterface = {\n  watchAssetPack?: (assetpackname: string) => void;\n};\n\n/** Interface provided by the dev module if devtools are present */\ndeclare global {\n  //TODO We kinda overlap with mod::tollium/js/internal/debuginterface.ts ?\n  interface Window {\n    whDev?: DevModuleInterface;\n  }\n}\n\n/** Get base url for assetpacks\n * @param assetpack - assetpack name, like \"platform:frontend\"\n * @returns The base URL for the assetpack, starting with and ending in a slash\n*/\nexport function getAssetPackBase(assetpack: string) {\n  return `/.wh/ea/ap/${assetpack.replace(':', '.')}/`;\n}\n","import { getAssetPackBase } from \"@mod-platform/js/concepts/frontend\";\nimport type { AuthorModeOptions } from \"@mod-publisher/webdesigns/authormode/authormode\";\nimport { getLocal, loadCSS, loadScript } from \"@webhare/dompack\";\nexport type { AuthorModeOptions };\n\n/** Load an asset pack\n * @param apname - The asset pack name (eg platform:tollium)\n * @returns A promise resolving to an array containing the assetpack script and CSS nodes\n*/\nexport async function loadAssetPack(apname: string): Promise<void> {\n  const basepath = `${getAssetPackBase(apname)}ap.`;\n  if (document.querySelector(`script[src$=\"${CSS.escape(basepath + \"mjs\")}\"`))\n    return; //we have it already\n\n  await Promise.all([loadScript(basepath + \"mjs\", { module: true }), loadCSS(basepath + 'css')]);\n}\n\n/** Setup author mode extensions */\nexport function setupAuthorMode(options?: AuthorModeOptions): void {\n  if (typeof window !== \"undefined\" && window.top === window && getLocal<string>(\"wh-feedback:accesstoken\")?.match(/^[^.]*\\.[^.]*\\.[^.]*$/)) { //in a browser\n    window.whAuthorModeOptions = options;\n    void loadAssetPack(\"platform:authormode\"); // load of assetpack is schedule, no need to wait for it\n  }\n}\n","import { getBrowser } from \"@webhare/dompack\";\nimport { generateRandomId } from \"@webhare/std\";\nimport { debugFlags, isLive } from \"@webhare/env\";\n\ninterface PxlEventDetails {\n  event: string;\n  data: PxlEventData;\n  options: PxlOptions;\n  isAlt: boolean;\n}\n\nexport type PxlEvent = CustomEvent<PxlEventDetails>;\n\nexport type PxlEventData = {\n  [K in `ds_${string}` | `db_${string}` | `dn_${string}`]: (K extends `ds_${string}` ? string :\n    (K extends `db_${string}` ? boolean :\n      (K extends `dn_${string}` ? number : never)))\n};\n\nexport interface PxlOptions {\n  /** Override pi (pxlId) to control or anonymize user ids*/\n  pi?: string | undefined;\n  /**  Base url to which to send PXL events. Defaults to \"/.wh/ea/pxl/\". */\n  url: string;\n  /**  Sample rate for the alternative record url as a fraction of the number of events, for example, setting it to 1/100 sends 1 in 100 events to the alternative record url. Defaults to 0 (no sampling). */\n  altSampleRate: number;\n  /**  Alternative record url. Defaults to \"/.wh/ea/pxl/alt/\". */\n  altUrl: string;\n  /** The number of days the user id is valid. Defaults to 30. */\n  sessionExpiration: number; //TODO if we ever camel this, also add 'Days' to the name\n  /** Set to true to omit some browser context fields (\"bu\", \"bs\" and \"bp\"). This option can\n      be used to reduce the length of the pxl url. Defaults to false. */\n  noBrowser: boolean;\n  /** Node responsible for generating this event (if not set, 'window' is assumed). Used for the event handlers */\n  node?: HTMLElement;\n  /** Send pixels as beacons */\n  beacon: boolean;\n  /** Callback to execute once pixel is sent */\n  onComplete?: () => void;\n}\n\n//event names must match isValidModuleScopedName, but we won't do the module name checks here. also isValidModuleScopedName lives in @webhare/services so..\nconst eventname_regex = /^([a-z0-9][-a-z0-9_]*[a-z0-9]):([a-z0-9][-.a-z0-9_]*[a-z0-9])$/;\nconst datakey_regex = /^(ds_[0-9a-z_]+)|(dn_[0-9a-z_]+)|(db_[0-9a-z_]+)$/;\n/*TODO: Not sure yet what the new maximum URL length will be\nconst max_data_length = 600; // The maximum number of bytes stored for the request*/\nconst max_sessionid_age = 30;\n\nlet globalOptions: Partial<PxlOptions> | undefined;\n\nlet pagesession: string | undefined; //current page session id (used to track multiple events from single page)\nlet useAltRecordURL = false; //send events for this page to the altrecordurl\nlet seqnr = 0;\n\nlet pxlUserId: string | undefined, pxlSessionId: string | undefined;\n\nfunction buildOptions(options: Partial<PxlOptions> | undefined): PxlOptions {\n  return {\n    url: \"/.wh/ea/pxl/\",\n    altSampleRate: 0,\n    altUrl: \"/.wh/ea/pxl/alt/\",\n    sessionExpiration: max_sessionid_age,\n    noBrowser: false,\n    beacon: false,\n    ...globalOptions,\n    ...options\n  };\n}\n\n/** Set global pxl options\n    @param options - Option updates\n*/\nexport function setPxlOptions(options: Partial<PxlOptions> | null) {\n  globalOptions = { ...globalOptions, ...options };\n\n  if (globalOptions.altUrl && globalOptions.altSampleRate) {\n    useAltRecordURL = Math.random() < globalOptions.altSampleRate;\n    if (debugFlags.pxl)\n      console.log(`[pxl] using altrecordurl for ${100 * globalOptions.altSampleRate}% of pageloads, this session is sent to the ${useAltRecordURL ? \"alternative\" : \"normal\"} url`);\n  } else\n    useAltRecordURL = false;\n}\n\nfunction pxlFailed(errormessage: string, ...params: unknown[]) {\n  console.error('[pxl] ' + errormessage, ...params);\n  if (!isLive)\n    throw new Error(errormessage); //big errors on test servers\n  return null;\n}\n\nexport function makePxlURL(baseurl: string, eventname: string, data?: PxlEventData | null, options?: Partial<PxlOptions>) {\n  options = { ...globalOptions, ...options };\n\n  if (typeof eventname !== \"string\")\n    return pxlFailed(`Invalid eventname name '${eventname}', expected string, got ${typeof eventname}`);\n  if (!eventname_regex.test(eventname))\n    return pxlFailed(`Invalid eventname name '${eventname}', must be a valid module:event name`);\n  if (data && typeof data !== \"object\")\n    return pxlFailed(`Invalid data, expected object, got ${typeof data}`);\n\n  if (!pagesession)\n    pagesession = generateRandomId();\n\n  //not using URL object, simplifies support of relative URLs\n  const url = typeof document !== \"undefined\" ? new URL(baseurl, document.baseURI) : new URL(baseurl);\n  url.searchParams.set(\"pe\", eventname);\n  url.searchParams.set(\"pp\", pagesession);\n  url.searchParams.set(\"pc\", String(++seqnr));\n  url.searchParams.set(\"ps\", getPxlSessionId());\n  url.searchParams.set(\"pi\", options?.pi ?? getPxlId());\n\n  if (options.altSampleRate)\n    url.searchParams.set(\"pr\", String(options.altSampleRate));\n\n  const browser = getBrowser();\n  url.searchParams.set(\"bt\", browser.triplet);\n  if (browser.device)\n    url.searchParams.set(\"bd\", browser.device);\n\n  if (typeof document !== \"undefined\") {\n    if (document.documentElement.dataset.whOb)\n      url.searchParams.set(\"ob\", document.documentElement.dataset.whOb.substring(0, 20));\n    if (document.location)\n      url.searchParams.set(\"bl\", document.location.href.substring(0, 1000));\n    if (document.referrer)\n      url.searchParams.set(\"br\", document.referrer.substring(0, 1000));\n\n    if (!options.noBrowser) {\n      url.searchParams.set(\"bu\", window.navigator.userAgent.substring(0, 300));\n      if (window.screen.width && window.screen.height)\n        url.searchParams.set(\"bs\", `${window.screen.width}x${window.screen.height}`);\n      if (window.devicePixelRatio)\n        url.searchParams.set(\"bp\", String(window.devicePixelRatio));\n    }\n  }\n\n  if (data) {\n    for (const [name, value] of Object.entries(data)) {\n      const test = datakey_regex.exec(name);\n      if (!test)\n        return pxlFailed(`Invalid data field name '${name}', should be ds_XXX, dn_XXX or db_XXX with X consisting of characters in the range 0 - 9, a - z or an underscore`);\n\n      const type = typeof value;\n\n      if (test[1]) { // String\n        if (value && type !== \"string\")\n          return pxlFailed(`Invalid value type '${type}', expected 'string' for field '${name}'`);\n\n        url.searchParams.set(name, value as string || '');\n      } else if (test[2]) { // Number\n        if (value && type !== \"number\")\n          return pxlFailed(`Invalid value type '${type}', expected 'number' for field '${name}'`);\n\n        url.searchParams.set(name, String(value) || '0');\n      } else if (test[3]) { // Boolean\n        if (value && type !== \"boolean\")\n          return pxlFailed(`Invalid value type '${type}', expected 'boolean' for field '${name}'`);\n\n        url.searchParams.set(name, value ? \"true\" : \"false\");\n      }\n    }\n  }\n  return url;\n}\n\nexport function getPxlId(): string {\n  if (!pxlUserId) {\n    try {\n      const timestampvar = localStorage.getItem(\"_wh.ti\");\n      if (timestampvar && new Date(timestampvar) > new Date) { //not expired yet\n        pxlUserId = localStorage.getItem(\"_wh.pi\") || undefined;\n        if (pxlUserId && debugFlags.pxl)\n          console.log(`[pxl] Using id ${pxlUserId} from localStorage`);\n      }\n      pxlUserId ||= generateRandomId();\n      const sessionExpireDays = (globalOptions?.sessionExpiration ?? max_sessionid_age);\n      const expiration = new Date(Date.now() + sessionExpireDays * 24 * 60 * 60 * 1000);\n      localStorage.setItem(\"_wh.pi\", pxlUserId);\n      localStorage.setItem(\"_wh.ti\", expiration.toISOString());\n    } catch {\n      pxlUserId ||= generateRandomId();\n    }\n  }\n  return pxlUserId;\n}\n\nexport function getPxlSessionId() {\n  if (!pxlSessionId) {\n    try {\n      pxlSessionId = sessionStorage[\"_wh.ps\"];\n      pxlSessionId ||= generateRandomId();\n      sessionStorage[\"_wh.ps\"] = pxlSessionId;\n    } catch { //privacy mode? just (re)try to generate an id\n      pxlSessionId ||= generateRandomId();\n    }\n  }\n  return pxlSessionId;\n}\n\n/** Send a pxl event\n    @param event - Event type, preferably in the format 'module:event'\n    @param data - Event data. A map whose keys must start with either ds_ (string), db_ (boolean) or dn_ (number)\n*/\nexport function sendPxlEvent(event: string, data?: PxlEventData | null, options?: Partial<PxlOptions>) {\n  const finaloptions = buildOptions(options);\n  const baseurl = useAltRecordURL ? finaloptions.altUrl : finaloptions.url;\n\n  if (debugFlags.pxl)\n    console.log(`[pxl] Event '${event}'`, data);\n\n  // Add the pxl event to the url. We wrap it in async() for simpler code but we won't force our callers to await us, they rarely want to\n  (async () => {\n    const url = makePxlURL(baseurl, event, data, finaloptions);\n    if (!url)\n      return;\n\n    if (finaloptions.beacon && typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n      navigator.sendBeacon(url);\n      return; //as beacons don't return anything per definition, we can stop here\n    }\n\n    if (debugFlags.pxl)\n      console.log(`[pxl] Pinging pxl '${url}'`);\n\n    // Load the pxl file using fetch\n    const fetchRes = await fetch(url, { mode: \"no-cors\", method: \"HEAD\", credentials: \"same-origin\", cache: \"no-store\", keepalive: true });\n    if (fetchRes.type === \"opaque\") { //we can't verify cross-server requests\n      if (debugFlags.pxl)\n        console.log(`[pxl] Assuming succesful pxl event '${event}'`);\n      return;\n    }\n    if (!fetchRes.ok) {\n      console.error(`[pxl] Failed to send pxl event '${event}'`, fetchRes);\n      return;\n    }\n\n    if (finaloptions.onComplete) //if we care about completion, we'll explicitly wait for the body to come in\n      await fetchRes.text(); //this will throw if the request failed, so we can skip the next check\n\n    if (debugFlags.pxl)\n      console.log(`[pxl] Successfully sent pxl event '${event}'`);\n  })().catch((error: Error) => {\n    console.error(`[pxl] Error while sending pxl event '${event}'`, error);\n  }).finally(() => {\n    finaloptions.onComplete?.(); //any exception here we'll keep uncaught\n  });\n}\n","/* TODO Move consilio pxl here eventually, but limit how much we actually want to export */\nimport { sendPxlEvent, type PxlEventData, type PxlOptions } from \"@mod-consilio/js/pxl\";\nimport { dtapStage } from \"@webhare/env\";\nimport type { FormAnalyticsEvent } from \"@webhare/forms\";\nimport type { PxlDataTypes } from \"@webhare/frontend\";\nexport { setPxlOptions, getPxlId as getPxlUserId, getPxlSessionId } from \"@mod-consilio/js/pxl\";\n\nexport type PxlData = Record<string, string | number | boolean>;\n\n// Track listener installation. Especially needed during the transition from @mod-publisher/js/forms to @webhare/frontend. After the transition we might not need stack traces anymore\nconst activeListenPrefixes = new Map<string, Error>;\n\n// Combine with `string & {}` to prevent TypeScript from eliminating `keyof PxlDataTypes`\ntype AllowedKeys = keyof PxlDataTypes | (string & {});\n\n// Filters out invalid types from the PXL data type\ntype FilterValidTypes<T extends object | void> = T extends object ? {\n  [K in keyof T]: T[K] extends undefined | string | number | boolean ?\n  T[K] :\n  { __error: \"Invalid property type used in PXL event declaration, allowed: boolean, number, string\"; __type: T[K] };\n} : T;\n\n/// Helper type to allow making the data parameter optional when the datatype is void\ntype ParamTuples<DataType, Key extends AllowedKeys> = Key extends keyof PxlDataTypes ?\n  [data: FilterValidTypes<PxlDataTypes[Key]>, options?: Partial<PxlOptions>] :\n  (DataType extends void ?\n    [data?: void, options?: Partial<PxlOptions>] :\n    [data: DataType, options?: Partial<PxlOptions>]);\n\n// Error type for when an event is not declared in PxlDataTypes and no data type override is provided\ntype NeedTypeParamError = { __error: \"Event not declared in PxlDataTypes and no data type override provided\" } & symbol;\n\nexport function sendPxl<DataType extends (Event extends keyof PxlDataTypes ? NeedTypeParamError : void | PxlData | NeedTypeParamError) = NeedTypeParamError, Event extends AllowedKeys = AllowedKeys>(eventKey: Event, ...params: ParamTuples<NoInfer<DataType>, Event>): void {\n  const [data, options] = params;\n  const pxldata: PxlEventData = {};\n  for (const [k, v] of Object.entries(data ?? {})) {\n    if (v === undefined)\n      continue;\n    if (typeof v === \"string\")\n      pxldata[`ds_${k}`] = v;\n    else if (typeof v === \"number\")\n      pxldata[`dn_${k}`] = v;\n    else if (typeof v === \"boolean\")\n      pxldata[`db_${k}`] = v;\n    else\n      throw new Error(`Invalid type '${typeof v}' for PXL data key '${k}'`);\n  }\n\n  sendPxlEvent(eventKey, pxldata, options);\n}\n\n/** Setup pxl events for form analytics events\n * @param options - Options for the form analytics setup\n     - `eventPrefix`. Prefix to use. Default is `platform:form_` but existing integrations may (also) require `publisher:form`\n*/\nexport function setupFormAnalytics(options?: { eventPrefix: string }): void {\n  const prefix = options?.eventPrefix || \"platform:form_\";\n  const registered = activeListenPrefixes.get(prefix);\n  if (registered)\n    if (dtapStage !== \"production\")\n      return console.error(`Duplicate setupFormAnalytics for prefix '${prefix}', earlier registration: `, registered);\n\n  activeListenPrefixes.set(prefix, new Error); //getStackTrace() would have been nicer, but doesn't get sourcemapped in the console\n\n  addEventListener(\"wh:form-analytics\", (e: FormAnalyticsEvent) => {\n    const formeventdata: { [K in `formmeta_${string}`]: string | number | boolean } = {};\n    for (const [key, val] of Object.entries(e.detail))\n      if (key !== \"event\" && [\"string\", \"number\", \"boolean\"].includes(typeof val))\n        formeventdata[`formmeta_${key}`] = val;\n\n    sendPxl<PxlData>(`${prefix}${e.detail.event}`, formeventdata, e.detail.event === \"abandoned\" ? { beacon: true } : undefined);\n  });\n}\n","import { getIPInfo } from \"@mod-publisher/js/analytics/geoip\";\n\nexport interface GetIPInfoOptions {\n  /** Language code in which you want the country name */\n  lang?: string;\n  /** How long to trust the previously cached result in days (default: 7) */\n  cacheDays?: number;\n}\n\nexport type GeoIPInfoResult = {\n  countryCode: string;\n  countryName?: string;\n};\n\nexport async function getGeoIPInfo(options?: GetIPInfoOptions): Promise<GeoIPInfoResult | null> {\n  const data = await getIPInfo({\n    countrylang: options?.lang,\n    cachedays: options?.cacheDays,\n  });\n\n  return data ? {\n    countryCode: data.countrycode,\n    countryName: data.countryname\n  } : null;\n}\n/** Get the remote client's IP address.\n *\n * Requires WebHare proxy 3.3.0+ and the `x-webhare-proxyoptions: addremoteip` header */\nexport function getRemoteIPAddress() {\n  return (performance.getEntries()[0] as PerformanceResourceTiming)?.serverTiming?.find(_ => _.name === 'remoteip')?.description ?? null;\n}\n","import utwenteCookies from \"@mod-utwente_design/js/cookiebar\";\nimport * as dompack from '@webhare/dompack';\nimport * as consenthandler from '@mod-publisher/js/analytics/consenthandler';\nimport './cobrowserchat.scss';\n\nlet startedload = false;\n\n/* API  and integration\n   https://cobrowser.zendesk.com/hc/en-us/categories/201390226-CoBrowser-Live-Chat\n*/\n\nwindow._cb = window._cb || [];\n// window._cb.push(['registerListener', function (event)\n// {\n//   //my_analytic_object.send(event);\n//   console.log('cobrowser event: ', event);\n// }]);\n\n\nfunction setupCobrowser(chtbtn: HTMLElement) {\n  if (!consenthandler.hasConsent(\"marketing\")) {\n    //show us as online as we can't actually check yet whether we're online\n    chtbtn.querySelector<HTMLElement>('.cb_online')!.style.display = \"\";\n    chtbtn.querySelector<HTMLElement>('.cb_offline')!.style.display = \"none\";\n  }\n\n  const onChatTouchBlur = function (event: TouchEvent) { //var, we need our function pointer inside the function\n    if (dompack.isHTMLElement(event.target) && event.target.closest('#my_cb_button')) //clink on our button, ignore\n      return;\n\n    chtbtn.classList.remove('cobrowserchatcontrol--opencontrol');\n    window.removeEventListener('touchstart', onChatTouchBlur);\n  };\n  chtbtn.querySelector('.cb_chatbutton')?.addEventListener(\"click\", function () {\n    chtbtn.classList.add(\"cobrowserchatcontrol--activated\");\n  });\n  chtbtn.querySelector('.cb_online .cb_chatbutton')?.addEventListener(\"click\", function () {\n    window.dataLayer.push({ event: 'chat-klik' });\n  });\n\n  chtbtn.addEventListener('touchstart', function (event) {\n    if (!chtbtn.classList.contains('cobrowserchatcontrol--opencontrol')) {\n      event.preventDefault();\n      chtbtn.classList.add('cobrowserchatcontrol--opencontrol');\n      window.addEventListener('touchstart', onChatTouchBlur);\n    }\n  });\n\n  const acceptnode = document.querySelector<HTMLInputElement>(\"input#cobrowserchatcontrol_accept_cookies\");\n  if (acceptnode)\n    acceptnode.addEventListener(\"change\", function () {\n      //accepting marketing cookies\n      if (acceptnode.checked) {\n        utwenteCookies._setPrefs({ c: true });\n        openCoBrowser();\n      }\n    });\n}\n\n//wait for cobrowser to appear and if so, open it!\nfunction openCoBrowser() {\n  const online = document.querySelector('#my_cb_button .cb_online');\n  if (online && startedload && getComputedStyle(online).display !== 'none') {\n    document.querySelector<HTMLElement>('#my_cb_button .cb_online .cb_click')?.click();\n  } else { //recheck in 200ms\n    setTimeout(openCoBrowser, 200);\n  }\n}\n\nfunction loadCobrowser() {\n  const chtbtn = dompack.qS(\"#my_cb_button\");\n  if (!chtbtn)\n    return;\n\n  //mark us as offline before loading\n  chtbtn.querySelector<HTMLElement>('.cb_online')!.style.display = \"none\";\n  chtbtn.querySelector<HTMLElement>('.cb_offline')!.style.display = \"\";\n  startedload = true; //now that we've disabled the button, it's safe for openCoBrowser to accept an enabled button\n\n  window._cb.push(['setSourceHash', '58886d0920b635.17133377']);\n  window._cb.push(['setPrivacyLevel', 'allowTracking']);\n  window._cb.push(['setEndpoint', 'https://app.cobrowser.com//sdk/']);\n  window._cb.push(['setDataEndpoint', 'https://app.cobrowser.com//']);\n  window._cb.push(['setVersion', '']);\n  window._cb.push(['forceTransport', 'jsonp']);\n  window._cb.push(['addPageview']);\n  window._cb.push(['setDefaultCss', true]);\n  window._cb.push(['setAutoLoad', true]);\n  window._cb.push(['setDebugMode', false]);\n  if (location.pathname.startsWith(\"/en/online-open-day/\") || location.pathname.startsWith(\"/en/online-open-day-int/\"))\n    window._cb.push(['pollAvailability', 5000]);\n  // window._cb.push(['setDebugMode', true]);\n\n  document.body.appendChild(dompack.create(\"script\", { id: \"cb_script\", src: \"https://app.cobrowser.com/sdk/loader.js\" }));\n}\n\ndompack.register('#my_cb_button', setupCobrowser);\nconsenthandler.onConsent(\"marketing\", () => loadCobrowser());\nif (location.hash && location.hash.includes(\"#cobrowser\"))\n  openCoBrowser();\n","import * as geoip from '@mod-publisher/js/analytics/geoip';\nimport * as storage from 'dompack/extra/storage';\n\nimport \"@mod-publisher/js/analytics/gtm\"; //?wh-debug=anl support\nimport * as cookie from 'dompack/extra/cookie';\nimport \"@mod-utwente_base/webdesigns/ws2016/src/cobrowserchat\";\nimport * as dompack from '@webhare/dompack';\nimport \"@mod-utwente_design/js/crm/consenthandler\";\n\nimport { getUserSettings, getUserGuid, setUserSettings, type UserSettings } from './usersettings';\nimport { getReferralInfo } from './referralinfo';\nimport { getUTUserInfo } from \"@mod-utwente_design/js/crm/auth\";\nimport { getNetworkForIP } from \"@mod-utwente_design/js/crm/networks\";\nexport { getUserSettings, getUserGuid, setUserSettings, getReferralInfo };\n\nimport { getRemoteIPAddress } from '@mod-publisher/js/analytics/clientinfo';\nimport { debugFlags } from '@webhare/env/src/envbackend';\nimport { pushToDataLayer, setupFormAnalyticsForGTM } from '@webhare/frontend';\n\nlet beacons: Record<string, number> = {};\nlet geoippromise: ReturnType<typeof geoip.getIPInfo> | null = null;\n\ndeclare global {\n  interface Window {\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    ga: any; //Ganalytics interface\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    _cb?: any; //cobrowseri nterface\n  }\n}\n\n///////////////////////////////////////////////////////////////////////////\n//\n//  communicatiekanaal voor meeloopdag formulieren (werken via postmesage)\n//\nfunction onMeeloopdagMessage(event: MessageEvent) {\n  if (event.data && event.data.formdone) { //callbacks meeloopdag aanmeldingen\n    if (window.dataLayer)\n      window.dataLayer.push({\n        event: 'formulier-submit',\n        form: event.data.formdone + '-' + (event.data.country || ''),\n        form_programme: event.data.study || '',\n        url: location.href\n      });\n\n    if (!location.href.includes('ut-mld-no-redirect'))\n      switch (event.data.formdone) {\n        case 'meeloopdagen-ba-de':\n          setTimeout(() => document.location = \"/de/schnuppertag/bachelor/danke\", 100);\n          break;\n        case 'meeloopdagen-ba-nl':\n          setTimeout(() => document.location = \"/meeloopdag/bachelor/bedankt\", 100);\n          break;\n        case 'meeloopdagen-ba-int':\n          setTimeout(() => document.location = \"/en/student-for-a-day/bachelor/thanks\", 100);\n          break;\n        case 'meeloopdagen-ma-de':\n          setTimeout(() => document.location = \"/de/schnuppertag/master/danke\", 100);\n          break;\n        case 'meeloopdagen-ma-nl':\n          setTimeout(() => document.location = \"/meeloopdag/master/bedankt\", 100);\n          break;\n        case 'meeloopdagen-ma-int':\n          setTimeout(() => document.location = \"/en/student-for-a-day/master/thanks\", 100);\n          break;\n      }\n  }\n}\n\n///////////////////////////////////////////////////////////////////////////\n//\n//  track eerste client id\n//\n\nfunction getGTMTracker(analyticsid: string) {\n  if (window.ga && window.ga.getAll)\n    for (const tracker of window.ga.getAll())\n      if (tracker.get('trackingId') === analyticsid)\n        return tracker;\n  return null;\n}\n\nfunction trackClientId() {\n  //schedule the retry, if we crash for any reason we'll be rescheduled\n  const retry = window.setTimeout(trackClientId, 500);\n  const tracker = getGTMTracker('UA-9767236-1') || getGTMTracker('UA-9767236-16');\n  if (tracker) {\n    const clientid = tracker.get('clientId');\n    if (clientid) {\n      if (clientid !== getUserSettings().clientid)\n        setUserSettings({ clientid: clientid });\n\n      window.clearTimeout(retry);\n      storage.setSession(\"didclientidcheck\", true);\n    }\n  }\n}\n\n\n\n///////////////////////////////////////////////////////////////////////////\n//\n// set up GTM dataLayer - must be done outside domready, so we have it ready before <body> opens\n\n//FIXME remove - temp IP experiment\n//console.log(\"Your IP: \", performance.getEntries()[0]?.serverTiming?.find(_=>_.name == 'remoteip')?.description);\n\n\nfunction setupGTMDataLayer() {\n  const usersettings = getUserSettings();\n  const base = {\n    paginatitel: document.title,\n    fileid: document.documentElement.dataset.id || 0,\n    hoofdniveau: document.documentElement.dataset.hoofdniveau || '',\n    subniveau: document.documentElement.dataset.subniveau || '',\n    taal: (document.documentElement.lang || '').split('-')[0],\n    opleiding: document.documentElement.dataset.programme || '',\n    type: document.documentElement.dataset.targetinterest || '',\n    userid: getUserGuid() || '',\n    site: document.documentElement.dataset.site || '',\n    experimentId: document.documentElement.dataset.experimentId || '',\n    experimentVariant: document.documentElement.dataset.experimentVariant || '',\n    country: usersettings?.country || '',\n    countryname: usersettings?.countryname || '',\n    network: getNetworkForIP(getRemoteIPAddress())\n  };\n\n  window.dataLayer.push(base);\n}\n\nexport async function requestGeoIP() {\n  //schedule a RPC if needed, reuse the earlier RPC if possible\n  if (!geoippromise)\n    geoippromise = geoip.getIPInfo({ cachedays: 1, countrylang: 'en' });\n\n  const geoinfo = (await geoippromise) as { countrycode: string; countryname: string }; //FIXME remove 'as' once all is WH 5.5\n  if (geoinfo) {\n    setUserSettings({ country: geoinfo.countrycode, countryname: geoinfo.countryname });\n    window.dataLayer.push({ country: geoinfo.countrycode, countryname: geoinfo.countryname });\n  }\n  return geoinfo?.countrycode || null;\n}\nexport function getUserCountry() {\n  const ccode = new URL(location.href).searchParams.get('ut-countrycode');\n  return ccode || getUserSettings().country || null;\n}\nexport function requestUserCountry() {\n  if (getUserCountry())\n    return Promise.resolve(getUserCountry());\n  return requestGeoIP();\n}\nexport function learnedAboutUser(newguid: string, firstname: string) {\n  const opts: UserSettings = {};\n  if (newguid)\n    opts.guid = newguid;\n  if (firstname)\n    opts.firstname = firstname;\n\n  setUserSettings(opts);\n  if (window.dataLayer)\n    window.dataLayer.push({ userid: getUserGuid() || '' });\n  updateCoBrowser();\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction addReferralInfoToForm(evt: any) { //TODO can't we remove this? utwente_voorlichting uses its own referralinfo handling and noone outside shouild need this?\n  if (!evt.detail.extrasubmit.referralinfo) {\n    evt.detail.extrasubmit.referralinfo = getReferralInfo();\n\n    const userbeacon = Object.keys(beacons).filter(name => name.startsWith('usertype-'))[0];\n    if (userbeacon)\n      evt.detail.extrasubmit.referralinfo.beaconusertype = userbeacon.substr(9);\n  }\n}\n\nexport function getUserBeacons() {\n  return beacons;\n}\n\nfunction storeBeacons() {\n  try {\n    localStorage[\"umc-beacons\"] = JSON.stringify(beacons);\n    window.setTimeout(function () { dompack.dispatchCustomEvent(window, \"ut-beaconchange\", { bubbles: true, cancelable: true }); }, 0);\n    return true;\n  } catch (e) {\n    console.log(e);\n    return false;\n  }\n}\n\nexport function triggerUserBeacon(tag: string, date?: number) {\n  if (!date)\n    date = Date.now();\n\n  if (window.dataLayer)\n    window.dataLayer.push({ event: 'trigger-user-beacon', beacon: tag });\n\n  if (debugFlags.umc)\n    console.log(`[umc] Added ${tag} with timestamp ${date}`);\n  beacons[tag] = date;\n  storeBeacons();\n}\n\nexport function setupRevisitBeacon(basetag: string, period: number) {\n  /* revisit beacons...\n     if <basetag>-firstvisit is not set or too old, set it AND set a <basetag>-firstvisit in sessionStorage\n     if <basetag>-firstvisit is set and <basetag>-firstvisit is in sessionStorage, ignore\n                                    else set <basetag>-secondvisit */\n\n  const firstvisit = beacons[basetag + \"-firstvisit\"];\n  const now = Date.now();\n\n  if (!firstvisit || firstvisit < (now - period * 86400 * 1000)) {\n    if (debugFlags.umc)\n      console.log(\"[umc] First visit \" + basetag);\n    beacons[basetag + \"-firstvisit\"] = now;\n    sessionStorage[basetag + \"-firstvisit\"] = \"y\";\n    storeBeacons();\n    return;\n  }\n  if (sessionStorage[basetag + \"-firstvisit\"] === \"y\") {\n    if (debugFlags.umc)\n      console.log(\"[umc] Still in first visit \" + basetag);\n    return;\n  }\n  if (debugFlags.umc)\n    console.log(\"[umc] Second visit \" + basetag);\n  beacons[basetag + \"-secondvisit\"] = now;\n  storeBeacons();\n}\n\nexport function clearUserBeacon(tag: string) {\n  if (!beacons[tag])\n    return;\n\n  if (window.dataLayer)\n    window.dataLayer.push({ event: 'clear-user-beacon', beacon: tag });\n\n  if (debugFlags.umc)\n    console.log(\"[umc] Clearing \" + tag);\n  delete beacons[tag];\n  storeBeacons();\n}\n\nfunction pickupGlobalBeacons() {\n  cookie.list().filter(ck => ck.name.match(/^ut-umc-setbeacon-/)).forEach(ck => {\n    triggerUserBeacon(ck.name.substr('ut-umc-setbeacon-'.length), parseInt(ck.value));\n    cookie.remove(ck.name, { domain: location.host.substr(location.host.indexOf('.')) });\n  });\n\n  //set user type (student/employee) based on logged in user\n  const userinfo = getUTUserInfo();\n  let usertype = '';\n  if (userinfo) {\n    if (userinfo.isemployee)\n      usertype = \"employee\";\n    else if (userinfo.isstudent)\n      usertype = \"student\";\n  }\n\n  const cookieusertype = cookie.read(\"ut-user-type\");\n  if (cookieusertype) {\n    //don't let the cookie overwrite 'student' or 'employee' if already set by logged in user\n    if (![\"student\", \"employee\"].includes(usertype))\n      usertype = cookieusertype;\n\n    if (location.host.endsWith('.utwente.nl'))\n      cookie.remove(\"ut-user-type\", { domain: 'utwente.nl' }); //to match the way the cookie is set\n    else\n      cookie.remove(\"ut-user-type\"); //assume it has no domain\n  }\n\n  if (usertype) {\n    //we used to only support 'student' and 'employee' but are generalizing for #1212\n    //clear 'other' beacons\n    const setbeacon = `usertype-${usertype}`;\n    Object.keys(beacons).filter(name => name !== setbeacon && name.startsWith('usertype-')).forEach(clearUserBeacon);\n    triggerUserBeacon(setbeacon);\n  }\n}\n\nfunction executeANLEvent(node: HTMLElement) { //generic analytics event\n  if (node.dataset.gtm)\n    window.dataLayer.push(JSON.parse(node.dataset.gtm));\n}\n\nfunction updateCoBrowser() {\n  //https://cobrowser.zendesk.com/hc/en-us/articles/115001322166-Visitor-identifier-visitor-ID-\n  const usersettings = getUserSettings();\n  if (window._cb && usersettings && (usersettings.guid || usersettings.firstname)) {\n    const visitorid = (usersettings.guid ? usersettings.guid.substr(0, 8) : \"\")\n      + (usersettings.firstname ? \" - \" + usersettings.firstname : \"\");\n\n    window._cb.push(['setVisitorIdentifier', visitorid]);\n  }\n}\n\n//Read beacons from local storage\ntry {\n  beacons = JSON.parse(localStorage[\"umc-beacons\"]) || {};\n} catch (ignore) {\n}\n\ndompack.register(\".ut-beacon\", node => triggerUserBeacon(node.dataset.setbeacon!));\ndompack.register(\"ut-anl\", node => executeANLEvent(node));\n\nwindow.addEventListener(\"wh:form-preparesubmit\", addReferralInfoToForm);\npickupGlobalBeacons();\n\n//For WH5.7, send the custom event.\nsetupFormAnalyticsForGTM({ eventPrefix: \"publisher:form\" });\naddEventListener(\"wh:form-analytics\", evt => {\n  if (evt.detail.event === \"submitted\" && (evt.target as HTMLFormElement).dataset.gtmSubmit)\n    setTimeout(() => pushToDataLayer({ event: \"formulier-submit\" }), 1); //timeout to give setupFormAnalyticsForGTM a chance to add variables\n});\n\nsetupGTMDataLayer();\nupdateCoBrowser();\n\nwindow.addEventListener(\"message\", evt => onMeeloopdagMessage(evt));\n\nrequestGeoIP().then(() => { }, () => { });\nif (!storage.getSession(\"didclientidcheck\"))\n  window.addEventListener(\"load\", trackClientId);\n","//Once everyone directly invokes setupConsentHandlerForUtwente() this API can go away\n\nimport { setupConsentHandlerForUtwente } from \"@mod-utwente_design/js/cookiebar\";\n\nsetupConsentHandlerForUtwente();\n","//NOTE we are also included by SIR FORM so keep compact / keep dependencies limited\n\nimport * as dompack from 'dompack';\nimport * as cookie from 'dompack/extra/cookie';\n\nlet usersettings: {\n  guid?: string;\n  clientid?: string;\n  country?: string;\n  countryname?: string;\n  firstname?: string;\n  firstreferrer?: string;\n  firstrefertime?: number;\n  \"brochure-lastprogramme\"?: string;\n} = {};\n\nexport type UserSettings = typeof usersettings;\n\nexport function getUserSettings() {\n  return usersettings || {};\n}\n\nexport function getUserGuid(): string | null {\n  return usersettings.guid || null;\n}\n\nexport function setUserSettings(settings: typeof usersettings) {\n  const lastguid = getUserGuid();\n  usersettings = { ...usersettings, ...settings };\n  cookie.write(\"ut-settings\", JSON.stringify(usersettings), { duration: 365 });\n\n  if (lastguid !== getUserGuid())\n    dompack.dispatchCustomEvent(window, \"ut-settings-changed\", { bubbles: true, cancelable: false, detail: { userguid: getUserGuid() } });\n}\n\n//Read usersettings from cookie\ntry {\n  usersettings = JSON.parse(cookie.read(\"ut-settings\")!) || {};\n} catch (e) {\n}\n","//NOTE we are also included by SIR FORM so keep compact / keep dependencies limited\n\nimport { getUserSettings, setUserSettings } from './usersettings';\nimport { getUserBeacons } from './index';\nimport { type UTReferralInfo } from '@mod-utwente_base/js/types';\nimport { debugFlags } from '@webhare/env';\nimport { browser, getCookie, setCookie } from '@webhare/dompack';\nimport utwenteCookies from '@mod-utwente_design/js/cookiebar';\n\ninterface SessionInfo {\n  referrer?: string;\n  start?: number;\n  gclid?: string;\n  wbraid?: string;\n  gbraid?: string;\n}\n\nfunction readSessionInfo(): SessionInfo {\n  try {\n    return JSON.parse(getCookie(\"ut-sess\")!) || {};\n  } catch (ignore) {\n    return {};\n  }\n}\n\nfunction writeSessionInfo(sessinfo: SessionInfo) {\n  setCookie(\"ut-sess\", JSON.stringify(sessinfo));\n}\n\n//returns getReferralInfo structure but with custom URL. used for eg SIR FORM PWA\nexport function getHardcodedURLReferralInfo(url: string): UTReferralInfo {\n  return {\n    device: browser.triplet,\n    firstreferrer: url\n  };\n}\n\nexport function getReferralInfo(): UTReferralInfo {\n  const sessioninfo = readSessionInfo();\n  const usersettings = getUserSettings();\n  const referralinfo: UTReferralInfo = {\n    device: browser.triplet,\n    firstreferrer: (usersettings ? usersettings.firstreferrer : '') || '',\n    firstrefertime: (usersettings ? usersettings.firstrefertime : 0) || 0,\n    sessionreferrer: (sessioninfo.referrer || \"\"),\n    sessionstart: (sessioninfo.start || 0),\n    clientid: (usersettings ? usersettings.clientid : '') || ''\n  };\n\n  if (utwenteCookies.getConsent()) {\n    for (const field of [\"gclid\", \"gbraid\", \"wbraid\"] as const)\n      if (sessioninfo[field])\n        referralinfo[field] = sessioninfo[field];\n  }\n\n  const userbeacon = Object.keys(getUserBeacons()).filter(name => name.startsWith('usertype-'))[0];\n  if (userbeacon)\n    return { ...referralinfo, beaconusertype: userbeacon.substring(9) };\n\n  return referralinfo;\n}\n\n\n///////////////////////////////////////////////////////////////////////////\n//\n//  track eerste referrer\n//\n\nfunction trackFirstReferrer() {\n  const usersettings = getUserSettings();\n  let referrer = (document.referrer || 'direct:').substr(0, 1000);\n\n  if (referrer) { //copy gclid & utm_ vars from the current URL to the referrer url\n    const referrerurl = new URL(referrer);\n    const urlparams = new URL(location.href).searchParams;\n    for (const varname of urlparams.keys()) {\n      if (varname.match(/^(gclid|utm_.*|fbclid|dyn_.*)$/))\n        referrerurl.searchParams.set(varname, urlparams.get(varname)!);\n    }\n\n    referrer = referrerurl.toString();\n  }\n\n  //Set sessionstorage referrer if not seen yet\n  const sessinfo = readSessionInfo();\n  let sessupdates: Record<string, string | number> | null = null;\n  if (!sessinfo.start) {\n    if (debugFlags.anl)\n      console.log(\"[anl] trackFirstReferrer: stored as session referrer: \" + referrer);\n    sessupdates = { referrer: referrer, start: Date.now() };\n  }\n\n  const urlinfo = new URL(location.href);\n  for (const grabVar of [\"gclid\", \"wbraid\", \"gbraid\"] as const)\n    if (urlinfo.searchParams.has(grabVar))\n      sessupdates = { ...sessupdates, [grabVar]: urlinfo.searchParams.get(grabVar) || '' };\n\n\n  if (sessupdates)\n    writeSessionInfo({ ...sessinfo, ...sessupdates });\n\n  if (usersettings.firstrefertime) {\n    const firstreferage = (Date.now() - usersettings.firstrefertime) / (86400 * 1000);\n    if (firstreferage < 90) {\n      if (debugFlags.anl)\n        console.log(\"[anl] trackFirstReferrer: ignoring referrer because currently stored referrer is \" + firstreferage + \" days old\");\n      return;\n    }\n  }\n\n  setUserSettings({ firstreferrer: referrer, firstrefertime: Date.now() });\n  if (debugFlags.anl)\n    console.log(\"[anl] trackFirstReferrer: stored as first referrer: \" + referrer);\n}\n\ntrackFirstReferrer();\n","// Auth is not really a 'crm' thing, but all related code is here too... so lets just put it here in @mod-utwente_design/js/crm/...\n\nimport * as dompack from 'dompack';\nimport * as wrdauth from '@mod-wrd/js/auth';\nimport { getNetworkForIP } from \"@mod-utwente_design/js/crm/networks\";\nimport { getRemoteIPAddress } from '@mod-publisher/js/analytics/clientinfo';\nimport \"@mod-publisher/js/analytics/gtm\"; //load as early as possible\nimport { dtapStage } from '@webhare/env';\n\nexport function getLoginLink({ prompt = false, silent = false, redirect = \"\" } = {}) {\n  const url = redirect ? redirect : location.href;\n  const gotourl = new URL('/.utdesign/auth/login.shtml', location.href);\n  gotourl.searchParams.set('goto', url.substr(location.origin.length + 1));\n  if (prompt)\n    gotourl.searchParams.set('prompt', '1');\n  if (silent)\n    gotourl.searchParams.set('silent', '1');\n  return gotourl.toString();\n}\n\nexport function getUTUserInfo() {\n  return wrdauth?.getDefaultAuth()?.getUserInfo();\n}\n\n\ndompack.register(\".ut-login--clicktologin,a[href^='x-ut-login:']\", node => node.addEventListener(\"click\", event => {\n  dompack.stop(event);\n  //TODO spinner while navigating?\n  location.href = getLoginLink({ redirect: node.dataset.redirect ? node.dataset.redirect : \"\" });\n}));\n\nif (dtapStage === \"development\" || dtapStage === \"test\")\n  console.log(\"To debug your login settings go to\", new URL(\"/.utdesign/auth/userinfo.shtml?path=\" + encodeURIComponent(location.pathname), location.href).toString());\n\nconst userinfo = getUTUserInfo();\nwindow.dataLayer?.push({\n  isloggedin: userinfo ? \"true\" : \"false\",\n  logintype: userinfo ? userinfo.isemployee ? \"Yes - employee\" : userinfo.isstudent ? \"Yes - student\" : \"Yes - other\" : \"No\",\n  company: getUTUserInfo()?.company ?? \"\",\n  network: getNetworkForIP(getRemoteIPAddress())\n});\n","/* eslint-disable */\n/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\n//ADDME move cookie state to sessionstorage, we don't need to transmit _c cookies on each request\n\nimport * as dompack from 'dompack';\nimport * as domcookie from 'dompack/extra/cookie';\nimport * as whintegration from '@mod-system/js/wh/integration';\nimport * as newauth from \"@webhare/frontend/src/auth\";\nimport Keyboard from 'dompack/extra/keyboard';\n\nimport JSONRPC from '@mod-system/js/net/jsonrpc';\nimport { navigateTo } from '@webhare/env';\nimport { isHTMLElement } from '@webhare/dompack';\n\nlet defaultauth: WRDAuthenticationProvider | null = null;\n\nfunction getBackVar(backurl) {\n  backurl = backurl.split('/').slice(3).join('/'); //strip origin, make relative to current server\n  return backurl ? '?b=' + encodeURIComponent(backurl) : '';\n}\n\nfunction getURLOrigin(url) {\n  return url.split('/').slice(0, 3).join('/');\n}\n\nexport class WRDAuthenticationProvider {\n  userinfo: object | null = null;\n  constructor(options) {\n    if (!options)\n      options = {};\n\n    this.cookiename = 'cookiename' in options ? options.cookiename : \"webharelogin\";\n\n    this.refresh();\n\n    window.$wh$legacyAuthProvider = this; //@webhare/frontend/src/auth needs this to keep us in sync\n  }\n\n  refresh() {\n    this.isloggedin = false;\n    this.userinfo = newauth.getUserInfo();\n    this.logouturl = \"\";\n    this.loginservice = new JSONRPC({ url: '/wh_services/wrd/auth' });\n\n    const jsstate = domcookie.read(this.cookiename + '_j');\n    const currentstate = domcookie.read(this.cookiename + '_c');\n\n    if (dompack.debugflags.aut) {\n      console.log(\"[aut] \" + this.cookiename + \"_j=\" + jsstate);\n      console.log(\"[aut] \" + this.cookiename + \"_c=\" + currentstate);\n    }\n    if (!jsstate)\n      return;\n\n    if (!currentstate || currentstate.substr(0, jsstate.length) !== jsstate) {\n      return;\n    } else {\n      if (dompack.debugflags.aut)\n        console.log(\"[aut] looks like we're still logged in\");\n\n      this.isloggedin = true;\n      if (currentstate.length > 1)\n        try {\n          this.userinfo = JSON.parse(currentstate.substr(jsstate.length));\n        } catch (e) {\n        }\n    }\n  }\n\n  //Get the current session id - use this if you need to discard settings\n  getCurrentSessionId() {\n    return domcookie.read(this.cookiename + '_j') || '';\n  }\n\n  logout() {\n    let backurl = location.href;\n    if (this.logouturl) {\n      const logouturl = new URL(this.logouturl, backurl).toString();\n      if (getURLOrigin(backurl) !== getURLOrigin(logouturl))\n        throw new Error(\"A logout URL is not allowed to change the origin\"); //we won't be an open redirect. and getBackVar will clear the origin anyway\n\n      backurl = logouturl;\n    }\n\n    const redirectto = '/.wrd/auth/logout.shtml' + getBackVar(backurl);\n    location.replace(redirectto);\n  }\n\n  setupLoginForm(form: HTMLFormElement) {\n    if (!form)\n      throw new Error(\"No such form\");\n\n    new Keyboard(form, { \"Enter\": evt => this._handleLoginForm(form, evt) });\n    form.addEventListener(\"submit\", evt => this._handleLoginForm(form, evt));\n    form.addEventListener(\"click\", evt => this._handleLoginClick(form, evt));\n  }\n  _handleLoginClick(form: HTMLFormElement, event: MouseEvent) {\n    if (form.hasAttribute(\"data-wh-wrdauth-attached\"))\n      return; //get out of the way - modern handlers are registered\n\n    if (isHTMLElement(event.target) && event.target.closest('.wh-wrdauth__loginbutton'))\n      return this._handleLoginForm(form, event); //will stop the event too\n  }\n  _handleLoginForm(form: HTMLFormElement, event: Event) {\n    if (form.hasAttribute(\"data-wh-wrdauth-attached\"))\n      return; //get out of the way - modern handlers are registered\n\n    dompack.stop(event);\n\n    const loginfield = form.querySelector('*[name=\"login\"]');\n    const passwordfield = form.querySelector('*[name=\"password\"]');\n    const persistentfield = form.querySelector('*[name=\"persistent\"]');\n\n    if (!loginfield)\n      throw new Error(\"No field named 'login' found\");\n    if (!passwordfield)\n      throw new Error(\"No field named 'password' found\");\n\n    const persistentlogin = persistentfield && persistentfield.checked;\n    this._tryLogin(form, loginfield.value, passwordfield.value, { persistent: persistentlogin });\n  }\n\n  login(login, password, options) {\n    options = { ...options };\n    return new Promise((resolve, reject) => {\n      const url = new URL(location.href);\n\n      const opts =\n      {\n        logincontrol: url.searchParams.get(\"wrdauth_logincontrol\") || \"\"\n      };\n\n      return this.loginservice.request('Login'\n        , [\n          location.href,\n          login,\n          password,\n          Boolean(options.persistent),\n          opts\n        ]\n        , function (response) { //success handler\n          resolve(response);\n        }\n        , function (error) {\n          reject(error);//FIXME translate to exception\n        }\n      );\n    });\n  }\n\n  loginSecondFactor(loginproof, type, data, options) {\n    return new Promise((resolve, reject) => {\n      const url = new URL(location.href);\n\n      const opts =\n      {\n        logincontrol: url.searchParams.get(\"wrdauth_logincontrol\") || \"\"\n      };\n\n      return this.loginservice.request('LoginSecondFactor'\n        , [\n          location.href,\n          loginproof,\n          type,\n          { ...data },\n          opts\n        ]\n        , function (response) { //success handler\n          resolve(response);\n        }\n        , function (error) {\n          reject(error);//FIXME translate to exception\n        }\n      );\n    });\n  }\n\n  /** Get the afterlogin submitinstruction from the wrdauth_logincontrol webvariable\n      @cell(string) opts.logincontrol Override wrdauth_logincontrol variable from the url\n      @return Submit instruction. The defult instruction is { \"type\": \"reload\" }.\n  */\n  getAfterLoginSubmitInstruction(opts = {}) {\n    const url = new URL(location.href);\n    const logincontrol = opts.logincontrol || url.searchParams.get(\"wrdauth_logincontrol\") || \"\";\n\n    return new Promise((resolve, reject) => {\n      this.loginservice.request('getAfterLoginSubmitInstruction',\n        [location.href, logincontrol],\n        function (response) { //success handler\n          resolve(response);\n        }\n        , function (error) {\n          reject(error);//FIXME translate to exception\n        }\n      );\n    });\n  }\n\n  //ADDME do we have direct callers or can we _tryLogin this?\n  //FIXME be more wh-form like, at least BEM the 'submitting' class\n  _tryLogin(form, login, password, options) {\n    const loginlock = dompack.flagUIBusy();\n    if (form)\n      form.classList.add(\"submitting\");\n\n    this.login(login, password, options).then(result => this.onLoginSuccess(loginlock, form, result))\n      .catch(error => this._onLoginFailure(loginlock, form, options, error));\n  }\n  onLoginSuccess(loginlock, form, response) {\n    if (form)\n      form.classList.remove(\"submitting\");\n\n    const completion = () => this._completeLoginSuccess(loginlock, response, form);\n    dompack.dispatchCustomEvent(form || document.documentElement, 'wh:wrdauth-onlogin',\n      {\n        bubbles: true,\n        cancelable: true,\n        detail: { callback: completion, userinfo: response.userinfo },\n        defaulthandler: completion\n      });\n  }\n  _completeLoginSuccess(loginlock, response, form) {\n    loginlock.release();\n    if (response.success) {\n      if (response.submitinstruction) {\n        navigateTo(response.submitinstruction);\n        return;\n      }\n\n      //The user has succesfully logged in\n      console.log(\"Reloading after succesfull login\");\n      navigateTo({ type: \"reload\" });\n      return;\n    }\n\n    this._failLogin(/* FIXME? Locale.get('wh-common.authentication.loginfail') || */'The specified login data is incorrect.', response, form);\n  }\n  _onLoginFailure(loginlock, form, options, code, msg) {\n    if (form)\n      form.classList.remove(\"submitting\");\n    loginlock.release();\n\n    this._failLogin(/* FIXME? Locale.get('wh-common.authentication.loginerror') || */'An error has occurred.', { code: code }, form);\n  }\n  _failLogin(message, response, form) {\n    if ([\"REQUIRESETUPSECONDFACTOR\", \"FAILEDVALIDATIONCHECKS\", \"REQUIRESECONDFACTOR\"].includes(response.code)) {\n      console.error(`Code \"${response.code}\" is NOT supported by @mod-wrd/js/auth - you will need to remove this library and fully switch to setupAuth in @webhare/frontend to support password requirements and/or MFA`);\n      message = \"An internal error has occured in the account management system. Please contact the webmaster.\";\n    }\n\n    const evtdetail = {\n      message: message,\n      code: response.code,\n      data: response.data\n    };\n\n    const cancelled = !dompack.dispatchCustomEvent(form || document.documentElement, \"wh:wrdauth-loginfailed\", { bubbles: true, cancelable: true, detail: evtdetail });\n    if (!cancelled) {\n      /*\n      if($wh.Popup && $wh.Popup.Dialog)\n        new $wh.Popup.Dialog( { text: failevent.message, buttons: [{ result: 'ok', title: \"Ok\" }] });\n      else*/\n      alert(message);\n    }\n  }\n  isLoggedIn() {\n    return newauth.isLoggedIn();\n  }\n  /** @deprecated Switch to frontend getUserInfo() */\n  getUserInfo(): any {\n    return newauth.getUserInfo();\n  }\n  setLogoutURL(url) {\n    this.logouturl = url;\n  }\n\n  startLogin(type, sp_tag, options) {\n    options = options || {};\n    const defer = Promise.withResolvers();\n\n    this.loginservice.request('StartLogin'\n      , [type, sp_tag, location.href, options]\n      , defer.resolve\n      , defer.reject //FIXME translate to exception\n    );\n\n    return defer.promise;\n  }\n  startSAMLLogin(sp_tag, options) {\n    return this.startLogin('saml', sp_tag, options);\n  }\n\n  //Setup the page with loginstate. automatically invoked on the default auth provider\n  setupPage() {\n    document.documentElement.classList.toggle(\"wh-wrdauth-loggedin\", this.isLoggedIn()); //legacy! will be removed\n    document.documentElement.classList.toggle(\"wh-wrdauth--isloggedin\", this.isLoggedIn());\n  }\n\n  static getDefaultAuth() {\n    return defaultauth;\n  }\n}\n\nexport function getDefaultAuth() {\n  return defaultauth;\n}\n\nif (window.$wh && window.$wh.WRDAuthenticationProvider) {\n  console.log(\"Both designfiles wrd.auth and @mod-wrd/js/auth are loaded. @mod-wrd/js/auth will not activate\");\n} else if (whintegration.config[\"wrd:auth\"]) {\n  defaultauth = new WRDAuthenticationProvider(whintegration.config[\"wrd:auth\"]);\n  defaultauth.setupPage();\n\n  dompack.register('.wh-wrdauth__logout, .whplugin-wrdauth-logout', node => {\n    node.whplugin_processed = true;\n    node.addEventListener(\"click\", event => {\n      event.stopPropagation();\n      event.preventDefault();\n      defaultauth.logout();\n    });\n  });\n  dompack.register('.wh-wrdauth__loginform, .whplugin-wrdauth-loginform', node => {\n    node.whplugin_processed = true;\n    defaultauth.setupLoginForm(node);\n  });\n\n  if (defaultauth.userinfo) {\n    dompack.register(\"*[data-wrdauth-text]\", node => {\n      const elname = node.dataset.wrdauthText;\n      if (elname in defaultauth.userinfo)\n        node.textContent = defaultauth.userinfo[elname];\n    });\n    dompack.register(\"*[data-wrdauth-value]\", node => {\n      const elname = node.dataset.wrdauthValue;\n      if (elname in defaultauth.userinfo)\n        node.value = defaultauth.userinfo[elname];\n    });\n  }\n}\n\nexport default WRDAuthenticationProvider;\n\nwindow.$wh$wrdauth = true; //flag our load - needed during transition to @webhare/wrdauth to prevent double loading\n","import * as dompack from '@webhare/dompack';\n\n//NOTE: Do *NOT* load @webhare/frontend or we enforce the new CSS reset!\nimport { navigateTo, type NavigateInstruction } from \"@webhare/env\";\nexport { frontendConfig as config } from '@webhare/frontend/src/init';\n\nexport function executeSubmitInstruction(instr: NavigateInstruction, options?: {\n  ismodal?: boolean;\n  iframe?: HTMLIFrameElement;\n}) {\n  if (!instr)\n    throw Error(\"Unknown instruction received\");\n\n  options = { ismodal: true, ...options };\n  //Are there any cirumstances where you would want to reelase this lock?\n  dompack.flagUIBusy({ modal: options.ismodal || false });\n  navigateTo(instr);\n}\n","export function getNetworkForIP(ip: string | null) {\n  /*\n  https://gitlab.webhare.com/utwente/utwente_base/-/issues/1768#note_140872\n  2001:67c:2564:*\n  2001:610:1908:*\n  130.89.*\n  145.126.0.0-145.126.127.255  (145.126.126.0/17)\n\n  guess we could integartie all kinds of CIDR logic.. but a few comparisons are faster/still less code. test_misc.es will validate the ranges\n\n  https://gitlab.webhare.com/utwente/utwente_base/-/issues/2063:\n  145.126.0.0/18 - 145.126.0.1 - 145.126.63.254\n  145.126.64.0/19 - 145.126.64.1 - 145.126.95.254\n\n  */\n  if (!ip)\n    return '';\n  if (ip.startsWith(\"2001:67c:2564:\")\n    || ip.startsWith(\"2001:610:1908:\")\n    || ip.startsWith(\"130.89.\")\n    || (ip.startsWith(\"145.126.\") && parseInt(ip.split('.')[2]) <= 95)\n  )\n    return 'internal';\n  return 'external';\n}\n","/* Dialogapi offers an API to which dialog providers cannot connect. It does\n   not implement the dialogs themselves\n*/\n\nimport * as dompack from 'dompack';\nimport * as domfocus from 'dompack/browserfix/focus';\nimport KeyboardHandler from \"dompack/extra/keyboard\";\n\nexport type DialogOptions =\n  {\n    /**  Allow the dialog to be cancelled by clicking outside the dialog. Defaults to true if no choices are specified */\n    allowcancel?: boolean;\n    /**  Element to focus on closing the dialog */\n    focusonclose?: HTMLElement;\n    /**  An AbortSignal which if set will close the dialog and resolve it with a null response */\n    signal?: EventTarget;\n    /**  Additional class to set on the dialog */\n    messageboxclassbase?: string;\n\n    borrow?: Element | string;\n  };\ntype DialogConstructor = (options?: DialogOptions) => DialogBase;\n\nconst dialogstack: DialogBase[] = [];\nlet keyhandler: KeyboardHandler | null = null;\nlet dialogconstructor: DialogConstructor | null = null;\nlet dialogoptions: DialogOptions | null = null;\n\nfunction onEscape(event: KeyboardEvent) {\n  if (!dialogstack.length)\n    return;\n\n  dompack.stop(event);\n  if (dialogstack[dialogstack.length - 1].options.allowcancel)\n    dialogstack[dialogstack.length - 1].resolve(null);\n}\n\nfunction onTab(event: KeyboardEvent, direction: number) {\n  if (!dialogstack.length)\n    return;\n\n  dompack.stop(event);\n\n  const focusable = domfocus.getFocusableComponents(dialogstack[dialogstack.length - 1].contentnode, true);\n  const el = domfocus.getCurrentlyFocusedElement();\n  const tofocusidx = el ? focusable.indexOf(el) + direction : -1;\n  const tofocus = tofocusidx < 0 ? focusable[focusable.length - 1] : tofocusidx >= focusable.length ? focusable[0] : focusable[tofocusidx];\n  if (tofocus)\n    dompack.focus(tofocus);\n}\n\nexport class DialogBase {\n  options: DialogOptions;\n  private _borrowedfrom: Element | null = null;\n  private _borrowednext: Element | null = null;\n  contentnode: Element | null; //FIXME a successor to DialogBase should not allow these to be | null. have our child inform us through super() about the contentnode and buttonsnode so we can ensure it's set\n  buttonsnode: Element | null = null;\n  private _deferred: PromiseWithResolvers<string | null>;\n  open: boolean;\n  private _previousfocus: Element | null = null;\n\n  constructor(options?: DialogOptions) {\n    this.options = {\n      allowcancel: true,\n      ...options\n    };\n\n    if (this.options.borrow && typeof this.options.borrow === 'string') {\n      const borrow = document.querySelector(this.options.borrow);\n      if (!borrow)\n        throw new Error(\"Invalid 'borrow' selectior: \" + this.options.borrow);\n      this.options.borrow = borrow;\n    }\n    // At this point, if this.options.borrow was a string, it's been resolved to an Element\n\n    if (this.options.borrow) {\n      this._borrowedfrom = (this.options.borrow as Element).parentElement;\n      this._borrowednext = (this.options.borrow as Element).nextElementSibling;\n    }\n\n    if (this.options.signal)\n      this.options.signal.addEventListener(\"abort\", () => { this.resolve(null); });\n\n    this.contentnode = null;\n    this._deferred = Promise.withResolvers();\n    this.open = false;\n  }\n\n  async runModal() {\n    if (this.open)\n      throw new Error(\"Attempting to re-open already opened dialog\");\n\n    if (!keyhandler)\n      keyhandler = new KeyboardHandler(window, {\n        \"Escape\": (evt: KeyboardEvent) => onEscape(evt),\n        \"Tab\": (evt: KeyboardEvent) => onTab(evt, +1),\n        \"Shift+Tab\": (evt: KeyboardEvent) => onTab(evt, -1)\n      }, { captureunsafekeys: true, listenoptions: { capture: true } });\n\n    this._previousfocus = domfocus.getCurrentlyFocusedElement();\n    this._openDialog();\n\n    this.open = true;\n    dialogstack.push(this);\n\n    try {\n      this.afterShow();\n      this._checkFocus();\n      return await this._deferred.promise;\n    } finally {\n      if (this.open)\n        this.closeDialog();\n    }\n  }\n\n  _openDialog() {\n    throw new Error(\"_openDialog not overridden by dialog class\");\n  }\n\n  _checkFocus() {\n    const focusable = domfocus.getFocusableComponents(this.contentnode, true);\n    if (focusable.length !== 0)\n      dompack.focus(focusable[0]);\n    else\n      dompack.focus(document.body);\n  }\n\n  //close the dialog. this may be invoked even when inside runModal to ensure synchronous dialog cleanup\n  closeDialog() {\n    if (!this.open)\n      return;\n\n    const myoffset = dialogstack.indexOf(this);\n    if (myoffset >= 0)\n      dialogstack.splice(myoffset, 1);\n\n    this.open = false;\n    if (this.options.borrow)\n      if (this._borrowedfrom)\n        this._borrowedfrom.insertBefore(this.options.borrow as Element, this._borrowednext);\n      else\n        this._borrowednext?.remove();\n\n    if (this.options.focusonclose)\n      dompack.focus(this.options.focusonclose);\n    else if (this._previousfocus)\n      dompack.focus(this._previousfocus as HTMLElement);\n\n    if (dialogstack.length === 0 && keyhandler) {\n      keyhandler.destroy();\n      keyhandler = null;\n    }\n  }\n\n  /**\n   * resolve the dialog with the specified answer\n   *\n   * @param response - Response (or choice) to return. null if the dialog was simply cancelled\n   */\n  resolve(response: string | null) {\n    if (this.open)\n      this.closeDialog();\n    this._deferred.resolve(response);\n  }\n\n  afterShow() {\n    // supposed to be empty but extenders can override\n  }\n}\n\nexport function setupDialogs(newdialogconstructor: DialogConstructor, options?: DialogOptions) {\n  if (dialogconstructor) {\n    console.error(\"Duplicate setupDialogs call!\");\n    return;\n  }\n\n  dialogconstructor = newdialogconstructor;\n  dialogoptions = { messageboxclassbase: 'dompack-messagebox__', ...options };\n}\n\n/** Verify whether the dialog api is initialized */\nexport function isCreateDialogAvailable(): boolean {\n  return Boolean(dialogconstructor);\n}\n\n/**\n * Create a dialog\n *\n * @param options - dialog settings\n */\nexport function createDialog(options?: DialogOptions) {\n  if (!dialogconstructor)\n    throw new Error(\"Cannot create dialog, no dialog class defined\");\n\n  const dialog = dialogconstructor(options);\n  if (dialog.options.borrow)\n    dialog.contentnode?.appendChild(dialog.options.borrow as Element);\n  return dialog;\n}\n\ntype DialogChoice =\n  {\n    /** Title for the choice */\n    title: string;\n    /** Override result to return if clicked (otherwise you'll just receive the title) */\n    result?: string;\n    className?: string;\n  };\n\n\n/**\n                     @param question - if a string, will be wrapped as textContent into a <p> and presented as the question\n                    - if a html node, will appear as the question (allowing you to insert html)\n                    - if an array of nodes, all these nodes will be inserted\n    @param choices - Buttons (choices) the message box will offer, eg Ok and Cancel\n    @param options - Dialog options\n */\nexport async function runMessageBox(question: string | HTMLElement | HTMLElement[], choices: DialogChoice[], options?: DialogOptions) {\n  choices = choices || [];\n  options = { allowcancel: choices.length === 0, ...options };\n\n  const dialog = createDialog(options);\n  const choicebuttons = choices.map(choice =>\n    dompack.create(\"button\", {\n      type: \"button\",\n      className: dialogoptions ? dialogoptions.messageboxclassbase + \"button \" + (choice.className || \"\") : \"\",\n      textContent: choice.title,\n      on: { click: () => dialog.resolve(choice.result || choice.title) },\n      dataset: { messageboxResult: choice.result || choice.title }\n    }));\n\n  if (typeof question === 'string')\n    question = dompack.create(\"p\", { textContent: question });\n\n  if (Array.isArray(question))\n    dialog.contentnode?.append(...question);\n  else\n    dialog.contentnode?.append(question);\n\n  if (dialog.buttonsnode) //this dialog has a separte node for the button area\n    dialog.buttonsnode.append(...choicebuttons);\n  else\n    dialog.contentnode?.append(dompack.create(\"div\", {\n      className: dialogoptions ? dialogoptions.messageboxclassbase + \"buttongroup\" : \"\",\n      childNodes: choicebuttons\n    }));\n\n  return dialog.runModal();\n}\n","export function getActiveElement(doc: Document | null): HTMLElement | null {\n  return doc?.activeElement as HTMLElement || null;\n}\n\nexport function getToplevelWindow() {\n  let toplevelwindow: Window = window;\n  while (toplevelwindow.frameElement)\n    toplevelwindow = toplevelwindow.parent;\n  return toplevelwindow;\n}\n\nexport function asIframe(node: Element | null): HTMLIFrameElement | null {\n  return node && (node as HTMLElement)?.matches?.('iframe') ? node as HTMLIFrameElement : null;\n}\n\n/**\n     Find the currently focused element\n *\n    @param limitdoc - If set, only return compontents in the specified document (prevents editable iframes from returning subframes)\n    @returns The element or null\n */\nexport function getCurrentlyFocusedElement(limitdoc?: Document): HTMLElement | null {\n  try {\n    let focused = getActiveElement(getToplevelWindow().document);\n    for (; ;) {\n      const frame = asIframe(focused);\n      if (frame && (!limitdoc || frame.ownerDocument !== limitdoc))\n        focused = getActiveElement(frame.contentDocument);\n      else\n        break;\n    }\n    if (focused && limitdoc && focused.ownerDocument !== limitdoc)\n      return null;\n    return focused;\n  } catch (e) {\n    return null;\n  }\n}\n\n/** Return whether the node is reachable for focus by keyboard navigation\n   (because tabIndex === -1 will be seen a non(keyboard)focusable by this function)\n\n    @param node - Node to test\n    @param ignoreInert - Ignore the inert attribute\n*/\nexport function canFocusTo(node: Element, { ignoreInertAttribute = false } = {}): node is HTMLElement { //returns if a -visible- node is focusable (this function does not check for visibility itself)\n  if (!node.closest) //callers are not necessarily calling us with HTMLElement, eg getClosestValidFocusTarget might supply a document\n    return false;\n  if (!ignoreInertAttribute && node.closest('[inert]'))\n    return false;\n\n  if ((node as HTMLElement).contentEditable === \"true\")\n    return true;\n  if (node.shadowRoot?.delegatesFocus)\n    return true;\n\n  return (node as HTMLElement).tabIndex >= 0 && !(node as HTMLInputElement).disabled && !(node.tagName === 'A' && !(node as HTMLAnchorElement).href);\n}\n\nexport function getFocusableComponents(startnode: Element | null, options?: boolean | { recurseFrames?: boolean; ignoreInertAttribute?: boolean }): HTMLElement[] {\n  if (typeof options !== \"object\") {\n    options = { recurseFrames: options };\n  }\n  let focusable: HTMLElement[] = [];\n  if (!startnode)\n    return focusable;\n  for (const currentnode of startnode.children) {\n    // Get current style (avoid mootools due to cross-frame issues)\n    const currentstyle = getComputedStyle(currentnode);\n    if (!currentstyle || currentstyle.display === \"none\" || currentstyle.visibility === \"hidden\") {\n      //if(currentnode.getStyle) console.log(\"getFocusableComponents skipping\",currentnode, $(currentnode).getStyle(\"display\"), currentnode.getStyle(\"visibility\"))\n      continue;\n    }\n\n    let iframe;\n    if (options?.recurseFrames && (iframe = asIframe(currentnode))) { //might contain more things to focus\n      try {\n        const subnodes = getFocusableComponents(iframe.contentDocument!.documentElement, options);\n        if (subnodes.length)\n          focusable = focusable.concat(subnodes);\n      } catch {\n        //assume permission error\n      }\n    } else if (canFocusTo(currentnode, options)) {\n      focusable.push(currentnode);\n    }\n\n    if ((currentnode as HTMLElement).isContentEditable)\n      continue; //don't look for further focusable nodes inside, the whole RTE counts as an editable component\n\n    const subnodes = getFocusableComponents(currentnode, options);\n    if (subnodes.length)\n      focusable = focusable.concat(subnodes);\n  }\n  return focusable;\n}\n\nexport function getAllFocusableComponents() {\n  return getFocusableComponents(getToplevelWindow().document.documentElement, true);\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from 'dompack';\n\n// import * as videotools from \"@mod-publisher/js/richcontent/video\";\nimport * as videotools from \"./video.ts\"; // NOTE: this also activated use of [data-video]\n\nvideotools.registerVideoSource(\"yuja\", { getPlaybackURL: getYujaPlaybackURL });\n\ndompack.register('.wh-video', node => node.dataset.video ? videotools.initializeVideoElementV1(node) : videotools.initializeVideoElementV2(node));\n\n\n/*\n\nhttps://support.yuja.com/hc/en-us/articles/20773906561559-YuJa-Video-Player-API\n\nUitleg hoe je custom code kan toevoegen om events te genereren.\n\n*/\n\n\n\nfunction getYujaPlaybackURL(video, playback) {\n  /*\n  NOTE\n  - autoplay  - NOT supported (Yuja dropped this feature somewhere in 2024/2025)\n  - startTime - supported\n  - endTime   - NOT supported\n  - controls  - NOT available??\n  - loop      - NOT supported\n  */\n\n  const args = [];\n\n  // Convert the parameters into a full playback URL\n  const params = new URL(\"https://www.example.org/?\" + video.id).searchParams;\n  const host = params.get(\"h\");\n  const videoid = params.get(\"v\");\n  const authorizationkey = params.get(\"a\");\n  // let playback_url = `//{host}/V/Video?v={videoid}&a={authorizationkey}`;\n  let playback_url = `//${host}/V/Video`;\n\n  args.push(\"v=\" + encodeURIComponent(videoid));\n  args.push(\"a=\" + encodeURIComponent(authorizationkey));\n\n  /*\n  An autostart existed in 2024:\n  https://web.archive.org/web/20240223172700/https://support.yuja.com/hc/en-us/articles/360051850373-Enabling-Auto-Start-for-a-Video-s-Direct-Link-Embed-Code\n\n  Although it had issues:\n  (it'll start playback muted ... which will confuse users)\n  https://gitlab.webhare.com/utwente/utwente_base/-/issues/1966#note_177518\n\n  But in 2025 it seems to have disappeared\n  */\n  // if (playback.autoplay)\n  // args.push(\"autostart=1\");\n\n  if (playback.starttime)\n    args.push(\"starttime=\" + playback.starttime);\n\n  if (playback.endtime)\n    console.warn(\"setting an endtime doesn't work for Yuja video's\");\n\n  if (!playback.controls)\n    console.warn(\"disabling video controls not possible for Yuja video's\");\n\n  if (playback.loop)\n    console.warn(\"loop isn't supported for Yuja video's\");\n\n  if (args.length > 0)\n    playback_url += \"?\" + args.join(\"&\");\n\n  // alert(playback_url);\n\n  return playback_url;\n}\n","/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\n/*\n\nThis is a modified video.ts (originally from the Publisher)\n\nNOTE!!\n- for networks listed in \"videonetworks_preload\" we preload the video player iframe\n\n\nDifferences:\n- 06/2023 - Support for \"video sources\" (additional video networks which registered)\n- 06/2025 - Support for preloading the embedded video players (in their iframe) so they can directly be started upon clicking the playbutton\n          - Using postMessage to force playback\n- 11/2025 - Preloaded video player iframes will now be made inert until we start playback (the play button has been used)\n            This prevents user being able to interact with the iframe. This prevents using keyboard navigation to get into the iframe and start the video.\n          - launchVideo() renamed to insertVideoPlayer()\n\n\nTestvideo:\nhttps://utwente-test.video.yuja.com/V/Video?v=471208&a=178921546\n\n- We register .wh-video\n- All elements with .wh-video--activate will load/start the video specified at the main .wh-video node (as JSON encoded in the data-wh-video attribute)\n- On the .wh-video--activate elements which store a .__initialized and .__initalized_iframe boolean\n\n\n<div class=\"wh-video wh-video--aspect_16_9 wh-requireconsent\"\n     data-wh-video=\"{&quot;id&quot;:&quot;h=utwente-test.video.yuja.com&amp;v=471208&amp;node=2121329&amp;a=178921546&quot;,&quot;network&quot;:&quot;yuja&quot;,&quot;title&quot;:&quot;ALD video audio adjusted&quot;}\"\n     title=\"ALD video audio adjusted\"\n     data-duration=\"491\"\n     data-wh-consent-required=\"marketing\"\n     >\n  <div class=\"wh-requireconsent__overlay\" hidden=\"\"></div>\n\n  <div class=\"wh-video--activate wh-video__innerframe\">\n    <!-- Our preview (image + custom play button) -->\n    <div class=\"wh-video__innerframe__preview\">\n      <picture>\n        <source srcset=\"/.wh/ea/uc/i01dd07bf0102faf43f00a3978c02e22f392134ec7af80701c28002000085/preview-hutwente-test.video.yuja.comv471208node2121329a178921546.avif\"\n                media=\"(max-width:640px)\"><img src=\"/.wh/ea/uc/i01dd07bf0102faf43f00a3978c02e22f392134ec7af80701c28002000085/preview-hutwente-test.video.yuja.comv471208node2121329a178921546.avif\" alt=\"\">\n      </picture>\n\n      <!-- Playbutton - the UT-icon* is added by Utwente_base -->\n      <div class=\"wh-video__playbutton UT-icon-UT_icon_82_play-16px\"></div>\n    </div>\n\n    <!-- The embedded video player -->\n    <iframe frameborder=\"0\" allowfullscreen=\"\"\n            src=\"//utwente-test.video.yuja.com/V/Video?v=471208&amp;a=178921546\"\n            title=\"Video: ALD video audio adjusted\" style=\"width: 100%; height: 100%;\"></iframe>\n    </div>\n  </div>\n*/\n\nimport * as dompack from 'dompack';\nimport { getTid } from \"@mod-tollium/js/gettid\";\n\n// import \"./video.css\";\n// import \"../internal/rtd.lang.json\";\nimport \"@mod-publisher/js/richcontent/video.css\";\nimport \"@mod-publisher/js/internal/rtd.lang.json\";\n\nimport * as consenthandler from '@mod-publisher/js/analytics/consenthandler';\n\n\nconst youtubedomain = 'www.youtube.com';\n\n\n\nconst videonetworks_preload = [\"yuja\"];\n\n\n\nif (!window.__videosources)\n  window.__videosources = [];\n\n\nexport function registerVideoSource(source, options) {\n  options = { //getPlayerNode: null\n    getPlaybackURL: \"\",\n    ...options\n  };\n\n  window.__videosources.push({ tag: source, ...options });\n}\n\n\nfunction createMyFrame(options) {\n  const inert = options && options.inert;\n\n  const ifrm = document.createElement(\"iframe\");\n  ifrm.style.width = \"100%\";\n  ifrm.style.height = \"100%\";\n  ifrm.setAttribute(\"frameborder\", 0);\n  ifrm.setAttribute(\"allowfullscreen\", \"\");\n\n  // Prevent the user from interacting with the iframe (like using tab navigation to get the focus within the iframe and start the video)\n  if (inert)\n    ifrm.setAttribute(\"inert\", \"\");\n\n  // delegate autoplay (for Chrome) and fullscreen permission to the video player iframe\n  // https://developer.chrome.com/blog/autoplay/#iframe_delegation\n  ifrm.setAttribute(\"allow\", \"autoplay; fullscreen\");\n\n  return ifrm;\n}\n\nfunction initYouTube(node, video, playback) {\n  const ifrm = createMyFrame(playback);\n\n  // List of embed parameters YouTube supports:\n  // https://developers.google.com/youtube/player_parameters\n\n  const args = [];\n\n  if (playback.autoplay)\n    args.push(\"autoplay=1\");\n\n  if (video.mute || playback.mute)\n    args.push(\"mute=1\");\n\n  if (video.starttime)\n    args.push(\"start=\" + Math.floor(video.starttime)); // seconds, whole integer (YouTube also uses t= in the shorturl??)\n\n  if (video.endtime)\n    args.push(\"end=\" + Math.floor(video.endtime));\n\n  if (typeof playback.controls !== \"undefined\" && !playback.controls)\n    args.push(\"controls=0\");\n\n  if (video.loop || playback.loop) {\n    /* from the documentation: https://developers.google.com/youtube/player_parameters\n       Note: This parameter has limited support in IFrame embeds. To loop a single video,\n       set the loop parameter value to 1 and set the playlist parameter value to the\n       same video ID already specified in the Player API URL:\n       https://www.youtube.com/embed/VIDEO_ID?playlist=VIDEO_ID&loop=1\n    */\n    args.push(\"loop=1\", \"playlist=\" + video.id);//To enable loop, set same video as playlist\n  }\n\n  args.push(\"rel=0\", \"enablejsapi=1\", \"origin=\" + location.origin); // disable 'related video's'\n\n  let youtube_url = `//${youtubedomain}/embed/${video.id}`;\n  if (args.length > 0)\n    youtube_url += \"?\" + args.join(\"&\");\n\n  ifrm.src = youtube_url;\n  ifrm.title = video.title ? \"YouTube video: \" + video.title : \"YouTube video\";\n  node.appendChild(ifrm);\n}\n\nfunction initVimeo(node, video, playback) {\n  const ifrm = createMyFrame(playback);\n  const args = [];\n\n  // List of embed parameters Vimeo supports:\n  // https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Player-parameters-overview\n\n  if (playback.autoplay)\n    args.push(\"autoplay=1\");\n\n  if (video.mute || playback.mute)\n    args.push(\"muted=1\");\n\n  if (video.endtime)\n    console.warn(\"setting an endtime doesn't work for Vimeo video's\");\n\n  // NOTE: actually disabling controls is possible, but ONLY if the video is hosted by a Plus account or higher\n  // if (typeof playback.controls != \"undefined\" && !playback.controls)\n  if (playback.controls === false)\n    console.warn(\"disabling video controls not possible for Vimeo video's\");\n\n  if (video.loop || playback.loop)\n    args.push(\"loop=1\");\n\n  if (playback.background)\n    args.push(\"background=1\");\n\n  if (playback.api) {\n    args.push(\"api=\" + playback.api);\n\n    // we need a player_id to distinguish from which iframe a message came.\n    // (in cross domain situations we cannot lookup/compare the event source with iframe.contentWindow)\n    if (playback.player_id)\n      args.push(\"player_id=\" + playback.player_id);\n  }\n\n  let vimeo_url = \"//player.vimeo.com/video/\" + video.id;\n  if (args.length > 0)\n    vimeo_url += \"?\" + args.join(\"&\");\n\n  if (video.starttime) {\n    // #t=3m28s\n    const t = video.starttime;\n    const minutes = Math.floor(t / 60);\n    const seconds = t % 60;\n    vimeo_url += \"#t=\" + minutes + \"m\" + seconds + \"s\";\n  }\n\n  ifrm.src = vimeo_url;\n  ifrm.title = video.title ? \"Vimeo video: \" + video.title : \"Vimeo video\";\n  node.appendChild(ifrm);\n}\n\nfunction insertVideoPlayer(node, video, opts) {\n\n  const options =\n  {\n    inert: false,\n    ...opts\n  };\n\n  if (node.__initalized_iframe) {\n    console.info(\"Ignored insertVideoPlayer - iframe already generated.\");\n    return;\n  }\n\n  node.__initalized_iframe = true;\n  node.setAttribute(\"data-iframeloaded\", \"\");\n\n  console.log(\"insertVideoPlayer\", node.__initalized_iframe, node);\n\n  switch (video.network) {\n    case 'youtube':\n      initYouTube(node, video, options);\n      break;\n\n    case 'vimeo':\n      initVimeo(node, video, options);\n      break;\n\n    default:\n      {\n        const ifrm = createMyFrame(options);\n\n        // Lookup custom handlers\n        let use_handler = null;\n        for (const handler of window.__videosources) {\n          if (handler.tag === video.network) {\n            use_handler = handler;\n            break;\n          }\n        }\n\n        if (use_handler) {\n          // let node = use_handler.getPlayerNode(video, opts);\n          const playback_url = use_handler.getPlaybackURL(video, options);\n          ifrm.src = playback_url;\n          ifrm.title = video.title ? \"Video: \" + video.title : \"Video\";\n          node.appendChild(ifrm);\n        } else\n          console.warn(`Unknown video network \"${video.network}\".`);\n\n        break;\n      }\n  }\n}\n\nexport function initializeVideoElementV1(node) {\n  const video = JSON.parse(node.dataset.video);\n  const opts = node.dataset.videoOptions ? JSON.parse(node.dataset.videoOptions) : {};\n  node.innerHTML = '';\n  insertVideoPlayer(node, video, opts);\n}\n\n\nexport function initializeVideoElementV2(node) {\n  const video = JSON.parse(node.dataset.whVideo);\n\n  const videonodes = dompack.qSA(node, \".wh-video--activate\");\n\n  // (pre)load the iFrame for the specified networks (usually the Yuja player)\n  // so a click can directly start the video instead of requiring a second click).\n  if (videonetworks_preload.includes(video.network)) {\n    insertVideoPlayer(videonodes[0], video, { autoplay: false, inert: true });\n  }\n\n  for (const videonode of videonodes) {\n\n    videonode.__initialized = false;\n    videonode.__initalized_iframe = false;\n\n    // Make any click on the video area trigger the video to play/autoplay.\n    // (to increate the hitarea beyond the actual play button)\n    videonode.addEventListener(\"click\", function () {\n      activateVideo(videonode, video);\n    });\n\n    // FIXME: We should move to using <button>, because now we need to handle aria- and keyboard handing\n    //        BUT we don't get the default browser focus styling.\n\n    const playbutton = videonode.querySelector(\".wh-video__playbutton\");\n    playbutton.setAttribute(\"tabindex\", \"0\");\n    playbutton.setAttribute(\"role\", \"button\");\n    playbutton.setAttribute(\"aria-label\", getTid(\"publisher:site.rtd.embedvideo.playbutton-aria\"));\n\n    playbutton.addEventListener(\"click\", function () {\n      activateVideo(videonode, video, { autoplay: true });\n    });\n\n    // Because we don't use <button> we must implement it's keyboard interaction\n    playbutton.addEventListener(\"keypress\", function (evt) {\n      // we are only interested in enter and space keypressed\n      if (evt.keyCode !== 13 && evt.keyCode !== 32)\n        return;\n\n      // prevent other code getting the event or the space both triggering the video AND scrolling the page\n      evt.preventDefault();\n\n      activateVideo(videonode, video, { autoplay: true });\n    });\n\n    if (video.autoplay) //activate immediately\n      if (node.dataset.whConsentRequired)\n        consenthandler.onConsent(node.dataset.whConsentRequired, () => activateVideo(videonode, { ...video, mute: true }, { autoplay: true }));\n      else\n        activateVideo(videonode, { ...video, mute: true }, { autoplay: true });\n  }\n}\n\nfunction activateVideo(videonode, video, opts) {\n  if (videonode.__initialized)\n    return;\n\n  videonode.querySelector(\".wh-video__innerframe__preview\").hidden = true;\n  videonode.__initialized = true;\n\n  // console.log(\"videonode.__initalized_iframe\", videonode.__initalized_iframe, videonode.hasAttribute(\"data-iframeloaded\"));\n\n  // If the video iframe was already preloaded we can send a message to the player in the iFrame to start playback.\n  // This may hopefully also cause the play on the video to be triggered within the current click event, so it won't be blocked by the autoplay policy.\n  if (videonode.hasAttribute(\"data-iframeloaded\")) {\n    const iFrame = videonode.querySelector(\"iframe\");\n    iFrame.removeAttribute(\"inert\");\n\n    switch (video.network) {\n      case \"youtube\":\n        iFrame.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'playVideo' }), 'https://www.youtube.com');\n        break;\n      case \"yuja\":\n        iFrame.contentWindow.postMessage({ name: \"Play\" }, \"*\");\n        break;\n    }\n  } else\n    insertVideoPlayer(videonode, video, opts);\n}\n\n//dompack.register('.wh-video', node => node.dataset.video ? initializeVideoElementV1(node) : initializeVideoElementV2(node));\n","\nimport {\n  getTid as getTidFromJSSDK,\n  getTidLanguage,\n  setTidLanguage,\n  getHTMLTid,\n} from \"@webhare/gettid\";\nimport { registerTexts } from \"@webhare/gettid/src/internal\";\n\n// Fill nodes with a data-texttid attribute with the translated text\nfunction convertElementTids(scope = document.body) {\n  // Only available in a DOM context and if the DOM is ready\n  if (typeof document === \"undefined\" || !scope)\n    return;\n  Array.from(scope.querySelectorAll(\"*[data-texttid]\")).forEach(function (node) {\n    node.textContent = getTid(node.getAttribute(\"data-texttid\") || \"\");\n  });\n}\n\n// If this script is run within a DOM context, convert data-texttid attributes automatically\nif (typeof document !== \"undefined\")\n  document.addEventListener(\"DOMContentLoaded\", () => convertElementTids());\n\nconst getTid = ((...args: Parameters<typeof getTidFromJSSDK>): string => getTidFromJSSDK(...args)) as typeof getTidFromJSSDK & {\n  tidLanguage: string;\n  html: typeof getHTMLTid;\n};\n\n// Define 'tidLanguage' as a property on the main export (so you can use getTid.tidLanguage)\nObject.defineProperty(getTid, \"tidLanguage\", { get: getTidLanguage, set: setTidLanguage });\n// Define 'html' as a method on the main export (so you can use getTid.html)\ngetTid.html = getHTMLTid;\n\n// Export getTid as the default function, explicitly export getTid, getHTMLTid and registerTexts as well\nexport {\n  getTid as default,\n  getTid,\n  getTidLanguage,\n  setTidLanguage,\n  getHTMLTid,\n  convertElementTids,\n  registerTexts\n};\n","// Auto-generated language file from /opt/wh/whtree/modules/publisher/js/internal/rtd.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"publisher\",\"en\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"nl\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Speel video af\",\"unrecognized\":\"De URL is niet herkend als een ondersteunde video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"de\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"ar\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"bg\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"el\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"es\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"id\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"pt\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"ro\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\nregisterTexts(\"publisher\",\"zh\",{\"site\":{\"rtd\":{\"embedvideo\":{\"playbutton-aria\":\"Play video\",\"unrecognized\":\"The URL is not recognized as a supported video URL\",\"videourl\":\"Video URL\"}}}});\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/nl.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/de.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/ar.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/bg.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/el.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/es.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/id.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/pt.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/ro.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/zh.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"@webhare/dompack\";\nimport { debugFlags } from \"@webhare/env\";\nimport * as whintegration from \"@mod-system/js/wh/integration\";\n\nimport \"./theme.scss\";\n\n/* To give something an animated color, just set the color to var(--theme-color), var(--theme-color-cta) or var(--theme-color-cta-hover) */\n\nconst animDuration = whintegration.config.site.colorscheme.length * 10; // seconds\nconst animSteps = 5; // per second\nlet animDelay = 0; // seconds\n\nlet colorschemeNode, colorschemeCTANode, colorschemeCTAHoverNode;\n\nlet syncTimeout = null;\nlet curThemeColor, curThemeColorCTA, curThemeColorCTAHover;\n\n// Disable the color animation on Chrome for Android, see #2712\nconst browser = dompack.getBrowser();\nconst disableColorAnimation = browser.name === \"chrome\" && browser.platform === \"android\";\n\nfunction initializeTheme(node) {\n  colorschemeNode = node;\n  colorschemeCTANode = node.querySelector(\".theme__docstate-cta\");\n  colorschemeCTAHoverNode = node.querySelector(\".theme__docstate-cta-hover\");\n\n  if (!whintegration.config.site.animatethemecolor || whintegration.config.site.colorscheme.length <= 1) {\n    if (debugFlags.uds)\n      console.log(\"[uds] No color animation\", whintegration.config.site.animatethemecolor, whintegration.config.site.colorscheme);\n    return;\n  }\n\n  // Read the stored animation start to pick up where we left off\n  let saveStart = dompack.getLocal(\"ucs-start\");\n  if (saveStart) {\n    saveStart = (Date.now() - saveStart) % (animDuration * 1000);\n    if (saveStart > 0)\n      animDelay = -~~(saveStart / 1000);\n  } else\n    dompack.setLocal(\"ucs-start\", Date.now());\n\n  // Check if custom properties are supported\n  let registered = false;\n  if (window.CSS.registerProperty) {\n    try {\n      // If '@property' is not available (if it's available, it will have the fallback value), register explicity\n      if (!getComputedStyle(colorschemeNode).getPropertyValue(\"--theme-color\")) {\n        if (debugFlags.uds)\n          console.log(\"[uds] Register --theme-color* properties\");\n        window.CSS.registerProperty(\n        {\n          name: \"--theme-color\",\n          syntax: \"<color>\",\n          initialValue: \"transparent\",\n          inherits: false\n        });\n        window.CSS.registerProperty(\n        {\n          name: \"--theme-color-cta\",\n          syntax: \"<color>\",\n          initialValue: \"transparent\",\n          inherits: false\n        });\n        window.CSS.registerProperty(\n        {\n          name: \"--theme-color-cta-hover\",\n          syntax: \"<color>\",\n          initialValue: \"transparent\",\n          inherits: false\n        });\n      } else if (debugFlags.uds)\n        console.log(\"[uds] Using --theme-color* @property's\");\n\n      if (!disableColorAnimation && !debugFlags.unc) {\n        // Activate the 'colorscheme*' animations, which animate the defined --theme-color* properties\n        setAnimation(document.documentElement, [ \"colorscheme\", \"colorscheme-cta\", \"colorscheme-cta-hover\" ]);\n      }\n      // Set the colorscheme nodes background to the --theme-color* properties to visualize it\n      colorschemeNode.style.backgroundColor = \"var(--theme-color)\";\n      colorschemeCTANode.style.backgroundColor = \"var(--theme-color-cta)\";\n      colorschemeCTAHoverNode.style.backgroundColor = \"var(--theme-color-cta-hover)\";\n\n      registered = true;\n    } catch (e) {\n      if (debugFlags.uds)\n        console.error(\"[uds] Registration failed\", e);\n    }\n  }\n  if (!registered) {\n    if (debugFlags.uds)\n      console.log(\"[uds] @property and registerProperty not available, falling back to color sync\");\n\n    if (!disableColorAnimation && !debugFlags.unc) {\n      // Set the 'colorscheme-background*' animations to the colorscheme nodes, which update their background colors\n      setAnimation(colorschemeNode, \"colorscheme-background\");\n      setAnimation(colorschemeCTANode, \"colorscheme-background-cta\");\n      setAnimation(colorschemeCTAHoverNode, \"colorscheme-background-cta-hover\");\n      // Sync the colorscheme node background colors to the --theme-color* variables\n      window.setInterval(checkThemeColors, 1000 / animSteps);\n      // Initial sync\n      checkThemeColors();\n    }\n  }\n\n  if (disableColorAnimation || debugFlags.unc) {\n    // Color animation is disabled, fall back to 'Dogwood Rose' (which is the second color in the scheme; if there's only\n    // one color, there's no animation at all)\n    const randomColor = whintegration.config.site.colorscheme[1];\n    if (debugFlags.uds)\n      console.log(\"[uds] Color animation disabled, showing random color\", randomColor);\n    curThemeColor = randomColor;\n    curThemeColorCTA = randomColor;\n    curThemeColorCTAHover = randomColor;\n    setThemeColors();\n  }\n}\n\nfunction setAnimation(node, names) {\n  const playState = disableColorAnimation || debugFlags.unc ? \"paused\" : \"\";\n  // steps() works on each keyframe, which all last 10s, animSteps is in steps per second s\n  const animNames = Array.isArray(names) ? names : [ names ];\n  const animationStyle = animNames.map(name => `${name} ${animDuration}s ${animDelay}s steps(${animSteps * 10}, end) infinite ${playState}`).join(\", \");\n  node.style.animation = animationStyle;\n\n  // Workaround Safari/Firefix resetting animation delay\n  if (animDelay) {\n    const observer = new MutationObserver(()=> {\n      const curDelay = parseInt(node.style.animationDelay);\n      if (!curDelay) {\n        if (debugFlags.uds)\n          console.warn(`[uds] Resetting ${names} animation delay`, curDelay, animDelay);\n        node.style.animationDelay = `${animDelay}s`;\n      }\n      observer.disconnect();\n    });\n    observer.observe(node, { attributes: true, attributeFilter: [ \"style\" ] });\n  }\n}\n\nfunction checkThemeColors() {\n  syncTimeout = syncTimeout || requestAnimationFrame(syncThemeColors);\n}\n\nfunction syncThemeColors() {\n  syncTimeout = null;\n  const anyChanges = [];\n  // Get the current colorscheme node background colors and update the --theme-color* variables\n  let themeColor = getComputedStyle(colorschemeNode).backgroundColor;\n  if (themeColor !== curThemeColor) {\n    curThemeColor = themeColor;\n    anyChanges.push(\"color\");\n  }\n  themeColor = getComputedStyle(colorschemeCTANode).backgroundColor;\n  if (themeColor !== curThemeColorCTA) {\n    curThemeColorCTA = themeColor;\n    anyChanges.push(\"color-cta\");\n  }\n  themeColor = getComputedStyle(colorschemeCTAHoverNode).backgroundColor;\n  if (themeColor !== curThemeColorCTAHover) {\n    curThemeColorCTAHover = themeColor;\n    anyChanges.push(\"color-cta-hover\");\n  }\n  if (anyChanges.length)\n    setThemeColors(anyChanges);\n}\n\nfunction setThemeColors(props) {\n  if (curThemeColor && (!props || props.includes(\"color\")))\n    document.documentElement.style.setProperty(\"--theme-color\", curThemeColor);\n  if (curThemeColorCTA && (!props || props.includes(\"color-cta\")))\n    document.documentElement.style.setProperty(\"--theme-color-cta\", curThemeColorCTA);\n  if (curThemeColorCTAHover && (!props || props.includes(\"color-cta-hover\")))\n    document.documentElement.style.setProperty(\"--theme-color-cta-hover\", curThemeColorCTAHover);\n}\n\ndompack.register(\".theme__docstate\", node => initializeTheme(node));\n","import * as dompack from '../../index';\nimport * as dialogapi from '../../api/dialog';\n\ninterface DialogOptions extends dialogapi.DialogOptions {\n  theme?: string;\n}\n\nexport class BasicDialog extends dialogapi.DialogBase {\n  private _dialogclass: string;\n  holdernode: Element;\n  modalitynode: Element;\n\n  constructor(classname: string, options?: DialogOptions) {\n    super(options);\n    this._dialogclass = classname;\n\n    this.contentnode = dompack.create('div', { className: this._dialogclass });\n    this.holdernode = dompack.create('div',\n      {\n        className: this._dialogclass + \"__holder\",\n        childNodes: [this.contentnode]\n      });\n    this.modalitynode = dompack.create('div',\n      {\n        className: this._dialogclass + \"__modalbg\",\n        childNodes: [this.holdernode],\n        on: {\n          click: (evt: MouseEvent) => this._onModalityClick(evt),\n          wheel: (evt: WheelEvent) => dompack.stop(evt) //prevent scrolling modal-covered site using mousewheel\n        }\n      });\n\n    if (options?.theme)\n      this.modalitynode.classList.add(options.theme);\n  }\n\n  _openDialog() {\n    document.body.appendChild(this.modalitynode);\n  }\n\n  closeDialog() {\n    this.modalitynode.remove();\n    super.closeDialog();\n  }\n\n  _onModalityClick(evt: MouseEvent) {\n    if (this.holdernode.contains(evt.target as Node))\n      return; //event was targetted at our holder\n\n    dompack.stop(evt);\n    if (this.options.allowcancel)\n      this.resolve(null);\n  }\n\n  afterShow() {\n    dompack.registerMissed(this.holdernode);\n  }\n}\n\nexport function createDialog(classname: string, options?: DialogOptions) {\n  return new BasicDialog(classname, options);\n}\n","//@ts-nocheck TODO Fix me!\nimport \"./dialog.scss\";\nimport * as dialog from 'dompack/components/dialog';\nimport * as dialogapi from 'dompack/api/dialog';\nimport * as dompack from 'dompack';\nimport { getTid } from \"@webhare/gettid\";\nimport \"./dialog.lang.json\";\nimport PerfectScrollbar from \"@mod-utwente_design/vendor/perfect-scrollbar-wh\";\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// NEW UT DIALOG\n\nexport async function runYesNoMessageBox(question: string) {\n  //support linefeeds\n  const node = <span>{question.split('\\n').map(n => [n, <br />])}</span>;\n  return dialogapi.runMessageBox(node,\n    [\n      { result: \"yes\", title: getTid(\"utwente_base:site-common.texts.yes\") },\n      { result: \"no\", title: getTid(\"utwente_base:site-common.texts.no\") }\n    ], { allowcancel: true });\n}\n\nexport class UTDialog extends dialog.BasicDialog {\n  utheadernode = <div class=\"ut-dialog__header\"></div>;\n  ps;\n\n  constructor(options) {\n    super('ut-dialog', options);\n\n    if (options && options.allowcancel) {\n      const closebtn = <button class=\"ut-dialog--isclose ut-dialog__closeicon UT-icon-UT_icon_47_cross-16px\"\n        onClick={evt => { dompack.stop(evt); this.resolve(\"close\"); }}\n        aria-label={getTid(\"utwente_base:frontend.ws2016.js.dialog-close-arialabel\")}\n        type=\"button\"\n      ></button>;\n      this.holdernode.appendChild(closebtn);\n    }\n\n    this.contentnode!.before(this.utheadernode);\n    this.modalitynode?.addEventListener(\"wheel\", evt => dompack.stop(evt)); //TODO - remove once UT is WH 4.34+\n\n    if (!options || !options.nativescroll)\n      this.ps = new PerfectScrollbar(this.contentnode!, {\n        swipePropagation: false,\n        wheelPropagation: false,\n        suppressScrollX: true\n      });\n\n    const observer = new ResizeObserver(() => this._checkContents());\n    observer.observe(this.contentnode!);\n  }\n\n  afterShow() {\n    //basic animation\n    void (this.holdernode.clientHeight);//force css update\n    this.holdernode.classList.add(\"ut-dialog--aftershow\");\n\n    // We must either set focus to the new content or use aria-live to announce the new content.\n    // Otherwise the screenreader user may not know something has happened at all.\n    this.holdernode.setAttribute(\"tabindex\", \"-1\");\n    this.holdernode.focus();\n\n    dompack.qSA(this.holdernode, '.wh-form__button').forEach(button => button.classList.add('cta__button'));\n    dompack.registerMissed(this.holdernode);\n\n    if (this.ps)\n      setTimeout(() => this.ps.update(), 510); //update scrollbare after animation\n  }\n\n  _checkContents() {\n    // add the bottom 30px if the popup would need to scroll\n    this.holdernode.parentNode/*this.modalitynode*/.classList.toggle(\"ut-dialog--expanded\", this.contentnode.scrollHeight > this.contentnode.offsetHeight);\n\n    if (this.ps) // Update perfect scrollbar\n      this.ps.update();\n  }\n}\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// LEGACY UT DIALOG\n\n/*\n  Simple modal dialog\n*/\nfunction showModalDialog(title, contents, options) {\n  if (!options)\n    options = {};\n\n  let modalnode = document.querySelector(\".dialog__modal\");\n  if (modalnode)\n    hideModalDialog();//close previous dialog\n\n  modalnode = document.createElement(\"div\");\n  modalnode.className = \"dialog__modal\" + (options.theme ? \" \" + options.theme : \"\");\n\n  if (options.theme && modalnode.classList.contains(\"withbackground\")) {\n    if (options.background) {\n      modalnode.style.backgroundImage = \"url(\" + options.background + \")\";\n    } else { //get blurred background from header\n      const blurredbg = document.querySelector(\".header__photo-0--background\");\n      if (blurredbg) {\n        const bg = window.getComputedStyle(blurredbg, null).getPropertyValue(\"background-image\");\n        if (bg)\n          modalnode.style.backgroundImage = bg;\n      }\n    }\n  }\n\n  const bodynode = document.createElement(\"div\");\n  bodynode.className = \"dialog__body\";\n  modalnode.appendChild(bodynode);\n\n  if (title !== \"\") {\n    const titlenode = document.createElement(\"div\");\n    titlenode.className = \"title\";\n    titlenode.innerHTML = title;\n    bodynode.appendChild(titlenode);\n  }\n\n  if (!options.disable_close) {\n    const closebtn = document.createElement(\"button\");\n    closebtn.className = \"close UT-icon-UT_icon_47_cross-16px\";\n    closebtn.setAttribute(\"type\", \"button\");\n    closebtn.setAttribute(\"aria-label\", getTid(\"utwente_base:frontend.ws2016.js.dialog-close-arialabel\"));\n    /*\n          let closebtn = <button class=\"ut-dialog--isclose ut-dialog__closeicon UT-icon-UT_icon_47_cross-16px\"\n                                 onClick={ evt => { dompack.stop(evt); this.resolve(\"close\") }}\n                                 aria-label={}></button>;\n    */\n    if (options.position_close && options.position_close === \"outside\")\n      modalnode.appendChild(closebtn);\n    else\n      bodynode.appendChild(closebtn);\n  }\n\n  const contentnode = document.createElement(\"div\");\n  contentnode.className = \"dialog__content\";\n  bodynode.appendChild(contentnode);\n\n  if (typeof contents === \"object\")\n    contentnode.appendChild(contents);\n  else if (typeof contents === \"string\")\n    contentnode.innerHTML = contents;\n\n  if (!options.disable_close) {\n    modalnode.addEventListener('click', hideModalDialog);\n    document.body.addEventListener('keydown', hideModalDialog);\n  }\n\n  document.body.appendChild(modalnode);\n\n  //basic animation\n  // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n  bodynode.clientHeight;//force css update\n  modalnode.classList.add(\"aftershow\");\n\n  return modalnode;\n}\n\nfunction hideModalDialog(ev) {\n  const dialognode = document.querySelector(\".dialog__modal\");\n  if (!dialognode)\n    return;\n\n  if (ev) {\n    if (ev.type === 'keydown' && ev.keyCode !== 27)\n      return;\n    if (ev.type === 'click' && ev.target !== dialognode && !ev.target.classList.contains(\"close\"))\n      return;\n  }\n\n  document.body.removeEventListener('keydown', hideModalDialog);\n  dialognode.removeEventListener('click', hideModalDialog);\n  document.body.removeChild(dialognode);\n}\n\nexport { showModalDialog, hideModalDialog };\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/webdesigns/ws2016/src/shared/dialog/dialog.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_base\",\"en\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"nl\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accepteer\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"Om deze functionaliteit te gebruiken:\",\"no\":\"Nee\",\"yes\":\"Ja\"}}});\nregisterTexts(\"utwente_base\",\"de\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"akzeptieren\",\"cookies-cookies\":\"Cookies\",\"cookies-touse\":\"Zur Nutzung dieser Funktion:\",\"no\":\"Nein\",\"yes\":\"Ja\"}}});\nregisterTexts(\"utwente_base\",\"ar\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"bg\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"el\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"es\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"id\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"pt\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"ro\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\nregisterTexts(\"utwente_base\",\"zh\",{\"site-common\":{\"texts\":{\"cookies-accept\":\"Accept\",\"cookies-cookies\":\"cookies\",\"cookies-touse\":\"To use this functionality you first need to:\",\"no\":\"No\",\"yes\":\"Yes\"}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/ar.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/bg.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/el.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/es.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/id.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/pt.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/ro.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/zh.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n","export function get(element) {\n  return getComputedStyle(element);\n}\n\nexport function set(element, obj) {\n  for (const key in obj) {\n    let val = obj[key];\n    if (typeof val === 'number') {\n      val = `${val}px`;\n    }\n    element.style[key] = val;\n  }\n  return element;\n}\n","export function div(className) {\n  const div = document.createElement('div');\n  div.className = className;\n  return div;\n}\n\nconst elMatches =\n  typeof Element !== 'undefined' &&\n  (Element.prototype.matches ||\n    Element.prototype.webkitMatchesSelector ||\n    Element.prototype.mozMatchesSelector ||\n    Element.prototype.msMatchesSelector);\n\nexport function matches(element, query) {\n  if (!elMatches) {\n    throw new Error('No element matching method supported');\n  }\n\n  return elMatches.call(element, query);\n}\n\nexport function remove(element) {\n  if (element.remove) {\n    element.remove();\n  } else {\n    if (element.parentNode) {\n      element.parentNode.removeChild(element);\n    }\n  }\n}\n\nexport function queryChildren(element, selector) {\n  return Array.prototype.filter.call(element.children, child =>\n    matches(child, selector)\n  );\n}\n","const cls = {\n  main: 'ps',\n  rtl: 'ps__rtl',\n  element: {\n    thumb: x => `ps__thumb-${x}`,\n    rail: x => `ps__rail-${x}`,\n    consuming: 'ps__child--consume',\n  },\n  state: {\n    focus: 'ps--focus',\n    clicking: 'ps--clicking',\n    active: x => `ps--active-${x}`,\n    scrolling: x => `ps--scrolling-${x}`,\n  },\n};\n\nexport default cls;\n\n/*\n * Helper methods\n */\nconst scrollingClassTimeout = { x: null, y: null };\n\nexport function addScrollingClass(i, x) {\n  const classList = i.element.classList;\n  const className = cls.state.scrolling(x);\n\n  if (classList.contains(className)) {\n    clearTimeout(scrollingClassTimeout[x]);\n  } else {\n    classList.add(className);\n  }\n}\n\nexport function removeScrollingClass(i, x) {\n  scrollingClassTimeout[x] = setTimeout(\n    () => i.isAlive && i.element.classList.remove(cls.state.scrolling(x)),\n    i.settings.scrollingThreshold\n  );\n}\n\nexport function setScrollingClassInstantly(i, x) {\n  addScrollingClass(i, x);\n  removeScrollingClass(i, x);\n}\n","class EventElement {\n  constructor(element) {\n    this.element = element;\n    this.handlers = {};\n  }\n\n  bind(eventName, handler) {\n    if (typeof this.handlers[eventName] === 'undefined') {\n      this.handlers[eventName] = [];\n    }\n    this.handlers[eventName].push(handler);\n    this.element.addEventListener(eventName, handler, false);\n  }\n\n  unbind(eventName, target) {\n    this.handlers[eventName] = this.handlers[eventName].filter(handler => {\n      if (target && handler !== target) {\n        return true;\n      }\n      this.element.removeEventListener(eventName, handler, false);\n      return false;\n    });\n  }\n\n  unbindAll() {\n    for (const name in this.handlers) {\n      this.unbind(name);\n    }\n  }\n\n  get isEmpty() {\n    return Object.keys(this.handlers).every(\n      key => this.handlers[key].length === 0\n    );\n  }\n}\n\nexport default class EventManager {\n  constructor() {\n    this.eventElements = [];\n  }\n\n  eventElement(element) {\n    let ee = this.eventElements.filter(ee => ee.element === element)[0];\n    if (!ee) {\n      ee = new EventElement(element);\n      this.eventElements.push(ee);\n    }\n    return ee;\n  }\n\n  bind(element, eventName, handler) {\n    this.eventElement(element).bind(eventName, handler);\n  }\n\n  unbind(element, eventName, handler) {\n    const ee = this.eventElement(element);\n    ee.unbind(eventName, handler);\n\n    if (ee.isEmpty) {\n      // remove\n      this.eventElements.splice(this.eventElements.indexOf(ee), 1);\n    }\n  }\n\n  unbindAll() {\n    this.eventElements.forEach(e => e.unbindAll());\n    this.eventElements = [];\n  }\n\n  once(element, eventName, handler) {\n    const ee = this.eventElement(element);\n    const onceHandler = evt => {\n      ee.unbind(eventName, onceHandler);\n      handler(evt);\n    };\n    ee.bind(eventName, onceHandler);\n  }\n}\n","import { setScrollingClassInstantly } from './lib/class-names';\n\nfunction createEvent(name) {\n  if (typeof window.CustomEvent === 'function') {\n    return new CustomEvent(name);\n  } else {\n    const evt = document.createEvent('CustomEvent');\n    evt.initCustomEvent(name, false, false, undefined);\n    return evt;\n  }\n}\n\nexport default function(\n  i,\n  axis,\n  diff,\n  useScrollingClass = true,\n  forceFireReachEvent = false\n) {\n  let fields;\n  if (axis === 'top') {\n    fields = [\n      'contentHeight',\n      'containerHeight',\n      'scrollTop',\n      'y',\n      'up',\n      'down',\n    ];\n  } else if (axis === 'left') {\n    fields = [\n      'contentWidth',\n      'containerWidth',\n      'scrollLeft',\n      'x',\n      'left',\n      'right',\n    ];\n  } else {\n    throw new Error('A proper axis should be provided');\n  }\n\n  processScrollDiff(i, diff, fields, useScrollingClass, forceFireReachEvent);\n}\n\nfunction processScrollDiff(\n  i,\n  diff,\n  [contentHeight, containerHeight, scrollTop, y, up, down],\n  useScrollingClass = true,\n  forceFireReachEvent = false\n) {\n  const element = i.element;\n\n  // reset reach\n  i.reach[y] = null;\n\n  // 1 for subpixel rounding\n  if (element[scrollTop] < 1) {\n    i.reach[y] = 'start';\n  }\n\n  // 1 for subpixel rounding\n  if (element[scrollTop] > i[contentHeight] - i[containerHeight] - 1) {\n    i.reach[y] = 'end';\n  }\n\n  if (diff) {\n    element.dispatchEvent(createEvent(`ps-scroll-${y}`));\n\n    if (diff < 0) {\n      element.dispatchEvent(createEvent(`ps-scroll-${up}`));\n    } else if (diff > 0) {\n      element.dispatchEvent(createEvent(`ps-scroll-${down}`));\n    }\n\n    if (useScrollingClass) {\n      setScrollingClassInstantly(i, y);\n    }\n  }\n\n  if (i.reach[y] && (diff || forceFireReachEvent)) {\n    element.dispatchEvent(createEvent(`ps-${y}-reach-${i.reach[y]}`));\n  }\n}\n","import * as CSS from './css';\nimport * as DOM from './dom';\n\nexport function toInt(x) {\n  return parseInt(x, 10) || 0;\n}\n\nexport function isEditable(el) {\n  return (\n    DOM.matches(el, 'input,[contenteditable]') ||\n    DOM.matches(el, 'select,[contenteditable]') ||\n    DOM.matches(el, 'textarea,[contenteditable]') ||\n    DOM.matches(el, 'button,[contenteditable]')\n  );\n}\n\nexport function outerWidth(element) {\n  const styles = CSS.get(element);\n  return (\n    toInt(styles.width) +\n    toInt(styles.paddingLeft) +\n    toInt(styles.paddingRight) +\n    toInt(styles.borderLeftWidth) +\n    toInt(styles.borderRightWidth)\n  );\n}\n\nexport const env = {\n  isWebKit:\n    typeof document !== 'undefined' &&\n    'WebkitAppearance' in document.documentElement.style,\n  supportsTouch:\n    typeof window !== 'undefined' &&\n    ('ontouchstart' in window ||\n      ('maxTouchPoints' in window.navigator &&\n        window.navigator.maxTouchPoints > 0) ||\n      (window.DocumentTouch && document instanceof window.DocumentTouch)),\n  supportsIePointer:\n    typeof navigator !== 'undefined' && navigator.msMaxTouchPoints,\n  isChrome:\n    typeof navigator !== 'undefined' &&\n    /Chrome/i.test(navigator && navigator.userAgent),\n};\n","import * as CSS from './lib/css';\nimport * as DOM from './lib/dom';\nimport cls from './lib/class-names';\nimport { toInt } from './lib/util';\n\nexport default function(i) {\n  const element = i.element;\n  const roundedScrollTop = Math.floor(element.scrollTop);\n  const rect = element.getBoundingClientRect();\n\n  i.containerWidth = Math.round(rect.width);\n  i.containerHeight = Math.round(rect.height);\n\n  i.contentWidth = element.scrollWidth;\n  i.contentHeight = element.scrollHeight;\n\n  if (!element.contains(i.scrollbarXRail)) {\n    // clean up and append\n    DOM.queryChildren(element, cls.element.rail('x')).forEach(el =>\n      DOM.remove(el)\n    );\n    element.appendChild(i.scrollbarXRail);\n  }\n  if (!element.contains(i.scrollbarYRail)) {\n    // clean up and append\n    DOM.queryChildren(element, cls.element.rail('y')).forEach(el =>\n      DOM.remove(el)\n    );\n    element.appendChild(i.scrollbarYRail);\n  }\n\n  if (\n    !i.settings.suppressScrollX &&\n    i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth\n  ) {\n    i.scrollbarXActive = true;\n    i.railXWidth = i.containerWidth - i.railXMarginWidth;\n    i.railXRatio = i.containerWidth / i.railXWidth;\n    i.scrollbarXWidth = getThumbSize(\n      i,\n      toInt((i.railXWidth * i.containerWidth) / i.contentWidth)\n    );\n    i.scrollbarXLeft = toInt(\n      ((i.negativeScrollAdjustment + element.scrollLeft) *\n        (i.railXWidth - i.scrollbarXWidth)) /\n        (i.contentWidth - i.containerWidth)\n    );\n  } else {\n    i.scrollbarXActive = false;\n  }\n\n  if (\n    !i.settings.suppressScrollY &&\n    i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight\n  ) {\n    i.scrollbarYActive = true;\n    i.railYHeight = i.containerHeight - i.railYMarginHeight;\n    i.railYRatio = i.containerHeight / i.railYHeight;\n    i.scrollbarYHeight = getThumbSize(\n      i,\n      toInt((i.railYHeight * i.containerHeight) / i.contentHeight)\n    );\n    i.scrollbarYTop = toInt(\n      (roundedScrollTop * (i.railYHeight - i.scrollbarYHeight)) /\n        (i.contentHeight - i.containerHeight)\n    );\n  } else {\n    i.scrollbarYActive = false;\n  }\n\n  if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {\n    i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;\n  }\n  if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {\n    i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;\n  }\n\n  updateCss(element, i);\n\n  if (i.scrollbarXActive) {\n    element.classList.add(cls.state.active('x'));\n  } else {\n    element.classList.remove(cls.state.active('x'));\n    i.scrollbarXWidth = 0;\n    i.scrollbarXLeft = 0;\n    element.scrollLeft = i.isRtl === true ? i.contentWidth : 0;\n  }\n  if (i.scrollbarYActive) {\n    element.classList.add(cls.state.active('y'));\n  } else {\n    element.classList.remove(cls.state.active('y'));\n    i.scrollbarYHeight = 0;\n    i.scrollbarYTop = 0;\n    element.scrollTop = 0;\n  }\n}\n\nfunction getThumbSize(i, thumbSize) {\n  if (i.settings.minScrollbarLength) {\n    thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);\n  }\n  if (i.settings.maxScrollbarLength) {\n    thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);\n  }\n  return thumbSize;\n}\n\nfunction updateCss(element, i) {\n  const xRailOffset = { width: i.railXWidth };\n  const roundedScrollTop = Math.floor(element.scrollTop);\n\n  if (i.isRtl) {\n    xRailOffset.left =\n      i.negativeScrollAdjustment +\n      element.scrollLeft +\n      i.containerWidth -\n      i.contentWidth;\n  } else {\n    xRailOffset.left = element.scrollLeft;\n  }\n  if (i.isScrollbarXUsingBottom) {\n    xRailOffset.bottom = i.scrollbarXBottom - roundedScrollTop;\n  } else {\n    xRailOffset.top = i.scrollbarXTop + roundedScrollTop;\n  }\n  CSS.set(i.scrollbarXRail, xRailOffset);\n\n  const yRailOffset = { top: roundedScrollTop, height: i.railYHeight };\n  if (i.isScrollbarYUsingRight) {\n    if (i.isRtl) {\n      yRailOffset.right =\n        i.contentWidth -\n        (i.negativeScrollAdjustment + element.scrollLeft) -\n        i.scrollbarYRight -\n        i.scrollbarYOuterWidth -\n        9;\n    } else {\n      yRailOffset.right = i.scrollbarYRight - element.scrollLeft;\n    }\n  } else {\n    if (i.isRtl) {\n      yRailOffset.left =\n        i.negativeScrollAdjustment +\n        element.scrollLeft +\n        i.containerWidth * 2 -\n        i.contentWidth -\n        i.scrollbarYLeft -\n        i.scrollbarYOuterWidth;\n    } else {\n      yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;\n    }\n  }\n  CSS.set(i.scrollbarYRail, yRailOffset);\n\n  CSS.set(i.scrollbarX, {\n    left: i.scrollbarXLeft,\n    width: i.scrollbarXWidth - i.railBorderXWidth,\n  });\n  CSS.set(i.scrollbarY, {\n    top: i.scrollbarYTop,\n    height: i.scrollbarYHeight - i.railBorderYWidth,\n  });\n}\n","import updateGeometry from '../update-geometry';\n\nexport default function(i) {\n  const element = i.element;\n\n  i.event.bind(i.scrollbarY, 'mousedown', e => e.stopPropagation());\n  i.event.bind(i.scrollbarYRail, 'mousedown', e => {\n    const positionTop =\n      e.pageY -\n      window.pageYOffset -\n      i.scrollbarYRail.getBoundingClientRect().top;\n    const direction = positionTop > i.scrollbarYTop ? 1 : -1;\n\n    i.element.scrollTop += direction * i.containerHeight;\n    updateGeometry(i);\n\n    e.stopPropagation();\n  });\n\n  i.event.bind(i.scrollbarX, 'mousedown', e => e.stopPropagation());\n  i.event.bind(i.scrollbarXRail, 'mousedown', e => {\n    const positionLeft =\n      e.pageX -\n      window.pageXOffset -\n      i.scrollbarXRail.getBoundingClientRect().left;\n    const direction = positionLeft > i.scrollbarXLeft ? 1 : -1;\n\n    i.element.scrollLeft += direction * i.containerWidth;\n    updateGeometry(i);\n\n    e.stopPropagation();\n  });\n}\n","import * as CSS from '../lib/css';\nimport * as DOM from '../lib/dom';\nimport cls, {\n  addScrollingClass,\n  removeScrollingClass,\n} from '../lib/class-names';\nimport updateGeometry from '../update-geometry';\nimport { toInt } from '../lib/util';\n\nexport default function(i) {\n  bindMouseScrollHandler(i, [\n    'containerWidth',\n    'contentWidth',\n    'pageX',\n    'railXWidth',\n    'scrollbarX',\n    'scrollbarXWidth',\n    'scrollLeft',\n    'x',\n    'scrollbarXRail',\n  ]);\n  bindMouseScrollHandler(i, [\n    'containerHeight',\n    'contentHeight',\n    'pageY',\n    'railYHeight',\n    'scrollbarY',\n    'scrollbarYHeight',\n    'scrollTop',\n    'y',\n    'scrollbarYRail',\n  ]);\n}\n\nfunction bindMouseScrollHandler(\n  i,\n  [\n    containerHeight,\n    contentHeight,\n    pageY,\n    railYHeight,\n    scrollbarY,\n    scrollbarYHeight,\n    scrollTop,\n    y,\n    scrollbarYRail,\n  ]\n) {\n  const element = i.element;\n\n  let startingScrollTop = null;\n  let startingMousePageY = null;\n  let scrollBy = null;\n\n  function mouseMoveHandler(e) {\n    if (e.touches && e.touches[0]) {\n      e[pageY] = e.touches[0].pageY;\n    }\n    element[scrollTop] =\n      startingScrollTop + scrollBy * (e[pageY] - startingMousePageY);\n    addScrollingClass(i, y);\n    updateGeometry(i);\n\n    e.stopPropagation();\n    if (e.type.startsWith('touch') && e.changedTouches.length > 1) {\n      e.preventDefault();\n    }\n  }\n\n  function mouseUpHandler() {\n    removeScrollingClass(i, y);\n    i[scrollbarYRail].classList.remove(cls.state.clicking);\n    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);\n  }\n\n  function bindMoves(e, touchMode) {\n    startingScrollTop = element[scrollTop];\n    if (touchMode && e.touches) {\n      e[pageY] = e.touches[0].pageY;\n    }\n    startingMousePageY = e[pageY];\n    scrollBy =\n      (i[contentHeight] - i[containerHeight]) /\n      (i[railYHeight] - i[scrollbarYHeight]);\n    if (!touchMode) {\n      i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);\n      i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);\n      e.preventDefault();\n    } else {\n      i.event.bind(i.ownerDocument, 'touchmove', mouseMoveHandler);\n    }\n\n    i[scrollbarYRail].classList.add(cls.state.clicking);\n\n    e.stopPropagation();\n  }\n\n  i.event.bind(i[scrollbarY], 'mousedown', e => {\n    bindMoves(e);\n  });\n  i.event.bind(i[scrollbarY], 'touchstart', e => {\n    bindMoves(e, true);\n  });\n}\n","import * as DOM from '../lib/dom';\nimport updateGeometry from '../update-geometry';\nimport { isEditable } from '../lib/util';\n\nexport default function(i) {\n  const element = i.element;\n\n  const elementHovered = () => DOM.matches(element, ':hover');\n  const scrollbarFocused = () =>\n    DOM.matches(i.scrollbarX, ':focus') || DOM.matches(i.scrollbarY, ':focus');\n\n  function shouldPreventDefault(deltaX, deltaY) {\n    const scrollTop = Math.floor(element.scrollTop);\n    if (deltaX === 0) {\n      if (!i.scrollbarYActive) {\n        return false;\n      }\n      if (\n        (scrollTop === 0 && deltaY > 0) ||\n        (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)\n      ) {\n        return !i.settings.wheelPropagation;\n      }\n    }\n\n    const scrollLeft = element.scrollLeft;\n    if (deltaY === 0) {\n      if (!i.scrollbarXActive) {\n        return false;\n      }\n      if (\n        (scrollLeft === 0 && deltaX < 0) ||\n        (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)\n      ) {\n        return !i.settings.wheelPropagation;\n      }\n    }\n    return true;\n  }\n\n  i.event.bind(i.ownerDocument, 'keydown', e => {\n    if (\n      (e.isDefaultPrevented && e.isDefaultPrevented()) ||\n      e.defaultPrevented\n    ) {\n      return;\n    }\n\n    if (!elementHovered() && !scrollbarFocused()) {\n      return;\n    }\n\n    let activeElement = document.activeElement\n      ? document.activeElement\n      : i.ownerDocument.activeElement;\n    if (activeElement) {\n      if (activeElement.tagName === 'IFRAME') {\n        activeElement = activeElement.contentDocument.activeElement;\n      } else {\n        // go deeper if element is a webcomponent\n        while (activeElement.shadowRoot) {\n          activeElement = activeElement.shadowRoot.activeElement;\n        }\n      }\n      if (isEditable(activeElement)) {\n        return;\n      }\n    }\n\n    let deltaX = 0;\n    let deltaY = 0;\n\n    switch (e.which) {\n      case 37: // left\n        if (e.metaKey) {\n          deltaX = -i.contentWidth;\n        } else if (e.altKey) {\n          deltaX = -i.containerWidth;\n        } else {\n          deltaX = -30;\n        }\n        break;\n      case 38: // up\n        if (e.metaKey) {\n          deltaY = i.contentHeight;\n        } else if (e.altKey) {\n          deltaY = i.containerHeight;\n        } else {\n          deltaY = 30;\n        }\n        break;\n      case 39: // right\n        if (e.metaKey) {\n          deltaX = i.contentWidth;\n        } else if (e.altKey) {\n          deltaX = i.containerWidth;\n        } else {\n          deltaX = 30;\n        }\n        break;\n      case 40: // down\n        if (e.metaKey) {\n          deltaY = -i.contentHeight;\n        } else if (e.altKey) {\n          deltaY = -i.containerHeight;\n        } else {\n          deltaY = -30;\n        }\n        break;\n      case 32: // space bar\n        if (e.shiftKey) {\n          deltaY = i.containerHeight;\n        } else {\n          deltaY = -i.containerHeight;\n        }\n        break;\n      case 33: // page up\n        deltaY = i.containerHeight;\n        break;\n      case 34: // page down\n        deltaY = -i.containerHeight;\n        break;\n      case 36: // home\n        deltaY = i.contentHeight;\n        break;\n      case 35: // end\n        deltaY = -i.contentHeight;\n        break;\n      default:\n        return;\n    }\n\n    if (i.settings.suppressScrollX && deltaX !== 0) {\n      return;\n    }\n    if (i.settings.suppressScrollY && deltaY !== 0) {\n      return;\n    }\n\n    element.scrollTop -= deltaY;\n    element.scrollLeft += deltaX;\n    updateGeometry(i);\n\n    if (shouldPreventDefault(deltaX, deltaY)) {\n      e.preventDefault();\n    }\n  });\n}\n","import * as CSS from '../lib/css';\nimport cls from '../lib/class-names';\nimport updateGeometry from '../update-geometry';\nimport { env } from '../lib/util';\n\nexport default function(i) {\n  const element = i.element;\n\n  let shouldPrevent = false;\n\n  function shouldPreventDefault(deltaX, deltaY) {\n    const roundedScrollTop = Math.floor(element.scrollTop);\n    const isTop = element.scrollTop === 0;\n    const isBottom =\n      roundedScrollTop + element.offsetHeight === element.scrollHeight;\n    const isLeft = element.scrollLeft === 0;\n    const isRight =\n      element.scrollLeft + element.offsetWidth === element.scrollWidth;\n\n    let hitsBound;\n\n    // pick axis with primary direction\n    if (Math.abs(deltaY) > Math.abs(deltaX)) {\n      hitsBound = isTop || isBottom;\n    } else {\n      hitsBound = isLeft || isRight;\n    }\n\n    return hitsBound ? !i.settings.wheelPropagation : true;\n  }\n\n  function getDeltaFromEvent(e) {\n    let deltaX = e.deltaX;\n    let deltaY = -1 * e.deltaY;\n\n    if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {\n      // OS X Safari\n      deltaX = (-1 * e.wheelDeltaX) / 6;\n      deltaY = e.wheelDeltaY / 6;\n    }\n\n    if (e.deltaMode && e.deltaMode === 1) {\n      // Firefox in deltaMode 1: Line scrolling\n      deltaX *= 10;\n      deltaY *= 10;\n    }\n\n    if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) {\n      // IE in some mouse drivers\n      deltaX = 0;\n      deltaY = e.wheelDelta;\n    }\n\n    if (e.shiftKey) {\n      // reverse axis with shift key\n      return [-deltaY, -deltaX];\n    }\n    return [deltaX, deltaY];\n  }\n\n  function shouldBeConsumedByChild(target, deltaX, deltaY) {\n    // FIXME: this is a workaround for <select> issue in FF and IE #571\n    if (!env.isWebKit && element.querySelector('select:focus')) {\n      return true;\n    }\n\n    if (!element.contains(target)) {\n      return false;\n    }\n\n    let cursor = target;\n\n    while (cursor && cursor !== element) {\n      if (cursor.classList.contains(cls.element.consuming)) {\n        return true;\n      }\n\n      const style = CSS.get(cursor);\n\n      // if deltaY && vertical scrollable\n      if (deltaY && style.overflowY.match(/(scroll|auto)/)) {\n        const maxScrollTop = cursor.scrollHeight - cursor.clientHeight;\n        if (maxScrollTop > 0) {\n          if (\n            (cursor.scrollTop > 0 && deltaY < 0) ||\n            (cursor.scrollTop < maxScrollTop && deltaY > 0)\n          ) {\n            return true;\n          }\n        }\n      }\n      // if deltaX && horizontal scrollable\n      if (deltaX && style.overflowX.match(/(scroll|auto)/)) {\n        const maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;\n        if (maxScrollLeft > 0) {\n          if (\n            (cursor.scrollLeft > 0 && deltaX < 0) ||\n            (cursor.scrollLeft < maxScrollLeft && deltaX > 0)\n          ) {\n            return true;\n          }\n        }\n      }\n\n      cursor = cursor.parentNode;\n    }\n\n    return false;\n  }\n\n  function mousewheelHandler(e) {\n    const [deltaX, deltaY] = getDeltaFromEvent(e);\n\n    if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {\n      return;\n    }\n\n    let shouldPrevent = false;\n    if (!i.settings.useBothWheelAxes) {\n      // deltaX will only be used for horizontal scrolling and deltaY will\n      // only be used for vertical scrolling - this is the default\n      element.scrollTop -= deltaY * i.settings.wheelSpeed;\n      element.scrollLeft += deltaX * i.settings.wheelSpeed;\n    } else if (i.scrollbarYActive && !i.scrollbarXActive) {\n      // only vertical scrollbar is active and useBothWheelAxes option is\n      // active, so let's scroll vertical bar using both mouse wheel axes\n      if (deltaY) {\n        element.scrollTop -= deltaY * i.settings.wheelSpeed;\n      } else {\n        element.scrollTop += deltaX * i.settings.wheelSpeed;\n      }\n      shouldPrevent = true;\n    } else if (i.scrollbarXActive && !i.scrollbarYActive) {\n      // useBothWheelAxes and only horizontal bar is active, so use both\n      // wheel axes for horizontal bar\n      if (deltaX) {\n        element.scrollLeft += deltaX * i.settings.wheelSpeed;\n      } else {\n        element.scrollLeft -= deltaY * i.settings.wheelSpeed;\n      }\n      shouldPrevent = true;\n    }\n\n    updateGeometry(i);\n\n    shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);\n    if (shouldPrevent && !e.ctrlKey) {\n      e.stopPropagation();\n      e.preventDefault();\n    }\n  }\n\n  if (typeof window.onwheel !== 'undefined') {\n    i.event.bind(element, 'wheel', mousewheelHandler);\n  } else if (typeof window.onmousewheel !== 'undefined') {\n    i.event.bind(element, 'mousewheel', mousewheelHandler);\n  }\n}\n","import updateGeometry from '../update-geometry';\nimport cls from '../lib/class-names';\nimport * as CSS from '../lib/css';\nimport { env } from '../lib/util';\n\nexport default function(i) {\n  if (!env.supportsTouch && !env.supportsIePointer) {\n    return;\n  }\n\n  const element = i.element;\n\n  function shouldPrevent(deltaX, deltaY) {\n    const scrollTop = Math.floor(element.scrollTop);\n    const scrollLeft = element.scrollLeft;\n    const magnitudeX = Math.abs(deltaX);\n    const magnitudeY = Math.abs(deltaY);\n\n    if (magnitudeY > magnitudeX) {\n      // user is perhaps trying to swipe up/down the page\n\n      if (\n        (deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) ||\n        (deltaY > 0 && scrollTop === 0)\n      ) {\n        // set prevent for mobile Chrome refresh\n        return window.scrollY === 0 && deltaY > 0 && env.isChrome;\n      }\n    } else if (magnitudeX > magnitudeY) {\n      // user is perhaps trying to swipe left/right across the page\n\n      if (\n        (deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) ||\n        (deltaX > 0 && scrollLeft === 0)\n      ) {\n        return true;\n      }\n    }\n\n    return true;\n  }\n\n  function applyTouchMove(differenceX, differenceY) {\n    element.scrollTop -= differenceY;\n    element.scrollLeft -= differenceX;\n\n    updateGeometry(i);\n  }\n\n  let startOffset = {};\n  let startTime = 0;\n  let speed = {};\n  let easingLoop = null;\n\n  function getTouch(e) {\n    if (e.targetTouches) {\n      return e.targetTouches[0];\n    } else {\n      // Maybe IE pointer\n      return e;\n    }\n  }\n\n  function shouldHandle(e) {\n    if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) {\n      return false;\n    }\n    if (e.targetTouches && e.targetTouches.length === 1) {\n      return true;\n    }\n    if (\n      e.pointerType &&\n      e.pointerType !== 'mouse' &&\n      e.pointerType !== e.MSPOINTER_TYPE_MOUSE\n    ) {\n      return true;\n    }\n    return false;\n  }\n\n  function touchStart(e) {\n    if (!shouldHandle(e)) {\n      return;\n    }\n\n    const touch = getTouch(e);\n\n    startOffset.pageX = touch.pageX;\n    startOffset.pageY = touch.pageY;\n\n    startTime = new Date().getTime();\n\n    if (easingLoop !== null) {\n      clearInterval(easingLoop);\n    }\n  }\n\n  function shouldBeConsumedByChild(target, deltaX, deltaY) {\n    if (!element.contains(target)) {\n      return false;\n    }\n\n    let cursor = target;\n\n    while (cursor && cursor !== element) {\n      if (cursor.classList.contains(cls.element.consuming)) {\n        return true;\n      }\n\n      const style = CSS.get(cursor);\n\n      // if deltaY && vertical scrollable\n      if (deltaY && style.overflowY.match(/(scroll|auto)/)) {\n        const maxScrollTop = cursor.scrollHeight - cursor.clientHeight;\n        if (maxScrollTop > 0) {\n          if (\n            (cursor.scrollTop > 0 && deltaY < 0) ||\n            (cursor.scrollTop < maxScrollTop && deltaY > 0)\n          ) {\n            return true;\n          }\n        }\n      }\n      // if deltaX && horizontal scrollable\n      if (deltaX && style.overflowX.match(/(scroll|auto)/)) {\n        const maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;\n        if (maxScrollLeft > 0) {\n          if (\n            (cursor.scrollLeft > 0 && deltaX < 0) ||\n            (cursor.scrollLeft < maxScrollLeft && deltaX > 0)\n          ) {\n            return true;\n          }\n        }\n      }\n\n      cursor = cursor.parentNode;\n    }\n\n    return false;\n  }\n\n  function touchMove(e) {\n    if (shouldHandle(e)) {\n      const touch = getTouch(e);\n\n      const currentOffset = { pageX: touch.pageX, pageY: touch.pageY };\n\n      const differenceX = currentOffset.pageX - startOffset.pageX;\n      const differenceY = currentOffset.pageY - startOffset.pageY;\n\n      if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) {\n        return;\n      }\n\n      applyTouchMove(differenceX, differenceY);\n      startOffset = currentOffset;\n\n      const currentTime = new Date().getTime();\n\n      const timeGap = currentTime - startTime;\n      if (timeGap > 0) {\n        speed.x = differenceX / timeGap;\n        speed.y = differenceY / timeGap;\n        startTime = currentTime;\n      }\n\n      if (shouldPrevent(differenceX, differenceY)) {\n        e.preventDefault();\n      }\n    }\n  }\n  function touchEnd() {\n    if (i.settings.swipeEasing) {\n      clearInterval(easingLoop);\n      easingLoop = setInterval(function() {\n        if (i.isInitialized) {\n          clearInterval(easingLoop);\n          return;\n        }\n\n        if (!speed.x && !speed.y) {\n          clearInterval(easingLoop);\n          return;\n        }\n\n        if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {\n          clearInterval(easingLoop);\n          return;\n        }\n\n        if (!i.element) {\n          clearInterval(easingLoop);\n          return;\n        }\n\n        applyTouchMove(speed.x * 30, speed.y * 30);\n\n        speed.x *= 0.8;\n        speed.y *= 0.8;\n      }, 10);\n    }\n  }\n\n  if (env.supportsTouch) {\n    i.event.bind(element, 'touchstart', touchStart);\n    i.event.bind(element, 'touchmove', touchMove);\n    i.event.bind(element, 'touchend', touchEnd);\n  } else if (env.supportsIePointer) {\n    if (window.PointerEvent) {\n      i.event.bind(element, 'pointerdown', touchStart);\n      i.event.bind(element, 'pointermove', touchMove);\n      i.event.bind(element, 'pointerup', touchEnd);\n    } else if (window.MSPointerEvent) {\n      i.event.bind(element, 'MSPointerDown', touchStart);\n      i.event.bind(element, 'MSPointerMove', touchMove);\n      i.event.bind(element, 'MSPointerUp', touchEnd);\n    }\n  }\n}\n","import * as CSS from './lib/css';\nimport * as DOM from './lib/dom';\nimport cls from './lib/class-names';\nimport EventManager from './lib/event-manager';\nimport processScrollDiff from './process-scroll-diff';\nimport updateGeometry from './update-geometry';\nimport { toInt, outerWidth } from './lib/util';\n\nimport clickRail from './handlers/click-rail';\nimport dragThumb from './handlers/drag-thumb';\nimport keyboard from './handlers/keyboard';\nimport wheel from './handlers/mouse-wheel';\nimport touch from './handlers/touch';\n\nconst defaultSettings = () => ({\n  handlers: ['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch'],\n  maxScrollbarLength: null,\n  minScrollbarLength: null,\n  scrollingThreshold: 1000,\n  scrollXMarginOffset: 0,\n  scrollYMarginOffset: 0,\n  suppressScrollX: false,\n  suppressScrollY: false,\n  swipeEasing: true,\n  useBothWheelAxes: false,\n  wheelPropagation: true,\n  wheelSpeed: 1,\n});\n\nconst handlers = {\n  'click-rail': clickRail,\n  'drag-thumb': dragThumb,\n  keyboard,\n  wheel,\n  touch,\n};\n\nexport default class PerfectScrollbar {\n  constructor(element, userSettings = {}) {\n    if (typeof element === 'string') {\n      element = document.querySelector(element);\n    }\n\n    if (!element || !element.nodeName) {\n      throw new Error('no element is specified to initialize PerfectScrollbar');\n    }\n\n    this.element = element;\n\n    element.classList.add(cls.main);\n\n    this.settings = defaultSettings();\n    for (const key in userSettings) {\n      this.settings[key] = userSettings[key];\n    }\n\n    this.containerWidth = null;\n    this.containerHeight = null;\n    this.contentWidth = null;\n    this.contentHeight = null;\n\n    const focus = () => element.classList.add(cls.state.focus);\n    const blur = () => element.classList.remove(cls.state.focus);\n\n    this.isRtl = CSS.get(element).direction === 'rtl';\n    if (this.isRtl === true) {\n      element.classList.add(cls.rtl);\n    }\n    this.isNegativeScroll = (() => {\n      const originalScrollLeft = element.scrollLeft;\n      let result = null;\n      element.scrollLeft = -1;\n      result = element.scrollLeft < 0;\n      element.scrollLeft = originalScrollLeft;\n      return result;\n    })();\n    this.negativeScrollAdjustment = this.isNegativeScroll\n      ? element.scrollWidth - element.clientWidth\n      : 0;\n    this.event = new EventManager();\n    this.ownerDocument = element.ownerDocument || document;\n\n    this.scrollbarXRail = DOM.div(cls.element.rail('x'));\n    element.appendChild(this.scrollbarXRail);\n    this.scrollbarX = DOM.div(cls.element.thumb('x'));\n    this.scrollbarXRail.appendChild(this.scrollbarX);\n    this.scrollbarX.setAttribute('tabindex', 0);\n    this.event.bind(this.scrollbarX, 'focus', focus);\n    this.event.bind(this.scrollbarX, 'blur', blur);\n    this.scrollbarXActive = null;\n    this.scrollbarXWidth = null;\n    this.scrollbarXLeft = null;\n    const railXStyle = CSS.get(this.scrollbarXRail);\n    this.scrollbarXBottom = parseInt(railXStyle.bottom, 10);\n    if (isNaN(this.scrollbarXBottom)) {\n      this.isScrollbarXUsingBottom = false;\n      this.scrollbarXTop = toInt(railXStyle.top);\n    } else {\n      this.isScrollbarXUsingBottom = true;\n    }\n    this.railBorderXWidth =\n      toInt(railXStyle.borderLeftWidth) + toInt(railXStyle.borderRightWidth);\n    // Set rail to display:block to calculate margins\n    CSS.set(this.scrollbarXRail, { display: 'block' });\n    this.railXMarginWidth =\n      toInt(railXStyle.marginLeft) + toInt(railXStyle.marginRight);\n    CSS.set(this.scrollbarXRail, { display: '' });\n    this.railXWidth = null;\n    this.railXRatio = null;\n\n    this.scrollbarYRail = DOM.div(cls.element.rail('y'));\n    element.appendChild(this.scrollbarYRail);\n    this.scrollbarY = DOM.div(cls.element.thumb('y'));\n    this.scrollbarYRail.appendChild(this.scrollbarY);\n    this.scrollbarY.setAttribute('tabindex', 0);\n    this.event.bind(this.scrollbarY, 'focus', focus);\n    this.event.bind(this.scrollbarY, 'blur', blur);\n    this.scrollbarYActive = null;\n    this.scrollbarYHeight = null;\n    this.scrollbarYTop = null;\n    const railYStyle = CSS.get(this.scrollbarYRail);\n    this.scrollbarYRight = parseInt(railYStyle.right, 10);\n    if (isNaN(this.scrollbarYRight)) {\n      this.isScrollbarYUsingRight = false;\n      this.scrollbarYLeft = toInt(railYStyle.left);\n    } else {\n      this.isScrollbarYUsingRight = true;\n    }\n    this.scrollbarYOuterWidth = this.isRtl ? outerWidth(this.scrollbarY) : null;\n    this.railBorderYWidth =\n      toInt(railYStyle.borderTopWidth) + toInt(railYStyle.borderBottomWidth);\n    CSS.set(this.scrollbarYRail, { display: 'block' });\n    this.railYMarginHeight =\n      toInt(railYStyle.marginTop) + toInt(railYStyle.marginBottom);\n    CSS.set(this.scrollbarYRail, { display: '' });\n    this.railYHeight = null;\n    this.railYRatio = null;\n\n    this.reach = {\n      x:\n        element.scrollLeft <= 0\n          ? 'start'\n          : element.scrollLeft >= this.contentWidth - this.containerWidth\n          ? 'end'\n          : null,\n      y:\n        element.scrollTop <= 0\n          ? 'start'\n          : element.scrollTop >= this.contentHeight - this.containerHeight\n          ? 'end'\n          : null,\n    };\n\n    this.isAlive = true;\n\n    this.settings.handlers.forEach(handlerName => handlers[handlerName](this));\n\n    this.lastScrollTop = Math.floor(element.scrollTop); // for onScroll only\n    this.lastScrollLeft = element.scrollLeft; // for onScroll only\n    this.event.bind(this.element, 'scroll', e => this.onScroll(e));\n    updateGeometry(this);\n  }\n\n  update() {\n    if (!this.isAlive) {\n      return;\n    }\n\n    // Recalcuate negative scrollLeft adjustment\n    this.negativeScrollAdjustment = this.isNegativeScroll\n      ? this.element.scrollWidth - this.element.clientWidth\n      : 0;\n\n    // Recalculate rail margins\n    CSS.set(this.scrollbarXRail, { display: 'block' });\n    CSS.set(this.scrollbarYRail, { display: 'block' });\n    this.railXMarginWidth =\n      toInt(CSS.get(this.scrollbarXRail).marginLeft) +\n      toInt(CSS.get(this.scrollbarXRail).marginRight);\n    this.railYMarginHeight =\n      toInt(CSS.get(this.scrollbarYRail).marginTop) +\n      toInt(CSS.get(this.scrollbarYRail).marginBottom);\n\n    // Hide scrollbars not to affect scrollWidth and scrollHeight\n    CSS.set(this.scrollbarXRail, { display: 'none' });\n    CSS.set(this.scrollbarYRail, { display: 'none' });\n\n    updateGeometry(this);\n\n    processScrollDiff(this, 'top', 0, false, true);\n    processScrollDiff(this, 'left', 0, false, true);\n\n    CSS.set(this.scrollbarXRail, { display: '' });\n    CSS.set(this.scrollbarYRail, { display: '' });\n  }\n\n  onScroll(e) {\n    if (!this.isAlive) {\n      return;\n    }\n\n    updateGeometry(this);\n    processScrollDiff(this, 'top', this.element.scrollTop - this.lastScrollTop);\n    processScrollDiff(\n      this,\n      'left',\n      this.element.scrollLeft - this.lastScrollLeft\n    );\n\n    this.lastScrollTop = Math.floor(this.element.scrollTop);\n    this.lastScrollLeft = this.element.scrollLeft;\n  }\n\n  destroy() {\n    if (!this.isAlive) {\n      return;\n    }\n\n    this.event.unbindAll();\n    DOM.remove(this.scrollbarX);\n    DOM.remove(this.scrollbarY);\n    DOM.remove(this.scrollbarXRail);\n    DOM.remove(this.scrollbarYRail);\n    this.removePsClasses();\n\n    // unset elements\n    this.element = null;\n    this.scrollbarX = null;\n    this.scrollbarY = null;\n    this.scrollbarXRail = null;\n    this.scrollbarYRail = null;\n\n    this.isAlive = false;\n  }\n\n  removePsClasses() {\n    this.element.className = this.element.className\n      .split(' ')\n      .filter(name => !name.match(/^ps([-_].+|)$/))\n      .join(' ');\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./rtd.css\";\nimport * as dompack from \"dompack\";\nimport * as browser from 'dompack/extra/browser';\nimport PerfectScrollbar from \"@mod-utwente_design/vendor/perfect-scrollbar-wh\";\n\n//custom scroller for rtd tables\ndompack.register(\".wh-rtd__tablewrap\", node => {\n  const container = <div class=\"wh-rtd__tablewrap__scrollcontainer\" />;\n  for (let c = 0; c < node.children.length; ++c)\n    container.appendChild(node.children[c]);\n  node.appendChild(container);\n\n  if (browser.getPlatform() === \"ios\" || browser.getPlatform() === \"android\") {\n    container.classList.add(\"nativescroll\");\n  } else {\n    new PerfectScrollbar(container, {\n      swipePropagation: true,\n      wheelPropagation: true,\n      suppressScrollY: true\n    });\n  }\n});\n\n// Add the 'fullwidth' class to (un)subscribe widgets in NEO articles\ndompack.register(\".article .wh-newsletter__formwidget\", node => node.classList.add(\"main__contents--fullwidth\"));\n","import { onDomReady } from \"@webhare/dompack\";\nimport \"./univers-next-faces.css\";\n\n//required by license, but this way it won't block any critical asset loading or page rendering\nonDomReady(() =>\n  void setTimeout(() =>\n    void fetch(\"https://cdn.fonts.net/t/1.css?apiType=css&projectid=7c052a08-29f5-4c10-ab60-eeb1623773d6\", { priority: \"low\" }).then(() => { }, () => { }), 200));\n","import * as dompack from \"dompack\";\nimport { getTid, getTidLanguage, setTidLanguage } from \"@webhare/gettid\";\nimport \"../../site.lang.json\";\n// Forms API\nimport { RPCFormBase, setupValidator, setup } from '@mod-publisher/js/forms';\nimport ImgEditField from \"@mod-publisher/js/forms/fields/imgedit\";\nimport RTDField from \"@mod-publisher/js/forms/fields/rtd\";\nimport * as embedvideo from '@mod-publisher/js/forms/fields/rtd/embedvideo';\nimport UploadField from \"@mod-publisher/js/forms/fields/upload\";\n\n//import { cSplitDateInput, cSplitTimeInput } from '../splitdatetimeinput';\n//import { DateField, TimeField } from '@mod-publisher/js/forms/fields/datetime';\n\nimport Pulldown from \"dompack/components/pulldown\";\nimport { getReferralInfo } from '../crm/referralinfo';\nimport \"./phone\";\n\nimport \"./styling\"; // must be inserted before widget/page CSS to avoid specificy issues - FIXME shouldn't be relying on import ordering.\nimport \"./linkhandling\";\nimport type { BusyModalEvent } from \"@webhare/dompack\";\nimport { debugFlags } from \"@webhare/env\";\n\nconst lang = document.documentElement.lang.substr(0, 2).toLowerCase();\nlet overlaylayer: HTMLElement | null = null;\n\n/*\ndompack.register(\".wh-styledinput input[type=time]\", node => { new TimeField(node); });\n//@ts-ignore only formfilters reads this, can we fix that one?\ndompack.register(\".wh-styledinput input[type=date]\", node => { node.splitcontrol = new DateField(node); });\n\ndompack.register(\".wh-formcontrol-styling input[type=time]\", node => { new TimeField(node); });\n//@ts-ignore only formfilters reads this, can we fix that one?\ndompack.register(\".wh-formcontrol-styling input[type=date]\", node => { node.splitcontrol = new DateField(node); });\n*/\n\n// check if prefilled field is changed so styling can be updated if changed\ndompack.qSA(\".wh-form .wh-form__fieldgroup.ut-prefilled\").forEach(grp => {\n  const fields = dompack.qSA(grp, \"input:not([readonly]):not([disabled]),select:not([readonly]):not([disabled]),textarea:not([readonly]):not([disabled])\");\n  fields.forEach(inp => inp.addEventListener(\"change\", () => grp.classList.add(\"ut-prefilled--changed\")));\n});\n\nfunction onBusyModal(evt: BusyModalEvent) {\n  const waittext = lang === 'nl' ? 'Een ogenblik geduld...' : lang === 'de' ? 'Bitte warte einen Moment...' : 'Please wait a moment...';\n\n  overlaylayer ||= <div class=\"rpc__overlay ut-spinner--showembeddedspinner\">\n    <div class=\"rpc__overlaywait\">\n      <span class=\"rpc__spinner\">\n        <span class=\"UT-icon-UT_icon_112_settings-24px ut-spinner\"></span>\n      </span>{waittext}\n    </div>\n  </div>;\n\n  if (evt.detail.show)\n    document.body.appendChild(overlaylayer!);\n  else\n    document.body.removeChild(overlaylayer!);\n}\n\nexport class UTRPCFormBase extends RPCFormBase {\n  getFormExtraSubmitData() {\n    return {\n      ...super.getFormExtraSubmitData(),\n      referralinfo: getReferralInfo(),\n      targetinterest: document.documentElement.dataset.targetinterest || '',\n      targetlanguage: document.documentElement.lang.substr(0, 2)\n    };\n  }\n}\n\nfunction fixupEmailField(emailfield: HTMLInputElement) {\n  if (emailfield.maxLength <= 0 || emailfield.maxLength > 100)\n    emailfield.maxLength = 100;\n}\n\n//Add required text under webforms pages\ndompack.register(\".wh-form.wh-styledinput\", node => {\n  const overridelanguage = node.closest('[lang]')?.getAttribute(\"lang\") ?? document.documentElement.lang ?? 'en';\n  const savelang = getTidLanguage(); //TODO need getTidForLanguage\n  setTidLanguage(overridelanguage.substring(0, 2));\n  const requiredtext = getTid('utwente_base:frontend.ws2016.js.starsrequired');\n  setTidLanguage(savelang);\n\n  if (node.querySelector(\".wh-form__fieldgroup--required\"))\n    node.appendChild(<div class=\"wh-form__requirednote\"><p>{requiredtext}</p></div>);\n});\n\n/* studylink trick: webpack questions tagged check_studylink_number should verify to have exactly 9 positions */\ndompack.register<HTMLInputElement>(\".utwente-check-studylink-number input\", node => {\n  node.minLength = 7;\n  node.maxLength = 7;\n  node.type = \"tel\";\n  node.pattern = \"[0-9]{7}\";\n\n  setupValidator(node, el => {\n    if (!el.value.match(/^[0-9]{7}$/))\n      return \"This is not a valid student number. To find your student number please check your Osiris application mail or login to the Osiris application system.\";\n  });\n});\n\nif (!debugFlags[\"ut-nocustomselect\"]) {\n  dompack.register(\".wh-styledinput select:not(.wh-form__prefillcontrol)\", node => { if (!node.closest(\".wh-form__fieldgroup--slimselect\")) new Pulldown(node, 'ut-pulldown'); });\n  dompack.register(\".wh-formcontrol-styling select:not(.wh-form__prefillcontrol)\", node => new Pulldown(node, 'ut-pulldown'));\n}\n\ndompack.register(\".wh-form__imgedit\", node => new ImgEditField(node));\ndompack.register(\".wh-form__upload\", node => new UploadField(node));\ndompack.register(\".wh-form__rtd\",\n  node => new RTDField(node, {\n    hidebuttons: ['table'],\n    onInsertVideo: embedvideo.insertVideo\n  }));\n\n// Limit all email fields to 100 chars: https://gitlab.webhare.com/utwente/utwente_base/-/issues/2059#note_167567\ndompack.register(`input[type=email]`, fixupEmailField);\n\nsetup({ validate: true });\nwindow.addEventListener(\"dompack:busymodal\", onBusyModal);\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/webdesigns/ws2016/src/site.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_base\",\"en\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"nl\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Voeg aan kalender toe\",\"consentblock-accept3thpartycookies\":\"Accepteer cookies van derden\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"om de plugin te laden.\",\"consentblock-facebook-line1\":\"Deze Facebook-plugin plaatst marketingcookies.\",\"consentblock-facebook-title\":\"Dit element plaatst cookies\",\"consentblock-issuu-accept3thpartycookies-suffix\":\"om de viewer te laden.\",\"consentblock-issuu-line1\":\"De viewer van Issuu plaatst marketingcookies.\",\"consentblock-issuu-title\":\"Deze viewer plaatst cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"om de speler te laden.\",\"consentblock-soundcloud-directlink\":\"de website van SoundCloud.\",\"consentblock-soundcloud-directlink-prefix\":\"Luisteren zonder cookies kan op\",\"consentblock-soundcloud-line1\":[\"De speler van \",1,\" plaatst marketingcookies.\"],\"consentblock-soundcloud-title\":\"Deze audiospeler plaatst cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"om de tijdlijn te bekijken.\",\"consentblock-twitterembed-line1\":\"De Twitter/X tijdlijn plaatst marketingcookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"om de speler te laden.\",\"consentblock-video-directlink\":[\"de website van \",1,\".\"],\"consentblock-video-directlink-prefix\":\"Kijken zonder cookies kan op\",\"consentblock-video-line1\":[\"De speler \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"\",\"subs\":[],\"subselse\":[\"van \",1]},\" plaatst marketingcookies.\"],\"consentblock-video-title\":\"Deze videospeler plaatst cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Sluit popup\",\"email\":\"Je e-mailadres\",\"error-imagenotfound\":\"Afbeelding niet gevonden\",\"error-invalidemail\":\"Fout in e-mailadres\",\"error-invalidurl\":\"Onbekende url\",\"imageissendto\":\"Afbeelding is verstuurd naar:\",\"landmark-deeplinks-arialabel\":\"Inhoudsopgave\",\"list\":\"Lijst\",\"nosuggestresults\":\"Geen resultaten\",\"notavalidmobilephonenumber\":\"Dit is geen geldig mobiel nummer.\",\"notavalidphonenumber\":\"Dit is geen geldig telefoonnummer.\",\"readmore\":\"Lees verder\",\"starsrequired\":\"* betekent dat een veld verplicht is\",\"submit\":\"Verstuur\",\"submitting\":\"Versturen...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"Er zijn geen resultaten\",\"feedbackbar-result\":\"Resultaat\",\"feedbackbar-results\":[1,\" resultaten\"],\"feedbackbar-resultslimited\":[\"De eerste \",2,\" resultaten worden getoond (van de totaal \",1,\" resultaten)\"],\"hidefilters_header\":\"Verberg filters\",\"search\":\"Zoeken\",\"showfilters_header\":\"Toon filters\",\"tease-noresults\":\"Geen resultaten\",\"tease-result\":[\"Toon \",1,\" resultaat\"],\"tease-results\":[\"Toon \",1,\" resultaten\"]},\"managedcta\":{\"beacon\":[\"Het beacon '\",1,\"' is getriggerd\"],\"beacon-maxdays\":[\"Het beacon '\",1,\"' is getriggerd in de afgelopen \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"dag\"],\"subselse\":[2,\" dagen\"]}],\"beacons-skipped\":[\"Het beacon '\",1,\"' is niet getriggerd\"],\"beacons-skipped-none\":\"Geen enkel beacon is getriggerd\",\"beacons-skipped-time\":[\"Het beacon '\",1,\"' zou getriggerd moeten zijn voor \",2,\", maar het is nu \",3],\"countries\":[\"Het GeoIP-land is een van \",1],\"countries-skipped\":[\"De landcode '\",2,\"' is niet een van \",1],\"explanation\":\"Deze CTA wordt getoond wanneer\",\"explanation-skipped\":\"Deze CTA wordt niet getoond omdat\",\"noctatoshow\":\"Geen van de CTA's voldoet aan de voorwaarden\",\"publish_from\":[\"De pagina wordt bekeken na \",1],\"publish_from-skipped\":[\"De huidige datum \",2,\" ligt voor de publicatiedatum \",1],\"publish_until\":[\"De pagina wordt bekeken voor \",1],\"publish_until-skipped\":[\"De huidige datum \",2,\" ligt na de publicatiedatum \",1],\"query\":[\"De zoekterm matcht een van de zoektermen \",1],\"query-skipped\":[\"De zoekterm '\",1,\"' matcht met geen van de zoektermen\"],\"query-skipped-error\":[\"De zoekterm '\",1,\"' veroorzaakte een fout: \",2],\"regex\":[\"De URL matcht een van de reguliere expressies \",1],\"regex-exclude\":[\"De URL matcht geen van de reguliere expressies \",1],\"regex-skipped\":[\"De URL '\",2,\"' matcht de reguliere expressie \",1],\"regex-skipped-error\":[\"De reguliere expressie '\",1,\"' veroorzaakte een fout: \",2],\"regex-skipped-none\":[\"De URL '\",1,\"' matcht geen van de reguliere expressies\"]},\"meetings\":{\"error-description\":[\"Er is een fout opgetreden bij verwerken van de bijeenkomst.\",\"\\n\",\"Probeer het later opnieuw\"],\"error-title\":\"Fout tijdens verwerken\",\"thanks-description\":\"Uw verzoek voor de bijeenkomst is opgeslagen. Er wordt binnenkort contact met u opgenomen.\",\"thanks-title\":\"Bijeenkomst is opgeslagen\"},\"neoform\":{\"authorizednotset\":\"Om de zichtbaarheid te beperken moet minstens één ontvanger of type medewerker worden geselecteerd.\",\"image-invalid-width\":[\"De breedte van de afbeelding voldoet niet aan de eisen van \",2,\" pixels. Het vult niet het hele gebied bovenaan de pagina. We vullen de ontbrekende ruimte met een gegenereerde achtergrond. Als je dit niet wilt, upload dan een afbeelding die voldoet aan de minimale breedteeisen (\",2,\" pixels).\"],\"image-read-error\":\"De geüploade afbeelding kon niet worden gelezen.\",\"minheight\":[\"De afbeelding is te klein. Deze moet minimaal \",2,\" pixels hoog zijn.\"]},\"newsevents\":{\"noresults\":\"Geen resultaten\",\"noupcoming\":\"Er zijn op dit moment geen aankomende evenementen\",\"thanks-cultural\":\"Bedankt voor de reservering\",\"thanks-event\":\"Bedankt voor de registratie\"},\"osiris\":{\"back\":\"Terug\",\"goal\":\"Doel\",\"loading\":\"Laden...\",\"more\":\"Lees meer\",\"moredetailslink\":[\"Ga naar <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">het detailoverzicht</a> in de OSIRIS Onderwijscatalogus\"],\"nocoursefound\":\"Vak niet gevonden\"},\"searchsheet\":{\"allevents\":\"Toon alle events\",\"downloadmap\":\"Download de plattegrond\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Sommige zoekresultaten zijn verwijderd\",\"image\":\"Afbeelding\",\"location\":\"Locatie\",\"news\":\"Nieuws\",\"overflow--email\":\"Stuur een e-mail\",\"people\":\"Persoon\",\"peoplepage\":\"People Page\",\"publication\":\"Publicatie\",\"related\":\"Gerelateerde zoekopdrachten\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"Geen resultaten\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 resultaat\"],\"subselse\":[1,\" resultaten\"]}]}]},\" voor \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Bedoelde je misschien \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". Probeer %S%alles te doorzoeken%/S%.\",\"searchdone\":\"Er zijn geen verdere zoekresultaten!\",\"searching\":[\"Zoeken naar \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Voorgesteld resultaat\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Probeer a.u.b. opnieuw.\",\"error-title\":\"Betaling mislukt.\",\"thanks-description\":[\"Veel dank voor uw donatie!\",\"\\n\",\"\\n\",\"Universiteitsfonds Twente\"],\"thanks-title\":\"Bedankt\"}}}}});\nregisterTexts(\"utwente_base\",\"de\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Zum Kalender hinzufügen\",\"consentblock-accept3thpartycookies\":\"Bitte akzeptiere Cookies von Dritten\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"um dieses Element zu anzuzeigen.\",\"consentblock-facebook-line1\":\"Dieses Element von Facebook setzt Marketing-Cookies.\",\"consentblock-facebook-title\":\"Dieses Element setzt Cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"um den Player zu starten.\",\"consentblock-soundcloud-directlink\":\"der Webseite von SoundCloud möglich.\",\"consentblock-soundcloud-directlink-prefix\":\"Abspielen ohne Cookies zu laden ist auf\",\"consentblock-soundcloud-line1\":[\"Der Player von \",1,\" setzt Marketing-Cookies.\"],\"consentblock-soundcloud-title\":\"Dieser Audio-Stream setzt Cookies\",\"consentblock-video-accept3thpartycookies-suffix\":\"um den Player zu starten.\",\"consentblock-video-directlink\":[\"auf der Webseite von \",1,\" möglich.\"],\"consentblock-video-directlink-prefix\":\"Abspielen ohne Cookies zu laden ist\",\"consentblock-video-line1\":[\"Der Player \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"\",\"subs\":[],\"subselse\":[\"von \",1]},\" setzt Marketing-Cookies.\"],\"consentblock-video-title\":\"Dieser Videoplayer setzt Cookies\",\"landmark-deeplinks-arialabel\":\"Inhaltsverzeichnis\",\"list\":\"Liste\",\"nosuggestresults\":\"Keine Ergebnisse\",\"notavalidmobilephonenumber\":\"Dies ist keine gültige Mobilnummer.\",\"notavalidphonenumber\":\"Dies ist keine gültige Telefonnummer.\",\"readmore\":\"Weiter Lesen\",\"starsrequired\":\"* zeigt ein Pflichtfeld an\",\"filteredoverview\":{\"feedbackbar-noresults\":\"Keine Ergebnis\",\"feedbackbar-result\":\"Ergebnis\",\"feedbackbar-results\":[1,\" Ergebnisse\"],\"hidefilters_header\":\"Filter ausblenden\",\"showfilters_header\":\"Filter anzeigen\",\"tease-noresults\":\"Es gibt keine Ergebnisse\",\"tease-result\":[\"Es gibt \",1,\" Ergebnis\"],\"tease-results\":[\"Es gibt \",1,\" Ergebnisse\"]},\"newsevents\":{\"noresults\":\"Keine Ergebnisse\",\"noupcoming\":\"Im Moment sind keine neuen Events bekannt\",\"thanks-cultural\":\"Vielen Dank für die Reservierung\",\"thanks-event\":\"Vielen Dank für die Registrierung\"},\"osiris\":{\"back\":\"Zurück\",\"goal\":\"Ziel\",\"loading\":\"Laden...\",\"more\":\"Weiterlesen\",\"moredetailslink\":[\"<a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">Mehr Details</a> aus dem OSIRIS Vorlesungsverzeichnis\"],\"nocoursefound\":\"Kurs nicht gefunden\"},\"searchsheet\":{\"allevents\":\"Alle Events zeigen\",\"downloadmap\":\"Download Campus-Karte\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Einzelne Suchergebnisse wurden gelöscht\",\"image\":\"Foto\",\"location\":\"Ort\",\"news\":\"News\",\"overflow--email\":\"E-Mail versenden\",\"people\":\"Personen\",\"peoplepage\":\"Persönliche Seite\",\"publication\":\"Publikation\",\"related\":\"Ähnliche Suchaufträge\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"Keine Ergebnisse\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 Ergebnis\"],\"subselse\":[1,\" Ergebnisse\"]}]}]},\" für \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Suchst du \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Wegbeschreibung\",\"searchall\":\". Du kannst versuchen %S%alle zu suchen%/S%.\",\"searchdone\":\"Keine weiteren Suchergebnisse vorhanden!\",\"searching\":[\"Suche \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Vorgeschlagene Ergebnisse\",\"utoday\":\"UToday\",\"video\":\"Video\"}}}}});\nregisterTexts(\"utwente_base\",\"ar\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"bg\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"el\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"es\",{\"frontend\":{\"ws2016\":{\"js\":{\"starsrequired\":\"* campo obligatorio\",\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"id\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"pt\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"ro\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\nregisterTexts(\"utwente_base\",\"zh\",{\"frontend\":{\"ws2016\":{\"js\":{\"addtocalendar\":\"Add to calendar\",\"consentblock-accept3thpartycookies\":\"Accept third-party cookies\",\"consentblock-facebook-accept3thpartycookies-suffix\":\"to load the plugin.\",\"consentblock-facebook-line1\":\"This Facebook plugin uses marketing cookies.\",\"consentblock-facebook-title\":\"This element uses cookies\",\"consentblock-soundcloud-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-soundcloud-directlink\":\"the SoundCloud website.\",\"consentblock-soundcloud-directlink-prefix\":\"Listen without cookies on\",\"consentblock-soundcloud-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-soundcloud-title\":\"This audio player uses cookies\",\"consentblock-twitterembed-accept3thpartycookies-suffix\":\"to view the timeline.\",\"consentblock-twitterembed-line1\":\"The Twitter/X timeline uses marketing cookies.\",\"consentblock-video-accept3thpartycookies-suffix\":\"to load the player.\",\"consentblock-video-directlink\":[\"the \",1,\" website.\"],\"consentblock-video-directlink-prefix\":\"Watch without cookies on\",\"consentblock-video-line1\":[\"The \",1,\" player uses marketing cookies.\"],\"consentblock-video-title\":\"This video player uses cookies\",\"details\":\"Details\",\"dialog-close-arialabel\":\"Close dialog\",\"email\":\"Your email address\",\"error-imagenotfound\":\"Unable to send image\",\"error-invalidemail\":\"Invalid email\",\"error-invalidurl\":\"Invalid url\",\"imageissendto\":\"The image is send to:\",\"landmark-deeplinks-arialabel\":\"Table of contents\",\"list\":\"List\",\"nosuggestresults\":\"No results\",\"notavalidmobilephonenumber\":\"This is not a valid mobile phone number.\",\"notavalidphonenumber\":\"This is not a valid phone number.\",\"readmore\":\"Read more\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"submitting\":\"Submitting...\",\"calendar\":{\"appleical\":\"Apple iCal\",\"facebook\":\"Facebook Event\",\"google\":\"Google Calendar\",\"outlook\":\"Outlook Calendar\",\"outlookcom\":\"Outlook.com\",\"yahoo\":\"Yahoo Kalender\"},\"filteredoverview\":{\"feedbackbar-noresults\":\"No results\",\"feedbackbar-result\":\"Result\",\"feedbackbar-results\":[1,\" results\"],\"feedbackbar-resultslimited\":[\"Showing the first \",2,\" results (out of a total of \",1,\" results)\"],\"hidefilters_header\":\"Hide filter\",\"search\":\"Search\",\"showfilters_header\":\"Filter\",\"tease-noresults\":\"No results\",\"tease-result\":[\"Show \",1,\" result\"],\"tease-results\":[\"Show \",1,\" results\"]},\"managedcta\":{\"beacon\":[\"The beacon '\",1,\"' has been triggered\"],\"beacon-maxdays\":[\"The beacon '\",1,\"' has been triggered in the last \",{\"t\":\"ifparam\",\"p\":2,\"value\":\"1\",\"subs\":[\"day\"],\"subselse\":[2,\" days\"]}],\"beacons-skipped\":[\"The beacon '\",1,\"' was not triggered\"],\"beacons-skipped-none\":\"No beacons are triggered\",\"beacons-skipped-time\":[\"The beacon '\",1,\"' should have been triggered before \",2,\", but is it \",3],\"countries\":[\"The GeoIP country is one of \",1],\"countries-skipped\":[\"The current country code '\",2,\"' is not one of \",1],\"explanation\":\"This CTA is shown if\",\"explanation-skipped\":\"This CTA is not shown because\",\"noctatoshow\":\"None of the CTAs satisfy the conditions\",\"publish_from\":[\"The page is viewed after \",1],\"publish_from-skipped\":[\"The current date \",2,\" is before the publication date \",1],\"publish_until\":[\"The page is viewed before \",1],\"publish_until-skipped\":[\"The current date \",2,\" is after publication date \",1],\"query\":[\"The search term matches one of the search terms \",1],\"query-skipped\":[\"The search term '\",1,\"'does not match any of the search terms\"],\"query-skipped-error\":[\"The search term '\",1,\"' caused an error: \",2],\"regex\":[\"The URL matches one of the regular expressions \",1],\"regex-exclude\":[\"The URL matches none of the regular expressions \",1],\"regex-skipped\":[\"The URL '\",2,\"' matches regular expression \",1],\"regex-skipped-error\":[\"The regular expression '\",1,\"' caused an error: \",2],\"regex-skipped-none\":[\"The URL '\",1,\"' matches none of the regular expressions\"]},\"meetings\":{\"error-description\":[\"An error occurred while processing the meeting.\",\"\\n\",\"Please try again later.\"],\"error-title\":\"Error while processing\",\"thanks-description\":\"Your request for the meeting is successfully stored. You will be contacted soon.\",\"thanks-title\":\"Meeting is stored\"},\"neoform\":{\"authorizednotset\":\"To limit visibility, select at least one of the recipients or employee types.\",\"image-invalid-width\":[\"The width of the picture does not meet the requirements of \",2,\" pixels. It does not fill the whole header area. We will fill the missing space with a generated background. If you don't want this, please upload a picture that meets the minimum width requirements (\",2,\" pixels).\"],\"image-read-error\":\"The uploaded image could not be read.\",\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"]},\"newsevents\":{\"noresults\":\"No results\",\"noupcoming\":\"No upcoming events available\",\"thanks-cultural\":\"Thank you for the reservation\",\"thanks-event\":\"Thank you for the registration\"},\"osiris\":{\"back\":\"Back\",\"goal\":\"Goal\",\"loading\":\"Loading...\",\"more\":\"Read more\",\"moredetailslink\":[\"Go to <a href=\\\"\",1,\"\\\" target=\\\"osiris\\\">the detailed overview</a> in the OSIRIS Course Catalog\"],\"nocoursefound\":\"Course not found\"},\"searchsheet\":{\"allevents\":\"Show all events\",\"downloadmap\":\"Download the campus map\",\"event\":\"Event\",\"events\":\"Events\",\"filteredresults\":\"Some search results have been deleted\",\"image\":\"Image\",\"location\":\"Location\",\"news\":\"News\",\"overflow--email\":\"Send an email\",\"people\":\"People\",\"peoplepage\":\"People Page\",\"publication\":\"Publication\",\"related\":\"Related searches\",\"results\":[{\"t\":\"tag\",\"tag\":\"b\",\"subs\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"0\",\"subs\":[\"No results\"],\"subselse\":[{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 result\"],\"subselse\":[1,\" results\"]}]}]},\" for \\\"\",2,\"\\\"\",{\"t\":\"ifparam\",\"p\":3,\"value\":\"\",\"subs\":[],\"subselse\":[\". Did you mean \\\"%S%\",3,\"%/S%\\\"?\"]}],\"route\":\"Route\",\"searchall\":\". You can try to %S%search all instead%/S%.\",\"searchdone\":\"We found no further search results!\",\"searching\":[\"Searching for \\\"\",1,\"\\\"...\"],\"suggestedresult\":\"Suggested result\",\"utoday\":\"UToday\",\"video\":\"Video\"},\"ufondsdonaties\":{\"error-description\":\"Please try again.\",\"error-title\":\"Payment failed.\",\"thanks-description\":\"Thank you for your donation!\",\"thanks-title\":\"Thank you\"}}}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/ar.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/bg.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/el.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/es.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/id.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/pt.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/ro.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/zh.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/language/default.xml\n","// eslint-disable-next-line @typescript-eslint/no-explicit-any -- we can't know the types passed to merge call\ntype FormatFunction = (value: any) => string | number;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- we can't know the types passed to merge call\ntype UpdateFunction = (node: HTMLElement, value: any) => void;\nconst formatters: { [key: string]: FormatFunction } = {};\nconst updaters: { [key: string]: UpdateFunction } = {};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- we can't know the types passed to merge call\nfunction mergeNode(node: HTMLElement, set: string, data: any) {\n  const parts = set.split(\":\");\n  const isNodeFunc = parts.length === 1;\n  if (parts.length > 2) {\n    console.error(`Illegal merge expression: '${set}'`, node);\n    return;\n  }\n\n  let func = \"\";\n  let exprpath = (isNodeFunc ? parts[0] : parts[1]).trim();\n\n  const callparts = exprpath.split(\"(\");\n  if (callparts.length > 1) {\n    if (callparts.length !== 2) {\n      console.error(`Illegal merge value: '${set}'`, node);\n      return;\n    }\n\n    func = callparts[0].trim();\n    const funcrest = callparts[1].split(\")\");\n    if (funcrest.length !== 2 || funcrest[1] !== \"\") {\n      console.error(`Illegal merge value: '${set}'`, node);\n      return;\n    }\n    exprpath = funcrest[0].trim();\n  }\n\n  let value = data;\n  if (exprpath !== \"*\") {\n    const exprpathparts = exprpath.split(\".\");\n    for (let i = 0; i < exprpathparts.length; ++i) {\n      value = value[exprpathparts[i].trim()];\n      if (typeof value === \"undefined\")\n        return;\n    }\n  }\n\n  if (isNodeFunc) {\n    if (func && updaters[func])\n      updaters[func](node, value);\n    else if (func)\n      console.error(`Unknown updating function '${func}' in '${set}'`, node);\n    else\n      console.error(`A function is required for merges without a property (in '${set}')`, node);\n    return;\n  }\n\n  const prop = parts[0].trim();\n  if (func) {\n    if (formatters[func])\n      value = formatters[func](value);\n    else {\n      console.error(`Unknown formatting function '${func}' in '${set}'`, node);\n      return;\n    }\n  }\n\n  if (typeof value !== \"string\" && typeof value !== \"number\") {\n    console.error(`Got a value of type ${typeof value} in '${set}'`, node);\n    return;\n  }\n\n  switch (prop) {\n    case 'events':\n    case 'styles':\n    case 'children':\n    case 'on':\n    case \"className\":\n    case \"class\":\n    case 'style':\n    case 'dataset':\n    case 'childNodes':\n      {\n        console.error(`Cannot modify '${prop}' with merge`, node);\n        return;\n      }\n    default:\n      {\n        // 1-to-1 name to property mapping\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any -- we don't know which keys will be set\n        (node as any)[prop] = value;\n        return;\n      }\n  }\n}\n\n/**\n     Apply all merge fields within a node, recursively\n *\n    @param mergenode - Root node to start merging\n    @param data - Merge data\n    @param options - filter: If set, a function that will be called for every node with merge functions. If it returns a falsy value, the node will be skipped.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- we can't know the types passed to merge call\nexport async function run(mergenode: ParentNode, data: any, { filter }: { filter?: (node: Element) => boolean } = {}) {\n  const nodes = mergenode.querySelectorAll('*[data-merge],*[data-wh-merge]') as NodeListOf<HTMLElement>;\n  for (const node of Array.from(nodes)) { //FIXME drop support for data-wh-merge as soon as we've completed the phase out\n    if (node.nodeType !== 1 || (filter && !filter(node)))\n      continue;\n\n    // Parse 'a=b;c=d(e)'\n    const sets = ((node as HTMLElement).dataset.merge || (node as HTMLElement).dataset.whMerge)?.split(\";\");\n    if (sets)\n      for (const set of sets)\n        mergeNode(node, set, data);\n  }\n}\n\n/**\n     Register a formatter function.\n *\n    @param name - Name of the formatter function\n    @param callback - Formatter function. Called with parameter (value), must return a formatted value to write to the property.\n */\nexport function registerFormatter(name: string, callback: FormatFunction) {\n  formatters[name] = callback;\n}\n\n/**\n     Register an updater function (used to update multiple properties of a node at once)\n *\n    @param name - Name of the updater function\n    @param callback - Updater function. Called with parameters (node: HTMLElement, value: Any).\n */\nexport function registerUpdater(name: string, callback: UpdateFunction) {\n  updaters[name] = callback;\n}\n","import * as dompack from '@webhare/dompack';\nimport type { FieldErrorOptions, FormFrontendMessage } from '../formbase';\nimport { debugFlags } from '@webhare/env';\nimport { getFieldDisplayName, getFieldNativeError } from '@webhare/forms/src/domsupport';\n\n///Fired at nodes to apply error\nexport type SetFieldErrorData = {\n  error: FormFrontendMessage;\n  reportimmediately: boolean;\n  serverside: boolean;\n  metadata: unknown;\n};\n\nexport type FieldValidator<E extends HTMLElement = HTMLElement> = (node: E) => Promise<FormFrontendMessage | undefined> | FormFrontendMessage | undefined;\n\nfunction setupServerErrorClear(field: HTMLElement) {\n  const group = field.closest<HTMLElement>('.wh-form__fieldgroup') || field;\n  field.propWhCleanupFunction = () => {\n    group.removeEventListener(\"change\", field.propWhCleanupFunction!, true);\n    group.removeEventListener(\"input\", field.propWhCleanupFunction!, true);\n    group.removeEventListener(\"blur\", field.propWhCleanupFunction!, true);\n    setFieldError(field, '', { serverside: true });\n    field.propWhCleanupFunction = undefined;\n  };\n\n  // to be rightly paranoid (plugins and JS directly editing other fields) we'll blur when anything anywhere seems to change\n  // eg wrd.testwrdauth-emailchange would fail on Chrome without this if the browser window was not currently focused\n  group.addEventListener(\"change\", field.propWhCleanupFunction, true);\n  group.addEventListener(\"input\", field.propWhCleanupFunction, true);\n  if (!field.closest('form[novalidate]')) //if we're doing html5 validation, errors will block submit, so let's already clear on blur\n    group.addEventListener(\"blur\", field.propWhCleanupFunction, true);\n}\n\nclass ComponentValidationState {\n  el: HTMLElement;\n\n  /** Explicitly set error */\n  explicit: {\n    error: FormFrontendMessage;\n    serverside: boolean;\n    reportimmediately: boolean;\n    metadata?: unknown;\n\n  } | null = null;\n\n  /** Dynamic errors (generated by the validation steps, refreshable instead of waiting for explciit errors) */\n  dynamicError: FormFrontendMessage | null = null;\n\n  validators: FieldValidator[] = [];\n\n  constructor(el: HTMLElement) {\n    this.el = el;\n  }\n\n  getState(): { error: FormFrontendMessage; suggested?: never } | { error?: never; suggested: FormFrontendMessage } | null {\n    const err = this.getError();\n    if (err)\n      return { error: err };\n\n    if (this.el.propWhValidationSuggestion)\n      return { suggested: this.el.propWhValidationSuggestion };\n\n    return null;\n  }\n\n  getError(): FormFrontendMessage | null {\n    return this.explicit?.error || this.dynamicError || getFieldNativeError(this.el) || null;\n  }\n\n  hasError(): boolean {\n    return Boolean(this.getError());\n  }\n}\n\nconst validations = new WeakMap<HTMLElement, ComponentValidationState>();\n\nexport function getValidationState(field: HTMLElement) {\n\n  const state = validations.get(field);\n  if (state)\n    return state;\n\n  const newstate = new ComponentValidationState(field);\n  validations.set(field, newstate);\n  return newstate;\n}\n\n/* TODO Are we sure we should expose this API? A form-level setupValidator might be better as we can then re-validate at the proper point in time\n   instead of relying on an external user to enable and shutdown the error. We're mixing two completely different systems with setupValidator (which\n   works nicely with our focusout hadling) and setFieldError (which is extremely stateful and relies on the error-setter managing all the edge cases)\n\n   Oh and serverside errors float somewhere halfway that spectrum.. as we setup explicit clearing callbacks to remove the state we created ourselves.\n*/\nexport function setFieldError(field: Element, error: FormFrontendMessage, options?: Partial<FieldErrorOptions>) {\n  if (!dompack.isHTMLElement(field))\n    throw new Error(`Field is not a valid target for handling errors`);\n\n  const state = getValidationState(field);\n  if (!error) {  //clearing\n    if (!state.explicit)\n      return; //no change\n\n    state.explicit = null;\n    if (debugFlags.fhv)\n      console.log(`[fhv] Clearing error state for ${getFieldDisplayName(field)}`, field, error, options);\n  } else { //changing ?\n    if (debugFlags.fhv)\n      console.log(`[fhv] ${state.explicit ? 'Updating' : 'Setting'} error state for ${getFieldDisplayName(field)}`, field, error, options);\n\n    state.explicit = {\n      error,\n      serverside: options?.serverside || false,\n      reportimmediately: options?.reportimmediately || false,\n      metadata: options?.metadata\n    };\n\n    if (options?.serverside)\n      setupServerErrorClear(field);\n  }\n\n  updateFieldError(field);\n}\n\nexport function updateFieldError(field: HTMLElement) {\n  const state = getValidationState(field);\n\n  dompack.dispatchCustomEvent(field, 'wh:form-setfielderror', //this is where parsley hooks in and cancels to handle the rendering of faults itself\n    {\n      bubbles: true,\n      cancelable: true,\n      detail: {\n        error: state.explicit?.error || getFieldNativeError(field) || '',\n        reportimmediately: state.explicit?.reportimmediately || false,\n        serverside: state.explicit?.serverside || false,\n        metadata: state.explicit?.metadata\n      }\n    });\n}\n\n/** Set up a custom validator\n * @param node - Form element to validate\n * @param checker - Sync or async function that returns a string with an error message or undefined if the field is valid.\n*/\nexport function setupValidator<NodeType extends HTMLElement>(node: NodeType, checker: FieldValidator<NodeType>): void {\n  getValidationState(node).validators.push(checker as FieldValidator);\n\n  //if the checker as a name, we'll add it. otherwise we'll ensure that data-wh-form-custom-validator is set so we can scan for it (and it's probably nice to see it in the dom)\n  node.dataset.whFormCustomValidator = ((node.dataset.whFormCustomValidator || \"\") + \" \" + (checker.name || \"?\")).trim();\n}\n","import * as dompack from 'dompack';\nimport { qSA } from 'dompack';\nimport * as datetime from 'dompack/types/datetime';\nimport AddressField from '@mod-publisher/js/forms/fields/addressfield';\nimport { setupValidator } from './customvalidation';\n\nimport { getTid } from \"@webhare/gettid\";\nimport { formatDate, parseISODate } from './datehelpers';\nimport { isValidDate } from '@webhare/std';\n\nfunction validateCheckboxGroup(groupnode: HTMLElement) {\n  const nodes = dompack.qSA<HTMLInputElement>(groupnode, \"input[type='checkbox']\");\n  const min = Number(groupnode.dataset.whMin) || 0;\n  const max = Number(groupnode.dataset.whMax) || 0;\n\n  const anyenabled = nodes.some(node => !node.disabled);\n  const numChecked = nodes.filter(node => node.checked).length;\n\n  if (anyenabled) {\n    if (numChecked < min)\n      return getTid(\"publisher:site.forms.commonerrors.mincheck\", min);\n    else if (max > 0 && numChecked > max)\n      return getTid(\"publisher:site.forms.commonerrors.maxcheck\", max);\n  }\n}\n\nfunction validateRadioGroup(groupnode: HTMLElement) {\n  const nodes = dompack.qSA<HTMLInputElement>(groupnode, \"input[type='radio']\");\n  const isrequired = nodes.some(node => node.required);\n\n  if (isrequired) {\n    const isanychecked = nodes.some(node => node.checked && !node.disabled);\n    if (!isanychecked)\n      return getTid(\"publisher:site.forms.commonerrors.required\");\n  }\n}\n\nexport function reformatDate(datestr: string): string {\n  const parsed = parseISODate(datestr);\n  return parsed ? formatDate(\"D-M-Y\", parsed.year, parsed.month, parsed.day) : \"\";\n}\n\nfunction validateDate(date: HTMLInputElement) {\n  if (date.getAttribute('type') !== 'date') //it's no longer a date field\n    return '';\n  if (!date.value) //any required checks should be handled by the HTML5 compat layer, nothing for us to check\n    return '';\n\n  const dateparts = date.value.match(/^([0-9]+)-([0-9]+)-([0-9]+)$/) || [];\n  const year = parseInt(dateparts[1]), month = parseInt(dateparts[2]), day = parseInt(dateparts[3]);\n  if (!isValidDate(year, month, day))\n    return getTid(\"publisher:site.forms.commonerrors.default\");\n\n  const normalizeddate = ('0000' + year).substr(-4) + '-' + ('00' + month).substr(-2) + '-' + ('00' + day).substr(-2);\n  const min = date.getAttribute(\"min\"), max = date.getAttribute(\"max\");\n  if (min && normalizeddate < min)\n    return getTid(\"publisher:site.forms.commonerrors.min\", reformatDate(min));\n  if (max && normalizeddate > max)\n    return getTid(\"publisher:site.forms.commonerrors.max\", reformatDate(max));\n\n  return '';\n}\n\nfunction validateTime(time: HTMLInputElement) {\n  if (time.getAttribute('type') !== 'time') //it's no longer a time field\n    return '';\n  if (!time.value) //any required checks should be handled by the HTML5 compat layer, nothing for us to check\n    return '';\n\n  const timeparts = time.value.match(/^([0-9]+):([0-9]+)(:([0-9]+))?$/) || [];\n  const hours = parseInt(timeparts[1]), minutes = parseInt(timeparts[2]), seconds = parseInt(timeparts[3]);\n  if (isNaN(hours) || isNaN(minutes) || hours < 0 || hours > 23 || minutes < 0 || minutes > 59 || (!isNaN(seconds) && (seconds < 0 || seconds > 59)))\n    return getTid(\"publisher:site.forms.commonerrors.default\");\n\n  return '';\n}\n\nexport function setup(form: HTMLElement) {\n  for (const datecontrol of qSA<HTMLInputElement>(form, 'input[type=date]')) {\n    for (const field of ['whMin', 'whMax', 'whValue'])\n      if (datecontrol.dataset[field]) {\n        //parse 'now' or 'now+5d'. be able to extract '+5d'\n        const datematch = datecontrol.dataset[field]!.match(/^now((\\+|-)\\d+d)?$/);\n\n        if (datematch) {\n          const propname = field.substr(2).toLowerCase();\n          let thedate;\n          if (datematch[1])\n            thedate = new Date(Date.now() + parseInt(datematch[1]) * 86400 * 1000);\n          else\n            thedate = new Date;\n\n          (datecontrol as unknown as Record<string, string>)[propname] = datetime.getISOLocalDate(thedate);\n        }\n      }\n\n    if (datecontrol.type !== 'date' && !datecontrol.whValidationPolyfilled) { //this browser doesn't natively support date fields\n      datecontrol.whValidationPolyfilled = true;\n      //ADDME some sort of global validator would be better so we don't get confused by fields that change their type\n      setupValidator(datecontrol, validateDate);\n    }\n  }\n\n  for (const timecontrol of qSA<HTMLInputElement>(form, 'input[type=time][data-wh-value]')) {\n    //parse 'now'\n    //ADDME: Support for stuff like 'now + 15 minutes' 'next whole hour + 2.5 hours'?\n    const timematch = timecontrol.dataset.whValue!.match(/^now$/);\n\n    if (timematch) {\n      const thedate = new Date;\n\n      let propvalue = ('0' + thedate.getHours()).substr(-2) + '-' + ('0' + thedate.getMinutes()).substr(-2);\n      if (parseInt(timecontrol.getAttribute(\"step\") || '0') % 60) //step not multiple of 60? seconds\n        propvalue += '-' + ('0' + thedate.getSeconds()).substr(-2);\n      timecontrol.value = propvalue;\n    }\n\n    if (timecontrol.type !== 'time' && !timecontrol.whValidationPolyfilled) { //this browser doesn't natively support time fields\n      timecontrol.whValidationPolyfilled = true;\n      //ADDME some sort of global validator would be better so we don't get confused by fields that change their type\n      setupValidator(timecontrol, validateTime);\n    }\n  }\n\n  // Setup checkbox group (min/max checked) validation\n  for (const checkboxgroup of qSA(form, \".wh-form__fieldgroup--checkboxgroup\"))\n    setupValidator(checkboxgroup, validateCheckboxGroup);\n\n  // Setup radio group (hidden/disabled) validation\n  for (const radiogroup of qSA(form, \".wh-form__fieldgroup--radiogroup\")) {\n    setupValidator(radiogroup, validateRadioGroup);\n\n    //we should probably disable by name (or form.elements[name] but validate() and form isn't really tracking name either...\n    dompack.qSA<HTMLInputElement>(radiogroup, `input[type='radio']`).forEach(\n      node => node.dataset.whFormSkipnativevalidation = \"true\"); //don't handle by both RadioGroupField *and* native validation\n\n  }\n\n  // Setup address field validation\n  for (const addresscontrol of qSA(form, \".wh-form__fieldgroup--addressfield\"))\n    new AddressField(addresscontrol);\n}\n","/**\n * Get ISO-formatted local date from a date (getISOString returns an UTC datetime)\n *\n * @param date - Date to return\n * @returns Date as a YYYY-MM-DD string\n */\nexport function getISOLocalDate(date: Date) {\n  return date.getFullYear() + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2);\n}\n","/* eslint-disable @typescript-eslint/no-floating-promises -- FIXME: needs API rework */\n\nimport * as dompack from \"@webhare/dompack\";\nimport FormBase from \"../formbase\";\nimport { debugFlags } from \"@webhare/env\";\nimport { verifyHareScriptAddress, type HareScriptAddressValidationResult, type AddressChecks, type HareScriptAddressValue } from \"@webhare/forms/src/address\";\nimport { setFieldError } from \"../internal/customvalidation\";\nimport { throwError } from \"@webhare/std\";\n\nclass SubField {\n  node;\n  fieldgroup: HTMLElement;\n  pos: number;\n\n  constructor(node: dompack.FormControlElement, pos: number) {\n    this.node = node;\n    this.pos = pos;\n    this.fieldgroup = node.closest(\".wh-form__fieldgroup\") ?? throwError(\"Could not find fieldgroup for field\");\n  }\n}\n\ninterface OrderingData {\n  countries: string[];\n  fieldorder: string[];\n}\n\nexport default class AddressField {\n  numvaliditycalls = 0;\n  node: HTMLElement;\n  formnode: HTMLFormElement;\n  countryNode: HTMLSelectElement;\n  currentcountry: string;\n  fieldName: string;\n  orderingData: OrderingData[];\n  allFields = new Map<string, SubField>;\n  _updatingFields = false;\n\n  constructor(node: HTMLElement) {\n    this.node = node;\n    //We won't FormBase.getForNode yet here so we're not too dependent on registration ordering\n    this.formnode = node.closest(\"form\") ?? throwError(\"Could not find form for addressfield\");\n\n    // AddressField is initialized for the address's country field, so first find the other fields\n    this.countryNode = dompack.qR(this.node, \"select.wh-form__pulldown\"); //TODO why aren't we targetting by ID ? this will work but seems ambiguous\n    if (!this.countryNode)\n      throw new Error(\"Could not find country select node\");\n    if (!this.countryNode.dataset.orderingdata)\n      throw new Error(\"Addressfield not properly configured\");\n\n    this.currentcountry = this.countryNode.value;\n    this.fieldName = this.countryNode.name.substr(0, this.countryNode.name.lastIndexOf(\".\"));\n    this.orderingData = JSON.parse(this.countryNode.dataset.orderingdata) as OrderingData[];\n    const prefixLength = this.fieldName.length + 1; // fieldName + \".\"\n    this.allFields = new Map();\n    let fieldpos = 0;\n    this.allFields.set(this.countryNode.name.substr(prefixLength), new SubField(this.countryNode, ++fieldpos));\n\n    for (const field of dompack.qSA<HTMLInputElement | HTMLTextAreaElement>(this.formnode, `[name^='${this.fieldName}.']`)) {\n      this.allFields.set(field.name.substring(prefixLength), new SubField(field, ++fieldpos));\n\n      field.addEventListener(\"change\", event => this._gotFieldChange(event));\n    }\n\n    if (this.orderingData) {\n      this.countryNode.addEventListener(\"change\", () => this._reconfigureFieldOrdering());\n      this._reconfigureFieldOrdering();\n    }\n  }\n\n  _gotFieldChange(event: Event) {\n    if (this._updatingFields)\n      return; // We're updating our own fields\n\n    if (event.target === this.countryNode && this.currentcountry !== this.countryNode.value) {\n      //country changed. clear errors on all fields before revalidating.. otherwise the errors will just seem to 'linger' for a while after switching\n      this._clearErrors();\n      this.currentcountry = this.countryNode.value;\n    }\n\n    if (this._getFieldValue(\"country\") === \"NL\") {\n      if (!this._getFieldValue(\"zip\") || !this._getFieldValue(\"nr_detail\"))\n        return;\n    }\n    this._checkValidity(event);\n  }\n\n  _getFieldValue(fieldname: string) {\n    const data = this.allFields.get(fieldname);\n    if (data)\n      return data.node.value;\n    return \"\";\n  }\n\n  _getFirstCountrySpecificField() {\n    let firstfield = null;\n    for (const [key, field] of this.allFields.entries())\n      if (key !== \"country\" && !field.fieldgroup.classList.contains(\"wh-form__fieldgroup--hidden\") && (!firstfield || firstfield.pos > field.pos))\n        firstfield = field;\n\n    return firstfield ?? throwError(\"Cannot find field for error\");\n  }\n\n  _reconfigureFieldOrdering() {\n    const country = this.countryNode.value;\n    if (country) {\n      const ordering = this.orderingData.find(e => e.countries.length === 0 || e.countries.includes(country));\n      if (ordering) {\n        let prevgroup;\n        for (let idx = 0; idx < ordering.fieldorder.length; ++idx) {\n          const item = this.allFields.get(ordering.fieldorder[idx]);\n          if (!item)\n            continue; //ordering may appear to fields that have not been rendered, eg 'state'\n\n          item.pos = idx + 1;\n          const fieldgroup = item.fieldgroup;\n          if (prevgroup) {\n            const compareres = prevgroup!.compareDocumentPosition(fieldgroup);\n            if (compareres & Node.DOCUMENT_POSITION_PRECEDING)\n              prevgroup!.parentNode!.insertBefore(fieldgroup, prevgroup!.nextSibling);\n          }\n          prevgroup = fieldgroup;\n        }\n      }\n    }\n\n    //street + city should skip client side validation for NL, we will be looking it up server side (FIXME we should consider overwriting our validation to delay validation until address lookups are complete)\n    for (const fieldname of ['street', 'city']) {\n      const field = this.allFields.get(fieldname);\n      if (field)\n        if (country.toUpperCase() === 'NL')\n          field.node.setAttribute(\"data-wh-form-skipnativevalidation\", \"\");\n        else\n          field.node.removeAttribute(\"data-wh-form-skipnativevalidation\");\n    }\n  }\n\n  _clearErrors() {\n    this.allFields.forEach(field => setFieldError(field.node, \"\", { reportimmediately: true }));\n  }\n\n  _getCurState() {\n    const value: HareScriptAddressValue = { country: \"\" };\n    const visiblefields: HTMLElement[] = [];\n    let anyset = false, allrequiredset = true;\n    this.allFields.forEach((field, key) => {\n      if (!field.fieldgroup.classList.contains(\"wh-form__fieldgroup--hidden\")) {\n        visiblefields.push(field.node.closest(\".wh-form__fieldgroup\")!);\n        value[key as keyof HareScriptAddressValue] = field.node.value;\n\n        if (!anyset && key !== 'country' && field.node.value)\n          anyset = true;\n        if (field.node.required && !field.node.value && !field.node.hasAttribute(\"data-wh-form-skipnativevalidation\"))\n          allrequiredset = false;\n      }\n    });\n\n    return { value, visiblefields, anyset, allrequiredset, lookupkey: JSON.stringify(value) };\n  }\n\n  async _checkValidity(event: Event) {\n    const form = FormBase.getForNode(this.formnode) ?? throwError(\"Parent form for address field not yet initialized\");\n    /* we used to clear fields that are no longer visible after a country change, add visible fields to the value we're checking\n       but not sure why. ignoring those fields should be okay? and this is a very eager trigger, so if we really do this, do\n       this on base of the country actually changing, not an external checkbox controlling visibility of the whole country field\n       and a stray update event\n       */\n    const curstate = this._getCurState();\n    if (!curstate.anyset) { //fields are empty..\n      this._clearErrors();\n      return; //then don't validate\n    }\n    if (!curstate.allrequiredset)\n      return; //no need to validate if we don't even have the required fields in place\n\n    let result: HareScriptAddressValidationResult;\n    const lock = dompack.flagUIBusy();\n    try {\n      curstate.visiblefields.forEach(el => el.classList.add(\"wh-form__fieldgroup--addresslookup\"));\n      ++this.numvaliditycalls;\n      result = await verifyHareScriptAddress(curstate.value as HareScriptAddressValue, {\n        lang: form.getLangCode(),\n        checks: (this.node.dataset.checks?.split(' ') ?? []) as AddressChecks[]\n      });\n    } catch (e) {\n      console.error(`Error while validating value: ${e}`);\n      return;\n    } finally {\n      if (--this.numvaliditycalls === 0) //we're the last call\n        curstate.visiblefields.forEach(el => el.classList.remove(\"wh-form__fieldgroup--addresslookup\"));\n\n      lock.release();\n    }\n    if (this._getCurState().lookupkey !== curstate.lookupkey)\n      return; //abandon this _checkValidity call, the field has already changed.\n\n    if (debugFlags.fhv)\n      console.log(`[fhv] Validation result for address '${this.fieldName}': ${result.status}`);\n\n    if (debugFlags.fdv) {\n      if ([\"different_citystreet\", \"incomplete\"].includes(result.status))\n        console.warn(`[fdv] Address validation was performed, processing incomplete address (status: '${result.status}')`);\n      else {\n        console.warn(`[fdv] Ignoring return status '${result.status}' of address validation`);\n        result.status = \"ok\";\n      }\n    }\n\n    this._clearErrors();\n\n    for (const err of result.errors) {\n      const field = this.allFields.get(err.fields[0]) ?? this._getFirstCountrySpecificField();\n      if (field)\n        form.setFieldError(field.node, err.message, { reportimmediately: true });\n    }\n\n    if (result.corrections) {\n      let anychanges = false;\n      this._updatingFields = true;\n\n      for (const [key, newvalue] of Object.entries(result.corrections)) {\n        const field = this.allFields.get(key);\n        if (field && field.node.value !== newvalue) {\n          dompack.changeValue(field.node, newvalue);\n          anychanges = true;\n        }\n      }\n\n      this._updatingFields = false;\n      if (anychanges)\n        form.refreshConditions();\n    }\n  }\n}\n","/* eslint-disable @typescript-eslint/no-floating-promises -- FIXME: needs API rework */\n\nimport * as dompack from '@webhare/dompack';\nimport { type DocEvent, type FormControlElement, type TakeFocusEvent, addDocEventListener, isFormControl } from '@webhare/dompack';\nimport * as domfocus from 'dompack/browserfix/focus';\nimport * as webharefields from './internal/webharefields';\nimport * as merge from './internal/merge';\nimport './internal/requiredstyles.css';\nimport { type SetFieldErrorData, getValidationState, setFieldError, setupValidator, updateFieldError } from './internal/customvalidation';\nimport { generateRandomId, isPromise, wrapSerialized } from '@webhare/std';\nimport { debugFlags, isLive, navigateTo, type NavigateInstruction } from '@webhare/env';\nimport { getFieldDisplayName, isFieldNativeErrored, isRadioOrCheckbox, isRadioNodeList, type ConstrainedRadioNodeList, parseCondition, getFormElementCandidates, isFormFieldLike, queryFormFieldLike, getFieldName } from '@webhare/forms/src/domsupport';\nimport { rfSymbol } from '@webhare/forms/src/registeredfield';\nimport type { FormAnalyticsEventData, FormAnalyticsSubEvents, FormCondition, FormFileValue, RPCFormMessage } from '@webhare/forms/src/types';\nimport { FieldMapDataProxy, FormFieldMap } from '@webhare/forms/src/fieldmap';\nimport { submitselector, type SubmitSelectorType } from '@webhare/dompack/src/browser';\nimport type { FormSubmitDetails } from './rpc';\nimport type { FormConfiguration } from '@webhare/forms';\n\n//Suggestion or error messages\nexport type FormFrontendMessage = HTMLElement | string;\n\ndeclare global {\n  interface HTMLElement {\n    //TODO Clean this up, these are internal. Move to a weakobject ?\n    propWhFormSavedRequired?: boolean;\n    propWhFormSavedEnabled?: boolean;\n    propWhFormSavedHidden?: boolean;\n    //TODO And how does this differ from propWhFormSavedRequired?\n    propWhFormInitialRequired?: boolean;\n    propWhFormCurrentEnabled?: boolean;\n    propWhFormCurrentRequired?: boolean;\n    propWhFormCurrentVisible?: boolean;\n    //TODO It's suspicious that both propWhFormCurrent... and propWhNodeCurrent... exist\n    propWhNodeCurrentEnabled?: boolean;\n    propWhNodeCurrentRequired?: boolean;\n    propWhNodeCurrentHidden?: boolean;\n    propWhFormlineCurrentVisible?: boolean;\n    propWhValidationSuggestion?: FormFrontendMessage | null;\n    propWhCleanupFunction?: () => void;\n    /** @deprecated Use `getFormHandler` or `getFormData` from `@webhare/forms` to access the form's API */\n    propWhFormhandler?: FormBase<object>;\n    whFormsApiChecker?: () => Promise<void> | void;\n    whUseFormGetValue?: boolean;\n    whValidationPolyfilled?: boolean;\n    __didPlaceholderWarning?: boolean;\n  }\n\n  interface GlobalEventHandlersEventMap {\n    \"wh:form-enable\": CustomEvent<{ enabled: boolean }>;\n    \"wh:form-require\": CustomEvent<{ required: boolean }>;\n    \"wh:form-getvalue\": CustomEvent<{ deferred: PromiseWithResolvers<unknown> }>;\n    \"wh:form-setfielderror\": CustomEvent<SetFieldErrorData>; //TODO can we phase this out? it's a too deep integration\n    \"wh:form-configure\": CustomEvent<FormConfiguration>;\n    \"wh:form-pagechange\": CustomEvent<{\n      formHandler: FormBase<object>;\n      /** TODO Add numPages and currentPage, but we'd need to figure out how to properly account for Captcha pages (you don't want either numPages or currentPage to count that one)\n      numPages: number;\n      currentPage: number;\n      */\n    }>;\n    \"wh:form-preparesubmit\": CustomEvent<{ extrasubmit: Record<string, unknown> }>;\n    \"wh:form-response\": CustomEvent<FormSubmitResult>;\n    \"wh:form-submitted\": CustomEvent<FormSubmitDetails>;\n  }\n}\n\ntype ExtraData = unknown;\n\ntype FormControlDescription = {\n  name: string;\n  multi: false;\n  node: HTMLElement;\n} | {\n  name: string;\n  multi: true;\n  nodes: HTMLInputElement[];\n};\n\nexport type FormResultValue = Record<string, unknown>;\n\n/** The result returned to onSubmitSuccess */\nexport type FormSubmitEmbeddedResult<UserResult = { [key: string]: unknown }> = UserResult & {\n  //webtool submit additions. TODO a future API shouldn't mix these at the same level but allow them in the FormSubmitResult\n  submittype?: string;\n  richvalues?: RichValues;\n  resultsguid?: string;\n  submitinstruction?: NavigateInstruction;\n};\n\nexport interface FormSubmitMessage {\n  name: string;\n  message: string;\n  metadata: unknown;\n}\n\nexport interface FormSubmitResult {\n  success: boolean;\n  //TODO a next form iteration should not mix all these additional props into the form user's 'result'\n  result: FormSubmitEmbeddedResult;\n  errors: FormSubmitMessage[];\n  warnings: FormSubmitMessage[];\n  messages: RPCFormMessage[];\n}\n\ntype RichValues = Array<{ field: string; value: string }>;\n\nexport interface FieldErrorOptions {\n  serverside: boolean;\n  reportimmediately: boolean;\n  metadata?: unknown;\n}\n\ntype LimitSet = undefined | HTMLElement | HTMLElement[];\n\ninterface ValidationOptions {\n  // focusfailed Focus the first invalid element (defaults to true)\n  focusfailed?: boolean;\n  iffailedbefore?: boolean;\n}\n\ninterface FormValidationResult {\n  /// True if the fields successfuly validated\n  valid: boolean;\n  failed: HTMLElement[];\n  firstfailed: HTMLElement | null;\n}\n\ninterface ValidationQueueElement {\n  limitset?: LimitSet;\n  options?: ValidationOptions;\n  defer: PromiseWithResolvers<FormValidationResult>;\n}\n\ninterface PageState {\n  pages: HTMLElement[];\n  curpage: number;\n}\n\nlet delayvalidation = false, validationpendingfor: EventTarget | null = null;\nlet didGlobalHandlers: true | undefined;\n\n/** Convert linefeeds to BR tags */\nfunction lineFeedsToBreaks(text: string): DocumentFragment {\n  const frag = new DocumentFragment;\n  for (const part of text.split(/\\r?\\n/)) {\n    if (frag.childNodes.length)\n      frag.appendChild(document.createElement(\"br\"));\n    frag.append(part);\n  }\n  return frag;\n}\n\nfunction getPageIdx(state: PageState, page: number | HTMLElement) {\n  if (typeof page === 'number') {\n    if (page < 0 || page >= state.pages.length)\n      throw new Error(`Cannot navigate to nonexisting page #${page}`);\n    return page;\n  }\n\n  const idx = state.pages.indexOf(page);\n  if (idx === -1) {\n    console.error(`Cannot find page by element`, page);\n    throw new Error(`Cannot find page`);\n  }\n\n  return idx;\n}\n\nfunction getErrorFields(validationresult: FormValidationResult) {\n  return validationresult.failed.map(field => getFieldName(field) || field.dataset.whFormGroupFor || \"?\")\n    .sort()\n    .filter((value, index, self) => self.indexOf(value) === index) //unique filter\n    .join(\" \");\n}\nfunction hasEverFailed(field: HTMLElement) {\n  if (field.matches(\"input[type=radio],input[type=checkbox]\")) //these are handled by their group, so do the failed check there\n    return field.closest(\".wh-form__fieldgroup\")?.classList.contains('wh-form__field--everfailed');\n\n  return field.classList.contains('wh-form__field--everfailed');\n}\nfunction doValidation(field: EventTarget | null, iffailedbefore: boolean) {\n  if (iffailedbefore || validationpendingfor)\n    releasePendingValidations(); //release any earlier validation. this also cancels 'delayvalidation' but better safe than sorry if we double-run here\n\n  if (delayvalidation) { //Can't be \"iffailedbefore\" as that would have been cleared above\n    if (debugFlags.fhv)\n      console.log(\"[fhv] doValidation: validations are delayed. now pending: \", field);\n    validationpendingfor = field;\n    return;\n  }\n\n  const form = (field as HTMLElement).closest?.('form');\n  if (!form || !form.propWhFormhandler)\n    return;\n\n  const formhandler = form.propWhFormhandler;\n  formhandler.validate([field as HTMLElement], { focusfailed: false, iffailedbefore: iffailedbefore });\n}\n\n\nfunction doDelayValidation() {\n  if (delayvalidation)\n    releasePendingValidations();\n\n  delayvalidation = true;\n}\n\nfunction releasePendingValidations() {\n  if (!delayvalidation)\n    return;\n\n  delayvalidation = false;\n\n  if (validationpendingfor) {\n    const tovalidate = validationpendingfor;\n    if (debugFlags.fhv)\n      console.log(\"[fhv] releasePendingValidations: \", tovalidate);\n    validationpendingfor = null;\n    doValidation(tovalidate, false);\n  }\n}\n\n/* Browser extensions such as 1Password interfere with the event model and may\n   cause focusout to not fire for email and password fields. They don't seem\n   to break focusin so we'll watch focusin to detect missed focusout events */\nlet lastfocusout: EventTarget | null = null;\nfunction handleFocusOutEvent(event: FocusEvent) {\n  lastfocusout = event.target;\n  doValidation(event.target, false);\n}\nfunction handleFocusInEvent(event: FocusEvent) {\n  if (event.relatedTarget && lastfocusout !== event.relatedTarget)\n    doValidation(event.relatedTarget, false);\n}\n\nfunction handleValidateAfterEvent(event: Event) {\n  doValidation(event.target, true);\n}\n\nexport default class FormBase<DataShape extends object = Record<string, unknown>> extends FormFieldMap<DataShape> {\n  /** @deprecated Use node.elements if you want a true HTMLFormControlsCollection, use getElementByName since WH5.4+ for properly typed elements */\n  readonly elements: HTMLFormControlsCollection;\n  private _formsessionid = generateRandomId();\n  private _firstinteraction: number | undefined;\n  protected _submitstart: number | undefined;\n  private validationqueue = new Array<ValidationQueueElement>;\n  private _submitter: SubmitSelectorType | null = null;\n  private _submittimeout: NodeJS.Timeout | undefined;\n  /** Is the form currently interactive? Used to ignore changes done by code/setFieldValue */\n  private isInteractive = true;\n  /** Did we warn about old style form controls? */\n  private didLegacyWarning = false;\n  /** Are we currently in the _submit handler? (prevent duplicate submit attemps while eg. inside onBeforeSubmit) */\n  private inSubmit = false;\n  /** Where should the exitButton navigate to? */\n  private exitButtonNavigateTo?: NavigateInstruction;\n  /** Name of last focused element */\n  #lastFocused = \"\";\n\n  readonly data = new Proxy<DataShape>({} as DataShape, new FieldMapDataProxy(this));\n\n  constructor(public readonly node: HTMLFormElement) {\n    if (node.nodeName !== 'FORM')\n      throw new Error(\"Specified node is not a <form>\"); //we want our clients to be able to assume 'this.node.elements' works\n\n    super(\"\", getFormElementCandidates(node, ''));\n\n    this.elements = node.elements;\n    if (this.node.propWhFormhandler)\n      throw new Error(\"Specified node already has an attached form handler\");\n    this.node.propWhFormhandler = this;\n\n    //TODO Can we scope these handlers to the form ? Or register only once needed?\n    if (!didGlobalHandlers) {\n      didGlobalHandlers = true;\n      window.addEventListener(\"mouseup\", releasePendingValidations, true);\n      window.addEventListener(\"focusin\", handleFocusInEvent, true);\n    }\n\n    //Implement webhare fields extensions, eg 'now' for date fields or 'enablecomponents'\n    webharefields.setup(this.node);\n    //Implement page navigation\n    addDocEventListener(this.node, \"click\", evt => this._checkClick(evt));\n    addDocEventListener(this.node, \"dompack:takefocus\", evt => this._onTakeFocus(evt));\n    addDocEventListener(this.node, \"input\", evt => this._onInputChange(), { capture: true });\n    addDocEventListener(this.node, \"change\", evt => this._onInputChange(), { capture: true });\n    addDocEventListener(this.node, 'submit', evt => this._submit(evt, null));\n    addDocEventListener(this.node, 'wh:form-dosubmit', evt => { throw new Error(`wh:form-dosubmit is no longer supported`); });\n    addDocEventListener(this.node, \"wh:form-setfielderror\", evt => this._doSetFieldError(evt));\n    addDocEventListener(this.node, \"mousedown\", doDelayValidation);\n    addDocEventListener(this.node, \"focusout\", handleFocusOutEvent, { capture: true });\n    addDocEventListener(this.node, \"input\", handleValidateAfterEvent, { capture: true });\n    addDocEventListener(this.node, \"change\", handleValidateAfterEvent, { capture: true });\n    addDocEventListener(this.node, \"focusin\", this.#recordLastFocus, { capture: true });\n    this.node.noValidate = true;\n\n    this._rewriteEnableOn();\n    this._updateConditions(true); //Update required etc handlers\n    this._applyPrefills();\n\n    //Update page navigation\n    const pagestate = this._getPageState();\n    this._updatePageVisibility(pagestate.pages, 0);\n    this._updatePageNavigation();\n  }\n\n  static getForNode<DataShape extends object = Record<string, unknown>>(node: HTMLElement): FormBase<DataShape> | null {\n    return (node.propWhFormhandler as FormBase<DataShape>) || null;\n  }\n\n  ///like namedItem but improves on the types returned. does *not* lookup by data-wh-form-name!\n  getElementByName(name: string): FormControlElement | ConstrainedRadioNodeList | null {\n    return this.node.elements.namedItem(name) as FormControlElement | ConstrainedRadioNodeList | null;\n  }\n\n  /** Get language for this form */\n  getLangCode() {\n    return this.node.closest<HTMLElement>('[lang]')?.lang ?? 'en';\n  }\n\n  #recordLastFocus = (evt: dompack.DocEvent<FocusEvent>) => {\n    if (this.node.contains(evt.target)) {\n      const name = getFieldName(evt.target) || evt.target.dataset.whFormGroupFor;\n      if (name)\n        this.#lastFocused = name;\n    }\n  };\n\n  #onUnload = () => {\n    this.sendFormEvent({\n      event: 'abandoned',\n      lastfocused: this.#lastFocused,\n      pagenum: this.getCurrentPageNumber()\n    });\n  };\n\n  protected __formStarted() {\n  }\n\n  protected sendFormEvent(event?: FormAnalyticsSubEvents) {\n    const now = Date.now();\n    if (event?.event === 'submitted')\n      removeEventListener(\"pagehide\", this.#onUnload);\n\n    if (!this._firstinteraction) {   //The user hasn't interacted with the form yet\n      if (!this.isInteractive) { //ignore events triggered by code, eg a form prefill\n        if (event?.event && debugFlags.anl)\n          console.log(`[anl] Form is supressing broadcast of '${event?.event}' because it hasn't been interacted with yet`);\n        return;\n      }\n\n      //The user has interacted, start the clock!\n      this._firstinteraction = now; //set for calculation base *and* to prevent endless loops\n      this.sendFormEvent({ event: \"started\" });\n      addEventListener(\"pagehide\", this.#onUnload);\n    }\n\n    if (!event)\n      return; //we were only triggered to signal First Interaction\n    this._firstinteraction ||= now;\n\n    const pagestate = this._getPageState();\n    const eventdata: FormAnalyticsEventData = {\n      ...event,\n      id: this.node.dataset.whFormId || '',\n      session: this._formsessionid,\n      pagetitle: this._getPageTitle(pagestate.curpage),\n      pagenum: pagestate.curpage + 1,\n      time: now - this._firstinteraction,\n      objref: this.node.dataset.whFormObjref || ''\n    };\n\n    if (this._submitstart) //is set during a pending submission\n      eventdata.waittime = Date.now() - this._submitstart;\n\n    dompack.dispatchCustomEvent(this.node, \"wh:form-analytics\", { bubbles: true, cancelable: false, detail: eventdata });\n  }\n\n  _rewriteEnableOn() { //ADDME move this to webhare server\n    // EnablingComponents may set data-wh-form-enable. input(radio/checkbox) and option qualify\n    type EnablingComponent = HTMLInputElement | HTMLOptionElement;\n\n    // This is the initialization, check the enable components for all elements within the form\n    for (const control of dompack.qSA<EnablingComponent>(this.node, \"*[data-wh-form-enable]\"))\n      for (const element of control.dataset.whFormEnable!.split(\" \")) {\n        const target = this.getElementByName(element);\n        if (target && target instanceof HTMLElement) {\n          const name = (control instanceof HTMLOptionElement ? control.closest<HTMLSelectElement>(\"select\") : control)?.name;\n          if (!name) //duplicated node?\n            continue;\n\n          let ourcondition: FormCondition = { field: name, matchtype: \"IN\", value: control.value };\n          if (target.dataset.whFormEnabledIf) //append to existing criterium\n            ourcondition = { conditions: [parseCondition(target.dataset.whFormEnabledIf), ourcondition], matchtype: \"AND\" };\n          target.dataset.whFormEnabledIf = JSON.stringify({ c: ourcondition });\n        }\n      }\n  }\n\n  _applyPrefills() {\n    //Apply prefills. Set in field order, so controls-enabling-controls things will generally work\n    const searchparams = new URL(location.href).searchParams;\n    for (const field of this._queryAllFields()) {\n      const allvalues = searchparams.getAll(field.name);\n      if (!allvalues.length)\n        continue;\n\n      if (field.multi && field.nodes[0].type === 'checkbox') {\n        for (const node of field.nodes) {\n          const shouldbechecked = allvalues.includes(node.value);\n          if (shouldbechecked !== node.checked) //NOTE: used to read 'field.checked' which doesn't exist so this if() would always evaluate to true\n            this.setFieldValue(node, shouldbechecked);\n        }\n      } else if (field.multi) { //implies radio\n        const tocheck = field.nodes.filter(_ => _.value === allvalues[allvalues.length - 1])[0];\n        if (tocheck && !tocheck.checked)\n          this.setFieldValue(tocheck, true);\n        if (!tocheck)\n          field.nodes.filter(_ => _.checked).forEach(_ => this.setFieldValue(_, false));\n      } else if (field.node.matches(\"input:not([type=file]),select,textarea\")) { //Limit URL prefills to simple elements - TODO allow custom components to decide on this themselves OR *explicitly* require fields to opt-in to being prefillable\n        if (!this._isNowSettable(field.node))\n          continue;\n        this.setFieldValue(field.node, allvalues[allvalues.length - 1]); //last value wins\n      }\n    }\n  }\n\n  /**\n   * Set or update the message for the specified field\n   * @param field - node on which the validation triggered\n   * @param type - type of the message (\"error\" or \"suggestion\") - a field or group can have both an \"error\" and \"suggestion\" visible\n   * @param getError - function which returns a reference to the error node (or DocumentFragment) or a text\n   *\n   * .wh-form__field--error      - Used to indicate this element has an error\n   * .wh-form__field--suggestion - Used to indicate this element has an suggestion\n   * .wh-form__error             - The error message container\n   * .wh-form_suggestion         - The suggestion message container\n   */\n  _updateFieldGroupMessageState(field: HTMLElement, type: \"error\" | \"suggestion\", getError: (field: HTMLElement) => FormFrontendMessage | null) {\n    //Please note that _updateFieldGroupMessageState doesn't *validate* anything - it takes the current error/suggestion status and updates the DOM accordingly\n\n    /*\n    ADDME: ability to show multiple messages in case both the toplevel and a subfield have an error/suggestion.\n           Example: a checkboxgroup in which too many options are selected AND the required textfield of a selected option is empty.\n\n    ADDME: how should an error message reference a required nested textfield?\n\n    ADDME: Support progressive enhancements such as splitdatetime which use a native form element\n           to store the value. (it's probably confusing that aria-described by ends up on an\n           element which needs receives focus and cannot be used to influence/fix the value).\n           (such as the splitdatetime)\n\n           Suggestion for possible solution:\n           - have the progressive enchancement code add an attribute to the native form element\n             with the ID of the (group)element.\n    */\n    const fieldgroup = field.closest<HTMLElement>(\".wh-form__fieldgroup\");\n    //console.log(\"_updateFieldGroupMessageState\", field, fieldgroup);\n    if (!fieldgroup)\n      return;\n\n    /* Within the group this field belongs to we lookup the first node we can find which is marked as having the\n       type of message we want (\"error\" or \"suggestion\").\n       First we'll see if the fieldgroup wants to report something (radio & checkboxes handle their errors at the group level)\n       otherwise whe'll look for the first node which has a message.\n    */\n    const field_with_message = fieldgroup.classList.contains(\"wh-form__field--\" + type) ? fieldgroup : fieldgroup.querySelector<HTMLElement>(\".wh-form__field--\" + type);\n    //Do not pick up errors from deeper groups (array rows)\n    const error = (field_with_message && field_with_message.closest(\".wh-form__fieldgroup\") === fieldgroup ? getError(field_with_message) : null) || null;\n\n    // Now mark the whole .wh-form__fieldgroup as having an error/suggestion\n    fieldgroup.classList.toggle(\"wh-form__fieldgroup--\" + type, Boolean(error));\n\n    // Lookup the error message from the field metadata\n    if (error) { //mark the field has having failed at one point. we will now switch to faster updating error state\n      if (!field.classList.contains('wh-form__field--everfailed')) {\n        if (debugFlags.fhv)\n          console.log('[fhv] marking as everfailed', field, 'because of error', error);\n        field.classList.add('wh-form__field--everfailed');\n      }\n    }\n\n    // Determine the contextnode to set ARIA attributes on\n\n    // ADDME: before looking up a group, check if there an attribute specifying\n    //        another element with role=\"group\" handled the input.\n\n    // Find the first role=\"group\" we can find\n    // (ineither the .wh-form__subfield or .wh-form__field)\n    const potentialgroupnode = field.closest<HTMLElement>(\"[role=group],.wh-form__subfield,wh-form__fieldgroup\");\n    const group = potentialgroupnode?.role === \"group\" ? potentialgroupnode : null;\n    const contextnode = group ?? field;\n\n    let messageid = \"\";\n    let messagenode = fieldgroup.querySelector(\".wh-form__\" + type); //either wh-form__error or wh-form__suggestion\n\n    // Create a container for the suggestion or error\n    if (messagenode) {\n      messageid = messagenode.id; // reuse the existing messagenode\n    } else {\n      if (!error)\n        return; //nothing to do\n\n      // Generate a temporary id for the message which we can use in\n      // the aria-describedby to point to the message.\n      const random = Math.floor((1 + Math.random()) * 0x10000000).toString(16);\n      messageid = \"whform-msg-\" + random; // `${fieldname}-${random}`;\n\n      const suggestionholder = field.closest('.wh-form__fields') || fieldgroup.querySelector('.wh-form__fields') || fieldgroup;\n      messagenode = dompack.create(\"div\", { className: \"wh-form__\" + type }); // add a wh-form__error or wh-form__suggestion message container\n      messagenode.id = messageid; // id to reference to in the aria-describedby\n      suggestionholder.appendChild(messagenode);\n    }\n\n    if (error) { // Do we show a message?\n      messagenode.replaceChildren(typeof error === \"string\" ? lineFeedsToBreaks(error) : error);\n      this._addDescribedBy(contextnode, messageid);\n\n      if (type === \"error\")\n        contextnode.setAttribute(\"aria-invalid\", \"true\");\n    } else {\n      messagenode.replaceChildren(); // remove previous errors/suggestions texts from the errornode\n      this._removeDescribedBy(contextnode, messageid);\n      contextnode.removeAttribute(\"aria-invalid\");\n    }\n\n  }\n\n  // add the specified id of the message element to the list of elements in aria-describedby\n  _addDescribedBy(contextnode: HTMLElement, messageid: string) {\n    const describedby = contextnode.getAttribute(\"aria-describedby\") ?? \"\";\n    const describedby_fields = describedby !== \"\" ? describedby.split(\" \") : [];\n\n    if (describedby_fields.indexOf(messageid) === -1) {\n\n      describedby_fields.push(messageid);\n      contextnode.setAttribute(\"aria-describedby\", describedby_fields.join(\" \"));\n    }\n  }\n\n  // remove the specified id of the message element from the list of elements in aria-describedby\n  _removeDescribedBy(contextnode: HTMLElement, messageid: string) {\n    const describedby = contextnode.getAttribute(\"aria-describedby\") ?? \"\";\n    const describedby_fields = describedby !== \"\" ? describedby.split(\" \") : [];\n\n    for (let idx = 0; idx < describedby_fields.length; idx++) {\n      if (describedby_fields[idx] === messageid) {\n        describedby_fields.splice(idx, 1); // remove that item\n        break;\n      }\n    }\n\n    if (describedby_fields.length > 0)\n      contextnode.setAttribute(\"aria-describedby\", describedby_fields.join(\" \"));\n    else\n      contextnode.removeAttribute(\"aria-describedby\");\n  }\n\n  _updateFieldGroupErrorState(field: HTMLElement) {\n    this._updateFieldGroupMessageState(field, 'error', failedfield => getValidationState(failedfield).getError());\n  }\n\n  _updateFieldGroupSuggestionState(field: HTMLElement) {\n    this._updateFieldGroupMessageState(field, 'suggestion', failedfield => failedfield.propWhValidationSuggestion || '');\n  }\n\n  _doSetFieldError(evt: DocEvent<CustomEvent<SetFieldErrorData>>) {\n    //FIXME properly handle multiple fields in this group reporting errors\n    dompack.stop(evt);\n\n\n    this._reportFieldValidity(evt.target);\n  }\n\n  /** @returns false on error */\n  _reportFieldValidity(node: HTMLElement): boolean {\n    const state = getValidationState(node).getState();\n    node.classList.toggle(\"wh-form__field--error\", Boolean(state?.error));\n    node.classList.toggle(\"wh-form__field--suggestion\", Boolean(state?.suggested));\n\n    this._updateFieldGroupErrorState(node);\n    this._updateFieldGroupSuggestionState(node);\n    return !(state && \"error\" in state);\n  }\n\n  //validate and submit. normal submissions should use this function, directly calling submit() skips validation and busy locking\n  async validateAndSubmit(extradata: ExtraData) {\n    await this._submit(null, extradata);\n  }\n\n  /** Override beforeSubmit to have a last chance to block/confirm actual form submission\n   * @returns true to continue submitting\n  */\n  beforeSubmit(extradata: ExtraData): boolean | Promise<boolean> {\n    return true;\n  }\n\n  async _submit(evt: SubmitEvent | null, extradata: ExtraData) {\n    if (this.node.classList.contains('wh-form--submitting') || this.inSubmit) { //already submitting\n      evt?.preventDefault(); //avoid 'No RPC handler installed' noise during 429 errors\n      return;\n    }\n\n    //A form element's default button is the first submit button in tree order whose form owner is that form element.\n    const submitter = this._submitter || this.node.querySelector(submitselector);\n    this._submitter = null;\n\n    if (debugFlags.fhv)\n      console.log('[fhv] received submit event, submitter:', submitter);\n\n    let tempbutton = null;\n    if (submitter) { //temporarily add a hidden field representing the selected button\n      tempbutton = document.createElement('input');\n      tempbutton.name = submitter.name;\n      tempbutton.value = submitter.value;\n      tempbutton.type = \"hidden\";\n      this.node.appendChild(tempbutton);\n    }\n\n    try {\n      this.inSubmit = true;\n      const beforeResult = this.beforeSubmit(extradata);\n      if (!beforeResult || (isPromise(beforeResult) && !await beforeResult))\n        return;\n\n      /* DEPRECATED - Switch to onBeforeSubmit in 5.7+ */\n      if (!dompack.dispatchCustomEvent(this.node, 'wh:form-beforesubmit', { bubbles: true, cancelable: true })) { //allow parsley to hook into us\n        console.error(\"The use of wh:form-beforesubmit is deprecated and will be removed in a future version. Use onBeforeSubmit instead\");\n        return;\n      }\n\n      await this._doSubmit(evt, extradata);\n    } finally {\n      tempbutton?.remove();\n      this.inSubmit = false;\n    }\n  }\n\n  private _shouldValidateField(el: HTMLElement) {\n    //TODO maybe we can get rid of the data attributes by checking for explicit symbols like whFormsApiChecker\n    return (el.whFormsApiChecker || el.matches(`${queryFormFieldLike},*[data-wh-form-name],*[data-wh-form-custom-validator`)) &&\n      this._isPartOfForm(el);\n  }\n\n  _getFieldsToValidate(startingpoint?: HTMLElement) {\n    return dompack.qSA<HTMLElement>(startingpoint ?? this.node, \"*\").filter(el => this._shouldValidateField(el));\n  }\n\n  //reset any serverside generated errors (generally done when preparing a new submission)\n  resetServerSideErrors() {\n    for (const field of this._getFieldsToValidate()) {\n      const state = getValidationState(field);\n      if (state?.explicit?.serverside && field.propWhCleanupFunction)\n        field.propWhCleanupFunction();\n    }\n  }\n\n  async _doSubmit(evt: SubmitEvent | null, extradata: ExtraData) {\n    if (evt)\n      evt.preventDefault();\n\n    const lock = dompack.flagUIBusy({ modal: true });\n    this._submitstart = Date.now();\n    this._submittimeout = setTimeout(() => this._submitHasTimedOut(), 5000);\n    this.node.classList.add('wh-form--submitting');\n\n    try {\n      this.resetServerSideErrors();\n\n      const validationresult = await this.validate();\n      if (validationresult.valid) {\n        const result = await this.submit(extradata);\n        if (result.result && result.result.submittype && result.result.submittype !== this._getVariableValueForConditions(\"formsubmittype\")) {\n          this.node.setAttribute(\"data-wh-form-var-formsubmittype\", result.result.submittype);\n          this._updateConditions(false);\n        }\n      } else {\n        this.sendFormEvent({ event: \"failed\", errorfields: getErrorFields(validationresult), errorsource: 'client' });\n      }\n    } finally {\n      lock.release();\n      this.node.classList.remove('wh-form--submitting');\n      if (this._submittimeout) {\n        clearTimeout(this._submittimeout);\n        this._submittimeout = undefined;\n      }\n      this._submitstart = undefined;\n    }\n  }\n\n  _submitHasTimedOut() { //TODO extend this to (background) RPCs too, and make waitfor more specific. also check whether we're stuck on client or server side\n    this.sendFormEvent({ event: \"slow\", waitfor: \"submit\" });\n  }\n\n  //default submission function. eg. RPC will override this\n  async submit(extradata?: ExtraData): Promise<{ result?: FormSubmitEmbeddedResult }> {\n    this.node.submit();\n    return {};\n  }\n\n  _onTakeFocus(evt: DocEvent<TakeFocusEvent>) {\n    const containingpage = evt.target.closest('.wh-form__page');\n    if (containingpage && containingpage.classList.contains('wh-form__page--hidden')) {\n      //make sure the page containing the errored component is visible\n      const pagenum = dompack.qSA(this.node, '.wh-form__page').findIndex(page => page === containingpage);\n      if (pagenum >= 0)\n        this.gotoPage(pagenum);\n    }\n  }\n\n  _checkClick(evt: DocEvent<MouseEvent>) {\n    const actionnode = evt.target?.closest<HTMLElement>(\"*[data-wh-form-action]\");\n    if (!actionnode) {\n      const submitter = evt.target.closest<SubmitSelectorType>(submitselector);\n      if (submitter?.form === this.node) { //if we found the submit buton AND it's for *this* form. don't intercept otherwise\n        if (!this.node.classList.contains('wh-form--allowsubmit')) { //we're not allowed to submit yet (not on a final page)\n          dompack.stop(evt);\n          if (this.node.classList.contains('wh-form--allownext'))  //but we can convert your action to a NextPage! which is likely what you intended\n            this.executeFormAction('next');\n          return;\n        }\n\n        this._submitter = submitter; //store as submitter in case a submit event actually occurs\n        setTimeout(() => this._submitter = null); //but clear it as soon as event processing ends\n      }\n      return;\n    }\n\n    dompack.stop(evt);\n    this.executeFormAction(actionnode.dataset.whFormAction!);\n  }\n\n  private _getPageState(): PageState {\n    const pages = dompack.qSA<HTMLElement>(this.node, '.wh-form__page');\n    const curpage = pages.findIndex(page => !page.classList.contains('wh-form__page--hidden'));\n    return { pages, curpage };\n  }\n\n  _updatePageVisibility(pagelist: HTMLElement[], currentpage: number) {\n    pagelist.forEach((page, idx) => {\n      page.classList.toggle('wh-form__page--hidden', idx !== currentpage);\n      page.classList.toggle('wh-form__page--visible', idx === currentpage);\n    });\n  }\n\n  ///Get the currently opened page (page node)\n  getCurrentPage() {\n    const state = this._getPageState();\n    return state.curpage >= 0 ? state.pages[state.curpage] : null;\n  }\n\n  /** Position the specified element's group or the form itself into view, using `.wh-anchor` nodes to correct for fixed headers\n      @param scrollto -  Element to position into view. If not set, the form it scrolled into view */\n  scrollIntoView(scrollto?: HTMLElement) {\n    const origscrollto = scrollto;\n    scrollto = (scrollto ? scrollto.closest<HTMLElement>('.wh-form__fieldgroup') : undefined) || this.node;\n    scrollto = scrollto.querySelector<HTMLElement>('.wh-anchor') || scrollto;\n    if (origscrollto && scrollto !== origscrollto && debugFlags.fhv)\n      console.log('[fhv] Modified scroll target from ', origscrollto, ' to anchor ', scrollto);\n    else if (debugFlags.fhv)\n      console.log('[fhv] Scroll to ', scrollto);\n\n    scrollto.scrollIntoView();\n  }\n\n  /** Get the current page number\n      @returns 0-based index of page to jump to */\n  getCurrentPageNumber() {\n    return this._getPageState().curpage;\n  }\n\n  /** Goto a specific page\n      @param page - 0-based index of page or the HTML element of the page to jump to */\n  async gotoPage(page: number | HTMLElement, { __isSubmit = false } = {}): Promise<void> {\n    const state = this._getPageState();\n    const pageidx = getPageIdx(state, page);\n    if (state.curpage === pageidx)\n      return;\n\n    const goingforward = pageidx > state.curpage;\n    if (!__isSubmit)\n      this.sendFormEvent({\n        event: goingforward ? __isSubmit ? 'submitted' : 'nextpage' : 'previouspage',\n        targetpagenum: pageidx + 1,\n        targetpagetitle: this._getPageTitle(pageidx)\n      });\n\n    this._updatePageVisibility(state.pages, pageidx);\n    if (goingforward) //only makes sense to update if we're making progress\n      merge.run(state.pages[pageidx], { form: await this.getFormValue() });\n\n    this._updatePageNavigation();\n\n    //scroll back up\n    this.scrollIntoView();\n\n    /* tell the page it's now visible - note that we specifically don't fire this on init, as it's very likely\n       users would 'miss' the event anyway - registerHandler usually executes faster than your wh:form-pagechange\n       registrations, if you wrapped those in a dompack.register */\n    dompack.dispatchCustomEvent(state.pages[pageidx], \"wh:form-pagechange\", { bubbles: true, cancelable: false, detail: { formHandler: this } });\n  }\n\n  private _getDestinationPage(pagestate: PageState, direction: number) {\n    let pagenum = pagestate.curpage + direction;\n    //TODO \"captcha\" should no longer exist since WH5.9 - unless there are still some static published forms around, so keep skipping them for a while\n    while (pagenum >= 0 && pagenum < pagestate.pages.length && (pagestate.pages[pagenum].propWhFormCurrentVisible === false || pagestate.pages[pagenum].dataset.whFormPagerole === \"captcha\"))\n      pagenum = pagenum + direction;\n    if (pagenum < 0 || pagenum >= pagestate.pages.length)\n      return -1;\n    return pagenum;\n  }\n\n  _getPageTitle(pagenum: number) {\n    const pagenode = this._getPageState().pages[pagenum];\n    if (!pagenode)\n      return \"\";\n    return pagenode.dataset.whFormPagetitle || (\"#\" + (pagenum + 1));\n  }\n\n  async executeFormAction(action: string) {\n    switch (action) {\n      case 'previous':\n        {\n          if (this.node.classList.contains('wh-form--allowprevious')) {\n            const pagestate = this._getPageState();\n            if (pagestate.curpage > 0)\n              this.gotoPage(this._getDestinationPage(pagestate, -1));\n            else if (this.node.dataset.whFormBacklink)\n              navigateTo({ type: \"redirect\", url: this.node.dataset.whFormBacklink });\n          }\n          return;\n        }\n      case 'next':\n        {\n          const pagestate = this._getPageState();\n          if (this.node.classList.contains('wh-form--allownext')) {\n            this.resetServerSideErrors();\n\n            const validationstatus = await this.validate(pagestate.pages[pagestate.curpage]);\n            if (validationstatus.valid) {\n              this.gotoPage(this._getDestinationPage(pagestate, +1));\n            } else {\n              this.sendFormEvent({ event: \"failed\", errorfields: getErrorFields(validationstatus), errorsource: 'nextpage' });\n            }\n          }\n          return;\n        }\n      case 'exit': {\n        if (!this.exitButtonNavigateTo)\n          throw new Error(\"No exit navigation target set for this form\");\n\n        navigateTo(this.exitButtonNavigateTo);\n        return;\n      }\n      default: {\n        console.error(`Unknown form action '${action}'`);\n      }\n    }\n  }\n\n  async refreshConditions() {\n    await this._updateConditions(false);\n  }\n\n  _onInputChange() {\n    this.sendFormEvent(); //only trigger implicit _firstinteraction event\n    this._updateConditions(false);\n  }\n\n  async _updateConditions(isinit: boolean) {\n    // Check pages visibility\n    const hiddenPages = [];\n    const mergeNodes = [];\n    let anychanges = false;\n\n    for (const formpage of dompack.qSA(this.node, \".wh-form__page\")) {\n      let visible = true;\n      if (formpage.dataset.whFormVisibleIf) {\n        visible = this._matchesCondition(formpage.dataset.whFormVisibleIf);\n        if (!visible)\n          hiddenPages.push(formpage); // We don't have to check fields on this page any further\n\n        if (visible !== formpage.propWhFormCurrentVisible) {\n          anychanges = true;\n          formpage.propWhFormCurrentVisible = visible;\n          mergeNodes.push(formpage);\n        }\n      }\n    }\n    if (anychanges)\n      this._updatePageNavigation();\n\n    const tovalidate = new Array<HTMLElement>;\n    const hiddengroups = [], enabledgroups = [], requiredgroups = [];\n    for (const formgroup of dompack.qSA(this.node, \".wh-form__fieldgroup\")) {\n      const groupPage = formgroup.closest<HTMLElement>(\".wh-form__page\");\n      const visible = (!groupPage || !hiddenPages.includes(groupPage)) && this._matchesCondition(formgroup.dataset.whFormVisibleIf);\n      if (!visible)\n        hiddengroups.push(formgroup);\n\n      const enabled = visible\n        && this._matchesCondition(formgroup.dataset.whFormEnabledIf);\n\n      if (enabled)\n        enabledgroups.push(formgroup);\n\n      //load initial status?\n      if (formgroup.propWhFormInitialRequired === undefined)\n        formgroup.propWhFormInitialRequired = formgroup.classList.contains(\"wh-form__fieldgroup--required\");\n\n      const required = enabled\n        && (formgroup.dataset.whFormRequiredIf ? this._matchesCondition(formgroup.dataset.whFormRequiredIf) : formgroup.propWhFormInitialRequired);\n\n      if (required)\n        requiredgroups.push(formgroup);\n\n      if (visible !== formgroup.propWhFormCurrentVisible // These are initially undefined, so this code will always run first time\n        || enabled !== formgroup.propWhFormCurrentEnabled\n        || required !== formgroup.propWhFormCurrentRequired) {\n        formgroup.propWhFormCurrentVisible = visible;\n        formgroup.propWhFormCurrentEnabled = enabled;\n        formgroup.propWhFormCurrentRequired = required;\n\n        formgroup.classList.toggle(\"wh-form__fieldgroup--disabled\", !enabled);\n        formgroup.classList.toggle(\"wh-form__fieldgroup--hidden\", !visible);\n        formgroup.classList.toggle(\"wh-form__fieldgroup--required\", required);\n\n        mergeNodes.push(formgroup);\n      }\n    }\n\n    for (const formline of dompack.qSA(this.node, \".wh-form__fieldline\")) {\n      const formgroup = formline.closest<HTMLElement>(\".wh-form__fieldgroup\");\n      if (!formgroup)\n        continue;\n      const visible = !hiddengroups.includes(formgroup) && this._matchesCondition(formline.dataset.whFormVisibleIf);\n      const enabled = visible && enabledgroups.includes(formgroup) && this._matchesCondition(formline.dataset.whFormEnabledIf);\n      const required = enabled && requiredgroups.includes(formgroup);\n\n      if (visible !== formline.propWhFormlineCurrentVisible) {  // These are initially undefined, so this code will always run first time\n        formline.propWhFormlineCurrentVisible = visible;\n        formline.classList.toggle(\"wh-form__fieldline--hidden\", !visible);\n      }\n\n      // Look for nodes that are explicit enable state (enablee/require) listeners, or that need to do so because they're real input controls\n      const inputtargets = dompack.qSA(formline, `${queryFormFieldLike},[data-wh-form-state-listener='true']`);\n\n      for (const node of inputtargets) {\n        //Record initial states\n        if (node.propWhFormSavedEnabled === undefined)\n          node.propWhFormSavedEnabled = \"disabled\" in node ? !node.disabled : !(\"whFormDisabled\" in node.dataset);\n\n        if (node.propWhFormSavedRequired === undefined)\n          node.propWhFormSavedRequired = Boolean(\"required\" in node && node.required);\n\n        // The field is enabled if all of these are matched:\n        // - we're setting it to enabled now\n        // - it hasn't been disabled explicitly (set initially on the node)\n        // - it hasn't been disabled through enablecomponents\n        const node_enabled = enabled && node.propWhFormSavedEnabled && this._matchesCondition(node.dataset.whFormEnabledIf);\n\n        if (node_enabled !== node.propWhNodeCurrentEnabled) {\n          node.propWhNodeCurrentEnabled = node_enabled;\n\n          // Give the formgroup a chance to handle it\n          if (dompack.dispatchCustomEvent(node, \"wh:form-enable\", { bubbles: true, cancelable: true, detail: { enabled: node_enabled } })) {\n            // Not cancelled, so run our default handler\n            if (isFormFieldLike(node)) //For true html5 inputs we'll use the native attributes. formstatelisteners: we use data attributes\n              node.disabled = !node_enabled;\n            else if (node_enabled)\n              node.removeAttribute(\"data-wh-form-disabled\");\n            else\n              node.setAttribute(\"data-wh-form-disabled\", \"\");\n          }\n\n          if (!isinit && !node_enabled && !tovalidate.includes(node))\n            tovalidate.push(node); // to clear errors for this disabled field\n        }\n\n        const node_required = (node.propWhFormSavedRequired || required) && node_enabled && visible;\n        if (node.propWhNodeCurrentRequired !== node_required) {\n          node.propWhNodeCurrentRequired = node_required;\n\n          // Give the formgroup a chance to handle it\n          if (dompack.dispatchCustomEvent(node, \"wh:form-require\", { bubbles: true, cancelable: true, detail: { required: node_required } })) {\n            // Not cancelled, so run our default handler\n            if (isFormFieldLike(node)) { //For true html5 inputs we'll use the native attributes. formstatelisteners: we use data attributes\n              if (!isFormControl(node) || node.type !== 'checkbox') //don't set required on checkboxes, that doesn't do what you want\n                node.required = node_required;\n            } else if (node_required)\n              node.setAttribute(\"data-wh-form-required\", \"\");\n            else\n              node.removeAttribute(\"data-wh-form-required\");\n          }\n\n          if (!isinit && !node_required && formgroup.classList.contains(\"wh-form__fieldgroup--error\") && !tovalidate.includes(node))\n            tovalidate.push(node); // to clear errors for this now optional field\n        }\n      }\n    }\n\n    for (const option of dompack.qSA<HTMLOptionElement>(this.node, \".wh-form__fieldgroup select option\")) {\n      const visible = this._matchesCondition(option.dataset.whFormVisibleIf);\n\n      //Record initial states\n      if (option.propWhFormSavedEnabled === undefined)\n        option.propWhFormSavedEnabled = !option.disabled;\n      if (option.propWhFormSavedHidden === undefined)\n        option.propWhFormSavedHidden = option.hidden;\n\n      const option_enabled = visible && option.propWhFormSavedEnabled;\n      const option_hidden = !visible || option.propWhFormSavedHidden;\n\n      if (option_enabled !== option.propWhNodeCurrentEnabled || option_hidden !== option.propWhNodeCurrentHidden) {\n        option.propWhNodeCurrentEnabled = option_enabled;\n        option.propWhNodeCurrentHidden = option_hidden;\n        option.disabled = !option_enabled;\n        option.hidden = option_hidden;\n\n        // If this option was the selected option, but is now disabled (but not the placeholder), reset the select's value\n        const selectnode = option.closest<HTMLSelectElement>(\"select\");\n        if (selectnode && option.selected && (!option_enabled || option_hidden) && option.dataset.placeholder === undefined) {\n          if (selectnode.options[0].dataset.placeholder !== undefined) { //we have a placeholder...\n            selectnode.selectedIndex = 0;\n          } else {\n            selectnode.selectedIndex = -1;\n            if (!selectnode.__didPlaceholderWarning) {\n              selectnode.__didPlaceholderWarning = true;\n              console.warn(\"This <select> lacks an explicit placeholder so we had to set selectedIndex to -1\", selectnode);\n            }\n          }\n        }\n\n        if (selectnode && !isinit && !tovalidate.includes(selectnode))\n          tovalidate.push(selectnode); // to clear errors for this option's select field\n      }\n    }\n\n    if (tovalidate.length)\n      await this.validate(tovalidate, { focusfailed: false, iffailedbefore: true });\n\n    this.fixupMergeFields(mergeNodes);\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-misused-promises -- FIXME: needs API rework\n  __scheduleUpdateConditions = wrapSerialized(() => this._updateConditions(false), { coalesce: true });\n\n  async fixupMergeFields(nodes: HTMLElement[]) {\n    // Rename the data-wh-merge attribute to data-wh-dont-merge on hidden pages and within hidden formgroups to prevent\n    // merging invisible nodes\n    // FIXME 'merge' has a filter option now - convert to that!\n    const formvalue = await this.getFormValue();\n    for (const node of nodes) {\n      if (node.propWhFormCurrentVisible) {\n        for (const mergeNode of dompack.qSA(node, '*[data-wh-dont-merge]')) {\n          mergeNode.dataset.merge = mergeNode.dataset.whDontMerge;\n          mergeNode.removeAttribute(\"data-wh-dont-merge\");\n        }\n        merge.run(node, { form: formvalue });\n      } else {\n        for (const mergeNode of dompack.qSA(node, '*[data-merge]')) {\n          mergeNode.dataset.whDontMerge = mergeNode.dataset.merge;\n          mergeNode.removeAttribute(\"data-merge\");\n        }\n      }\n    }\n  }\n\n  _matchesCondition(conditiontext: string | undefined) {\n    if (!conditiontext)\n      return true;\n\n    return this._matchesConditionRecursive(parseCondition(conditiontext));\n  }\n\n  _getConditionRawValue(fieldname: string, options?: { checkdisabled?: boolean }) {\n    if (this.node.hasAttribute(\"data-wh-form-var-\" + fieldname))\n      return this.node.getAttribute(\"data-wh-form-var-\" + fieldname);\n\n    const matchfield = this.getElementByName(fieldname);\n    if (!matchfield) {\n      console.error(`No match for conditional required field '${fieldname}'`);\n      return null;\n    }\n\n    if (isRadioNodeList(matchfield)) {\n      let currentvalue = null;\n\n      for (const field of matchfield)\n        if (((options && options.checkdisabled) || this._isNowSettable(field)) && field.checked) {\n          if (field.type !== \"checkbox\")\n            return field.value;\n\n          if (!currentvalue)\n            currentvalue = [];\n          currentvalue.push(field.value);\n        }\n      return currentvalue;\n    } else {\n      //Can we set this field?\n      if ((!options || !options.checkdisabled) && !this._isNowSettable(matchfield))\n        return null;\n    }\n\n    if (matchfield.type === \"checkbox\")\n      return (matchfield as HTMLInputElement).checked ? [matchfield.value] : null;\n\n    if (matchfield.type === \"radio\")\n      return (matchfield as HTMLInputElement).checked ? matchfield.value : null;\n\n    return matchfield.value;\n  }\n\n  _getVariableValueForConditions(conditionfield: string, options?: { matchcase?: boolean; checkdisabled?: boolean }) {\n    if (this.node.hasAttribute(\"data-wh-form-var-\" + conditionfield))\n      return this.node.getAttribute(\"data-wh-form-var-\" + conditionfield);\n\n    const fields = conditionfield.split(\"$\");\n\n    if (fields.length > 1) {\n      // If the condition field has a subfield, check if it's available through a form var\n      // The '$' in the attribute name is replaced with '.' to make the attribute name valid\n      const attrname = fields.join(\".\");\n      if (this.node.hasAttribute(\"data-wh-form-var-\" + attrname))\n        return this.node.getAttribute(\"data-wh-form-var-\" + attrname);\n    }\n\n    let currentvalue = this._getConditionRawValue(fields[0], options);\n    if (fields.length === 1 || currentvalue === null) //no subs to process\n      return currentvalue;\n\n    // Look for an extrafield match\n    const matchfield = this.getElementByName(fields[0]);\n    if (!matchfield) {\n      console.error(`No match for conditional required field '${conditionfield}'`);\n      return null;\n    }\n\n    if (matchfield instanceof HTMLSelectElement) {\n      if (Array.isArray(currentvalue)) {\n        const selectedvalue = currentvalue;\n        currentvalue = [];\n        for (const val of selectedvalue) {\n          const selected = dompack.qS<HTMLOptionElement>(matchfield, `option[value=\"${CSS.escape(val)}\"]`);\n          if (!selected?.dataset.__extrafields)\n            return null;\n          const extrafields = JSON.parse(selected.dataset.__extrafields);\n          currentvalue.push(extrafields[fields[1]]);\n        }\n      } else {\n        const selected = dompack.qS<HTMLOptionElement>(matchfield, `option[value=\"${CSS.escape(currentvalue)}\"]`);\n        if (!selected?.dataset.__extrafields)\n          return null;\n        const extrafields = JSON.parse(selected.dataset.__extrafields);\n        currentvalue = extrafields[fields[1]];\n      }\n      return currentvalue;\n    } else {\n      console.error(\"Subfield matching not supported for non-select fields\");\n      return null;\n    }\n  }\n\n\n  _matchesConditionRecursive(condition: FormCondition): boolean {\n    switch (condition.matchtype) {\n      case \"AND\":\n        for (const subcondition of condition.conditions)\n          if (!this._matchesConditionRecursive(subcondition))\n            return false;\n        return true;\n\n      case \"OR\":\n        for (const subcondition of condition.conditions)\n          if (this._matchesConditionRecursive(subcondition))\n            return true;\n        return false;\n\n      case \"NOT\":\n        return !this._matchesConditionRecursive(condition.condition);\n\n      case \"AGE<\":\n      case \"AGE>=\": {\n        const currentvalue = this._getVariableValueForConditions(condition.field);\n        if (!currentvalue)\n          return false;\n\n        const now = new Date, birthdate = new Date(Array.isArray(currentvalue) ? currentvalue[0] : currentvalue); //should never be an array, but _getVariableValueForConditions is generic\n        let age = now.getFullYear() - birthdate.getFullYear();\n        //birthdate not hit yet this year? then you lose a year\n        if (now.getMonth() < birthdate.getMonth()\n          || (now.getMonth() === birthdate.getMonth() && now.getDate() < birthdate.getDate())) {\n          --age;\n        }\n\n        return (condition.matchtype === 'AGE<' ? age < condition.value : age >= condition.value);\n      }\n    }\n\n    const currentvalue = this._getVariableValueForConditions(condition.field, condition.options);\n\n    if (condition.matchtype === \"HASVALUE\")\n      return Boolean(currentvalue) === Boolean(condition.value);\n\n    if ([\"IN\", \"HAS\", \"IS\"].includes(condition.matchtype)) {\n      const matchcase = condition.options?.matchcase !== false; // Defaults to true\n      const compareagainst = Array.isArray(condition.value) ? condition.value : condition.value ? [condition.value] : [];\n      const currentValArray: string[] = Array.isArray(currentvalue) ? currentvalue : currentvalue ? [currentvalue] : [];\n\n      // If the match is not case-sensitive, the condition value is already uppercased, so we only have to uppercase the\n      // current value(s) when checking\n      if (!matchcase)\n        currentValArray.forEach((_, idx) => currentValArray[idx] = currentValArray[idx].toUpperCase());\n\n      // The current value and the condition value should (at least) overlap\n      if (!currentValArray.some(value => compareagainst.includes(value)))\n        return false;\n\n      // For \"HAS\" and \"IS\" conditions, all of the required values should be selected (there shouldn't be required values\n      // that are not selected)\n      if ((condition.matchtype === \"HAS\" || condition.matchtype === \"IS\") && compareagainst.some(value => !currentValArray.includes(value)))\n        return false;\n\n      // For an \"IS\" condition, all of the selected values should be required (there shouldn't be selected values that are\n      // not required)\n      if (condition.matchtype === \"IS\" && currentValArray.some(value => !compareagainst.includes(value)))\n        return false;\n\n      return true;\n    }\n\n    return console.error(`No support for conditional type '${condition.matchtype}'`), false;\n  }\n\n  _updatePageNavigation() {\n    const pagestate = this._getPageState();\n    const nextpage = this._getDestinationPage(pagestate, +1);\n    const morepages = nextpage !== -1;\n    const curpagerole = pagestate.pages[pagestate.curpage] ? pagestate.pages[pagestate.curpage].dataset.whFormPagerole : '';\n    const nextpagerole = morepages ? pagestate.pages[nextpage].dataset.whFormPagerole : \"\";\n\n    this.node.classList.toggle(\"wh-form--allowprevious\", Boolean((pagestate.curpage > 0 && curpagerole !== 'thankyou') || (pagestate.curpage <= 0 && this.node.dataset.whFormBacklink)));\n    this.node.classList.toggle(\"wh-form--allownext\", morepages && nextpagerole !== 'thankyou');\n    this.node.classList.toggle(\"wh-form--allowsubmit\", curpagerole === 'thankyou'\n      ? pagestate.pages[pagestate.curpage].dataset.whFormExitButton !== undefined\n      : (!morepages || nextpagerole === 'thankyou'));\n  }\n\n  _navigateToThankYou(richvalues?: RichValues) {\n    const state = this._getPageState();\n\n    if (state.curpage >= 0) {\n      const nextpage = this._getDestinationPage(state, +1);\n      if (nextpage !== -1 && state.pages[nextpage] && state.pages[nextpage].dataset.whFormPagerole === 'thankyou') {\n        const rawNavigateTo = state.pages[nextpage].dataset.whFormNavigateTo;\n        const exitButton = state.pages[nextpage].dataset.whFormExitButton;\n        const parsedNavTo = rawNavigateTo ? JSON.parse(rawNavigateTo) : null;\n        if (parsedNavTo)\n          this.exitButtonNavigateTo = parsedNavTo;\n\n        const redirectdelay = parseInt(state.pages[nextpage].dataset.whFormPageredirectDelay ?? \"\");\n\n        if (exitButton) {\n          const submitButton = this.node.querySelector<HTMLElement>(\".wh-form__button--submit\");\n          const submitButtonLabel = submitButton?.querySelector<HTMLElement>(\".wh-form__buttonlabel\");\n          if (submitButton && submitButtonLabel) {\n            submitButton.dataset.whFormAction = \"exit\";\n            submitButtonLabel.textContent = exitButton;\n          } else {\n            console.error(`Unable to find the submit button '.wh-form__button--submit .wh-form__buttonlabel' - I need to replace its label with '${exitButton}'!`);\n          }\n        }\n\n        if (parsedNavTo && !(redirectdelay >= 0) && !exitButton) {\n          navigateTo(parsedNavTo);\n          return;\n        }\n\n        this.updateRichValues(state.pages[nextpage], richvalues);\n        this.gotoPage(nextpage, { __isSubmit: true });\n        if (parsedNavTo && redirectdelay >= 0) {\n          // If redirectdelay==0 (redirect immediately, while showing the thank you page), redirect after a small delay to\n          // give the browser time to hide the busy layer\n          // Might be caused by this: https://stackoverflow.com/a/60439478\n          setTimeout(() => navigateTo(parsedNavTo), redirectdelay * 1000 || 100);\n        }\n      }\n    }\n  }\n  updateRichValues(page: HTMLElement, richvalues?: RichValues) {\n    if (richvalues) {\n      for (const { field, value } of richvalues) {\n        const node = page.querySelector(`.wh-form__fieldgroup--richtext[data-wh-form-group-for=\"${CSS.escape(field)}\"] .wh-form__richtext`);\n        if (node) {\n          node.innerHTML = value;\n          dompack.registerMissed(node);\n        }\n      }\n    }\n  }\n\n  private ensureLegacyWarning(field: HTMLElement) {\n    if (!this.didLegacyWarning && !isLive)\n      console.warn(`[form] ${getFieldDisplayName(field)} is using wh:form-getvalue/wh:form-setvalue events. It should switch to JSFormElement`);\n\n    this.didLegacyWarning = true;\n  }\n\n  /* Override this to overwrite the processing of individual fields. Note that\n     radio and checkboxes are not passed through getFieldValue, and that\n     getFieldValue may return undefined or a promise. */\n  async getFieldValue(field: HTMLElement) {\n    if (field[rfSymbol])\n      return field[rfSymbol].getValue();\n\n    if (field.hasAttribute('data-wh-form-name') || field.whUseFormGetValue) {\n      //create a deferred promise for the field to fulfill\n      const deferred = Promise.withResolvers<unknown>();\n      //if cancelled, we'll assume the promise is taken over\n      if (!dompack.dispatchCustomEvent(field, 'wh:form-getvalue', { bubbles: true, cancelable: true, detail: { deferred } })) {\n        this.ensureLegacyWarning(field);\n        return deferred.promise;\n      }\n    }\n    if (!isFormFieldLike(field)) {\n      /* Can't fail on these, weird embeddings do weird things. Eg google's recaptcha v2 triggers this because it assigns a random name=\n         to the iframe it injects and then we pick that up.. (may need to move this error behind a debugflag if that's the only likely cause) */\n      if (debugFlags.fhv)\n        console.log(`[fhv] Cannot get value on non-FormControl`, field);\n      return undefined; //TODO throw? but wasn't currently fatal\n    }\n\n    if (field.matches('input[type=file]')) //We don't care for multiple yet, as our form RPC APIs don't support that either\n      return [...(field as HTMLInputElement).files || []].map(file => ({ fileName: file.name, file: file, link: null })) satisfies FormFileValue[];\n\n    return field.value;\n  }\n\n  /* Override this to overwrite the setting of individual fields. In contrast\n     to getFieldValue, this function will also be invoked for radio and checkboxes */\n  setFieldValue(fieldnode: HTMLElement, value: unknown) {\n    if (fieldnode[rfSymbol])\n      return fieldnode[rfSymbol].setValue(value);\n\n    if (fieldnode.hasAttribute('data-wh-form-name')) {\n      if (!dompack.dispatchCustomEvent(fieldnode, 'wh:form-setvalue', { bubbles: true, cancelable: true, detail: { value } })) {\n        this.ensureLegacyWarning(fieldnode);\n        return;\n      }\n      // Event is not cancelled, set node value directly\n    }\n\n    if (!isFormFieldLike(fieldnode)) {\n      console.error(`Cannot set value on non-FormControl`, fieldnode, value);\n      return; //TODO throw? but wasn't currently fatal\n    }\n\n    //NOTE this blocks a lot of 'new sets' being done through setFieldValue, eg resetting an array by setting it to []. which is fine for me, just use the data proxy..\n    if (typeof value !== \"string\" && typeof value !== \"number\" && typeof value !== \"boolean\") {\n      console.error(`Setting value of type ${typeof value} on a FormControl`, fieldnode, value);\n      return; //TODO throw? but wasn't currently fatal\n    }\n\n    const saveInteractive = this.isInteractive;\n    try {\n      this.isInteractive = false;\n      if (isFormControl(fieldnode))\n        dompack.changeValue(fieldnode, value);\n      else\n        fieldnode.value = value;\n    } finally {\n      this.isInteractive = saveInteractive;\n    }\n  }\n\n  _isPartOfForm(el: HTMLElement) {\n    //In HTML terms, an input must either have *no* form attribute or explicitly point to us. eg <input form> is *outside* a form\n    //However nodes may live in fragments (eg arrayedits) that are not in the DOM and not attached anywhere, so we also consider anything outside the DOM to be in our form...\n    return !(\"form\" in el) || el.form === this.node || !document.contains(el)\n      || (!this.node && !el.hasAttribute(\"form\")); //FIXME remove this workaround needed now to work around form init race where arrayfields try to use _queryAllFields\n  }\n\n  _queryAllFields(options?: {\n    skiparraymembers?: boolean;\n    skipfield?: HTMLElement;\n    onlysettable?: boolean;\n    startnode?: HTMLElement;\n  }): FormControlDescription[] {\n    const foundfields = new Array<FormControlDescription>;\n    const skiparraymembers = options && options.skiparraymembers;\n\n    for (const field of this._getFieldsToValidate(options?.startnode)) {\n      if (options && field === options.skipfield) //arrayfield.es needs it\n        continue;\n      if (!this._isPartOfForm(field))\n        continue;\n      if (options && options.onlysettable && !this._isNowSettable(field))\n        continue;\n      if (skiparraymembers && field.closest(\".wh-form__arrayrow\"))\n        continue;\n\n      const name = getFieldName(field);\n      if (!name)\n        continue;\n\n      let addto = foundfields.find(_ => _.name === name);\n      if (isRadioOrCheckbox(field)) { //expect multiple inputs with this name?\n        if (!addto) {\n          addto = { name: name, multi: true, nodes: [] };\n          foundfields.push(addto);\n        } else if (!addto.multi) {\n          console.error(`[fhv] Encountered duplicate field '${name}'`, field);\n          continue;\n        }\n        addto.nodes.push(field);\n      } else {\n        if (addto) {\n          console.error(`[fhv] Encountered duplicate field '${name}'`, field);\n          continue;\n        }\n\n        foundfields.push({ name: name, multi: false, node: field });\n      }\n    }\n\n    return foundfields;\n  }\n\n  /** Return the names of all form elements */\n  getFormElementNames() {\n    return this._queryAllFields().map(_ => _.name);\n  }\n\n  /** getValue from a field as returned by _queryAllFields (supporting both multilevel and plain fields)\n      @returns promise */\n  _getQueryiedFieldValue(field: FormControlDescription) {\n    if (!field.multi)\n      return this.getFieldValue(field.node);\n\n    return field.nodes.filter(node => node.checked).map(node => node.value);\n  }\n\n  /** Return a promise resolving to the submittable form value */\n  async getFormValue(): Promise<FormResultValue> {\n    const outdata: FormResultValue = {};\n    const fieldpromises = new Array<Promise<void>>;\n\n    for (const field of this._queryAllFields({ onlysettable: true, skiparraymembers: true }))\n      this._processFieldValue(outdata, fieldpromises, field.name, this._getQueryiedFieldValue(field));\n\n    await Promise.all(fieldpromises);\n    return outdata;\n  }\n\n  _isNowSettable(node: HTMLElement) {\n    // If the node is disabled, it's not settable\n    if (\"disabled\" in node && node.disabled)\n      return false;\n\n    // If the node's field group is disabled or hidden, it's not settable\n    const formgroup = node.closest(\".wh-form__fieldgroup\");\n    if (formgroup) {\n      if (formgroup.classList.contains(\"wh-form__fieldgroup--disabled\"))\n        return false;\n      if (formgroup.classList.contains(\"wh-form__fieldgroup--hidden\"))\n        return false;\n    }\n\n    // If the node's form page is hidden dynamically, it's not settable\n    const formpage = node.closest<HTMLElement>(\".wh-form__page\");\n    if (formpage) {\n      if (formpage.propWhFormCurrentVisible === false)\n        return false;\n    }\n    // The node is settable\n    return true;\n  }\n\n  _processFieldValue(outdata: FormResultValue, fieldpromises: Array<Promise<void>>, fieldname: string, receivedvalue: unknown) {\n    if (receivedvalue === undefined)\n      return;\n    if (isPromise(receivedvalue)) {\n      fieldpromises.push(new Promise<void>((resolve, reject) => {\n        receivedvalue.then(result => {\n          if (result !== undefined)\n            outdata[fieldname] = result;\n\n          resolve();\n        }).catch(e => reject(e as Error));\n      }));\n    } else {\n      outdata[fieldname] = receivedvalue;\n    }\n  }\n\n  //get the option lines associated with a specific radio/checkbox group\n  getOptions(name: string) {\n    const nodes = this.getElementByName(name);\n    if (!(nodes instanceof RadioNodeList))\n      return [];\n\n    return [...nodes].map(node => ({\n      inputnode: node,\n      fieldline: node.closest<HTMLElement>('.wh-form__fieldline'),\n      value: node.value\n    }));\n  }\n\n  /** gets the selected option associated with a radio/checkbox group as an array\n      */\n  getSelectedOptions(name: string) {\n    let opts = this.getOptions(name);\n    opts = opts.filter(node => node.inputnode.checked);\n    return opts;\n  }\n\n  /** get the selected option associated with a radio/checkbox group. returns an object that's either null or the first selected option\n      */\n  getSelectedOption(name: string) {\n    const opts = this.getSelectedOptions(name);\n    return opts.length ? opts[0] : null;\n  }\n\n  /** get the fieldgroup for an element */\n  getFieldGroup(name: string): HTMLElement | null {\n    let node = this.getElementByName(name);\n    if (node instanceof RadioNodeList)\n      node = node[0];\n\n    return node ? node.closest<HTMLElement>('.wh-form__fieldgroup') : null;\n  }\n\n  /** get the values of the currently selected radio/checkbox group */\n  private getValues(name: string) {\n    return this.getSelectedOptions(name).map(node => node.value);\n  }\n  /** get the value of the first currently selected radio/checkbox group */\n  private getValue(name: string) {\n    const vals = this.getValues(name);\n    return vals.length ? vals[0] : null;\n  }\n\n  /** @deprecated Just import setupValidator from \\@mod-publisher/js/forms */\n  static setupValidator(node: HTMLElement, checker: (node: HTMLElement) => Promise<string> | string) {\n    setupValidator(node, checker);\n  }\n\n  /** @deprecated Just import setFieldError from \\@mod-publisher/js/forms */\n  static setFieldError(field: HTMLElement, error: string, options?: Partial<FieldErrorOptions>) {\n    setFieldError(field, error, options);\n  }\n\n  setFieldError(field: HTMLElement, error: string, options?: Partial<FieldErrorOptions>) {\n    setFieldError(field, error, options);\n  }\n\n  async validateSingleFormField(field: HTMLElement): Promise<boolean> {\n    return true;\n  }\n\n  async _validateSingleFieldOurselves(field: HTMLElement): Promise<boolean> {\n    const state = getValidationState(field);\n\n    if (!state.explicit && isFieldNativeErrored(field)) {\n      //browser checks go first, any additional checks are always additive (just disable browserchecks you don't want to apply)\n      updateFieldError(field);\n      return this._reportFieldValidity(field);\n    }\n\n    //TODO we probably *shouldn't* be bothering running our validations if state.explicit is set, but then setFieldError needs to rerun the checks once the explicit error is dropped\n    state.dynamicError = null;\n    await this.validateSingleFormField(field);\n\n    if (!state.dynamicError)\n      for (const validator of state.validators) {\n        state.dynamicError = await validator(field) || null;\n        if (state.dynamicError)\n          break; //one is enough\n      }\n\n    if (!state.dynamicError && field.whFormsApiChecker)\n      await field.whFormsApiChecker();\n\n    return this._reportFieldValidity(field);\n  }\n\n  /** validate the form\n      @param limitset - A single element, nodelist or array of elements to validate (or their children)\n      @returns a promise that will fulfill when the form is validated\n       */\n  async validate(limitset?: LimitSet, options?: ValidationOptions): Promise<FormValidationResult> {\n    if (debugFlags.fdv) {\n      console.warn(`[fdv] Validation of form was skipped`);\n      return { valid: true, failed: [], firstfailed: null };\n    }\n\n    //Overlapping validations are dangerous, because we can't evaluate 'hasEverFailed' too early... if an earlier validation is still running it may still decide to mark fields as failed.\n    const defer = Promise.withResolvers<FormValidationResult>();\n    this.validationqueue.push({ defer, limitset, options });\n    if (this.validationqueue.length === 1)\n      this._executeNextValidation(); //we're first on the queue so process it\n\n    return defer.promise;\n  }\n\n  async _executeNextValidation() {\n    while (this.validationqueue.length) {\n      const item = this.validationqueue[0];\n      try {\n        const result = await this._executeQueuedValidation(item.limitset, item.options);\n        item.defer.resolve(result);\n      } catch (error) {\n        item.defer.reject(error as Error);\n      }\n      this.validationqueue.shift(); //remove the top item\n    }\n  }\n\n  async _executeQueuedValidation(limitset?: LimitSet, options?: ValidationOptions): Promise<FormValidationResult> {\n    const original = limitset;\n    if (!limitset)  //validate entire form if unspecified what to validate\n      limitset = this._getFieldsToValidate();\n\n    const tovalidate = new Set<HTMLElement>;\n    for (const node of Array.isArray(limitset) ? limitset : [limitset]) {\n      /* If you're explicitly validating a radio/checkbox, we need to validate its group (but not recurse down) as that's where radiogroup.es and checkboxgroup.es attach their validations\n         If you're targeting a group, we'll end up validating both the radio/checkbox (directly attached here) and any eg. embedded textedits  */\n      if (node.matches(`input[type=radio],input[type=checkbox]`)) {\n        const group = node.closest<HTMLElement>(\".wh-form__fieldgroup\");\n        if (group)\n          tovalidate.add(group);\n        continue;\n      }\n\n      if (this._shouldValidateField(node))\n        tovalidate.add(node);\n      for (const subnode of this._getFieldsToValidate(node)) //TODO this is overly recursive esp. if limitset is empty...\n        tovalidate.add(subnode);\n    }\n\n    /* This was:\n    tovalidate = Array.from(tovalidate); //we need an array now for further processing\n       but that breaks on some old mootools integrations, see https://gitlab.webhare.com/webharebv/codekloppers/-/issues/677#note_146801\n       wokaround: */\n    let tovalidatelist = [...tovalidate]; //we need an array now for further processing\n\n    if (options && options.iffailedbefore)\n      tovalidatelist = tovalidatelist.filter(node => hasEverFailed(node));\n\n    if (debugFlags.fhv)\n      console.log(\"[fhv] Validation of %o expanded to %d elements: %o\", original, tovalidatelist.length, [...tovalidatelist]);\n\n    const lock = dompack.flagUIBusy();\n    try {\n      if (!tovalidatelist.length)\n        return { valid: true, failed: [], firstfailed: null };\n\n      const validationresults = await Promise.all(tovalidatelist.map(fld => this._validateSingleFieldOurselves(fld)));\n      //remove the elements from validate for which the promise failed\n      const failed = tovalidatelist.filter((fld, idx) => !validationresults[idx]);\n      const result: FormValidationResult = {\n        valid: failed.length === 0,\n        failed: failed,\n        firstfailed: null\n      };\n\n      result.firstfailed = result.failed.length ? result.failed[0] : null;\n      if (result.firstfailed && (!options || options.focusfailed)) {\n        //FIXME shouldn't getFocusableComponents also return startnode if focusable?\n        const tofocus = domfocus.canFocusTo(result.firstfailed) ? result.firstfailed : domfocus.getFocusableComponents(result.firstfailed)[0];\n        if (tofocus)\n          dompack.focus(tofocus, { preventScroll: true });\n\n        this.scrollIntoView(result.firstfailed);\n      }\n\n      if (debugFlags.fhv)\n        console.log(`[fhv] Validation of ${tovalidatelist.length} fields done, ${result.failed.length} failed`, result);\n\n      return result;\n    } finally {\n      lock.release();\n    }\n  }\n\n  reset() {\n    this.node.reset();\n    this.gotoPage(0);\n  }\n}\n","export const rfSymbol = Symbol('RegisteredField');\n\ndeclare global {\n  interface HTMLElement {\n    [rfSymbol]?: FormFieldAPI;\n  }\n}\n\nexport interface FormFieldAPI {\n  getValue(): unknown;\n  setValue(newvalue: unknown): void;\n}\n","/* eslint-disable @typescript-eslint/no-floating-promises -- FIXME: needs API rework */\n\nimport { getTid } from \"@webhare/gettid\";\nimport \"./arrayfield.css\";\nimport { throwError } from \"@webhare/std\";\nimport { addDocEventListener, qS, qSA, type DocEvent, registerMissed, stop } from \"@webhare/dompack\";\nimport { getFieldName, getFormElementCandidates, getFormHandler, parseCondition, setFieldName } from \"@webhare/forms/src/domsupport\";\nimport type { FormCondition } from \"@webhare/forms/src/types\";\nimport { RecordFieldHandler, type FormParent } from \"@webhare/forms/src/fieldmap\";\nimport type FormBase from \"../formbase\";\nimport { setup } from \"../internal/webharefields\";\n\n\nfunction fixupConditionRecursive(node: HTMLElement, condition: FormCondition, mapping: Map<string, string>): boolean {\n  switch (condition.matchtype) {\n    case \"AND\":\n    case \"OR\":\n      {\n        let anychanges = false;\n        for (const subcondition of condition.conditions)\n          anychanges = fixupConditionRecursive(node, subcondition, mapping) || anychanges;\n        return anychanges;\n      }\n    case \"NOT\":\n      {\n        return fixupConditionRecursive(node, condition.condition, mapping);\n      }\n    default:\n      {\n        const newName = mapping.get(condition.field);\n        if (newName && node.querySelector(`[name=\"${newName}\"]`)) {\n          condition.field = newName;\n          return true;\n        }\n      }\n  }\n  return false;\n}\n\ntype NewType = FormParent;\n\nexport default class ArrayField {\n  valueNode: HTMLInputElement;\n  nextrowid = 0;\n  template;\n  insertPoint: HTMLElement;\n  arrayBaseName;\n\n  constructor(private handler: NewType, private node: HTMLElement, items: HTMLElement[], private name: string) {\n    this.arrayBaseName = node.dataset.whFormGroupFor || throwError(\"Missing array base name\");\n\n    // The template for new rows. If we have arrays-in-array, it will still be the first <template>\n    this.template = qS<HTMLTemplateElement>(node, \"template\") || throwError(\"Missing array template\");\n    // The node before which to add new rows\n    this.insertPoint = this.template.parentNode!.lastElementChild! as HTMLElement;\n    if (!this.insertPoint.matches(\".wh-form__arrayadd\"))\n      throw new Error(\"Missing array insert point\");\n\n    // Event handler for add/delete button clicks\n    this.insertPoint.addEventListener(\"click\", event => this.onAddRow(event));\n    addDocEventListener(node, \"click\", event => this._onClick(event));\n\n    // Proxy node for getting/setting properties and receiving events\n    this.valueNode = qS<HTMLInputElement>(node, \"input.wh-form__arrayinput\") ?? throwError(\"Missing array input\");\n    this.valueNode.whUseFormGetValue = true;\n    this.valueNode.addEventListener(\"wh:form-getvalue\", event => this._onGetValue(event));\n    //@ts-expect-error wh:form-setvalue isn't defined - but it'll go away anyway\n    this.valueNode.addEventListener(\"wh:form-setvalue\", event => this._onSetValue(event));\n\n    // Initialize initial value rows\n    for (const rownode of qSA(this.node, \".wh-form__arrayrow\"))\n      this._fixupRowNode(rownode);\n\n    this._checkValidity();\n  }\n\n  get form(): FormBase {\n    const form = getFormHandler(this.node.closest(\"form\") ?? throwError(\"Could not find <form>\")) ?? throwError(\"Could not find form for arrayfield\");\n    if (!form._getFieldsToValidate) //avoid calling into formbase from our constructor, it may not be there yet...\n      throw new Error(\"The <form> is not ready yet\");\n    return form;\n  }\n\n  addRow(): HTMLElement {\n    // Instatiate a new row\n    const newrow = this.template.content.cloneNode(true) as HTMLElement;\n    (newrow.firstElementChild! as HTMLElement).dataset.whFormRowid = String(this.nextrowid++);\n\n    // Insert the new row\n    this.insertPoint.parentNode!.insertBefore(newrow, this.insertPoint);\n    const addedrow = this.insertPoint.previousElementSibling! as HTMLElement;\n\n    /* If the form is relying on legacy dompack.register to go through ImgEditField and do the actual\n       customElements.define call.... then the 'name' attributes won't actually work on the 'new' elements.\n       therefore dompack.registerMissed must run before _fixupRowNode */\n    registerMissed(addedrow);\n    setup(addedrow);\n\n    this._fixupRowNode(addedrow as HTMLElement);\n    this._checkValidity();\n    this.form.__scheduleUpdateConditions();\n    return this.insertPoint.previousSibling as HTMLElement;\n  }\n\n  /* seems a unused API ?.  .. if we need to provide this, just let people pass us a row node instead of understanding IDs\n    removeRow(id)\n    {\n      // Remove a row by id\n      let node = this.node.querySelector(`.wh-form__arrayrow[data-row-id=${id}]`);\n      if (node)\n        this._removeRowNode(node);\n    }\n  */\n\n  private onAddRow(event: Event) {\n    stop(event);\n    this.addRow();\n  }\n  _onClick(event: DocEvent<MouseEvent>) {\n    // Check if a delete button was clicked\n    const delNode = event.target.closest(\".wh-form__arraydelete\");\n    if (delNode) {\n      event.preventDefault();\n      this._removeRowNode(delNode.closest(\".wh-form__arrayrow\")!);\n    }\n  }\n\n  getRowHandler(row: HTMLElement): RecordFieldHandler {\n    const rowBaseName = this.valueNode.name + \".\" + row.dataset.whFormRowid;\n    const rowFields = getFormElementCandidates(row, rowBaseName).filter(_ => _.dataset.whFormCellname !== \"row_uid\"); //row_uid points back to us, so requesting that triggers a loop\n    return new RecordFieldHandler(this.handler, rowBaseName, rowFields);\n  }\n\n  getValue() {\n    const rows = [];\n    for (const row of qSA(this.node, \".wh-form__arrayrow\").filter(n => n.parentNode === this.template.parentNode)) {\n      const handler = this.getRowHandler(row);\n      const rowval = handler.getValue();\n      rows.push(rowval);\n    }\n    return rows;\n  }\n\n  _onGetValue(event: CustomEvent<{ deferred: PromiseWithResolvers<unknown> }>) {\n    // We're using the deferred promise to return our value\n    event.preventDefault();\n    event.stopPropagation();\n\n    // Create a promise for each row that resolves with the combined value of all fields in the row\n    const valuePromises = [];\n    for (const row of qSA(this.node, \".wh-form__arrayrow\").filter(n => n.parentNode === this.template.parentNode)) {\n      const rowFields = this._queryAllFields(row);\n      // Create a promise for each of the row's subfields to get its value\n      const rowPromises = rowFields.map(field => (this.form as FormBase)._getQueryiedFieldValue(field)); //FIXME get rid of 'as FormBase' to support array-in-array\n      // Add an all promise for the value promises and add it to the list of row promises\n      valuePromises.push(Promise.all(rowPromises).then(values => {\n        // Combine the values into a value object for this row\n        const rowValue: Record<string, unknown> = { formrowid: row.dataset.whFormRowid };\n        values.forEach((value, idx) => {\n          // The values are returned in the order that the promises were added to the list of value promises, so we can use\n          // the index of the value to get the original field\n          const rowField = rowFields[idx];\n          const firstnode = rowField.multi ? rowField.nodes[0] : rowField.node;\n          rowValue[firstnode.dataset.whFormCellname!] = value;\n        });\n        return rowValue;\n      }));\n    }\n    // Wait for all the row promises (which resolves with a list of promise resolution values, which will be the final value\n    // of the array field)\n    Promise.all(valuePromises).then(valueRows => event.detail.deferred.resolve(valueRows));\n  }\n\n  setValue(newvalue: unknown[]) {\n    if (!Array.isArray(newvalue))\n      throw new Error(`Invalid value for array field '${this.name}': ${JSON.stringify(newvalue)}`);\n\n    // Remove all current rows (TODO optimize)\n    while (this.insertPoint.previousElementSibling?.classList.contains(\"wh-form__arrayrow\"))\n      this._removeRowNode(this.insertPoint.previousElementSibling);\n\n    // Check if we have an array value\n    for (const value of newvalue) {\n      // Add a row\n      const row = this.addRow();\n      const handler = this.getRowHandler(row);\n      handler.setValue(value);\n    }\n    this._checkValidity();\n  }\n\n  _onSetValue(event: CustomEvent<{ value: unknown }>) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    // Remove all current rows\n    while (this.insertPoint.previousElementSibling?.classList.contains(\"wh-form__arrayrow\"))\n      this._removeRowNode(this.insertPoint.previousElementSibling);\n\n    // Check if we have an array value\n    if (Array.isArray(event.detail.value)) {\n      for (const value of event.detail.value) {\n        // Add a row\n        const row = this.addRow();\n        // Initialize the row's fields\n        for (const field of this._queryAllFields(row)) {\n          for (const fieldnode of (field.multi ? field.nodes : [field.node])) {\n            if (fieldnode.dataset.whFormCellname && fieldnode.dataset.whFormCellname in value) {\n              (this.form as FormBase).setFieldValue(fieldnode, value[fieldnode.dataset.whFormCellname]); //FIXME get rid of 'as FormBase' to support array-in-array\n            }\n          }\n        }\n      }\n    }\n    this._checkValidity();\n  }\n\n  _fixupRowNode(node: HTMLElement) {\n    const rowid = node.dataset.whFormRowid;\n\n    // Rename all fields to avoid duplicate field names\n    const mapping = new Map<string, string>;\n    for (const fieldnode of getFormElementCandidates(node, this.arrayBaseName)) {\n\n      // Leave embedded arrayfields alone! Except if this is specifically the wh-form__arrayinput one level down\n      const nodeArray = fieldnode.closest(\".wh-form__fieldgroup--array\");\n      if (nodeArray && nodeArray !== this.node && !(fieldnode.matches(\".wh-form__arrayinput\") && (nodeArray.parentNode! as HTMLElement).closest(\".wh-form__fieldgroup--array\") === this.node)) {\n        // console.log(\"Skipping\", fieldnode, \"as it's not in our array\");\n        continue;\n      }\n\n      // Rename fields\n      const fieldname = getFieldName(fieldnode);\n      // When rendering, the fields simply have their arrayname prefixed in their name=, see InstantiateField in array.whlib (TODO seems dangerous, eg preset radio buttons interfering with each other?\n      // So we'll just take the part after the first dot as the cellname\n      fieldnode.dataset.whFormCellname ||= fieldname.substring(this.arrayBaseName.length + 1);\n\n      const cellname: string = fieldnode.dataset.whFormCellname;\n      const subname = this.valueNode.name + \".\" + rowid + \".\" + cellname;\n      // console.log(\"for\", this.name, \"rename\", fieldname, \"to\", subname, fieldnode);\n      setFieldName(fieldnode, subname);\n      mapping.set(fieldname, subname);\n\n      // Rename id's to make them unique; update the labels within the field's fieldgroup to point to the new id\n      if (fieldnode.id) {\n        const labelnodes = qSA<HTMLLabelElement>(node, `label[for=\"${fieldnode.id}\"]`);\n        fieldnode.id += \"-\" + rowid;\n        for (const labelnode of labelnodes)\n          labelnode.htmlFor = fieldnode.id;\n      }\n\n      // Rewrite conditions after all fields have been renamed\n      for (const type of [\"visible\", \"enabled\", \"required\"]) {\n        for (const conditionnode of qSA(node, `[data-wh-form-${type}-if]`)) {\n          const condition = parseCondition(conditionnode.dataset[`whForm${type[0].toUpperCase() + type.slice(1)}If`]!);\n          if (fixupConditionRecursive(node, condition, mapping))\n            conditionnode.dataset[`whForm${type[0].toUpperCase() + type.slice(1)}If`] = JSON.stringify({ c: condition });\n        }\n      }\n    }\n\n    this.getRowHandler(node); //initializes deeper arrays. fieldmap should probably be handling this and build a full mapping top to botom...\n  }\n\n  _removeRowNode(node: Element) {\n    // Remove the row node\n    node.remove();\n    this._checkValidity();\n  }\n\n  _checkValidity() {\n    const minRows = parseInt(this.valueNode.dataset.whMin || \"0\");\n    const maxRows = parseInt(this.valueNode.dataset.whMax || \"0\");\n\n    const numRows = this.node.querySelectorAll(\".wh-form__arrayrow\").length;\n    if (numRows < minRows)\n      this.valueNode.setCustomValidity(getTid(\"publisher:site.forms.commonerrors.minarray\", minRows));\n    else if (maxRows > 0 && numRows > maxRows)\n      this.valueNode.setCustomValidity(getTid(\"publisher:site.forms.commonerrors.maxarray\", maxRows));\n    else\n      this.valueNode.setCustomValidity(\"\");\n\n    // Disable the add button if the maximum number of rows is reached\n    if (maxRows > 0 && numRows >= maxRows)\n      this.node.classList.add(\"wh-form__array--maxrows\");\n    else\n      this.node.classList.remove(\"wh-form__array--maxrows\");\n  }\n\n  _queryAllFields(node: HTMLElement) {\n    return (this.form as FormBase)._queryAllFields({ startnode: node, skipfield: this.valueNode });  //FIXME get rid of 'as FormBase' to support array-in-array\n  }\n}\n","import { getFieldName } from \"./domsupport\";\nimport { rfSymbol, type FormFieldAPI } from \"./registeredfield\";\nimport ArrayField from \"@mod-publisher/js/forms/fields/arrayfield\";\nimport type { AddressValue } from \"@webhare/address\";\nimport { omit, nameToSnakeCase, nameToCamelCase, throwError, isDate } from \"@webhare/std\";\nimport type { RecursivePartial } from \"@webhare/js-api-tools\";\nimport type { FormFieldLike } from \"./jsformelement\";\n\nexport interface FormParent {\n  __scheduleUpdateConditions(): void;\n}\n\n\ninterface FormField {\n  getValue(): unknown;\n\n  /** Set a value\n   * @param newvalue - The new value to set\n   * @param ignoreInvalid - Do not throw if the value is invalid. Used for eg. prefills which can't usefully handle it anyway\n   * @returns True if succesfully set */\n\n  setValue(newvalue: unknown): void;\n}\n\ntype ValueType = \"number\" | \"boolean\" | \"date\";\n\nfunction unmapFieldName(camelCaseName: string) {\n  return camelCaseName.startsWith(\"__formfield\") ? camelCaseName : nameToSnakeCase(camelCaseName);\n\n}\nfunction mapFieldName(htmlName: string) {\n  return htmlName.startsWith(\"__formfield\") ? htmlName : nameToCamelCase(htmlName);\n}\n\nfunction mapValue(type: ValueType, invalue: string) {\n  switch (type) {\n    case \"number\":\n      return parseFloat(invalue);\n    case \"boolean\":\n      return invalue === \"true\";\n    case \"date\":\n      return new Date(invalue);\n  }\n}\n\nfunction unmapValue(type: ValueType | undefined, invalue: unknown, fieldDescr: string) {\n  switch (type) {\n    case null:\n      if (typeof invalue !== \"string\")\n        throw new Error(`Invalid type ${typeof invalue} for string field ${fieldDescr}: ${invalue}`);\n      return invalue;\n\n    case \"number\":\n      if (typeof invalue !== \"number\")\n        throw new Error(`Invalid type ${typeof invalue} for number field ${fieldDescr}: ${invalue}`);\n      return String(invalue);\n\n    case \"boolean\":\n      if (typeof invalue !== \"boolean\")\n        throw new Error(`Invalid type ${typeof invalue} for boolean field ${fieldDescr}: ${invalue}`);\n      return String(invalue);\n\n    case \"date\":\n      if (!isDate(invalue))\n        throw new Error(`Invalid type ${typeof invalue} for date field ${fieldDescr}: ${invalue}`);\n      return invalue.toISOString();\n  }\n}\n\nclass HTMLFormFieldHandler implements FormField {\n  valuetype?: ValueType;\n\n  constructor(private form: FormParent, private readonly field: FormFieldLike) {\n    this.valuetype = field.dataset.whFormValueType as undefined | ValueType;\n    if (!this.valuetype && field.matches('input[type=number]'))\n      this.valuetype = \"number\";\n  }\n\n  getValue(): unknown {\n    if (this.field.matches('input[type=checkbox]'))\n      return (this.field as HTMLInputElement).checked;\n    if (this.field.matches('input[type=date]'))\n      return (this.field as HTMLInputElement).valueAsDate;\n\n    if (this.field.tagName === \"SELECT\") {\n      const selectedrow = (this.field as HTMLSelectElement).selectedOptions[0];\n      if (!selectedrow || selectedrow.dataset.placeholder !== undefined)\n        return null; //didn't select a 'real' option\n\n      return this.valuetype ? mapValue(this.valuetype, selectedrow.value) : selectedrow.value;\n    }\n\n    return this.valuetype ? mapValue(this.valuetype, this.field.value as string) : this.field.value;\n  }\n\n  setValue(newvalue: unknown): void {\n    if (this.field.matches('input[type=checkbox]')) {\n      //For convenience we're interpreting setting a checkbox as 'truthy' instead of explicit true/false\n      const setvalue = Boolean(newvalue);\n      if (setvalue === (this.field as HTMLInputElement).checked)\n        return;\n\n      (this.field as HTMLInputElement).checked = setvalue;\n    } else if (this.field.matches('input[type=date]')) {\n      if ((this.field as HTMLInputElement)?.valueAsDate?.getTime() === (newvalue as Date | null)?.getTime())\n        return;\n      (this.field as HTMLInputElement).valueAsDate = newvalue as Date;\n    } else if (this.field.tagName === \"SELECT\" && newvalue === null) { //'null' resets the select to 'no value', so figure out if there's a placeholder row\n      const setvalue = (this.field as HTMLSelectElement).options[0]?.dataset.placeholder !== undefined ? 0 : -1;\n      if ((this.field as HTMLSelectElement).selectedIndex === setvalue)\n        return;\n      (this.field as HTMLSelectElement).selectedIndex = setvalue;\n    } else {\n      const setvalue = this.valuetype ? unmapValue(this.valuetype, newvalue, this.field.name) : newvalue;\n      if (this.field.value === setvalue)\n        return;\n      this.field.value = setvalue;\n    }\n    this.form.__scheduleUpdateConditions();\n  }\n}\n\nclass RadioFormFieldHandler implements FormField {\n  valuetype?: ValueType;\n  constructor(private form: FormParent, private readonly name: string, private readonly rnodes: HTMLInputElement[]) {\n    const group = rnodes[0].closest<HTMLElement>(\".wh-form__fieldgroup\");\n    if (!group) { //value metadata is stored at the fieldgroup level, so reject these\n      console.error(\"Missing group for radiofield \", group);\n      console.error('if a radio field does not want to participate in the form, it should set attribute form=\"\"');\n    } else {\n      this.valuetype = group.dataset.whFormValueType as undefined | ValueType;\n    }\n  }\n  getValue(): unknown {\n    const node = this.rnodes.find(_ => _.checked);\n    return (node ? this.valuetype ? mapValue(this.valuetype, node.value) : node.value : null);\n  }\n  setValue(newvalue: unknown): void {\n    if (newvalue === null) {\n      for (const node of this.rnodes)\n        node.checked = false;\n\n      this.form.__scheduleUpdateConditions();\n      return;\n    }\n\n    const myname = `radio group ${this.name}`;\n    const setvalue = unmapValue(this.valuetype, newvalue, myname);\n\n    const node = this.rnodes.find(_ => _.value === setvalue);\n    if (!node)\n      throw new Error(`No such value '${setvalue}' in radio group '${this.name}`);\n\n    node.checked = true;\n    this.form.__scheduleUpdateConditions();\n  }\n}\n\nclass CheckboxGroupHandler implements FormField {\n  valuetype?: ValueType;\n  constructor(private form: FormParent, private readonly name: string, private readonly cboxes: HTMLInputElement[]) {\n    this.valuetype = (cboxes[0].closest<HTMLElement>(\".wh-form__fieldgroup\") ?? throwError(\"RadioFormFieldHandler: Missing group\")).dataset.whFormValueType as undefined | ValueType;\n  }\n  getValue(): unknown {\n    return this.cboxes.filter(_ => _.checked).map(_ => this.valuetype ? mapValue(this.valuetype, _.value) : _.value);\n  }\n  setValue(newvalue: unknown): void {\n    const myname = `checkbox group '${this.name}'`;\n    if (!Array.isArray(newvalue))\n      throw new Error(`Value for ${myname} should be an array, got '${JSON.stringify(newvalue)}'`);\n\n    const toset = newvalue.map(_ => unmapValue(this.valuetype, _, myname));\n\n    this.cboxes.forEach(_ => _.checked = toset.includes(_.value));\n    this.form.__scheduleUpdateConditions();\n\n    //in case the error is caught and ignored (eg prefill), we'll update what we can\n    const missing = toset.filter(_ => !this.cboxes.some(cbox => cbox.value === _));\n    if (missing.length)\n      throw new Error(`Invalid value(s) for ${myname}: ${missing.join(', ')}`);\n  }\n}\n\nclass RegisteredFieldHandler implements FormField {\n  constructor(protected form: FormParent, private readonly field: FormFieldAPI) {\n  }\n\n  getValue(): unknown {\n    return this.field.getValue();\n  }\n  setValue(newvalue: unknown): void {\n    this.field.setValue(newvalue);\n  }\n}\n\nexport class ArrayFieldHandler extends RegisteredFieldHandler implements FormField {\n  constructor(form: FormParent, private node: HTMLElement, items: HTMLElement[]) {\n    node[rfSymbol] ||= new ArrayField(form, node, items, getFieldName(items[0]));\n    super(form, node[rfSymbol]);\n  }\n\n  __scheduleUpdateConditions() {\n    this.form.__scheduleUpdateConditions();\n  }\n}\n\n/** The FormFieldMap exposes a multi-level (ie unflattened) view of the form values. Internally it works with the\n   original names because generated fields names, eg __formfieldbbbwVsWih_0DrJOc0beS7Q_, cannot be assumed to be snake_case and convertable */\nexport abstract class FormFieldMap<DataShape> {\n  /** Field mapping. Uses original names */\n  protected fieldmap = new Map<string, FormField>();\n\n  constructor(protected fieldName: string, nodes: HTMLElement[]) {\n    const subpos = fieldName ? fieldName.length + 1 : 0;\n    const groups = Map.groupBy(nodes, _ => getFieldName(_).substring(subpos).split('.')[0]);\n\n    for (const [name, items] of groups) {\n      const fullName = (fieldName ? fieldName + '.' : '') + name;\n      if (!name) {\n        console.error(`There are fields without a name:`, items);\n        continue;\n      }\n\n      if (items[0].matches('input[type=radio]')) {\n        this.fieldmap.set(name, new RadioFormFieldHandler(this, fullName, items as HTMLInputElement[]));\n        continue;\n      }\n\n      if (items[0].matches('.wh-form__arrayinput')) {\n        const arraygroup = items[0].closest<HTMLElement>('.wh-form__fieldgroup--array');\n        if (arraygroup) {\n          this.fieldmap.set(name, new ArrayFieldHandler(this, arraygroup, items));\n          continue;\n        }\n      }\n\n      const hasGroupLeader = getFieldName(items[0]) === fullName; //ie name has no followup '.xx'\n      if (hasGroupLeader) { //if no subname, it's the group leader ?\n        if (items[0].matches('input[type=checkbox]')) {//is it a checkbox group?\n          const cboxgroup = items[0].closest(\".wh-form__fieldgroup--checkboxgroup\");\n          if (cboxgroup) {\n            this.fieldmap.set(name, new CheckboxGroupHandler(this, fullName, items as HTMLInputElement[]));\n            continue;\n          }\n        }\n\n        this.fieldmap.set(name, new HTMLFormFieldHandler(this, items[0] as FormFieldLike));\n        continue;\n      }\n\n      //We're an implicit record (even if with just one member)\n      if (items[0].matches('select[name$=\".country\"][data-orderingdata]')) //looks like address.whlib\n        this.fieldmap.set(name, new AddressFieldHandler(this, fullName, items));\n      else\n        this.fieldmap.set(name, new RecordFieldHandler(this, fullName, items));\n    }\n  }\n\n  abstract __scheduleUpdateConditions(): void;\n\n  /** Get a field handler by name */\n  getField(name: string, options: { allowMissing: true }): FormField | null;\n  getField(name: string, options?: { allowMissing?: boolean }): FormField;\n\n  getField(name: string, options?: { allowMissing?: boolean }): FormField | null {\n    const mapName = unmapFieldName(name);\n    const match = this.fieldmap.get(mapName);\n    if (match)\n      return match;\n    if (options?.allowMissing)\n      return null;\n\n    throw new Error(`Field '${name}' not found in this form`); //TODO report the fukll anme\n  }\n\n  getFieldNames(): string[] {\n    return [...this.fieldmap.keys()].map(mapFieldName);\n  }\n\n  /** Set a value for multiple fields\n   * @param data - The data to set\n   * @param ignoreUnknownFields - Do not throw if a field is not found in the form. This is the default\n   */\n  assign(data: RecursivePartial<DataShape>, { ignoreUnknownFields = true } = {}) {\n    for (const [key, value] of Object.entries(data as object)) {\n      const field = this.getField(key, { allowMissing: ignoreUnknownFields });\n      if (field)\n        field.setValue(value);\n    }\n  }\n}\n\nexport class RecordFieldHandler extends FormFieldMap<object> implements FormField {\n  constructor(private form: FormParent, baseName: string, nodes: HTMLElement[]) {\n    super(baseName, nodes);\n  }\n\n  getValue(): unknown {\n    const retval: Record<string, unknown> = {};\n    for (const [name, field] of this.fieldmap) {\n      const val = field.getValue();\n      if (val !== undefined) //Suppress undefined values (where we cannot safely re-set them, eg images in Object.keys\n        retval[mapFieldName(name)] = val;\n    }\n\n    return retval;\n  }\n\n  setValue(newvalue: unknown): void {\n    if (typeof newvalue !== 'object' || newvalue === null)\n      throw new Error(`Invalid value for record field '${this.fieldName}': ${newvalue}`);\n\n    for (const [name, field] of this.fieldmap) {\n      const prettyName = mapFieldName(name);\n      if (prettyName in newvalue)\n        field.setValue((newvalue as Record<string, unknown>)[prettyName]);\n    }\n  }\n\n  __scheduleUpdateConditions() {\n    this.form.__scheduleUpdateConditions();\n  }\n}\n\n/* TODO cleanup... this is a workaround to translate nr_detail to houseNumber. ideally the server would just send house_number as field\n        name but that transition will take time. also we need a nice way to 'take over' addressifelds rather than fieldmapper special casing\n        its detection\n*/\ntype OldAddressValue = Omit<AddressValue, \"houseNumber\"> & { nrDetail?: string };\n\nclass AddressFieldHandler extends RecordFieldHandler {\n  constructor(form: FormParent, baseName: string, nodes: HTMLElement[]) {\n    super(form, baseName, nodes);\n  }\n\n  getValue(): unknown {\n    const val = super.getValue() as OldAddressValue;\n    if (val?.country === null)\n      return null;\n\n    return val?.nrDetail !== undefined ? { ...omit(val, [\"nrDetail\"]), houseNumber: val.nrDetail } : val;\n  }\n\n  setValue(val: unknown) {\n    if (val === null) {\n      super.setValue({ country: null, city: \"\", street: \"\", zip: \"\", nrDetail: \"\", state: \"\" });\n      return;\n    }\n\n    ///@ts-expect-error ugly hack, not really worth overwriting with as\n    super.setValue(val?.houseNumber !== undefined ? { ...omit(val, [\"houseNumber\"]), nrDetail: val.houseNumber } : val);\n  }\n}\n\nexport class FieldMapDataProxy implements ProxyHandler<object> {\n  constructor(private readonly form: FormFieldMap<object>) {\n  }\n  get(target: object, p: string | symbol) {\n    //Don't attempt to validate getters... it will break various introspection calls (eg requesting constructor, checking for 'then'...)\n    const field = typeof p === \"string\" ? this.form.getField(p, { allowMissing: true }) : null;\n    return field ? field.getValue() : (target as Record<string | symbol, unknown>)[p];\n  }\n  set(target: unknown, p: string, value: unknown): boolean {\n    this.form.getField(p).setValue(value);\n    return true;\n  }\n  ownKeys(target: object): ArrayLike<string | symbol> {\n    return this.form.getFieldNames();\n  }\n  getOwnPropertyDescriptor(target: unknown, prop: string) { // allows ownKeys to actually return to Object.keys\n    return { enumerable: true, configurable: true };\n  }\n}\n","import type { AddressValue } from \"@webhare/address\";\nimport { stringify, emplace, omit } from \"@webhare/std\";\nimport { getFormService, type HareScriptAddressValidationResult, type HareScriptAddressValue } from \"./formservice\";\n\nexport type { HareScriptAddressValue, HareScriptAddressValidationResult } from \"./formservice\";\n\nexport type AddressChecks = \"nl-zip-suggest\" | \"nl-zip-force\";\n\nexport type AddressValidationStatus = \"ok\" | \"unknown\" | \"error\";\n// not_supported\" | \"ok\" | \"not_enough_data\" | \"invalid_city\" | \"invalid_zip\" | \"invalid_nr_detail\" | \"zip_not_found\" | \"address_not_found\" | \"different_citystreet\" | \"incomplete\" | \"lookup_failed\";\n\nexport interface AddressValidationOptions {\n  checks?: AddressChecks[];\n  lang?: string;\n}\n\nexport interface AddressValidationResult {\n  status: AddressValidationStatus;\n  errors: Array<{\n    ///Fields affected by the error\n    fields: string[];\n    ///Error message in the requested language\n    message: string;\n  }>;\n  corrections: Partial<Record<keyof AddressValue, string>> | null;\n}\n\nlet lookupcache: Map<string, Promise<AddressValidationResult>> | undefined;\n\nexport async function verifyHareScriptAddress(address: HareScriptAddressValue, options: AddressValidationOptions = {}): Promise<HareScriptAddressValidationResult> {\n  if (!lookupcache)\n    lookupcache = new Map<string, Promise<AddressValidationResult>>;\n\n  const lookupkey = stringify({ address, options }, { stable: true });\n  const lookup = emplace(lookupcache, lookupkey, {\n    insert: () => getFormService().verifyAddress(location.pathname, address, options)\n  });\n  return await lookup;\n}\n\nexport async function verifyAddress(address: AddressValue, options: AddressValidationOptions = {}): Promise<AddressValidationResult> {\n  if (!lookupcache)\n    lookupcache = new Map<string, Promise<AddressValidationResult>>;\n\n  // convert houseNumber to nr_detail\n  const hsAddress = { ...omit(address, [\"houseNumber\"]), nr_detail: address.houseNumber };\n\n  const hsresult = await verifyHareScriptAddress(hsAddress, options);\n\n  // back-convert nr_detail to houseNumber\n  let corrections: AddressValidationResult[\"corrections\"] = null;\n  if (hsresult.corrections) {\n    corrections = {};\n    for (const [key, value] of Object.entries(hsresult.corrections) as Array<[keyof HareScriptAddressValue, string]>) {\n      corrections[key === \"nr_detail\" ? \"houseNumber\" as const : key] = value;\n    }\n  }\n  return {\n    status: hsresult.status,\n    errors: hsresult.errors.map(error => ({ fields: error.fields.map(f => f === \"houseNumber\" ? \"nr_detail\" : f), message: error.message })),\n    corrections,\n  };\n}\n","import { isValidDate, isValidTime } from '@webhare/std';\n\nexport function formatDate(dateformat: string, year: number, month: number, day: number): string {\n  if (!isValidDate(year, month, day, { minYear: 1 }))\n    return '';\n\n  let output = '';\n\n  for (const c of dateformat.split(\"\")) {\n    switch (c.toUpperCase()) {\n      case \"Y\":\n        output += ('000' + year).slice(-4);\n        break;\n      case \"M\":\n        output += ('0' + month).slice(-2);\n        break;\n      case \"D\":\n        output += ('0' + day).slice(-2);\n        break;\n      default:\n        output += c;\n        break;\n    }\n  }\n  return output;\n}\n\nexport function formatISODate(year: number, month: number, date: number) {\n  return formatDate(\"Y-M-D\", year, month, date);\n}\n\nexport function formatISOTime(hour: number, minute: number, second: number | null, msec: number | null) {\n  if (!isValidTime(hour, minute, second !== null ? second : 0, msec !== null ? msec : 0))\n    return '';\n\n  let time = ('0' + hour).slice(-2) + ':' + ('0' + minute).slice(-2);\n  if (second !== null)\n    time += ':' + ('0' + second).slice(-2);\n  if (msec !== null)\n    time += '.' + ('00' + msec).slice(-3);\n  return time;\n}\n\nexport interface DateParts {\n  day: number;\n  month: number;\n  year: number;\n}\n\nexport function parseDate(format: string, newdate: string, options?: { nofail: boolean }): DateParts | null {\n  if (!newdate) //empty\n    return null;\n\n  //replace . and / with -\n  const setdate = newdate.replace(/[./]/g, '-');\n  const parts = setdate.split('-');\n\n  if (parts.length === 3) { //parseable\n    format = format.toLowerCase();\n    const dayoffset = format.indexOf('d');\n    const monthoffset = format.indexOf('m');\n    const yearoffset = format.indexOf('y');\n\n    const daypos = 0 + (dayoffset > monthoffset ? 1 : 0) + (dayoffset > yearoffset ? 1 : 0);\n    const monthpos = 0 + (monthoffset > dayoffset ? 1 : 0) + (monthoffset > yearoffset ? 1 : 0);\n    const yearpos = 0 + (yearoffset > dayoffset ? 1 : 0) + (yearoffset > monthoffset ? 1 : 0);\n\n    const day = parseInt(parts[daypos], 0);\n    const month = parseInt(parts[monthpos], 0);\n    const year = parseInt(parts[yearpos], 0);\n\n    // The browser will always add 1900 for years 0-99, so handle years < 100\n    // if (year >= 0 && year < 100 && this.options.cutoffyear > 0)\n    // {\n    //   if (year < this.options.cutoffyear)\n    //     year += 2000;\n    //   else\n    //     year += 1900;\n    // }\n    if (isValidDate(year, month, day))\n      return { year, month, day };\n  }\n  if (options && options.nofail)\n    return null;\n\n  throw new Error(`Invalid date value: '${newdate}'`);\n}\n\n//compare two dates. return -1 if lhs<rhs, 0 if lhs==rhs, 1 if lhs>rhs\nexport function compareDate(lhs: DateParts | null, rhs: DateParts | null) {\n  if (!lhs)\n    return rhs ? -1 : 0; //if rhs is set, <null> is before anything. oterhwise equal\n  else if (!rhs)\n    return 1; //lhs must be set, so lhs>rhs\n\n  return lhs.year < rhs.year ? -1\n    : lhs.year > rhs.year ? 1\n      : lhs.month < rhs.month ? -1\n        : lhs.month > rhs.month ? 1\n          : lhs.day < rhs.day ? -1\n            : lhs.day > rhs.day ? 1\n              : 0;\n}\n\nexport function parseISODate(newdate: string, options?: { nofail: boolean }) {\n  return parseDate('y-m-d', newdate, options);\n}\n\nexport function getLocalToday(): DateParts {\n  const today = new Date;\n  return { year: today.getFullYear(), month: 1 + today.getMonth(), day: today.getDate() };\n}\n\nexport function parseISOTime(intime: string, { nofail = false } = {}) {\n  const split = intime.match(/^([0-9]+):([0-9]+)(:([0-9]+))?(\\.([0-9]+))?$/);\n  if (split) {\n    const hour = parseInt(split[1], 10);\n    const minute = parseInt(split[2], 10);\n    const second = parseInt(split[4] || \"0\", 10);\n    const msec = parseInt(split[6] || \"0\", 10);\n    return { hour, minute, second, msec };\n  }\n  if (nofail)\n    return undefined;\n\n  throw new Error(`Invalid time value: '${intime}'`);\n}\n\nexport function getWeekNumber(jsdate: Date) {\n  jsdate = new Date(jsdate); //don't modify the caller's date!\n  jsdate.setHours(0, 0, 0, 0);\n  // Thursday in current week decides the year.\n  jsdate.setDate(jsdate.getDate() + 3 - (jsdate.getDay() + 6) % 7);\n  // January 4 is always in week 1.\n  const week1 = new Date(jsdate.getFullYear(), 0, 4);\n  // Adjust to Thursday in week 1 and count number of weeks from jsdate to week1.\n  return 1 + Math.round(((jsdate.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);\n}\n\nexport function makeJSUTCDate(dateparts: DateParts) {\n  return new Date(Date.UTC(dateparts.year, dateparts.month - 1, dateparts.day));\n}\n\nexport function formatJSUTCISODate(dateobj: Date) {\n  return dateobj.getUTCFullYear() + '-' + ('0' + (dateobj.getUTCMonth() + 1)).slice(-2) + '-' + ('0' + dateobj.getUTCDate()).slice(-2);\n}\n","/* Support APIs to deal with DOM native form elements (eg input, select, textarea) */\n\nimport type FormBase from '@mod-publisher/js/forms/formbase';\nimport { reformatDate } from \"@mod-publisher/js/forms/internal/webharefields\";\nimport { getTid } from \"@webhare/gettid\";\nimport { isFormControl, isHTMLElement, qSA, type FormControlElement } from \"@webhare/dompack\";\nimport type { FormCondition } from \"./types\";\nimport { JSFormElement, type FormFieldLike } from \"./jsformelement\";\nimport { throwError } from '@webhare/std';\n\nexport type ConstrainedRadioNodeList = RadioNodeList & NodeListOf<HTMLInputElement>;\n\n//Query elements that are likely to be formfieldlike. Anything with a [name] but not eg button (and not data-wh-form-name which usually relies on getformvalue events)\nexport const queryFormFieldLike = `[name]:not(button):not(a):not(output)`;\n\nexport function isInputElement(field: Element): field is HTMLInputElement {\n  return isHTMLElement(field) && field.tagName === 'INPUT';\n}\n\n/// Implements required, disabled, ..\nexport function isFormFieldLike(control: HTMLElement): control is FormFieldLike {\n  return isFormControl(control as HTMLElement) || control instanceof JSFormElement;\n}\n\nexport function isRadioOrCheckbox(field: Element): field is HTMLInputElement {\n  return isInputElement(field) && [\"radio\", \"checkbox\"].includes(field.type);\n}\n\n// Constrains the RadioNodeList type to only return HTMLInputElements. reduces number of casts we need\nexport function isRadioNodeList(el: RadioNodeList | Element): el is ConstrainedRadioNodeList {\n  return el instanceof RadioNodeList;\n}\n\nexport function getFieldName(field: HTMLElement): string {\n  return field.dataset.whFormName || (field as HTMLInputElement).name || '';\n}\n\nexport function setFieldName(field: HTMLElement, newname: string) {\n  if (field.dataset.whFormName !== undefined)\n    field.dataset.whFormName = newname;\n  else if ((field as HTMLInputElement).name !== undefined)\n    (field as HTMLInputElement).name = newname;\n  else\n    throw new Error('Cannot set name on field without existing name');\n}\n\nexport function getFieldDisplayName(field: HTMLElement | ConstrainedRadioNodeList): string {\n  if (isRadioNodeList(field))\n    return `radiogroup '${(field.item(0) as HTMLInputElement)?.name || (field.item(0) as HTMLElement)?.id || '<unnamed>'}'`;\n  if (isFormControl(field))\n    return `native field '${field.name || field.id || '<unnamed>'}'`;\n  if (field.dataset.whFormName)\n    return `custom field '${field.dataset.whFormName || field.id || '<unnamed>'}'`;\n  if (field.classList.contains('wh-form__fieldgroup'))\n    return `field group '${field.dataset.whFormGroupFor || field.id || '<unnamed>'}'`;\n  return `${field.tagName} element '${field.id || '<unnamed>'}'`;\n}\n\n/** The WH Form rendering generates wh-fileedit elements. If no handler is detected for them, we downgrade them to input type=file before\n *  the form actually sets up its handler (it's still safe to rewrite top level form elements then)\n*/\nexport function downgradeUploadFields(form: HTMLElement) {\n  for (const uploadfield of qSA(form, \"wh-fileedit\")) {\n    const input = document.createElement(\"input\");\n    input.type = \"file\";\n    for (const attr of uploadfield.attributes)\n      input.setAttribute(attr.name, attr.value);\n\n    uploadfield.replaceWith(input);\n  }\n}\n\nexport function getErrorForValidity(field: FormControlElement): string {\n  const validity = field.validity;\n  if (validity.customError && field.validationMessage)\n    return field.validationMessage;\n\n  if (validity.valueMissing)\n    return getTid(\"publisher:site.forms.commonerrors.required\");\n  if (field instanceof HTMLInputElement) {\n    if (validity.rangeOverflow) {\n      const max = field.type === 'date' ? reformatDate(field.max) : field.max;\n      return getTid(\"publisher:site.forms.commonerrors.max\", max);\n    }\n    if (validity.rangeUnderflow) {\n      const min = field.type === 'date' ? reformatDate(field.min) : field.min;\n      return getTid(\"publisher:site.forms.commonerrors.min\", min);\n    }\n    if (validity.tooShort)\n      return getTid(\"publisher:site.forms.commonerrors.minlength\", field.minLength);\n    if (validity.tooLong)\n      return getTid(\"publisher:site.forms.commonerrors.maxlength\", field.maxLength);\n    if (validity.stepMismatch)\n      if (!field.step || parseInt(field.step) === 1)\n        return getTid(\"publisher:site.forms.commonerrors.step1mismatch\");\n      else\n        return getTid(\"publisher:site.forms.commonerrors.stepmismatch\", field.step);\n  }\n\n  if (validity.badInput)\n    return getTid(\"publisher:site.forms.commonerrors.default\");\n  if (validity.typeMismatch)\n    if ([\"email\", \"url\", \"number\"].includes(field.type))\n      return getTid(\"publisher:site.forms.commonerrors.\" + field.type);\n\n  for (const key of [\"badInput\", \"customError\", \"patternMismatch\", \"rangeOverflow\", \"rangeUnderflow\", \"stepMismatch\", \"typeMismatch\", \"valueMissing\"] as const)\n    if (validity[key])\n      return key;\n\n  return '?';\n}\n\nexport function isFieldNativeErrored(field: HTMLElement): field is FormControlElement {\n  return isFormControl(field) && !field.hasAttribute(\"data-wh-form-skipnativevalidation\") && !field.checkValidity();\n}\n\nexport function getFieldNativeError(field: HTMLElement) {\n  if (isFieldNativeErrored(field))\n    return getErrorForValidity(field);\n\n  return null;\n}\n\n\nexport function parseCondition(conditiontext: string): FormCondition {\n  interface FormConditionWrapper {\n    c: FormCondition;\n  }\n\n  return (JSON.parse(conditiontext) as FormConditionWrapper).c;\n}\n\nexport function getFormElementCandidates(basenode: HTMLElement, namePrefix: string) {\n  const parentForm = basenode.closest('form');\n  if (!parentForm)\n    throw new Error('No form found for element');\n\n  const candidates = qSA<HTMLElement>(basenode, queryFormFieldLike).filter(el => !(\"form\" in el) || el.form === parentForm);\n  if (namePrefix)\n    return candidates.filter(el => getFieldName(el).startsWith(namePrefix + '.'));\n  else\n    return candidates;\n}\n\n/** Get the handler for a form element */\nexport function getFormHandler<FormType extends FormBase<object> = FormBase>(node: HTMLFormElement, options: { allowMissing: true }): FormType | null;\nexport function getFormHandler<FormType extends FormBase<object> = FormBase>(node: HTMLFormElement, options?: { allowMissing?: boolean }): FormType;\n\nexport function getFormHandler<FormType extends FormBase<object> = FormBase>(node: HTMLFormElement, { allowMissing = false } = {}): FormType | null {\n  //FIXME convert to Symbol? but make sure we work cross-realm (ie tests)\n  return (node.propWhFormhandler as FormType) || (allowMissing ? null : throwError('No form handler found for form'));\n}\n\n/** Get the data for a form element. Shorthand for getFormHandler\\<FormBase\\<Shape\\>\\>(xx).data */\nexport function getFormData<DataShape extends object = Record<string, unknown>>(node: HTMLFormElement, options: { allowMissing: true }): DataShape | null;\nexport function getFormData<DataShape extends object = Record<string, unknown>>(node: HTMLFormElement, options?: { allowMissing?: boolean }): DataShape;\n\nexport function getFormData<DataShape extends object = Record<string, unknown>>(node: HTMLFormElement, { allowMissing = false } = {}): DataShape | null {\n  return getFormHandler<FormBase<DataShape>>(node, { allowMissing })?.data;\n}\n","export interface FormFieldLike extends HTMLElement {\n  disabled: boolean;\n  name: string;\n  required: boolean;\n  value: unknown;\n}\n\n/** Base class for customElements that need to act as WebHare (Publisher) form elements */\nexport abstract class JSFormElement<ValueType> extends HTMLElement implements FormFieldLike {\n  static formAssociated = true;\n  static observedAttributes = [\"required\", \"disabled\"];\n\n  // #internals = this.attachInternals();\n\n  constructor() {\n    super();\n  }\n\n  get name() {\n    return this.getAttribute('name') || '';\n  }\n  set name(newname: string) {\n    this.setAttribute('name', newname);\n  }\n  get required(): boolean {\n    return this.hasAttribute('required');\n  }\n  set required(required: boolean) {\n    if (required)\n      this.setAttribute(\"required\", \"\");\n    else\n      this.removeAttribute(\"required\");\n\n    this.refreshState();\n  }\n\n  get disabled(): boolean {\n    return this.hasAttribute('disabled');\n  }\n  set disabled(disable: boolean) {\n    if (disable)\n      this.setAttribute(\"disabled\", \"\");\n    else\n      this.removeAttribute(\"disabled\");\n\n    this.refreshState();\n  }\n\n  abstract value: ValueType;\n\n  /** Invoked whenever disabled/required states change */\n  protected refreshState() {\n  }\n\n  attributeChangedCallback(name: string, oldValue: unknown, newValue: unknown) {\n    if ([\"disabled\", \"required\"].includes(name))\n      this.refreshState();\n  }\n}\n","/* eslint-disable @typescript-eslint/no-floating-promises -- FIXME: needs API rework */\n\nimport * as dompack from '@webhare/dompack';\nimport * as focus from 'dompack/browserfix/focus';\nimport * as merge from './internal/merge';\nimport FormBase, { type FormResultValue, type FormSubmitEmbeddedResult, type FormSubmitMessage, type FormSubmitResult } from './formbase';\nimport { getFormService, getTSFormService, type PublisherFormService } from \"@webhare/forms/src/formservice\";\nimport * as emailvalidation from './internal/emailvalidation';\nimport { runMessageBox } from 'dompack/api/dialog';\nimport { debugFlags, isLive, navigateTo, type NavigateInstruction } from \"@webhare/env\";\nimport { isBlob, pick } from '@webhare/std';\nimport { setFieldError } from './internal/customvalidation';\nimport type { RPCFormTarget, RPCFormInvokeBase, RPCFormSubmission } from '@webhare/forms/src/types';\nimport { SingleFileUploader, type UploadResult } from '@webhare/upload';\nimport { createClient } from '@webhare/jsonrpc-client';\nimport { setupCaptchaFieldGroup } from './fields/captchafield';\nimport { getFormConfiguration } from '@webhare/forms/src/registration';\nimport type { CaptchaProvider } from '../captcha/api';\n\nfunction unpackObject(formvalue: FormResultValue): RPCFormInvokeBase[\"vals\"] {\n  return Object.entries(formvalue).map(_ => ({ name: _[0], value: _[1] }));\n}\n\nexport interface FormSubmitDetails<DataShape extends object = Record<string, unknown>> {\n  form: HTMLElement;\n  rpchandler: RPCFormBase<DataShape>;\n  extrasubmitdata?: unknown;\n  submitted: FormResultValue;\n  result: unknown;\n  errors: FormSubmitMessage[];\n}\n\ntype UploadCache = WeakMap<Blob, UploadResult>;\n\nfunction buildTarget(target: string): RPCFormTarget {\n  return { target, url: location.href.split('/').slice(3).join('/') };\n}\n\nclass FormSubmitter {\n  private readonly target;\n  private readonly cache: UploadCache;\n\n  constructor(target: string, cache: UploadCache | null, private readonly offline: boolean) {\n    this.target = buildTarget(target);\n    this.cache = cache || new WeakMap();\n  }\n\n  private async uploadFile(file: Blob) {\n    if (this.offline)\n      throw new Error(\"Cannot upload files in offline mode\"); //TODO convert to dataurl and test it\n\n    //TODO what if the server discarded the token? we should negotiate with the server which files it (still) wants\n    const completed = this.cache.get(file);\n    if (completed)\n      return completed;\n\n    const uploader = new SingleFileUploader(file);\n    //Ask the server if it's okay to upload these files\n    const uploadinstructions = await getTSFormService().requestUpload(this.target, uploader.manifest);\n    //Run the actual upload. Options: onProgress, signal\n    const uploadedfile: UploadResult = await uploader.upload(uploadinstructions);\n    this.cache.set(file, uploadedfile);\n    return uploadedfile;\n  }\n\n  private async convertSubmittable(formvalue: unknown): Promise<unknown> {\n    //TODO combine multiple uploads into one\n    if (Array.isArray(formvalue))\n      return await Promise.all(formvalue.map(file => this.getSubmittable(file)));\n\n    if (formvalue && typeof formvalue === 'object') {\n      if (isBlob(formvalue))\n        return await this.uploadFile(formvalue as Blob);\n\n      const result: Record<string, unknown> = {};\n      for (const [key, value] of Object.entries(formvalue)) {\n        result[key] = await this.getSubmittable(value);\n        //console.log(key, value, result[key]);\n      }\n      return result;\n    }\n    return formvalue;\n  }\n\n  async getSubmittable(formvalue: object): Promise<FormResultValue> {\n    return await this.convertSubmittable(formvalue) as FormResultValue;\n  }\n}\n\n/** Directly submit a RPC form to WebHare\n *  @param target - Formtarget as obtained from\n * @deprecated Switch to \\@webhare/forms submitForm and buildFormSubmission\n */\nexport async function submitForm(target: string, formvalue: FormResultValue, options?: { extrasubmit: unknown }): Promise<FormSubmitResult> {\n  const submitparameters = await buildRPCFormSubmission(target, formvalue, { extraSubmit: options?.extrasubmit || null, });\n  return await submitRPCForm(submitparameters);\n}\n\n/** Return a value safe for RPC submission or typed serialization */\nexport async function buildRPCFormSubmission<DataShape extends object = Record<string, unknown>>(target: string, formValue: DataShape, options?:\n  {\n    extraSubmit?: unknown;\n    offline?: boolean;\n    uploadCache?: WeakMap<Blob, UploadResult>;\n    __setupEvent?: FormSubmitDetails<DataShape>;\n  }): Promise<RPCFormSubmission> {\n  const submitter = new FormSubmitter(target, options?.uploadCache || null, options?.offline || false);\n\n  const vals = await submitter.getSubmittable(formValue);\n\n  if (options?.__setupEvent) {\n    const eventdetail = options.__setupEvent;\n    eventdetail.extrasubmitdata = options.extraSubmit || null;\n    eventdetail.submitted = vals;\n  }\n\n  const submitparameters: RPCFormSubmission = {\n    ...buildTarget(target),\n    vals: unpackObject(vals),\n    extrasubmit: options?.extraSubmit || null\n  };\n  return submitparameters;\n}\n\nexport async function submitRPCForm(submission: RPCFormSubmission): Promise<FormSubmitResult> {\n  // TODO switch over to typed rpc, allow rpc options that make sense to be specified as options to submitRPCForm\n  const client = createClient<PublisherFormService>(\"publisher:forms\");\n  return await client.formSubmit(submission);\n}\n\nexport default class RPCFormBase<DataShape extends object = Record<string, unknown>> extends FormBase<DataShape> {\n  __formhandler = {\n    errors: [],\n    warnings: [],\n    formid: \"\",\n    url: \"\",\n    target: \"\",\n    submitting: false\n  };\n\n  #hadFocus = false;\n  #completedUploads = new WeakMap<Blob, UploadResult>;\n  #settingUpCaptcha = false;\n\n  pendingrpcs = new Array<Promise<unknown>>;\n\n  constructor(formnode: HTMLFormElement) {\n    super(formnode);\n    this.__formhandler.formid = formnode.dataset.whFormId || ''; //needed for 'old' __formwidget: stuff\n    this.__formhandler.url = location.href.split('/').slice(3).join('/');\n    this.__formhandler.target = formnode.dataset.whFormTarget || '';\n    window.addEventListener(\"wh:form-configure\", () => this.checkCaptcha());\n    this.node.addEventListener(\"focusin\", this.#onFirstFocus, true);\n\n    if (!this.__formhandler.target) {\n      if (this.__formhandler.formid) {\n        console.error(\"This page needs to be republished!\");\n      } else {\n        if (!isLive)\n          console.error(\"Missing data-wh-form-target on form, did your witty apply '[form.formattributes]' to the <form> tag ?\", formnode);\n        throw new Error(\"Form does not appear to be a WebHare form\");\n      }\n    }\n\n    this.checkCaptcha();\n  }\n\n  getRPCFormIdentifier(): RPCFormTarget { //submitinfo as required by some RPCs\n    return buildTarget(this.__formhandler.target);\n  }\n\n  async #getSubmitVals(): Promise<FormResultValue> {\n    const formvalue = await this.getFormValue();\n    const submitter = new FormSubmitter(this.__formhandler.target, this.#completedUploads, false);\n    return await submitter.getSubmittable(formvalue);\n  }\n\n  //Invoke a function on the form on the server\n  async _invokeRPC(background: boolean, methodname: string, args: unknown[]) {\n    const waiter = Promise.withResolvers<void>();\n\n    if (!background)\n      this.onRPC(waiter.promise);\n\n    const lock = dompack.flagUIBusy({ modal: !background });\n    try {\n      const rpc = getFormService().formInvoke({\n        ...this.getRPCFormIdentifier(),\n        vals: unpackObject(await this.#getSubmitVals()),\n        methodname,\n        args\n      });\n      this.pendingrpcs.push(rpc);\n      const result = await rpc;\n      this._processMessages(result.messages);\n      return result.result;\n    } finally {\n      lock.release();\n      waiter.resolve();\n    }\n  }\n\n  /* Override this to implement support for incoming field messages */\n  processFieldMessage(field: string, prop: string, value: unknown) {\n    if (field.startsWith(\"#page.\")) {\n      const matchpage = field === \"#page.thankyou\" ? this.node.querySelector<HTMLElement>(`.wh-form__page[data-wh-form-pagerole=thankyou]`) : null;\n      if (!matchpage) { //we currently don't have anything to edit on other pages than thankyou\n        console.warn(\"Message for non-page field: \" + field + \", prop: \" + prop + \", value: \" + String(value));\n        return;\n      }\n\n      if (prop === 'data') {\n        const dataval = value as { redirect: NavigateInstruction | null; exitbutton: string };\n        matchpage.dataset.whFormNavigateTo = dataval.redirect ? JSON.stringify(dataval.redirect) : undefined;\n        matchpage.dataset.whFormExitButton = dataval.exitbutton;\n      }\n    } else {\n      const fieldnode = this.node.querySelector<HTMLElement>(`*[name=\"${CSS.escape(field)}\"], *[data-wh-form-name=\"${CSS.escape(field)}\"]`);\n      if (!fieldnode) {\n        console.warn(\"Message for non-existent field: \" + field + \", prop: \" + prop + \", value: \" + String(value));\n        return;\n      }\n      if (prop === 'value') {\n        this.setFieldValue(fieldnode, value);\n        return;\n      }\n    }\n    console.warn(\"Unknown field message: field: \" + field + \", prop: \" + prop + \", value: \" + String(value));\n  }\n\n  //Override this function to easily submit extra fields\n  getFormExtraSubmitData(): object | Promise<object> {\n    return {};\n  }\n\n  //Invoked when RPC is occuring. Is passed a promise that will resolve on completion\n  //onRPC is DEPRECATED, switching to event based api\n  onRPC(promise: Promise<void>) {\n  }\n\n  /** Invoke a function on the form on the server\n      @param methodname - Name of the function on the form\n      @param args - Arguments for the function\n      @returns Promise that resolves to the result of the rpc call\n  */\n  invokeRPC(methodname: string, ...args: unknown[]) {\n    return this._invokeRPC(false, methodname, args);\n  }\n\n  /** Invoke a function on the form on the server, doesn't call .onRPC or request modality layers\n      @param methodname - Name of the function on the form\n      @param args - Arguments for the function\n      @returns Promise that resolves to the result of the rpc call\n  */\n  invokeBackgroundRPC(methodname: string, ...args: unknown[]) {\n    return this._invokeRPC(true, methodname, args);\n  }\n\n  _processMessages(messages: Array<{ field: string; prop: string; data: unknown }>) {\n    for (const msg of messages) {\n      this.processFieldMessage(msg.field, msg.prop, msg.data);\n    }\n  }\n\n  async _flushPendingRPCs() {\n    while (this.pendingrpcs.length) {\n      try {\n        await this.pendingrpcs.pop();\n      } catch (ignore) {\n        //*we* can't handle those...\n      }\n    }\n  }\n\n  async buildFormSubmission(extradata?: object, options?: { __setupEvent?: FormSubmitDetails<DataShape> }): Promise<RPCFormSubmission> {\n    //Request extrasubmit first, so that if it returns a promise, it can execute in parallel with getFormValue\n    const extraSubmitAwaitable = this.getFormExtraSubmitData();\n    //FIXME we want getFormValue to be sync (and just use 'this.data' here) - who is still sending promises our way? too much to sort out for a backport\n    const formvalue = await this.getFormValue() as DataShape;\n    const extraSubmit = { ...extradata, ...(await extraSubmitAwaitable as Record<string, unknown>) };\n\n    await this._flushPendingRPCs();\n    dompack.dispatchCustomEvent(this.node, \"wh:form-preparesubmit\", {\n      bubbles: true, cancelable: false, detail: {\n        extrasubmit: extraSubmit\n      }\n    });\n\n    const submitparameters = await buildRPCFormSubmission<DataShape>(this.__formhandler.target, formvalue, {\n      extraSubmit,\n      offline: false,\n      uploadCache: this.#completedUploads,\n      //hack because we need to record the 'vars' value before unpackObject flattens it for safe HareScript RPC\n      __setupEvent: options?.__setupEvent\n    });\n\n    return submitparameters;\n  }\n\n  #onFirstFocus = () => {\n    this.#hadFocus = true;\n    this.checkCaptcha();\n  };\n\n  private checkCaptcha() {\n    //Checks whether to show captcha based on configuration. Note that even if *we* think it's not needed, form submission may still require a captcha\n    const config = getFormConfiguration();\n    const shouldShow = config?.captcha === \"onLoad\" || (config?.captcha === \"onActivate\" && this.#hadFocus);\n    if (shouldShow && this.node.dataset.whFormCaptcha !== undefined && !this.#settingUpCaptcha && !this.getElementByName(\"__form_captcha\")) {\n      this.#settingUpCaptcha = true;\n      void getFormService().getCaptchaConfiguration(this.getRPCFormIdentifier()).then(captchaConfig => {\n        if (captchaConfig) {\n          setupCaptchaFieldGroup(this, captchaConfig);\n        }\n      });\n    }\n  }\n\n  async submitForm(parameters: RPCFormSubmission): Promise<FormSubmitResult> {\n    return await submitRPCForm(parameters);\n  }\n\n  async submit(extradata?: object): Promise<{ result?: FormSubmitEmbeddedResult }> {\n    //ADDME timeout and free the form after some time\n    if (this.__formhandler.submitting) //throwing is the safest solution... having the caller register a second resolve is too dangerous\n      throw new Error(\"The form is already being submitted\");\n\n    const waiter = Promise.withResolvers<void>();\n    let insubmitrpc = false;\n    this.onRPC(waiter.promise);\n\n    const eventdetail: FormSubmitDetails<DataShape> = {\n      form: this.node,\n      rpchandler: this,\n      submitted: {},\n      errors: [],\n      result: null\n    };\n\n    try {\n      this.__formhandler.submitting = true;\n\n      const submitparameters = await this.buildFormSubmission(extradata, { __setupEvent: eventdetail });\n\n      if (debugFlags.fhv)\n        console.log('[fhv] start submission', submitparameters);\n\n      insubmitrpc = true; //so we can easily determine exception source\n      const result = await this.submitForm(submitparameters);\n      insubmitrpc = false;\n\n      if (debugFlags.fhv)\n        console.log('[fhv] received response', result);\n\n      this._processMessages(result.messages);\n\n      if (!dompack.dispatchCustomEvent(this.node, \"wh:form-response\", { bubbles: true, cancelable: true, detail: result }))\n        return result;\n\n      eventdetail.result = result.result;\n      eventdetail.errors = result.errors;\n\n      let didfirstfocus = false;\n      const globalerrors = [];\n      for (const error of result.errors) {\n        if (!error.name) {\n          globalerrors.push(error);\n          continue;\n        }\n\n        let failednode = this.node.querySelector('[name=\"' + error.name + '\"], [data-wh-form-name=\"' + error.name + '\"]');\n        if (!failednode) {\n          if (error.name === \"__form_captcha\") { //created on demand\n            const serverMetadata = error.metadata as { provider: CaptchaProvider };\n            failednode = setupCaptchaFieldGroup(this, serverMetadata.provider);\n          } else {\n            console.error(\"[fhv] Unable to find node '\" + error.name + \"' which caused error:\" + error.message);\n            continue;\n          }\n        }\n        if (!didfirstfocus) {\n          dompack.focus(failednode);\n          didfirstfocus = true;\n        }\n        setFieldError(failednode, error.message, { reportimmediately: true, serverside: true, metadata: error.metadata });\n      }\n\n      if (result.success) {\n        this.sendFormEvent({ event: 'submitted' });\n        if (dompack.dispatchCustomEvent(this.node, \"wh:form-submitted\", { bubbles: true, cancelable: true, detail: eventdetail as FormSubmitDetails<Record<string, unknown>> })) {\n          merge.run(this.node, { form: await this.getFormValue() });\n\n          //FIXME why is going to 'thank you' not in the formbase?\n          this._navigateToThankYou(result.result && result.result.richvalues);\n          this.onSubmitSuccess(result.result);\n        }\n      } else {\n        const failedfields = result.errors.map(error => error.name || \"*\").sort().join(\" \");\n        this.sendFormEvent({ event: 'failed', errorfields: failedfields, errorsource: 'server' });\n\n        if (globalerrors.length) {\n          if (dompack.dispatchCustomEvent(this.node, \"wh:form-globalerrors\", { bubbles: true, cancelable: true, detail: { globalerrors } }))\n            this.displayGlobalErrors(globalerrors);\n        }\n\n        if (dompack.dispatchCustomEvent(this.node, \"wh:form-failed\", { bubbles: true, cancelable: true, detail: eventdetail }))\n          this.onSubmitFailed(result.errors, result.result);\n      }\n      return pick(result, [\"result\"]);\n    } catch (e) {\n      this.sendFormEvent({ event: 'exception', exception: String(e), errorsource: insubmitrpc ? 'server' : 'client' });\n\n      if (dompack.dispatchCustomEvent(this.node, \"wh:form-exception\", { bubbles: true, cancelable: true, detail: eventdetail }))\n        this.onSubmitException(e as Error);\n\n      throw e;\n    } finally {\n      waiter.resolve();\n      this.__formhandler.submitting = false;\n    }\n  }\n\n  displayGlobalErrors(globalerrors: FormSubmitMessage[]) {\n    try {\n      const errors = globalerrors.map(error => dompack.create(\"p\", { textContent: error.message }));\n      runMessageBox(errors, [{ title: \"OK\" }]); //TODO: language?\n    } catch (e) {\n      console.error(\"runMessageBox failed\", e);\n      // eslint-disable-next-line no-alert -- alert is our fallback without message boxes\n      alert(globalerrors.map(error => error.message).join(\"\\n\"));\n    }\n  }\n\n  //Get the first group that failed error handling\n  getFirstFailedGroup() {\n    return this.node.querySelector(\".wh-form__fieldgroup-error\");\n  }\n\n  //override this to deal with succesful submissions\n  onSubmitSuccess(result: FormSubmitEmbeddedResult<unknown>) {\n    const formpos = this.node.getBoundingClientRect();\n    if (formpos.top < 0)\n      this.node.scrollIntoView({ block: 'start', behavior: 'smooth' });\n\n    if (result && result.resultsguid)\n      this.node.dataset.whFormResultguid = result.resultsguid;\n\n    if (result && result.submitinstruction)\n      navigateTo(result.submitinstruction);\n  }\n\n  //override this to deal with failed submissions\n  onSubmitFailed(errors: FormSubmitMessage[], result: unknown) {\n  }\n\n  //override this to deal with form exceptions\n  onSubmitException(e: Error) {\n  }\n\n  async validateSingleFormField(field: HTMLElement): Promise<boolean> {\n    if (field instanceof HTMLInputElement && field.type === \"email\") { //TODO perhaps move this to webharefields.es ?\n      if (focus.getCurrentlyFocusedElement() === field) { //TODO clearing suggestion on change should probably be generalized\n        if (field.propWhValidationSuggestion) {\n          field.propWhValidationSuggestion = null;\n        }\n      }\n\n      //Just because it's focused doesn't mean we shouldn't validate it\n      const validation = emailvalidation.validateField(this, field);\n      this.pendingrpcs.push(validation);\n      if (!(await validation))\n        return false;\n    }\n    return true;\n  }\n}\n","import * as dompack from 'dompack';\nimport { getTid, getTidLanguage } from \"@webhare/gettid\";\nimport { getFormService } from \"@webhare/forms/src/formservice\";\nimport { isValidEmail, sleep } from '@webhare/std';\nimport { setFieldError } from './customvalidation';\nimport type { EmailValidationResult } from '@webhare/forms/src/types';\nimport type FormBase from '../formbase';\nimport type RPCFormBase from '../rpc';\nimport { debugFlags } from '@webhare/env';\n\nconst cache:\n  {\n    [key: string]: Promise<EmailValidationResult>;\n  } = {};\n\nfunction mayValidateField(field: HTMLInputElement) {\n  if (field.disabled || field.readOnly) //FIXME shouldn't we just decide not to validate at a much higher level if something cannot be changed ?\n    return false;\n\n  if (field.autocomplete && field.autocomplete.split(' ').includes(\"username\")) //Well, we shouldn't *force* usernames as a blacklisted domain might still have been explicitly added as login. but suggestions are still useful?\n    return false;\n  return true;\n}\n\nfunction acceptEmailSuggestion<DataShape extends object = Record<string, unknown>>(evt: Event, form: FormBase<DataShape>, field: HTMLInputElement, suggestion: string) {\n  dompack.stop(evt);\n  field.value = suggestion;\n  field.propWhValidationSuggestion = null;\n  form._reportFieldValidity(field);\n}\n\nexport async function validateField<DataShape extends object = Record<string, unknown>>(form: FormBase<DataShape> | RPCFormBase<DataShape>, field: HTMLInputElement) {\n  if (field.dataset.whFormEmailBlocked) {\n    delete field.dataset.whFormEmailBlocked;\n    setFieldError(field, \"\"); //explicitly clear our earlier setFieldError, but only if we set it. FIXME To really cleanly solve this we need better integration with rpc.ts - we want to be in the setupValidation chain and simply return errors instead of being explictly invoked\n  }\n\n  const checkvalue: string = field.value;\n  if (!checkvalue || !mayValidateField(field)) {\n    return true; //not a problem\n  }\n\n  if (!isValidEmail(checkvalue)) {\n    //TODO why aren't we just returning the error like a validator callback? may also help avoid the whFormEamailBlocked hack..\n    field.dataset.whFormEmailBlocked = \"true\";\n    setFieldError(field, getTid(\"publisher:site.forms.commonerrors.email\"));\n    return false;\n  }\n\n  //user is 'done' with email field apparently. remotely validate it\n  const key = \"e_\" + field.name + \".\" + checkvalue; //e_ prefix protects against funny people using 'constructor' etc. TODO just switch to a Map<> or similar. TODO only include field.name if needed, and also bind to the form then\n  if (cache[key] === undefined) {\n    const rpcCall = \"getRPCFormIdentifier\" in form ?\n      //TODO rendering.whlib should add a data attribute if there are form+field-specific checks, perhaps we can even generalize that for all fields instead of just email whenever they need to do direct validation\n      getFormService().formValidateEmail({ ...form.getRPCFormIdentifier(), field: field.name }, checkvalue)\n      : getFormService().validateEmail(getTidLanguage(), checkvalue);\n\n    //wrap in timeout\n    cache[key] = Promise.race([rpcCall, sleep(3000).then(() => { throw new Error(\"Timeout\"); })]);\n  }\n\n  //TODO should we ever clear the cache? only relevant probably if someone is on the frontend testing emails and doesn't want to refresh\n  let result: EmailValidationResult | undefined;\n\n  try {\n    result = await cache[key];\n  } catch (e) { //timeout or other error, or offline form (PWA?)\n    if (debugFlags.fhv)\n      console.log('[fhv] Email validation error or timeout for value', checkvalue, e);\n  }\n\n  if (checkvalue !== field.value || !mayValidateField(field))\n    return true; //the field already changed, don't report about old errors\n\n  if (result?.blocked) {\n    field.dataset.whFormEmailBlocked = \"true\";\n    setFieldError(field, result.blocked);\n    return false;\n  }\n\n  if (result?.force) {\n    field.value = result.force;\n\n    //we should be able to assume we won't have to revalidate a server-provided suggestion\n    cache[\"e_\" + field.name + \".\" + result.force] = Promise.resolve<EmailValidationResult>({});\n\n    return true;\n  } else if (result?.suggestion) {\n    const suggestion = getTid(\"publisher:site.forms.commonerrors.email_suggestion\", \"___SUGGESTION___\").split(\"___SUGGESTION___\");\n\n    //we should be able to assume we won't have to revalidate a server-provided suggestion\n    cache[\"e_\" + field.name + \".\" + result.suggestion] = Promise.resolve<EmailValidationResult>({});\n\n    field.propWhValidationSuggestion =\n      <span class=\"wh-form__emailcorrection\">\n        {suggestion[0]}\n        <a href=\"#\" class=\"wh-form__emailcorrected\" on={{ click: (evt: Event) => acceptEmailSuggestion(evt, form, field, result.suggestion as string) }}>{result.suggestion}</a>\n        {suggestion[1]}\n      </span>;\n    return true;\n  }\n  return true;\n}\n","import * as dompack from '@webhare/dompack';\nimport { initializeCaptcha, type CaptchaProvider } from \"@mod-publisher/js/captcha/api\";\nimport { setFieldError, type SetFieldErrorData } from '../internal/customvalidation';\n\nimport \"../../captcha/__captcha.lang.json\"; //TODO or have forms send this tid (so it can also be overridden there)\nimport { JSFormElement } from '@webhare/forms';\nimport { getTid } from '@webhare/gettid';\nimport type RPCFormBase from '../rpc';\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    \"wh-captcha\": CaptchaField;\n  }\n}\n\nexport default class CaptchaField extends JSFormElement<string> {\n  value = '';\n  provider: CaptchaProvider | null = null;\n\n  constructor() {\n    super();\n    this.addEventListener('wh:form-setfielderror', evt => void this._setFieldError(evt));\n    this.whFormsApiChecker = () => this.check();\n\n    const form = this.closest('form');\n    if (form)\n      form.addEventListener('reset', () => this.onReset());\n  }\n\n  check(): void {\n    if (!this.value)\n      setFieldError(this, getTid(\"publisher:site.forms.commonerrors.required\"), { reportimmediately: false });\n    else\n      setFieldError(this, \"\", { reportimmediately: false });\n  }\n\n  setup(provider: CaptchaProvider) {\n    if (this.provider)\n      throw new Error(\"CaptchaField is already setup\");\n\n    this.provider = provider;\n    this.initialize();\n  }\n\n  private initialize() {\n    this.value = '';\n    this.replaceChildren();\n    void initializeCaptcha(this.provider!, this, {\n      onResponse: (result: string) => { this.value = result; }\n    });\n  }\n\n  private onReset() {\n    void this.initialize();\n  }\n\n  async _setFieldError(evt: CustomEvent<SetFieldErrorData>) {\n    dompack.stop(evt);\n    if (!evt.detail.error) //error cleared\n      return;\n\n    if (this.value) { //we were already sending a response!\n      console.log(\"Captcha response was rejected, resetting\");\n      this.onReset(); //better restart the control, timeout or duplicate submission\n    }\n  }\n}\n\nexport function setupCaptchaFieldGroup(form: RPCFormBase<object>, provider: CaptchaProvider): CaptchaField {\n  /* Setup a page-less holder for the captcha field\n\n    <div class=\"wh-form__page wh-form__page--visible\">\n      <div class=\"wh-form__fieldgroup\" data-wh-form-group-for=\"__form_captcha\">\n        ...\n    */\n\n  const captchaControl = dompack.create(\"wh-captcha\", { class: \"wh-form__captcha\", dataset: { whFormName: \"__form_captcha\", whFormRequired: \"true\" } });\n\n  const virtualCaptchaPage = dompack.create(\"div\", { class: \"wh-form__captchapage\" }, [\n    dompack.create(\"div\", { class: \"wh-form__fieldgroup\", dataset: { whFormGroupFor: \"__form_captcha\" } }, [\n      dompack.create(\"label\", { class: \"wh-form__label\" }, [getTid(\"publisher:site.captcha.title\")]),\n      dompack.create(\"div\", { class: \"wh-form__fields\" },\n        [dompack.create(\"div\", { class: \"wh-form__fieldline\" }, [captchaControl])]\n      )\n    ])\n  ]);\n\n  //Position it before the navbuttons, but if they are missing for whatever reason, just add to the end of the form\n  const buttonarea = dompack.qS(form.node, \".wh-form__navbuttons\");\n  if (buttonarea)\n    buttonarea.before(virtualCaptchaPage);\n  else\n    form.node.appendChild(virtualCaptchaPage);\n\n  void captchaControl.setup(provider);\n\n  return captchaControl;\n}\n\n\ncustomElements.define(\"wh-captcha\", CaptchaField);\n","import { getTid } from \"@webhare/gettid\";\nimport \"./__captcha.lang.json\";\n\nexport interface CaptchaProvider {\n  name: string;\n  apikey: string;\n}\n\nexport interface CaptchaSettings {\n  title: string;\n  onResponse: (response: string) => void;\n}\n\nexport interface CaptchaProviderRegistration {\n  initialize: (provider: CaptchaProvider, injectInto: HTMLElement, settings: CaptchaSettings) => Promise<void>;\n}\n\nexport const captcharegistry: Record<string, CaptchaProviderRegistration> = {};\n\n\nexport async function initializeCaptcha(provider: CaptchaProvider, injectInto: HTMLElement, settings?: Partial<CaptchaSettings>): Promise<void> {\n  if (!captcharegistry[provider.name])\n    throw new Error(`Captcha provider '${provider.name}' not registered`);\n  if (!settings?.onResponse)\n    throw new Error(\"onResponse callback is required\");\n\n  const finalsettings: CaptchaSettings = {\n    title: settings?.title ?? getTid(\"publisher:site.captcha.title\"),\n    onResponse: settings?.onResponse ?? (() => { }),\n  };\n\n  await captcharegistry[provider.name].initialize(provider, injectInto, finalsettings);\n}\n","// Auto-generated language file from /opt/wh/whtree/modules/publisher/js/captcha/__captcha.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"publisher\",\"en\",{\"site\":{\"captcha\":{\"explain\":\"Please check the box below\",\"title\":\"Verification\"}}});\nregisterTexts(\"publisher\",\"nl\",{\"site\":{\"captcha\":{\"explain\":\"Vink het vakje hieronder aan\",\"title\":\"Verificatie\"}}});\nregisterTexts(\"publisher\",\"de\",{\"site\":{\"captcha\":{\"explain\":\"Bitte setze das Häkchen\",\"title\":\"Kontrolle\"}}});\nregisterTexts(\"publisher\",\"ar\",{\"site\":{\"captcha\":{\"explain\":\"يرجى جعل علامة ألإختيار على المربع أدنى\",\"title\":\"قربت الإنتهاء\"}}});\nregisterTexts(\"publisher\",\"bg\",{\"site\":{\"captcha\":{\"explain\":\"Моля, проверете полето отдолу\",\"title\":\"Почти е готово\"}}});\nregisterTexts(\"publisher\",\"el\",{\"site\":{\"captcha\":{\"explain\":\"Παρακαλώ ελέγξτε το παρακάτω πλαίσιο\",\"title\":\"Σχεδόν έτοιμο\"}}});\nregisterTexts(\"publisher\",\"es\",{\"site\":{\"captcha\":{\"explain\":\"Por favor, marque la casilla a continuación\",\"title\":\"Casi listo\"}}});\nregisterTexts(\"publisher\",\"id\",{\"site\":{\"captcha\":{\"explain\":\"Mohon centang kotak dibawah\",\"title\":\"Hampir selesai\"}}});\nregisterTexts(\"publisher\",\"pt\",{\"site\":{\"captcha\":{\"explain\":\"Por favor, marque o campo abaixo.\",\"title\":\"Quase pronto.\"}}});\nregisterTexts(\"publisher\",\"ro\",{\"site\":{\"captcha\":{\"explain\":\"Te rugăm să verifici căsuța de mai jos\",\"title\":\"Aproape terminat\"}}});\nregisterTexts(\"publisher\",\"zh\",{\"site\":{\"captcha\":{\"explain\":\"请查看下方方框\",\"title\":\"接近完成\"}}});\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/nl.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/de.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/ar.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/bg.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/el.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/es.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/id.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/pt.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/ro.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/zh.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n","import * as dompack from 'dompack';\nimport { getTid } from \"@webhare/gettid\";\nimport { FileEditElement as FileEditElementBase } from './fileeditbase';\nimport './upload.css';\nimport { isFile } from '@webhare/std';\n\n\n\n//FIXME nicer class name? eg add form or field to these (and imgedit) class names?\nexport class FileUploadFormElement extends FileEditElementBase {\n  constructor() {\n    super();\n    this.refresh();\n  }\n\n  #constructFileHolder() {\n    const fileholder = document.createElement(\"div\");\n    fileholder.classList.add('file');\n    return fileholder;\n  }\n\n  refresh() {\n    const nodes = [];\n\n    for (const [idx, file] of this.currentFiles.entries()) {\n      const fileholder = this.#constructFileHolder();\n\n      // const label = getLabelText(this.node);\n      // aria-label={label}\n      const filename = isFile(file) ? file.name : file.fileName;\n      /* for ease of 'form like' presentation, we're currently using an <input>. but quite hacky, eg. we need readonly to have it not interfere with clicks. */\n      const filenamefield =\n        <input part=\"filename\" class=\"file__name\" type=\"text\" value={filename} readonly />;\n\n      const deletebutton = <button part=\"button deletebutton\" class=\"deletebutton file__deletebutton\" />;\n      this.setupDeleteButton(deletebutton, idx);\n\n      fileholder.append(filenamefield, deletebutton);\n      nodes.push(fileholder);\n    }\n\n    if (this.currentFiles.length < this.maxFiles) {\n      const fileholder = this.#constructFileHolder();\n      fileholder.classList.add('file--placeholder');\n\n      const filenamefield =\n        <input part=\"filename\" class=\"file__name\" type=\"text\" value=\"\" placeholder={getTid(\"publisher:site.forms.upload-emptytext\")} disabled readonly />;\n\n      const uploadbutton = <button part=\"button selectbutton\" type=\"button\" class=\"wh-form__uploadfieldselect wh-form__button\"><span class=\"wh-form__buttonlabel\">{getTid(\"publisher:site.forms.selectfile\")}</span></button>;\n      this.setupUploadButton(fileholder);\n      fileholder.append(filenamefield, uploadbutton);\n      nodes.push(fileholder);\n    }\n\n    this.maindiv.replaceChildren(...nodes);\n  }\n}\n\n//////// Legacy version. We expect existing users to migrate to the version above\n\nexport default class UploadField {\n  constructor(node: HTMLElement) {\n    if (!customElements.get(\"wh-fileedit\"))\n      customElements.define(\"wh-fileedit\", FileUploadFormElement);\n  }\n}\n","/* eslint-disable @typescript-eslint/no-floating-promises -- FIXME: needs API rework */\n\nimport * as dompack from 'dompack';\nimport { requestFile } from \"@webhare/upload\";\n\nimport { getTid } from \"@webhare/gettid\";\nimport { setFieldError } from '@mod-publisher/js/forms/internal/customvalidation';\nimport { getFieldDisplayName } from '@webhare/forms/src/domsupport';\nimport { JSFormElement } from '@webhare/forms/src/jsformelement';\nimport type { FormFileValue } from '@webhare/forms/src/types';\nimport \"@mod-publisher/js/forms/internal/form.lang.json\"; //we need eg publisher:site.forms.selectfile\n\nfunction isAcceptableType(fileType: string, masks: string[]) {\n  if (masks.includes(fileType))\n    return true;\n\n  const basetype = fileType.split('/')[0];\n  if (['image', 'video', 'audio'].includes(basetype) && masks.includes(basetype + '/*'))\n    return true;\n\n  return false;\n}\n\n\nexport abstract class FileEditElement extends JSFormElement<FormFileValue[]> {\n  root;\n  maindiv;\n  readonly group: HTMLElement | null;\n\n  /** The current uploaded files */\n  protected currentFiles = new Array<FormFileValue>;\n  /** Maximum number of files */\n  protected maxFiles;\n\n  constructor() {\n    super();\n    this.root = this.attachShadow({ mode: 'open', delegatesFocus: true });\n    this.maindiv = document.createElement(\"div\");\n    this.maindiv.inert = this.disabled;\n\n    const csslink = document.createElement(\"link\");\n    csslink.rel = \"stylesheet\";\n    csslink.href = \"/.wh/ea/p/forms/controls.css\";\n    this.root.append(csslink, this.maindiv);\n\n    this.group = this.closest<HTMLElement>(\".wh-form__fieldgroup\");\n    this.whFormsApiChecker = async () => { await this._check(); };\n    this.maxFiles = parseInt(this.getAttribute(\"max-files\")!) || 1;\n    if (this.getAttribute(\"value\"))\n      this.#setValue(JSON.parse(this.getAttribute(\"value\")!));\n\n    if (this.group) {\n      this.group.addEventListener(\"dragover\", evt => evt.preventDefault());\n      this.group.addEventListener(\"dragenter\", evt => evt.preventDefault());\n      this.group.addEventListener(\"drop\", evt => this.doDrop(evt));\n    }\n  }\n  abstract refresh(): void;\n  isSet(): boolean {\n    return this.currentFiles.length > 0;\n  }\n  async _check() {\n    const error = this.required && !this.isSet();\n    if (error)\n      setFieldError(this, getTid(\"publisher:site.forms.commonerrors.required\"), { reportimmediately: false });\n    else\n      setFieldError(this, \"\", { reportimmediately: false });\n    return error;\n  }\n\n  protected refreshState() {\n    this.maindiv.inert = this.disabled;\n  }\n\n  get value(): FormFileValue[] {\n    return this.currentFiles;\n  }\n\n  set value(value: FormFileValue[]) {\n    this.#setValue(value);\n    this.refresh();\n  }\n\n  #setValue(value: Array<Partial<FormFileValue>>) { //taking a partial so we can do a better job at fixing missing fields from incorrect callers\n    //updates the value but does not fire events/refresh()\n    const toset: FormFileValue[] = [];\n\n    for (const row of value) {\n      if (row?.file) {\n        if (!this._isAcceptableType(row.file.type))\n          throw new Error(`File type ${row.file.type} is not acceptable for ${getFieldDisplayName(this)}`);\n        toset.push({ fileName: row.fileName || row.file.name, file: row.file, link: null });\n      } else if (row?.link) {\n        toset.push({ fileName: row.fileName || \"\", file: null, link: row.link });\n      } else {\n        throw new Error(`Incorrect value type received for ${getFieldDisplayName(this)} - expect 'file' or 'link' to be set`);\n      }\n\n      if (toset.length >= this.maxFiles)\n        break;\n    }\n    this.currentFiles = toset;\n  }\n\n  _isAcceptableType(mimetype: string) {\n    const accept = this.getAttribute(\"accept\")?.split(',').map(mask => mask.trim()) ?? [];\n    return !accept.length || isAcceptableType(mimetype, accept);\n  }\n\n  private doDrop(evt: DragEvent) {\n    //FIXME check 'accept' - or can the drag handlers do that?\n    evt.preventDefault();\n\n    const files = evt.dataTransfer?.files;\n    if (files)\n      this.processUpload(files[0]);\n  }\n\n  async uploadFile(evt: Event) {\n    evt.preventDefault();\n\n    if (this.disabled || this.currentFiles.length >= this.maxFiles)\n      return; //should not even have been offered?\n\n    const accept = this.getAttribute(\"accept\")?.split(',') ?? [];\n    using lock = dompack.flagUIBusy();\n    void (lock);\n\n    const file = await requestFile({ accept });\n    if (!file)\n      return;\n\n    await this.processUpload(file);\n  }\n\n  private async processUpload(file: File) {\n    if (this.disabled || this.currentFiles.length >= this.maxFiles)\n      return; //should not even have been offered?\n\n    if (!this._isAcceptableType(file.type)) {\n      //TODO tell server it can destroy the file immediately (should have told uploadsession at the start?\n      const msg = this.dataset.whAccepterror || getTid(\"publisher:site.forms.commonerrors.badfiletype\");\n      setFieldError(this, msg, { reportimmediately: true });\n      return;\n    }\n\n    this.currentFiles.push({ fileName: file.name, file: file, link: null });\n    this.refresh();\n    dompack.dispatchCustomEvent(this, 'change', { bubbles: true, cancelable: false });\n  }\n\n  protected deleteFile(evt: Event, idx: number) {\n    if (evt)\n      dompack.stop(evt);\n\n    this.currentFiles.splice(idx, 1);\n    this.refresh();\n    dompack.dispatchCustomEvent(this, 'change', { bubbles: true, cancelable: false });\n  }\n\n  protected setupUploadButton(button: HTMLElement) {\n    button.addEventListener(\"click\", evt => void this.uploadFile(evt));\n  }\n\n  protected setupDeleteButton(button: HTMLElement, idx: number) {\n    button.addEventListener(\"click\", evt => this.deleteFile(evt, idx));\n    button.ariaLabel = getTid(\"publisher:site.forms.imgedit-remove\");\n  }\n}\n","// Auto-generated language file from /opt/wh/whtree/modules/publisher/js/forms/internal/form.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"publisher\",\"en\",{\"site\":{\"forms\":{\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"nextpage\":\"Next\",\"previouspage\":\"Previous\",\"selectfile\":\"Select file\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"starsrequired\":\"* indicates a required field\",\"submit\":\"Submit\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\",\"addressfield\":{\"address_not_found\":\"The address could not be found.\",\"invalid_nr_detail\":\"Invalid house number.\",\"invalid_zip\":\"Invalid ZIP or postal code.\",\"zip_not_found\":\"Unknown combination of postal code and house number.\"},\"commonerrors\":{\"alphanum\":\"This value should be alphanumeric.\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"check\":[\"You must select between \",1,\" and \",2,\" choices.\"],\"date\":\"This is not a valid date\",\"default\":\"This value seems to be invalid.\",\"digits\":\"This value should be digits.\",\"email\":\"This value should be a valid email.\",\"email_baddomain\":[\"Due to difficulties with mailing to \",1,\" email addresses we kindly request you to use an alternative email provider.\"],\"email_suggestion\":[\"Did you mean \",1,\"?\"],\"equalto\":\"This value should be the same.\",\"formunavailable\":\"This form is currently unavailable\",\"integer\":\"This value should be a valid integer.\",\"length\":[\"This value length is invalid. It should be between \",1,\" and \",2,\" characters long.\"],\"max\":[\"This value should be lower than or equal to \",1,\".\"],\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxcheck\":[\"You must select \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 choice\"],\"subselse\":[1,\" choices\"]},\" or fewer.\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxlength\":[\"This value is too long. It should have \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 character\"],\"subselse\":[1,\" characters\"]},\" or fewer.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"min\":[\"This value should be greater than or equal to \",1,\".\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"mincheck\":[\"You must select at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 choice\"],\"subselse\":[1,\" choices\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minlength\":[\"This value is too short. It should have \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 character\"],\"subselse\":[1,\" characters\"]},\" or more.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"notblank\":\"This value should not be blank.\",\"number\":\"This value should be a valid number.\",\"pattern\":\"This value seems to be invalid.\",\"range\":[\"This value should be between \",1,\" and \",2,\".\"],\"required\":\"This value is required.\",\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\",\"url\":\"This value should be a valid url.\"}}}});\nregisterTexts(\"publisher\",\"nl\",{\"site\":{\"forms\":{\"imgedit-explain-upload\":\"Sleep bestanden hier of klik om te uploaden\",\"imgedit-groupelement-replace\":[1,\", Vervang afbeelding\"],\"imgedit-groupelement-upload\":[1,\", Upload afbeelding\"],\"imgedit-remove\":\"Verwijder afbeelding\",\"nextpage\":\"Volgende\",\"previouspage\":\"Vorige\",\"selectfile\":\"Selecteer bestand\",\"splitdatetime-day-arialabel\":\"dag\",\"splitdatetime-hours-arialabel\":\"uur\",\"splitdatetime-minutes-arialabel\":\"minuut\",\"splitdatetime-month-arialabel\":\"maand\",\"splitdatetime-seconds-arialabel\":\"seconde\",\"splitdatetime-year-arialabel\":\"jaar\",\"starsrequired\":\"* betekent dat een veld verplicht is\",\"submit\":\"Versturen\",\"upload-emptytext\":\"Geen bestand geselecteerd\",\"upload-filename\":[\"Geselecteerde bestand is \",1],\"upload-remove\":\"Verwijder bestand\",\"addressfield\":{\"address_not_found\":\"Het adres kon niet worden gevonden.\",\"invalid_nr_detail\":\"Ongeldig huisnummer.\",\"invalid_zip\":\"Ongeldige postcode.\",\"zip_not_found\":\"Combinatie van postcode en huisnummer komt niet voor.\"},\"commonerrors\":{\"alphanum\":\"De waarde moet alfanumeriek zijn.\",\"badfiletype\":\"Dit bestandstype is niet toegestaan\",\"check\":[\"Kies minimaal \",1,\" en maximaal \",2,\" items.\"],\"date\":\"Dit is geen geldige datum.\",\"default\":\"Deze waarde is onjuist.\",\"digits\":\"De waarde moet numeriek zijn.\",\"email\":\"Dit is geen geldig e-mailadres.\",\"email_baddomain\":[\"Vanwege problemen met het e-mailen naar \",1,\" e-mailadressen, willen we je vragen om een alternatief e-mailadres te gebruiken.\"],\"email_suggestion\":[\"Bedoel je \",1,\"?\"],\"equalto\":\"De waardes moeten identiek zijn.\",\"formunavailable\":\"Dit formulier is momenteel niet beschikbaar\",\"integer\":\"De waarde moet een nummer zijn.\",\"length\":[\"De waarde moet tussen \",1,\" en \",2,\" karakters lang zijn.\"],\"max\":[\"De waarde mag niet groter zijn dan \",1,\".\"],\"maxarray\":[\"U kunt maximaal \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 onderdeel\"],\"subselse\":[1,\" onderdelen\"]},\" toevoegen.\"],\"maxcheck\":[\"Kies maximaal \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"De afbeelding is te groot. Deze mag maximaal \",2,\" pixels hoog zijn.\"],\"maxlength\":[\"De waarde is te lang. Deze mag maximaal \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 karakter\"],\"subselse\":[1,\" karakters\"]},\" lang zijn.\"],\"maxwidth\":[\"De afbeelding is te groot. Deze mag maximaal \",2,\" pixels breed zijn.\"],\"min\":[\"De waarde mag niet lager zijn dan \",1,\".\"],\"minarray\":[\"U moet minimaal \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 onderdeel\"],\"subselse\":[1,\" onderdelen\"]},\" toevoegen.\"],\"mincheck\":[\"Kies minimaal \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"De afbeelding is te klein. Deze moet minimaal \",2,\" pixels hoog zijn.\"],\"minlength\":[\"De tekst is te kort. Deze moet uit minimaal \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 karakter\"],\"subselse\":[1,\" karakters\"]},\" bestaan.\"],\"minwidth\":[\"De afbeelding is te klein. Deze moet minimaal \",2,\" pixels breed zijn.\"],\"notblank\":\"De waarde mag niet leeg zijn.\",\"number\":\"De waarde moet een nummer zijn.\",\"pattern\":\"De waarde is onjuist.\",\"range\":[\"De waarde moet tussen \",1,\" en \",2,\" liggen.\"],\"required\":\"Dit veld is verplicht.\",\"step1mismatch\":\"De waarde moet een geheel getal zijn\",\"stepmismatch\":[\"De waarde moet een meervoud zijn van \",1,\".\"],\"time\":\"Dit is geen geldige tijd.\",\"unacceptableemail\":\"Dit e-mailadres is hier niet toegestaan\",\"upload_cannotcheck\":\"Dit bestand kan niet geüpload worden omdat we het momenteel niet kunnen verifiëren\",\"upload_suspicious\":\"Dit bestand ziet er verdacht uit en kan helaas niet geüpload worden\",\"url\":\"Dit is geen geldige URL.\"}}}});\nregisterTexts(\"publisher\",\"de\",{\"site\":{\"forms\":{\"nextpage\":\"Weiter\",\"previouspage\":\"Zurück\",\"selectfile\":\"Datei auswählen\",\"starsrequired\":\"* zeigt ein Pflichtfeld an\",\"submit\":\"Abschicken\",\"addressfield\":{\"address_not_found\":\"Die Adresse konnte nicht gefunden werden.\",\"invalid_nr_detail\":\"Ungültige Hausnummer.\",\"invalid_zip\":\"Ungültige Postleitzahl.\",\"zip_not_found\":\"Unbekannte Postleitzahl/Hausnummer Kombination.\"},\"commonerrors\":{\"alphanum\":\"Die Eingabe darf nur Zahlen und/oder Buchstaben befassen.\",\"check\":[\"Wähle zwischen \",1,\" und \",2,\" Angaben.\"],\"default\":\"Die Eingabe ist nicht korrekt.\",\"digits\":\"Die Eingabe darf nur Zahlen enthalten.\",\"email\":\"Die Eingabe muss eine gültige E-Mail-Adresse sein.\",\"email_baddomain\":[\"Aufgrund von technischen Schwierigkeiten mit dem Mailprovider \",1,\" benötigen wir eine andere E-Mail Adresse.\"],\"email_suggestion\":[\"Meinst du \",1,\"?\"],\"equalto\":\"Dieses Feld muss übereinstimmen mit dem anderen Feld.\",\"integer\":\"Die Eingabe muss eine Zahl sein.\",\"length\":[\"Die Länge der Eingabe ist ungültig. Es können zwischen \",1,\" und \",2,\" Zeichen eingegeben werden.\"],\"max\":[\"Die Eingabe muss kleiner oder gleich \",1,\" sein.\"],\"maxcheck\":[\"Wähle maximal \",1,\" Angaben aus.\"],\"maxlength\":[\"Die Eingabe ist zu lang. Es dürfen höchstens \",1,\" Zeichen eingegeben werden.\"],\"min\":[\"Die Eingabe muss größer oder gleich \",1,\" sein.\"],\"mincheck\":[\"Die Eingabe ist zu kurz. Es müssen mindestens \",1,\" Zeichen eingegeben werden.\"],\"minlength\":[\"Wähle mindestens \",1,\" Optionen aus.\"],\"notblank\":\"Die Eingabe darf nicht leer sein.\",\"number\":\"Die Eingabe muss eine Zahl sein.\",\"pattern\":\"Die Eingabe ist ungültig.\",\"range\":[\"Die Eingabe muss zwischen \",1,\" und \",2,\" liegen.\"],\"required\":\"Dies ist ein Pflichtfeld.\",\"url\":\"Die Eingabe muss eine gültige URL sein.\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"ar\",{\"site\":{\"forms\":{\"nextpage\":\"التالى\",\"previouspage\":\"السابق\",\"selectfile\":\"حدد الملف\",\"starsrequired\":\"يشير إلى حقل مطلوب *\",\"submit\":\"قدم\",\"addressfield\":{\"address_not_found\":\"لم يتمكن العثور على العنوان.\",\"invalid_nr_detail\":\"رقم المنزل غير صالح مع الإضافة.\",\"invalid_zip\":\"الرمز البريدي غير صالح.\",\"zip_not_found\":\"تركيبة الرمز البريدي ورقم المنزل غير معروفة.\"},\"commonerrors\":{\"alphanum\":\"تأكد من إدخال حروف وأرقام فقط\",\"check\":[\"يجب اختيار بين \",1,\" و \",2,\" خيار.\"],\"default\":\"تأكد من صحة القيمة المدخلة\",\"digits\":\"تأكد من إدخال أرقام\",\"email\":\"تأكد من إدخال بريد الكتروني صالح\",\"email_baddomain\":[\"نظرًا لصعوبة إرسال البريد إلى \",1,\" عناوين البريد الإلكتروني يرجى إستخدام بريد إلكتروني بديل\"],\"email_suggestion\":[\"هل تقصد \",1,\"؟\"],\"equalto\":\"تأكد من تطابق القيمتين المدخلة.\",\"integer\":\"تأكد من إدخال عدد صحيح بدون كسور\",\"length\":[\"القيمة المدخلة غير صالحة. تأكد من إدخال قيمة بين \",1,\" و\",2,\" خانة\"],\"max\":[\"القيمة المدخلة يجب أن تساوي أو تكون أقل من \",1,\".\"],\"maxcheck\":[\"يجب اختيار \",1,\" خيار أو أقل\"],\"maxlength\":[\"القيمة المدخلة طويلة بالغاية. تأكد من إدخال \",1,\" حروف أو أقل\"],\"min\":[\"القيمة المدخلة يجب أن تساوي أو تكون أكبر من \",1,\".\"],\"mincheck\":[\"يجب اختيار \",1,\" خيار على الأقل.\"],\"minlength\":[\"القيمة المدخلة قصيرة بالغاية. تأكد من إدخال \",1,\" حرف أو أكثر\"],\"notblank\":\"تأكد من تعبئة الحقل\",\"number\":\"تأكد من إدخال رقم صالح\",\"pattern\":\"القيمة المدخلة غير صالحة\",\"range\":[\"القيمة المدخلة يجب أن تكون بين \",1,\" و \",2,\".\"],\"required\":\"هذا الحقل مطلوب\",\"url\":\"تأكد من إدخال رابط صالح\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"bg\",{\"site\":{\"forms\":{\"nextpage\":\"Напред.\",\"previouspage\":\"Назад.\",\"selectfile\":\"Избери файл.\",\"starsrequired\":\"* Обозначава задължително поле\",\"submit\":\"Качи.\",\"addressfield\":{\"address_not_found\":\"Адресът не бе намерен.\",\"invalid_nr_detail\":\"Невалиден номер.\",\"invalid_zip\":\"Невалиден пощенски код.\",\"zip_not_found\":\"Непозната комбинация на пощенски код и номер на къщата.\"},\"commonerrors\":{\"alphanum\":\"Стойността трябва да садържа само букви или цифри.\",\"check\":[\"Трябва да изберете между \",1,\" и \",2,\" стойности.\"],\"default\":\"Невалидна стойност.\",\"digits\":\"Невалидни цифри.\",\"email\":\"Невалиден имейл адрес.\",\"email_baddomain\":\"Поради технически причини, Ви молим да използвате различен имейл доставчик.\",\"email_suggestion\":[\"Имахте предвид \",1,\"?\"],\"equalto\":\"Стойността трябва да съвпада.\",\"integer\":\"Невалиден номер.\",\"length\":[\"Дължината на стойността трябва да бъде между \",1,\" и \",2,\" символа.\"],\"max\":[\"Стойността трябва да бъде по-малка или равна на \",1,\".\"],\"maxcheck\":[\"Трябва да изберете най-много \",1,\" стойности.\"],\"maxlength\":[\"Стойността е прекалено дълга. Макс. дължина: \",1,\" символа.\"],\"min\":[\"Стойността трябва да бъде по-голяма или равна на \",1,\".\"],\"mincheck\":[\"Трябва да изберете поне \",1,\" стойности.\"],\"minlength\":[\"Стойността е прекалено кратка. Мин. дължина: \",1,\" символа.\"],\"notblank\":\"Полето е задължително.\",\"number\":\"Невалиден номер.\",\"pattern\":\"Невалидна стойност.\",\"range\":[\"Стойността трябва да бъде между \",1,\" и \",2,\".\"],\"required\":\"Полето е задължително.\",\"url\":\"Невалиден URL адрес.\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"el\",{\"site\":{\"forms\":{\"nextpage\":\"Επόμενο\",\"previouspage\":\"Προηγούμενο\",\"selectfile\":\"Επιλέξτε αρχείο\",\"starsrequired\":\"* υποδηλώνει πεδίο που απαιτείται να συμπληρωθεί\",\"submit\":\"Υποβάλλετε\",\"addressfield\":{\"address_not_found\":\"Δεν ήταν δυνατή η εύρεση της διεύθυνσης.\",\"invalid_nr_detail\":\"Μη έγκυρος αριθμός σπιτιού.\",\"invalid_zip\":\"Μη έγκυρος ταχυδρομικός κώδικας.\",\"zip_not_found\":\"Άγνωστος συνδυασμός ταχυδρομικού κώδικα και αριθμού κατοικίας.\"},\"commonerrors\":{\"alphanum\":\"Η τιμή πρέπει να είναι αλφαριθμητικό.\",\"check\":[\"Πρέπει να επιλέξετε μεταξύ \",1,\" και \",2,\" επίλογων.\"],\"default\":\"Η τιμή φαίνεται να είναι μη έγκυρη.\",\"digits\":\"Η τιμή πρέπει να είναι ψηφία.\",\"email\":\"Η τιμή πρέπει να είναι ένα έγκυρο email.\",\"email_baddomain\":[\"Λόγω δυσκολιών με την αποστολή e-mail σε \",1,\" διευθύνσεις ηλεκτρονικού ταχυδρομείου, σας παρακαλούμε να χρησιμοποιήσετε έναν εναλλακτικό πάροχο ηλεκτρονικού ταχυδρομείου.\"],\"email_suggestion\":[\"Μήπως εννοείτε \",1,\";\"],\"equalto\":\"Η τιμή πρέπει να είναι η ίδια.\",\"integer\":\"Η τιμή πρέπει να είναι ένας έγκυρος ακέραιος.\",\"length\":[\"Το μήκος του κειμένου είναι μη έγκυρο. Πρέπει να είναι μεταξύ \",1,\" και \",2,\" χαρακτήρων.\"],\"max\":[\"Η τιμή πρέπει να είναι μικρότερη ή ίση με \",1,\".\"],\"maxcheck\":[\"Πρέπει να επιλέξετε \",1,\" ή λιγότερες επιλογές.\"],\"maxlength\":[\"Η κείμενο είναι πολύ μεγάλο. Πρέπει να είναι \",1,\" ή και λιγότεροι χαρακτήρες.\"],\"min\":[\"Η τιμή πρέπει να είναι μεγαλύτερη ή ίση με \",1,\".\"],\"mincheck\":[\"Πρέπει να επιλέξετε τουλάχιστον \",1,\" επιλογές.\"],\"minlength\":[\"Το κείμενο είναι πολύ μικρό. Πρέπει να είναι \",1,\" ή και περισσότεροι χαρακτήρες.\"],\"notblank\":\"Η τιμή δεν πρέπει να είναι κενή.\",\"number\":\"Η τιμή πρέπει να είναι ένας έγκυρος αριθμός.\",\"pattern\":\"Η τιμή φαίνεται να είναι μη έγκυρη.\",\"range\":[\"Η τιμή πρέπει να είναι μεταξύ \",1,\" και \",2,\".\"],\"required\":\"Η τιμή αυτή απαιτείται.\",\"url\":\"Η τιμή πρέπει να είναι ένα έγκυρο url.\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"es\",{\"site\":{\"forms\":{\"nextpage\":\"Siguiente\",\"previouspage\":\"Anterior\",\"selectfile\":\"Seleccionar archivo\",\"starsrequired\":\"* Campos obligatorios\",\"submit\":\"Enviar\",\"addressfield\":{\"address_not_found\":\"La dirección no pudo ser encontrada.\",\"invalid_nr_detail\":\"Número de casa con adición inválido.\",\"invalid_zip\":\"Código postal inválido.\",\"zip_not_found\":\"Combinación desconocida de código postal y número de casa.\"},\"commonerrors\":{\"alphanum\":\"Este valor debe ser alfanumérico.\",\"check\":[\"Debe seleccionar entre \",1,\" y \",2,\" opciones.\"],\"default\":\"Este valor parece ser inválido.\",\"digits\":\"Este valor debe ser un dígito válido.\",\"email\":\"Este valor debe ser un correo válido.\",\"email_baddomain\":[\"Debido a las dificultades con el envío de correos a \",1,\" direcciones de correo electrónico, le pedimos amablemente que utilice un proveedor de correo electrónico alternativo.\"],\"email_suggestion\":[\"¿Se refiere a \",1,\"?\"],\"equalto\":\"Este valor debe ser idéntico.\",\"integer\":\"Este valor debe ser un número entero válido.\",\"length\":[\"Esta longitud de valor no es válida. Debe tener entre \",1,\" y \",2,\" caracteres de longitud.\"],\"max\":[\"Este valor debe ser menor o igual a \",1,\".\"],\"maxcheck\":[\"Debe seleccionar \",1,\" opciones o menos.\"],\"maxlength\":[\"Este valor es muy largo. La longitud máxima es de \",1,\" caracteres.\"],\"min\":[\"Este valor debe ser mayor o igual que \",1,\".\"],\"mincheck\":[\"Debe seleccionar al menos \",1,\" opciones.\"],\"minlength\":[\"Este valor es muy corto. La longitud mínima es de \",1,\" caracteres.\"],\"notblank\":\"Este valor no debe estar en blanco.\",\"number\":\"Este valor debe ser un número válido.\",\"pattern\":\"Este valor parece ser inválido.\",\"range\":[\"Este valor debe estar entre \",1,\" y \",2,\".\"],\"required\":\"Este valor es necesario.\",\"url\":\"Este valor debe ser una URL válida.\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"id\",{\"site\":{\"forms\":{\"nextpage\":\"Lanjut\",\"previouspage\":\"Sebelumnya\",\"selectfile\":\"Pilih file\",\"starsrequired\":\"* menandakan bagian yang harus diisi\",\"submit\":\"Kirim\",\"addressfield\":{\"address_not_found\":\"Alamat tidak ditemukan.\",\"invalid_nr_detail\":\"Nomor rumah (dengan penambahan) tidak ditemukan.\",\"invalid_zip\":\"Kode pos tidak ditemukan.\",\"zip_not_found\":\"Kombinasi nomor rumah dan kodepos tidak ditemukan.\"},\"commonerrors\":{\"alphanum\":\"harus berupa alphanumeric\",\"check\":[\"pilih antar \",1,\" dan \",2,\" pilihan\"],\"default\":\"Isi tidak valid\",\"digits\":\"Harus berupa digit\",\"email\":\"Email tidak valid\",\"email_baddomain\":[\"Karena ada kesulitan dengan provider email \",1,\", kami meminta anda menggunakan provider email alternatif\"],\"email_suggestion\":[\"Apakah yang kamu maksud \",1,\"?\"],\"equalto\":\"Isi harus sama\",\"integer\":\"Angka tidak valid\",\"length\":[\"Panjang karakter harus dalam rentang \",1,\" dan \",2],\"max\":[\"Harus lebih kecil atau sama dengan \",1,\".\"],\"maxcheck\":[\"Pilih maksimal \",1,\" pilihan\"],\"maxlength\":[\"Isian terlalu panjang, maksimal \",1,\" karakter atau kurang.\"],\"min\":[\"Isi Harus lebih besar atau sama dengan \",1,\".\"],\"mincheck\":[\"Pilih minimal \",1,\" pilihan\"],\"minlength\":[\"Terlalu pendek, minimal \",1,\" karakter atau lebih.\"],\"notblank\":\"Tidak boleh kosong\",\"number\":\"Angka tidak valid\",\"pattern\":\"Tidak valid\",\"range\":[\"Isi harus dalam rentang \",1,\" dan \",2,\".\"],\"required\":\"Isian harus disi\",\"url\":\"Isi harus berupa URL valid\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"pt\",{\"site\":{\"forms\":{\"nextpage\":\"Próximo.\",\"previouspage\":\"Anterior\",\"selectfile\":\"Selecionar o arquivo\",\"starsrequired\":\"* Preenchimento obrigatório\",\"submit\":\"Enviar\",\"addressfield\":{\"address_not_found\":\"O endereço não pôde ser encontrado.\",\"invalid_nr_detail\":\"Número de casa inválido.\",\"invalid_zip\":\"CEP ou caixa postal inválido.\",\"zip_not_found\":\"Combinação desconhecida de código postal e número de casa.\"},\"commonerrors\":{\"alphanum\":\"Este campo deve ser alfa numérico.\",\"check\":[\"Você deve escolher entre \",1,\" e \",2,\" opções.\"],\"default\":\"Este valor parece ser inválido.\",\"digits\":\"Este campo deve conter apenas dígitos.\",\"email\":\"Este campo deve ser um email válido.\",\"email_baddomain\":[\"Devido a dificuldades com o envio de correio para \",1,\" endereços de e-mail, pedimos que use um provedor de e-mail alternativo\"],\"email_suggestion\":[\"Você quis dizer \",1,\"?\"],\"equalto\":\"Este valor deveria ser igual.\",\"integer\":\"Este campo deve ser um inteiro válido.\",\"length\":[\"O tamanho deste campo é inválido. Ele deveria ter entre \",1,\" e \",2,\" caracteres.\"],\"max\":[\"Este campo deve ser menor ou igual a \",1,\".\"],\"maxcheck\":[\"Você deve escolher \",1,\" opções ou mais\"],\"maxlength\":[\"Este campo é grande demais. Ele deveria ter \",1,\" caracteres ou menos.\"],\"min\":[\"Este campo deve ser maior ou igual a \",1,\".\"],\"mincheck\":[\"Você deve escolher pelo menos \",1,\" opções.\"],\"minlength\":[\"Este campo é pequeno demais. Ele deveria ter \",1,\" caracteres ou mais.\"],\"notblank\":\"Este campo não pode ficar vazio.\",\"number\":\"Este campo deve ser um número válido.\",\"pattern\":\"Este campo parece estar inválido.\",\"range\":[\"Este campo deve estar entre \",1,\" e \",2,\".\"],\"required\":\"Este campo é obrigatório.\",\"url\":\"Este campo deve ser um URL válida.\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"ro\",{\"site\":{\"forms\":{\"nextpage\":\"Următorul/ Următoarea ( if it's not followed by a noun the first version is fine; if it's followed by a noun the translation might change)\",\"previouspage\":\"Anterior\",\"selectfile\":\"Selectează fișier\",\"starsrequired\":\"* câmpuri obligatorii\",\"submit\":\"Trimite\",\"addressfield\":{\"address_not_found\":\"Adresa nu a putut fi găsită.\",\"invalid_nr_detail\":\"Număr de casă invalid.\",\"invalid_zip\":\"Cod poștal invalid.\",\"zip_not_found\":\"Combinație de cod poștal și număr de casă invalidă.\"},\"commonerrors\":{\"alphanum\":\"Trebuie să conțină doar cifre sau litere.\",\"check\":[\"Trebuie să selectezi între variantele \",1,\" și \",2,\" .\"],\"default\":\"Această valoare pare să fie incorectă.\",\"digits\":\"Această valoare ar trebui să fie numerică.\",\"email\":\"Această valoare ar trebui să fie o adresă de email validă.\",\"email_baddomain\":[\"Datorită dificultăților cu trimiterea mesajelor la adresa de email \",1,\"  te rugăm să folosești o altă adresă de email.\"],\"email_suggestion\":[\"Voiai să scrii \",1,\"?\"],\"equalto\":\"Această valoare ar trebui să fie la fel.\",\"integer\":\"Această valoare ar trebui să reprezinte un întreg.\",\"length\":[\"Lungimea acestei valori este invalidă. Ar trebui să conțină un număr de caractere cuprins între \",1,\" și \",2,\".\"],\"max\":[\"Această valoare ar trebui să fie mai mică sau egală cu \",1,\".\"],\"maxcheck\":[\"Trebuie să selectezi minim \",1,\" variante sau mai puține.\"],\"maxlength\":[\"Această valoare este prea lungă. Ar trebui să conțină \",1,\" caractere sau mai puține.\"],\"min\":[\"Această valoare ar trebui să fie mai mare sau egală cu \",1,\".\"],\"mincheck\":[\"Trebuie să selectezi cel puțin \",1,\" variante.\"],\"minlength\":[\"Această valoare este prea scurtă. Ar trebui să aibă \",1,\" caractere sau mai multe.\"],\"notblank\":\"Această valoare nu ar trebui lăsată necompletată.\",\"number\":\"Trebuie să scrii un număr valid\",\"pattern\":\"Acest câmp nu este completat corect.\",\"range\":[\"Valoarea trebuie să fie între \",1,\" și \",2,\".\"],\"required\":\"Această valoare trebuie completată.\",\"url\":\"Această valoare ar trebui să fie un URL valid.\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\nregisterTexts(\"publisher\",\"zh\",{\"site\":{\"forms\":{\"nextpage\":\"下一步\",\"previouspage\":\"上一步\",\"selectfile\":\"选择文件\",\"starsrequired\":\"* 由星号标注的问题是必须回答的\",\"submit\":\"提交\",\"addressfield\":{\"address_not_found\":\"查无本地址\",\"invalid_nr_detail\":\"无效房间号\",\"invalid_zip\":\"无效邮政编码\",\"zip_not_found\":\"未知的房间号与邮政编码组合\"},\"commonerrors\":{\"alphanum\":\"请输入字母或数字\",\"check\":[\"请选择 \",1,\" 到 \",2,\" 个选项\"],\"default\":\"不正确的值\",\"digits\":\"请输入正确的号码\",\"email\":\"请输入一个有效的电子邮箱地址\",\"email_baddomain\":[\"因为技术原因，我们无法发送邮件到\",1,\"邮箱，我们恳请您更换使用另外的邮箱地址\"],\"email_suggestion\":[\"你的意思是\",1,\"？\"],\"equalto\":\"输入值应该相同\",\"integer\":\"请输入正确的整数\",\"length\":[\"字符长度应该在 \",1,\" 到 \",2,\" 之间\"],\"max\":[\"输入值请小于或等于 \",1],\"maxcheck\":[\"请选择不超过 \",1,\" 个选项\"],\"maxlength\":[\"请输入至多 \",1,\" 个字符\"],\"min\":[\"输入值请大于或等于 \",1],\"mincheck\":[\"请至少选择 \",1,\" 个选项\"],\"minlength\":[\"请输入至少 \",1,\" 个字符\"],\"notblank\":\"请输入值\",\"number\":\"请输入正确的数字\",\"pattern\":\"无效值\",\"range\":[\"输入值应该在 \",1,\" 到 \",2,\" 之间\"],\"required\":\"必填项\",\"url\":\"请输入一个有效的链接\",\"badfiletype\":\"This file type is not allowed\",\"cannotprocessfile\":\"This file looks suspicious and can unfortunately not be uploaded\",\"date\":\"This is not a valid date\",\"formunavailable\":\"This form is currently unavailable\",\"maxarray\":[\"You can add at most \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"maxheight\":[\"The image is too big. It should be at most \",2,\" pixels high.\"],\"maxsignupsreached\":\"The maximum number of signups has been reached\",\"maxwidth\":[\"The image is too big. It should be at most \",2,\" pixels wide.\"],\"minarray\":[\"You must add at least \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"1 item\"],\"subselse\":[1,\" items\"]},\".\"],\"minheight\":[\"The image is too small. It should be at least \",2,\" pixels high.\"],\"minwidth\":[\"The image is too small. It should be at least \",2,\" pixels wide.\"],\"step1mismatch\":\"The value must be a whole number\",\"stepmismatch\":[\"The value should be a multiple of \",1,\".\"],\"time\":\"This is not a valid time\",\"unacceptableemail\":\"This email address is not acceptable here\",\"upload_cannotcheck\":\"This file cannot be uploaded as we are currently unable to verify it\",\"upload_suspicious\":\"This file looks suspicious and can unfortunately not be uploaded\"},\"imgedit-explain-upload\":\"Drag and drop files here or click to upload\",\"imgedit-groupelement-replace\":[1,\", Replace image\"],\"imgedit-groupelement-upload\":[1,\", Upload image\"],\"imgedit-remove\":\"Remove image\",\"splitdatetime-day-arialabel\":\"day\",\"splitdatetime-hours-arialabel\":\"hour\",\"splitdatetime-minutes-arialabel\":\"minute\",\"splitdatetime-month-arialabel\":\"month\",\"splitdatetime-seconds-arialabel\":\"second\",\"splitdatetime-year-arialabel\":\"year\",\"upload-emptytext\":\"No file chosen\",\"upload-filename\":[\"Uploaded file is \",1],\"upload-remove\":\"Remove file\"}}});\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/nl.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/de.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/ar.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/bg.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/el.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/es.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/id.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/pt.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/ro.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/zh.xml\n// Adding dependency: /opt/wh/whtree/modules/publisher/language/default.xml\n","/* import ImgEditField from '@mod-publisher/js/forms/fields/imgedit';\n*/\nimport * as dompack from '@webhare/dompack';\nimport { FileEditElement } from './fileeditbase';\nimport { emplace } from '@webhare/std';\nimport { getTid } from '@webhare/gettid';\nimport { getFileAsDataURL } from '@webhare/upload';\nimport { setFieldError } from '@mod-publisher/js/forms/internal/customvalidation';\n\nlet revoker: FinalizationRegistry<string> | undefined;\nconst cachedURLs = new WeakMap<File, string>();\n\nfunction createFileURL(file: File): string {\n  return emplace(cachedURLs, file, {\n    insert: () => {\n      const newurl = URL.createObjectURL(file);\n      //setup a finalizer to revoke object urls\n      revoker ||= new FinalizationRegistry<string>((oldurl) => URL.revokeObjectURL(oldurl));\n      //as soon as file is lost to us\n      revoker.register(file, newurl);\n      return newurl;\n    }\n  });\n}\n\nasync function getImageDimensions(file: File): Promise<{ width: number; height: number }> {\n  const img = await dompack.loadImage(await getFileAsDataURL(file));\n  return { width: img.naturalWidth, height: img.naturalHeight };\n}\n\ninterface ImgEditTexts {\n  explainUpload?: string;\n}\n\nexport class ImgEditElement extends FileEditElement {\n  static observedAttributes = [\"min-width\", \"max-width\", \"min-height\", \"max-height\"];\n\n  private static texts: ImgEditTexts | null = null;\n\n  minWidth: number;\n  maxWidth: number;\n  minHeight: number;\n  maxHeight: number;\n\n  constructor() {\n    super();\n    // this.addEventListener(\"keypress\", evt => this.checkForUploadOrClear(evt)); // handle space+enter to active\n\n    this.maindiv.classList.add(\"images\");\n\n    this.minWidth = parseInt(this.getAttribute(\"min-width\") || \"0\") || 0;\n    this.maxWidth = parseInt(this.getAttribute(\"max-width\") || \"0\") || 0;\n    this.minHeight = parseInt(this.getAttribute(\"min-height\") || \"0\") || 0;\n    this.maxHeight = parseInt(this.getAttribute(\"max-height\") || \"0\") || 0;\n\n    this.refresh();\n  }\n\n  attributeChangedCallback(name: string, _oldValue: string, newValue: string) {\n    const value = parseInt(newValue);\n    if (isNaN(value))\n      return;\n    switch (name) {\n      case \"min-width\": {\n        this.minWidth = value;\n        break;\n      }\n      case \"max-width\": {\n        this.maxWidth = value;\n        break;\n      }\n      case \"min-height\": {\n        this.minHeight = value;\n        break;\n      }\n      case \"max-height\": {\n        this.maxHeight = value;\n        break;\n      }\n    }\n  }\n\n  static setTexts(textupdate: ImgEditTexts) {\n    if (!ImgEditElement.texts)\n      ImgEditElement.texts = {};\n\n    Object.assign(ImgEditElement.texts, textupdate);\n    dompack.qSA<ImgEditElement>(\"wh-imgedit\").forEach(node => node.refresh()); //update any existing nodes\n  }\n\n  async _check() {\n    const error = await super._check();\n    if (!error && this.isSet() && (this.minWidth || this.maxWidth || this.minHeight || this.maxHeight)) {\n      for (const file of this.currentFiles) {\n        if (file.file) {\n          const size = await getImageDimensions(file.file);\n          if (this.minWidth && size.width < this.minWidth)\n            setFieldError(this, getTid(\"publisher:site.forms.commonerrors.minwidth\", size.width, this.minWidth), { reportimmediately: false });\n          else if (this.maxWidth && size.width > this.maxWidth)\n            setFieldError(this, getTid(\"publisher:site.forms.commonerrors.maxwidth\", size.width, this.maxWidth), { reportimmediately: false });\n          else if (this.minHeight && size.height < this.minHeight)\n            setFieldError(this, getTid(\"publisher:site.forms.commonerrors.minheight\", size.height, this.minHeight), { reportimmediately: false });\n          else if (this.maxHeight && size.height > this.maxHeight)\n            setFieldError(this, getTid(\"publisher:site.forms.commonerrors.maxheight\", size.height, this.maxHeight), { reportimmediately: false });\n        }\n      }\n    }\n    return error;\n  }\n\n  refresh() {\n    const nodes = [];\n    for (const [idx, file] of this.currentFiles.entries()) {\n      const imgholder = dompack.create(\"div\", { class: \"image\", part: \"image\" });\n      const img = dompack.create(\"img\", { class: 'image__img', src: file.link ?? createFileURL(file.file) });\n\n      const deletebutton = dompack.create(\"button\", { part: \"button deletebutton\", class: \"deletebutton image__deletebutton\" });\n      this.setupDeleteButton(deletebutton, idx);\n\n      imgholder.append(img, deletebutton);\n      nodes.push(imgholder);\n    }\n\n    if (this.currentFiles.length < this.maxFiles) {\n      //add an extra 'image' which is the placeholder for additional uploads\n      const imgholder = dompack.create(\"div\", { class: \"image image--placeholder\", part: \"image placeholder\" });\n      const contentwrapper = dompack.create(\"div\", { class: \"image__content\" });\n      const uploadicon = dompack.create(\"div\", { class: \"image__uploadicon\", part: \"uploadicon\" });\n      const explain = dompack.create(\"div\", {\n        class: \"image__explain\",\n        textContent: ImgEditElement.texts?.explainUpload || getTid(\"publisher:site.forms.imgedit-explain-upload\")\n      });\n      imgholder.append(contentwrapper);\n      contentwrapper.append(uploadicon, explain);\n      imgholder.tabIndex = 0;\n      this.setupUploadButton(imgholder);\n      nodes.push(imgholder);\n    }\n\n    /* FIXME aria label, currently set at group level, should be per image?\n\n          // Set the aria-label to a combined label of the field together with the action which activating it through click/enter/space will perform\n          this.node.setAttribute(\"aria-label\", getTid(\"publisher:site.forms.imgedit-groupelement-upload\", this.node.dataset.arialabel));\n\n                    // Set the aria-label to a combined label of the field together with the action which activating it through click/enter/space will perform\n          this.node.setAttribute(\"aria-label\", getTid(\"publisher:site.forms.imgedit-groupelement-replace\", this.node.dataset.arialabel));\n*/\n\n    this.maindiv.replaceChildren(...nodes);\n  }\n}\n\n//////// Legacy version. We expect existing users to migrate to the version above\n\nexport default class ImgEditField {\n  constructor(node: HTMLElement) {\n    if (!customElements.get(\"wh-imgedit\"))\n      customElements.define(\"wh-imgedit\", ImgEditElement);\n  }\n}\n","import FormBase from '@mod-publisher/js/forms/rpc';\nimport type { FormConfiguration, FormHandlerFactory } from \"@webhare/forms\";\nimport { dispatchCustomEvent, flagUIBusy, qSA, register } from \"@webhare/dompack\";\nimport { emplace, sleep } from \"@webhare/std\";\nimport { downgradeUploadFields } from \"./domsupport\";\n\nlet formConfiguration: FormConfiguration | undefined;\nlet handlers: Map<string, FormHandlerFactory | PromiseWithResolvers<FormHandlerFactory>> | undefined;\nlet configuredRegistrations: true | undefined;\nconst firstWarningMs = 150, warningIntervalMs = 5000;\n\nasync function scheduleFormSetup(form: HTMLFormElement, factory: FormHandlerFactory) {\n  using lock = flagUIBusy();\n  void (lock);\n\n  //Ensure any custom elements in the form are actually registered or our communication with these elements may fail\n  const customEls = [...new Set(qSA(form, \"[name]\").map(_ => _.tagName.toLowerCase()))].filter(_ => _.includes(\"-\"));\n  if (customEls.length) {\n    const initPromise = Promise.all(customEls.map(_ => customElements.whenDefined(_))).then(() => ({ timeout: false }));\n\n    let nextWarning = Date.now() + firstWarningMs;\n    for (; ;) {\n      const timeoutPromise = sleep(new Date(nextWarning)).then(() => ({ timeout: true }));\n      const result = await Promise.race([initPromise, timeoutPromise]);\n      if (!result.timeout)\n        break;\n\n      const missing = customEls.filter(tag => !customElements.get(tag)).join(\", \");\n      if (missing === 'wh-fileedit') {\n        console.warn(`Developers: we recommend explicitly registering a component for \".wh-form__upload\"`);\n        downgradeUploadFields(form);\n        break;\n      }\n      console.warn(`Still waiting for the following custom elements to be defined in form ${form.id ?? form.dataset.whFormId}:`, missing);\n      nextWarning = Date.now() + warningIntervalMs;\n    }\n  }\n  factory(form);\n}\n\nexport function configureForms(setup: FormConfiguration) {\n  if (!Object.keys(setup).length)\n    return;\n\n  formConfiguration = { ...formConfiguration, ...setup };\n  dispatchCustomEvent(window, \"wh:form-configure\", { bubbles: true, cancelable: false, detail: formConfiguration });\n}\n\nexport function registerHandlers(addHandlers: Record<string, FormHandlerFactory>) {\n  if (!handlers) { //register initial handlers (now that form support is activated)\n    //we want to stop distinguishing between these, not worth the effort/complexity seperating  them\n    const defaultHandler = (form: HTMLFormElement) => new FormBase(form);\n    addHandlers = {\n      \"publisher:form\": defaultHandler,\n      \"publisher:rpc\": defaultHandler,\n      ...addHandlers\n    };\n    handlers = new Map;\n  }\n\n  //Configure the handlers. If there's a resolvable promise waiting for us, resolve it, otherwise directly insert the handler\n  for (const [handlername, handler] of Object.entries(addHandlers))\n    emplace(handlers, handlername, {\n      insert: () => handler,\n      update: current => {\n        if (\"promise\" in current) {\n          current.resolve(handler);\n          return current;\n        } else\n          throw new Error(`Handler '${handlername}' is already registered`);\n      }\n    });\n\n  //Set up a registration for form elements, but ensure they only go through one scheduleFormSetup ever\n  if (!configuredRegistrations) { //register for forms that have yet to appear\n    register<HTMLFormElement>(\"form[data-wh-form-handler]\", form => {\n      //Get the current handler or set up a promise that will receive the handler\n      const handler = emplace(handlers!, form.dataset.whFormHandler!, { insert: () => Promise.withResolvers<FormHandlerFactory>() });\n      if (\"promise\" in handler)\n        void handler.promise.then(factory => scheduleFormSetup(form, factory));\n      else\n        void scheduleFormSetup(form, handler);\n\n    });\n    configuredRegistrations = true;\n  }\n}\n\nexport function registerHandler(handlername: string, handler: FormHandlerFactory) {\n  registerHandlers({ [handlername]: handler });\n}\n\nexport function getFormConfiguration(): FormConfiguration | undefined {\n  return formConfiguration;\n}\n","/* To verify tree shaking viability, try:\n   whcd\n   cd whtree\n   echo 'import \"@webhare/forms\"' | node_modules/.bin/esbuild --loader:.css=empty --tsconfig=tsconfig.json --bundle --minify\n*/\n\n// This gets TypeScript to refer to us by our @webhare/... name in auto imports:\ndeclare module \"@webhare/forms\" {\n}\n\nimport FormBase from '@mod-publisher/js/forms/rpc';\nimport { default as LocalFormBase } from \"@mod-publisher/js/forms/formbase\"; //'FormBase', the RPC-ing one, is the one you want 99% of the time. LocalFormBase is for pure local handling (eg a PWA Config screen)\nimport { verifyAddress, type AddressValidationResult, type AddressChecks } from './address';\nimport { FileUploadFormElement as FileEditElement } from \"@mod-publisher/js/forms/fields/upload\";\nimport { ImgEditElement } from \"@mod-publisher/js/forms/fields/imgedit\";\nimport { JSFormElement } from './jsformelement';\nimport type { FormFileValue, FormAnalyticsEvent } from './types';\nimport { getFormHandler, getFormData } from './domsupport';\nimport { configureForms, registerHandlers } from './registration';\n\n/* TODO / NOTES\n  - we cannot move this file into jssdk namespace, the lang.json compiler doesn't accept paths that cannot be translated to a WH resource\n  - lang.json isn't really TS compatible, a nicer followup TS interface would allow something like\n    import myModuleTexts from \"wh:tid/mymodle\";\n    and offer intellisense (after solving the problems like \"what if a module wants to export multiple sets, how to implement HTMLTid and variables, etc\")\n  - so for now we'll hardcode importing form.lang.json so external users don't have to do this, take the treeshaking hit, and plan to move builtin texts\n    to some sort of /.wh/generated/builtin-language-texts system where we load the common builtin texts per language on demand\n*/\nimport \"@mod-publisher/js/forms/internal/form.lang.json\";\nimport { omit } from '@webhare/std';\n\nexport { FormBase, verifyAddress, ImgEditElement, FileEditElement, JSFormElement, getFormHandler, getFormData };\nexport type { FormSubmitResult } from \"@mod-publisher/js/forms/formbase\";\nexport { buildRPCFormSubmission as buildFormSubmission, submitRPCForm as submitForm } from \"@mod-publisher/js/forms/rpc\";\nexport type { RPCFormSubmission as FormSubmission } from \"./types\";\nexport type { AddressValidationResult, AddressChecks, FormFileValue, FormAnalyticsEvent };\nexport { DateField, TimeField } from \"@mod-publisher/js/forms/fields/datetime\";\nexport { registerHandler } from \"./registration\";\nexport { setupGoogleRecaptcha } from \"@mod-publisher/js/captcha/google-recaptcha\";\nexport { setupFriendlyCaptcha } from \"./friendly-captcha\";\nexport { setupValidator } from \"@mod-publisher/js/forms/internal/customvalidation\";\nexport { LocalFormBase };\n\nexport type FormHandlerFactory = (form: HTMLFormElement) => LocalFormBase;\n\nexport type FormConfiguration = {\n  captcha?: \"onLoad\" | \"onActivate\";\n};\n\nexport type FormSetupOptions = FormConfiguration & {\n  handlers: Record<string, FormHandlerFactory>;\n};\n\n/// Initialize all forms we already have the handler for\nexport function setupForms(options?: Partial<FormSetupOptions>) {\n  registerHandlers(options?.handlers ?? {});\n  if (options)\n    configureForms(omit(options, [\"handlers\"]));\n}\n","/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\nimport * as dompack from \"dompack\";\nimport * as datehelpers from \"../internal/datehelpers\";\nimport Keyboard from 'dompack/extra/keyboard';\nimport DatePicker from '@mod-publisher/js/forms/internal/datepicker';\n\nimport { __setUnderlyingValue, setupMyValueProperty } from \"../internal/datetime-valueprops\";\nimport { getTid } from \"@webhare/gettid\";\nexport { __setUnderlyingValue } from \"../internal/datetime-valueprops\";\n\n/*\nReplaces date/time inputs into separate number type inputs\nField ordering can be set by data attribute data-dateformat\n\nnice to have:\n - placeholder translations\n - Field ordering by localization\n*/\n\ninterface MultiInputSubstitionOptions {\n  baseclass: string;\n}\n\nabstract class MultiInputSubstition {\n  protected _replacednode: HTMLInputElement;\n  protected placeholders: Record<string, string> = {};\n  options: MultiInputSubstitionOptions;\n\n  constructor(inpnode: HTMLInputElement, options: Partial<MultiInputSubstitionOptions>) {\n    this.options = {\n      baseclass: 'datetime',\n      ...options\n    };\n\n    this._baseclass = this.options.baseclass;\n    this._replacednode = inpnode;\n    this._replacednode._split_doupdate = () => this._split_doupdate();\n    this._replacednode.classList.add(this._baseclass + '--replaced');\n    this._replacednode.setAttribute(\"tabindex\", \"-1\"); //disable focus by tabbing replaced field\n    this._replacednode.addEventListener('change', () => this._onOriginalChange());\n\n    if (window.MutationObserver) {\n      const _observer = new MutationObserver(() => this._onObserve());\n      _observer.observe(this._replacednode, { attributes: true, attributeFilter: ['disabled', 'required', 'class'], subtree: false, childList: false });\n    }\n\n    this._nodes = {};\n    setupMyValueProperty(this._replacednode);\n  }\n  _onOriginalChange() { //capture browser initiated changes (they don't go through our value property)\n    if (this._replacednode.value === this._lastsetvalue)\n      return;\n\n    this._lastsetvalue = this._replacednode.value;\n    this._refreshReplacingFields();\n  }\n  _onBlur(field) {\n    if (!isNaN(parseInt(field.value)))\n      field.value = ('000' + parseInt(field.value)).slice(-this._getFieldTextLength(field));\n  }\n  _onReset(evt) {\n    dompack.stop(evt);\n    if (this._replacednode.disabled)\n      return;\n\n    this._replacednode.value = '';\n    dompack.dispatchDomEvent(this._replacednode, 'input');\n    dompack.dispatchDomEvent(this._replacednode, 'change');\n  }\n  _handlePastedValue(inval) {\n    return false;\n  }\n  protected _onInput(field: HTMLInputElement | null) {\n    //now with EARLY focus\n    //FIXME cleanup field first?\n    //FIXME determine whether to use NUMBER of TEL.\n    // if(field && field.input.length === )\n    if (!field)\n      return false;\n\n    if (this._handlePastedValue(field.value)) {\n      this._refreshReplacingFields();\n      return true;\n    }\n\n    const maxlength = this._getFieldTextLength(field);\n    if (field.value.length >= maxlength) {\n      const nextfield = this._getNextField(field);\n      if (nextfield) {\n        dompack.focus(nextfield);\n\n        if (field.value.length > maxlength) { //copy over remaining contents\n          nextfield.value = field.value.substr(maxlength);\n          field.value = field.value.substr(0, maxlength);\n          dompack.dispatchDomEvent(nextfield, 'input');\n          return true; //the next field's _onInput will deal with all the normal validations\n        }\n      }\n    }\n    return false;\n  }\n  protected getLanguageCode() {\n    return this._replacednode.closest('[lang]')?.lang || document.documentElement.lang || null;\n  }\n\n  _finalize() {\n    this._refreshAttributes();\n    this._refreshReplacingFields();\n\n    this._controlsnode = <span class={`${this._baseclass}__controls`}></span>;\n    this._inputgroup.appendChild(this._controlsnode);\n    dompack.after(this._replacednode, this._inputgroup);\n\n    this._inputgroup.addEventListener(\"input\", ev => this._onInput(ev.target), true);\n    this._inputgroup.addEventListener(\"focus\", ev => this._onFocus(ev.target), true);\n    this._inputgroup.addEventListener('blur', evt => this._onBlur(evt.target), true);\n\n    new Keyboard(this._inputgroup, {\n      \"ArrowDown\": (evt) => this._trySpin(evt, -1),\n      \"ArrowUp\": (evt) => this._trySpin(evt, +1),\n      \"ArrowLeft\": (evt) => this._arrowHorizontal(evt, -1),\n      \"ArrowRight\": (evt) => this._arrowHorizontal(evt, +1),\n      \"Backspace\": (evt) => this._handleBackspace(evt)\n    }, {\n      captureunsafekeys: true,\n      onkeypress: (evt, key) => this._onKeyPress(evt, key)\n    });\n\n  }\n  _constructPart(partname, options) {\n    return dompack.create(\"input\", {\n      className: `${this._baseclass}__part ${this._baseclass}__${partname}`,\n      pattern: \"[0-9]*\",\n      inputmode: \"numeric\",\n      autocomplete: \"off\",\n      placeholder: this.placeholders[partname],\n      type: \"tel\", //we need 'tel' for fine selection control, we can't control selectionStart/End of a type=number\n      ...options\n    });\n  }\n  _onObserve() {\n    this._refreshAttributes();\n  }\n\n  _split_doupdate() {\n    this._refreshReplacingFields();\n    if (this._currentdatepicker)\n      this._currentdatepicker.readDateNode();\n  }\n\n  _refreshAttributes() {\n    const isdisabled = this._replacednode.disabled;\n    const isrequired = this._replacednode.required;\n\n    dompack.toggleClass(this._inputgroup, this._baseclass + '--disabled', isdisabled);\n    dompack.toggleClass(this._inputgroup, this._baseclass + '--required', isrequired);\n    this._getSubInputs().forEach(node => { node.disabled = isdisabled; node.required = isrequired; });\n  }\n\n  _getSubInputs() {\n    throw new Error(\"Override!\");\n  }\n\n  _setReplacedValue(setvalue) {\n    if (setvalue !== this._lastsetvalue) {\n      __setUnderlyingValue(this._replacednode, setvalue); //direct update to prevent it from rewriting our fields\n      this._lastsetvalue = setvalue;\n\n      //TODO would be more correct to fire 'input' on any value change, but 'change' only on calendar pick OR blur\n      dompack.dispatchDomEvent(this._replacednode, 'input');\n      dompack.dispatchDomEvent(this._replacednode, 'change');\n    }\n  }\n\n  _onFocus(field) {\n    if (this._getSubInputs().indexOf(field) >= 0) //one of our handled fields\n      field.select(); //select contents fully on focus, makes it easier to start typing new values\n  }\n\n  _trySpin(evt, change) {\n    const field = evt.target;\n    const nodeidx = this._getSubInputs().indexOf(field);\n    if (nodeidx < 0) //not one of our inputs\n      return; //not handling!\n\n    dompack.stop(evt);\n    if (this._spinNode(field, nodeidx, change))\n      this._onInput(null);\n    return true;\n  }\n\n  _arrowHorizontal(evt, dir) {\n    const field = evt.target;\n\n    if ((field.selectionStart !== field.selectionEnd) //theres a selection, let the browser deal with that\n      || (dir < 0 && field.selectionStart > 0) //not at the left edge\n      || (dir > 0 && field.selectionEnd < field.value.length)) // not at the right edge\n      return;\n\n    dompack.stop(evt);\n\n    const subinputs = this._getSubInputs();\n    const gotofield = subinputs[subinputs.indexOf(field) + dir];\n    if (gotofield) {\n      dompack.focus(gotofield);\n      gotofield.selectionEnd = gotofield.selectionStart = dir > 0 ? 0 : gotofield.value.length;\n    }\n  }\n\n  _onKeyPress(evt, key) {\n    if ((key >= '0' && key <= '9') || key.length > 1) //digit or special key\n      return true;\n    dompack.stop(evt);\n  }\n\n  _handleBackspace(evt) {\n    const field = evt.target;\n    const nodeidx = this._getSubInputs().indexOf(field);\n    if (nodeidx <= 0) //not one of our fields, or the first (where we can't go back anywhere)\n      return false; //not handling\n\n    if (field.selectionEnd > 0) //selection does not include the left side of the field\n      return false;\n\n    //remove selection, if any (we're a \"backspace\" after all)\n    dompack.stop(evt);\n    field.value = field.value.substr(0, field.selectionStart) + field.value.substr(field.selectionEnd);\n\n    const prevfield = this._getSubInputs()[nodeidx - 1];\n    dompack.focus(prevfield);\n    if (prevfield.value.length > 0) //do a backspace in the previous field as if we were one\n      prevfield.value = prevfield.value.substr(0, prevfield.value.length - 1);\n\n    prevfield.selectionEnd = prevfield.selectionStart = prevfield.value.length;\n    return true;\n  }\n}\n\nexport interface DateFieldOptions extends MultiInputSubstitionOptions {\n  placeholders: {\n    year: string;\n    month: string;\n    day: string;\n  };\n  datepicker: boolean;\n  resetcontrol: boolean;\n  weeknumbers: boolean;\n}\n\nexport class DateField extends MultiInputSubstition {\n  declare options: DateFieldOptions;\n\n  constructor(inpnode: HTMLInputElement, options?: Partial<DateFieldOptions>);\n  /** @deprecated You should ensure the inputnode is a HTMLInputElement */\n  constructor(inpnode: HTMLElement, options?: Partial<DateFieldOptions>);\n\n  constructor(inpnode: HTMLInputElement, options?: Partial<DateFieldOptions>) {\n    options = {\n      datepicker: true,\n      resetcontrol: true,\n      weeknumbers: false,\n      ...options\n    };\n\n    super(inpnode, options);\n    if (!this._replacednode)\n      return;\n\n    this.placeholders = this.options.placeholders ?? (this.getLanguageCode()?.startsWith('nl') ? { year: \"jjjj\", month: \"mm\", day: \"dd\" } : { year: \"yyyy\", month: \"mm\", day: \"dd\" });\n    this.previous = { value: '' };\n\n    const dateformat = inpnode.dataset.format || \"d-m-y\";\n    const parseddate = dateformat.match(/^([dmy])([^dmy]*)([dmy])([^dmy]*)([dmy])$/);\n    if (!parseddate)\n      throw new Error(`Unrecognized date format '${dateformat}'`);\n\n    this._inputgroup = <span class={`${this._baseclass} ${this._baseclass}__date`}>\n      {this._constructDatePart(parseddate[1])}\n      <span class={`${this._baseclass}__sep`}>{parseddate[2]}</span>\n      {this._constructDatePart(parseddate[3])}\n      <span class={`${this._baseclass}__sep`}>{parseddate[4]}</span>\n      {this._constructDatePart(parseddate[5])}\n    </span>;\n\n    this._nodes.day.min = 1;\n    this._nodes.day.max = 31;\n    this._nodes.month.min = 1;\n    this._nodes.month.max = 12;\n\n    if (this._replacednode.min !== \"\") { //Should be iso date\n      const minyear = this._replacednode.min.split(/[^0-9]+/)[0];\n      if (minyear !== \"\")\n        this._nodes.year.min = minyear;\n    }\n\n    if (this._replacednode.max !== \"\") { //Should be iso date\n      const maxyear = this._replacednode.max.split(/[^0-9]+/)[0];\n      if (maxyear !== \"\")\n        this._nodes.year.max = maxyear;\n    }\n\n    this._finalize();\n\n    if (this.options.datepicker) {\n      this._datepickercontrol = <span class={`${this._baseclass}__togglepicker`}></span>;\n      this._datepickercontrol.addEventListener(\"click\", evt => this._onDatePickerClick(evt));\n      this._controlsnode.appendChild(this._datepickercontrol);\n    }\n    if (this.options.resetcontrol) {\n      this._resetcontrol = <span class={`${this._baseclass}__reset`}></span>;\n      this._resetcontrol.addEventListener(\"click\", evt => this._onReset(evt));\n      this._controlsnode.appendChild(this._resetcontrol);\n    }\n  }\n\n  _onDatePickerClick(evt) {\n    dompack.stop(evt);\n\n    if (this._currentdatepicker || this._replacednode.disabled)\n      return;\n    this._currentdatepicker = new DatePicker(this);\n  }\n  __closedDatepicker() {\n    this._currentdatepicker = null;\n\n    //return focus to last replacement input (so if using tab you go to next field)\n    const inplst = this._inputgroup.querySelectorAll(\"input\");\n    if (inplst.length)\n      inplst[inplst.length - 1].focus();\n  }\n\n  _constructDatePart(which) {\n    const partname = { d: \"day\", m: \"month\", y: \"year\" }[which];\n    if (this._nodes[partname])\n      throw new Error(`Duplicate '${partname}' node`);\n\n    this._nodes[partname] = this._constructPart(partname, { maxlength: partname === \"year\" ? 4 : 2 });\n    return this._nodes[partname];\n  }\n\n  _getSubInputs() {\n    return [this._nodes.day, this._nodes.month, this._nodes.year];\n  }\n\n  _setDateByParts(parts) {\n    this._nodes.day.value = ('0' + parts.day).substr(-2);\n    this._nodes.month.value = ('0' + parts.month).substr(-2);\n    this._nodes.year.value = ('000' + parts.year).substr(-4);\n  }\n\n  _refreshReplacingFields() {\n    this._lastsetvalue = this._replacednode.value;\n\n    if (this._replacednode.value) { //Should be iso date\n      this._currentdate = datehelpers.parseISODate(this._replacednode.value, { nofail: true });\n      if (this._currentdate) {\n        this._setDateByParts(this._currentdate);\n        return;\n      }\n    }\n    this._nodes.day.value = \"\";\n    this._nodes.month.value = \"\";\n    this._nodes.year.value = \"\";\n  }\n\n  _getFieldTextLength(field) {\n    return field === this._nodes.year ? 4 : 2;\n  }\n  _getNextField(field) {\n    return field === this._nodes.day ? this._nodes.month\n      : field === this._nodes.month ? this._nodes.year\n        : null;\n\n  }\n\n  _getCurrentAsISODate() {\n    let year = parseInt(this._nodes.year.value, 0);\n    const month = parseInt(this._nodes.month.value, 0);\n    const day = parseInt(this._nodes.day.value, 0);\n\n    if (year >= 0 && year <= 99 && this._replacednode.dataset.shortyearcutoff !== \"\") {\n      const cutoff = parseInt(this._replacednode.dataset.shortyearcutoff);\n      if (year < cutoff) //to do someday.. current century might not be 2000 anymore\n        year += 2000;\n      else\n        year += 1900;\n    }\n\n    return datehelpers.formatISODate(year, month, day);\n  }\n\n  _spinNode(node, nodeidx, change) {\n    const isodate = this._getCurrentAsISODate();\n    if (!isodate)\n      return; //not sure what to do with a corrupt\n\n    let newdate = new Date(isodate);\n    if (node === this._nodes.day) {\n      newdate = new Date(Number(newdate) + (change * 86400000));\n    } else if (node === this._nodes.month) {\n      newdate.setUTCMonth(newdate.getUTCMonth() + change);\n    } else if (node === this._nodes.year) {\n      newdate.setUTCFullYear(newdate.getUTCFullYear() + change);\n    } else {\n      return;\n    }\n\n    this._setReplacedValue(datehelpers.formatJSUTCISODate(newdate));\n    this._split_doupdate();\n    return true;\n  }\n\n  _handlePastedValue(inval) {\n    //if we're spotting a xx-xx-xx or xx/xx/xx pattern, assume a paste\n    const is_dashed = inval.match(/.+-.+-.+/);\n    const is_slashed = inval.match(/.+\\/.+\\/.+/);\n    if (is_dashed || is_slashed) {\n      const parseddate = datehelpers.parseDate('d-m-y', inval, { nofail: true });\n      if (parseddate) {\n        this._setReplacedValue(datehelpers.formatISODate(parseddate.year, parseddate.month, parseddate.day));\n        this._refreshReplacingFields();\n        return true;\n      }\n    }\n    return false;\n  }\n\n  private getInputValues() {\n    return {\n      year: this._nodes.year.value,\n      month: this._nodes.month.value,\n      day: this._nodes.day.value\n    };\n  }\n\n  _onInput(field: HTMLInputElement | null) {\n    if (super._onInput(field))\n      return true;\n\n    const fields = this.getInputValues();\n    if (!fields.year && !fields.month && !fields.day) { //full field clear\n      this._replacednode.setCustomValidity('');\n      this._setReplacedValue(\"\");\n      return;\n    }\n\n    let year = parseInt(fields.year, 0);\n    const month = parseInt(fields.month, 0);\n    const day = parseInt(fields.day, 0);\n\n    if (year >= 0 && year <= 99 && this._replacednode.dataset.shortyearcutoff !== \"\") {\n      const cutoff = parseInt(this._replacednode.dataset.shortyearcutoff);\n      if (year < cutoff) //TODO current century might not be 2000 anymore\n        year += 2000;\n      else\n        year += 1900;\n    }\n\n    const finaldate = datehelpers.formatISODate(year, month, day);\n    this._replacednode.setCustomValidity(finaldate ? \"\" : getTid(\"publisher:site.forms.commonerrors.date\"));\n    this._setReplacedValue(finaldate);\n    return true;\n  }\n\n  _onKeyPress(evt, key) {\n    if (key === '-' || key === '/') {\n      const nextfield = this._getNextField(evt.target);\n      if (nextfield)\n        dompack.focus(nextfield);\n      return false;\n    }\n    return super._onKeyPress(evt, key);\n  }\n\n  /*\n    onKeyUp( ev, node )\n    {\n      ev.preventDefault();\n      ev.stopPropagation();\n\n      let prevval = this.previous.value;\n      this.previous.value = node.value;\n\n      if( ev.keyCode === 8 && node.value === \"\" && prevval === \"\" )//backspace\n      {\n        //Try to set focus on previous input\n        let prevnode = node.parentNode.previousSibling;\n        if( prevnode )\n        {\n          let previnp = prevnode.querySelector(\"input\");\n          if( previnp )\n            previnp.focus();\n        }\n\n        return;\n      }\n\n      //First some basic validation\n      let value = node.value.replace(/[^0-9]+/g,'');\n\n      if( value === \"\" || value !== node.value || 1*value < 1*node.min || 1*value > 1*node.max )\n        return;\n\n      //Is field value minimal length\n      if( (node === this.yearnode && value.length < 4) || (node !== this.yearnode && value.length < 2) )\n        return;\n\n      if( prevval === node.value )\n          return;//Only go to next input if value changed\n\n      //Try to set focus on next input\n      let nextnode = node.parentNode.nextSibling;\n      if( !nextnode )\n        return;\n\n      let nextinp = nextnode.querySelector(\"input\");\n      if( nextinp )\n        nextinp.focus();\n    }\n  */\n\n  _onReset(evt) {\n    this.closePicker();\n    super._onReset(evt);\n  }\n\n  //-------- PUBLIC API ---------------\n  closePicker() { //close any open date picker\n    if (this._currentdatepicker)\n      this._currentdatepicker._dismissOverlay();\n  }\n}\n\nexport interface TimeFieldOptions extends MultiInputSubstitionOptions {\n  placeholders: {\n    hour: string;\n    minute: string;\n    second: string;\n    msec: string;\n  };\n  resetcontrol: boolean;\n}\n\nexport class TimeField extends MultiInputSubstition {\n\n  constructor(inpnode: HTMLInputElement, options?: Partial<TimeFieldOptions>);\n  /** @deprecated You should ensure the inputnode is a HTMLInputElement */\n  constructor(inpnode: HTMLElement, options?: Partial<TimeFieldOptions>);\n\n  constructor(inpnode: HTMLInputElement, options?: Partial<TimeFieldOptions>) {\n    options = {\n      resetcontrol: true,\n      ...options\n    };\n\n    super(inpnode, options);\n    if (!this._replacednode)\n      return;\n\n    this.placeholders = this.options.placeholders ?? (this.getLanguageCode()?.startsWith('nl') ? { hour: \"hh\", minute: \"mm\", second: \"ss\", msec: \"mmm\" } : { hour: \"uu\", minute: \"mm\", second: \"ss\", msec: \"mmm\" });\n    const step = parseFloat(this._replacednode.getAttribute(\"step\") || '0');\n    this.previous = { value: '' };\n    this._showmsec = step !== Math.floor(step); //fraction\n    this._showsecond = this._showmsec || (step % 60 !== 0); //unable to round to minute... so seconds\n\n    this._inputgroup = <span class={`${this._baseclass} ${this._baseclass}__time`}>\n      {this._constructTimePart(\"hour\")}\n      <span class={`${this._baseclass}__sep`}>:</span>\n      {this._constructTimePart(\"minute\")}\n    </span>;\n\n    this._nodes.hour.max = 23;\n    this._nodes.minute.max = 59;\n\n    if (this._showsecond) {\n      this._inputgroup.appendChild(<span class={`${this._baseclass}__sep`}>:</span>);\n      this._inputgroup.appendChild(this._constructTimePart(\"second\"));\n      this._nodes.second.max = 59;\n    }\n    if (this._showmsec) {\n      this._inputgroup.appendChild(<span class={`${this._baseclass}__sep`}>.</span>);\n      this._inputgroup.appendChild(this._constructTimePart(\"msec\"));\n      this._nodes.msec.max = 999;\n    }\n\n    this._finalize();\n\n    if (this.options.resetcontrol) {\n      this._resetcontrol = <span class={`${this._baseclass}__reset`}></span>;\n      this._resetcontrol.addEventListener(\"click\", evt => this._onReset(evt));\n      this._controlsnode.appendChild(this._resetcontrol);\n    }\n  }\n\n  _spinNode(node, nodeidx, change) {\n    let newval = (parseInt(node.value) || 0) + change;\n    const max = parseInt(node.getAttribute(\"max\"));\n\n    if (newval < 0 || newval > max) {\n      if (nodeidx === 0) //already at top level, no wrapping..\n        return false;\n\n      newval = change < 0 ? max : 0; //wrap it!\n      if (nodeidx > 0) //spin higher node too\n        if (!this._spinNode(this._getSubInputs()[nodeidx - 1], nodeidx - 1, change))\n          return false;\n    }\n\n    //Cannot use dompack.changeValue here as we need to explicitly tell onInput not to move the next field\n    node.value = ('000' + newval).slice(nodeidx === 3 ? -3 : -2);\n    return true;\n  }\n\n  _constructTimePart(partname) {\n    if (this._nodes[partname])\n      throw new Error(`Duplicate '${partname}' node`);\n\n    this._nodes[partname] = this._constructPart(partname, {\n      maxlength: partname === 'msec' ? 3 : 2,\n      min: \"0\"\n    });\n\n    return this._nodes[partname];\n  }\n\n  _refreshReplacingFields() {\n    this._lastsetvalue = this._replacednode.value;\n\n    const time = datehelpers.parseISOTime(this._replacednode.value, { nofail: true });\n    if (time) {\n      this._currenttime = time;\n      this._nodes.hour.value = (\"0\" + this._currenttime.hour).slice(-2);\n      this._nodes.minute.value = (\"0\" + this._currenttime.minute).slice(-2);\n      if (this._nodes.second)\n        this._nodes.second.value = (\"0\" + this._currenttime.second).slice(-2);\n      if (this._nodes.msec)\n        this._nodes.msec.value = (\"00\" + this._currenttime.msec).slice(-3);\n      return;\n    }\n\n    this._nodes.hour.value = \"\";\n    this._nodes.minute.value = \"\";\n    if (this._nodes.second)\n      this._nodes.second.value = \"\";\n    if (this._nodes.msec)\n      this._nodes.msec.value = \"\";\n  }\n\n  _getFieldTextLength(field) {\n    return field === this._nodes.msec ? 3 : 2;\n  }\n  _getSubInputs() {\n    return [\n      this._nodes.hour,\n      this._nodes.minute,\n      ...(this._nodes.second ? [this._nodes.second] : []),\n      ...(this._nodes.msec ? [this._nodes.msec] : [])\n    ];\n  }\n\n  private getInputValues() {\n    return {\n      hour: this._nodes.hour.value,\n      minute: this._nodes.minute.value,\n      second: this._nodes.second?.value ?? \"\",\n      msec: this._nodes.msec?.value ?? \"\"\n    };\n  }\n\n  _onInput(field: HTMLInputElement | null) {\n    if (super._onInput(field))\n      return true;\n\n    const fields = this.getInputValues();\n    if (!fields.hour && !fields.minute && !fields.second && !fields.msec) { //full field clear\n      this._replacednode.setCustomValidity('');\n      this._setReplacedValue(\"\");\n      return;\n    }\n\n    const hour = parseInt(fields.hour, 0);\n    const minute = parseInt(fields.minute, 0);\n    const second = parseInt(fields.second, 0);\n    const msec = parseInt(fields.msec, 0);\n\n    const finaltime = datehelpers.formatISOTime(hour, minute, this._showsecond ? second : null, this._showmsec ? msec : null);\n    this._replacednode.setCustomValidity(finaltime ? \"\" : getTid(\"publisher:site.forms.commonerrors.time\"));\n    this._setReplacedValue(finaltime);\n    return true;\n  }\n\n  _onKeyPress(evt, key) {\n    if (key === ':' || key === '.') {\n      const nextfield = this._getNextField(evt.target);\n      if (nextfield)\n        dompack.focus(nextfield);\n      return false;\n    }\n    return super._onKeyPress(evt, key);\n  }\n\n  _getNextField(field) {\n    return field === this._nodes.hour ? this._nodes.minute\n      : field === this._nodes.minute ? this._nodes.second\n        : null;\n\n  }\n\n\n  /*\n    onKeyUp( ev, node )\n    {\n      ev.preventDefault();\n      ev.stopPropagation();\n\n      let prevval = this.previous.value;\n      this.previous.value = node.value;\n\n      if( ev.keyCode === 8 && node.value === \"\" && prevval === \"\" )//backspace\n      {\n        //Try to set focus on previous input\n        let prevnode = node.parentNode.previousSibling;\n        if( prevnode )\n        {\n          let previnp = prevnode.querySelector(\"input\");\n          if( previnp )\n            previnp.focus();\n        }\n\n        return;\n      }\n\n      //First some basic validation\n      let value = node.value.replace(/[^0-9]+/g,'');\n      if( value === \"\" || value !== node.value || 1*value < 1*node.min || 1*value > 1*node.max )\n        return;\n\n      //Is field value minimal length\n      if( value.length < 2 )\n        return;\n\n      if( prevval === node.value )\n          return;//Only go to next input if value changed\n\n      //Try to set focus on next input\n      let nextnode = node.parentNode.nextSibling;\n      if( !nextnode )\n        return;\n\n      let nextinp = nextnode.querySelector(\"input\");\n      if( nextinp )\n        nextinp.focus();\n    }\n  */\n}\n","/* eslint-disable */\n/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\nimport * as dompack from 'dompack';\nimport KeyboardHandler from \"dompack/extra/keyboard\";\nimport * as datehelpers from \"./datehelpers\";\n// import \"./datestrings.lang.json\";\n//import { getTid } from \"@webhare/gettid\";\n\n// FIXME work with backend\nconst langcodes =\n{\n  \"nl\": \"am;pm;januari;februari;maart;april;mei;juni;juli;augustus;september;oktober;november;december;maandag;dinsdag;woensdag;donderdag;vrijdag;zaterdag;zondag;jan;feb;mrt;apr;mei;jun;jul;aug;sep;okt;nov;dec;ma;di;wo;do;vr;za;zo\",\n  \"de\": \"am;pm;Januar;Februar;März;April;Mai;Juni;Juli;August;September;Oktober;November;Dezember;Montag;Dienstag;Mittwoch;Donnerstag;Freitag;Samstag;Sonntag;Jan.;Febr.;März;Apr.;Mai;Juni;Juli;Aug.;Sept.;Okt.;Nov.;Dez.;Mo;Di;Mi;Do;Fr;Sa;So\",\n  \"en\": \"am;pm;January;February;March;April;May;June;July;August;September;October;November;December;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday;Sunday;Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec;Mon;Tue;Wed;Thu;Fri;Sat;Sun\"\n};\n\n//Load any needed localizations yourself: frameworks.mootools.more.locale.nl-nl.date, frameworks.mootools.more.locale.es-es.date, frameworks.mootools.more.locale.de-de.date, frameworks.mootools.more.locale.fr-fr.date\n\n/*\n\nConverting calendar.js code to calendar2.js\n\n    Changed classes\n      - .-wh-calendar-popup   ->   .wh-datepicker > .value\n      - .-wh-calendar-icon    ->   .wh-datepicker > .arrow\n\n    Changed <input> attributes:\n      - data-formatting -> data-format\n      - data-empty -> placeholder\n\n    Load:\n      LOAD: wh.ui.calendar2\n      LOAD: wh.locale.common.de-de.date\n      LOAD: wh.locale.common.en-us.date\n      LOAD: wh.locale.common.nl-nl.date\n\n    Taal instellen:\n      Locale.use(\"de-DE\");\n      Locale.use(\"en-US\");\n      Locale.use(\"nl-NL\");\n*/\n\n\n/////////////////////\n//\n//\n\n//NOTE preparing to sync this with dompack selectlist.es\n\nclass ComponentOverlay {\n  constructor() {\n    this._boundGlobalEvents = null;\n  }\n  _startOverlayDismissCapture() {\n    //set up capturing handlers to kill our pulldowns asap when something else is clicked\n    if (!this._boundGlobalEvents)\n      this._boundGlobalEvents = evt => this._globalEvents(evt);\n\n    if (!dompack.debugflags.meo) {\n      window.addEventListener(\"keyup\", this._boundGlobalEvents, true);\n      window.addEventListener(\"mousedown\", this._boundGlobalEvents, true);\n      window.addEventListener(\"touchstart\", this._boundGlobalEvents, true);\n    }\n  }\n  _endOverlayDismissCapture() {\n    window.removeEventListener(\"keyup\", this._boundGlobalEvents, true);\n    window.removeEventListener(\"mousedown\", this._boundGlobalEvents, true);\n    window.removeEventListener(\"touchstart\", this._boundGlobalEvents, true);\n  }\n  _globalEvents(evt) {\n    if (evt && evt.type === \"keyup\") {\n      if (evt.keyCode === 27)\n        this._dismissOverlay();\n      return;\n    }\n\n    if (!dompack.contains(this._anchornode, evt.target) && !dompack.contains(this._items, evt.target))\n      this._dismissOverlay();\n  }\n}\n\n\n\n//\n//\n////////////////////\n\n\n\n/*\n * $wh.CalendarTable\n * Builds a plain calendar table based on mootools locale settings\n *\n */\n\nclass CalendarTable extends ComponentOverlay {\n  constructor() {\n    super();\n    this.options = {\n      weeknumbers: false,\n      header_weeknr: '', //weeknr.\n      min: null, //minimal date\n      max: null //maximal date (out of range gets disabled class\n    };\n    this.cdate = null;\n    this.showdate = null;\n  }\n\n  _onDayClick(evt) {\n    const clickedday = evt.target.closest(`.${this.options.baseclass}__day--selectable`);\n    // console.error(clickedday, clickedday.dataset.whDatepickerDate);\n    if (!clickedday)\n      return;\n\n    dompack.stop(evt);\n    this._dismissOverlay();\n\n    dompack.changeValue(this._datenode, clickedday.dataset.whDatepickerDate);\n  }\n\n  getTable(showdate, options) {\n    this.options = { ...this.options, options };\n\n    const caltable = dompack.create('table', {\n      className: this.options.baseclass + '__days',\n      on: { click: evt => this._onDayClick(evt) }\n    });\n    const calbody = dompack.create('tbody');\n    caltable.appendChild(calbody);\n\n    //Build week rows\n    const rownode = <tr class={this.options.baseclass + '__weekdays'}></tr>;\n    if (this.options.weeknumbers)\n      rownode.appendChild(<td></td>); //placeholder for upperleft corner\n\n    for (let w = 0; w < 7; ++w) {\n      rownode.appendChild(<th scope=\"column\" class={this.options.baseclass + '__weekday'}><span>{this._languagetexts[w + 33]}</span></th>);\n    }\n    calbody.appendChild(rownode);\n\n    const mindate = this.options.min ? {\n      day: this.options.min.getUTCDay(),\n      month: this.options.min.getUTCMonth(),\n      year: this.options.min.getUTCFullYear()\n    } : null;\n\n    const maxdate = this.options.max ? {\n      day: this.options.max.getUTCDay(),\n      month: this.options.max.getUTCMonth(),\n      year: this.options.max.getUTCFullYear()\n    } : null;\n\n    //What is the weekday for the first day of the selected month ?\n    const startofmonth = datehelpers.makeJSUTCDate({ ...showdate, day: 1 });\n    const showmonth = startofmonth.getUTCMonth();\n    const showyear = startofmonth.getUTCFullYear();\n\n    //    console.log(startofmonth);\n    const startofmonth_weekday = startofmonth.getUTCDay(); //0-6 where 0=Sunday\n\n    //Work backwards to a monday (start of the week)\n    const backwardsdays = startofmonth_weekday === 0 ? 6 : startofmonth_weekday - 1;\n    let currentgriddate = startofmonth.getTime() - (backwardsdays * 86400 * 1000);\n\n    //Build the grid!\n    for (let week = 0; week < 6; ++week) {\n      const rownode = dompack.create('tr', { className: this.options.baseclass + '__week' });\n\n      for (let day = 0; day < 7; ++day) {\n        const date = new Date(currentgriddate);\n        if (this.options.weeknumbers && day === 0)\n          rownode.appendChild(<th class={this.options.baseclass + '__weeknr'} scope=\"row\"><span>{datehelpers.getWeekNumber(date)}</span></th>);\n\n        const dateY = date.getUTCFullYear();\n        const dateM = date.getUTCMonth();\n        const dateD = date.getUTCDate();\n\n        const celldate = { year: dateY, month: dateM + 1, day: dateD };\n\n        const dayclass = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'][day];\n        const daynode = dompack.create('td', {\n          className: `${this.options.baseclass}__day ${this.options.baseclass}__day--${dayclass}`,\n          childNodes: [dompack.create(\"span\", { textContent: date.getUTCDate() })],\n          dataset: { whDatepickerDate: datehelpers.formatJSUTCISODate(date) }\n        });\n\n        if (dateM !== showmonth || dateY !== showyear)\n          daynode.classList.add(this.options.baseclass + '__day--othermonth');\n\n        if ((mindate && dateY < mindate.year && dateM < mindate.month && dateD < mindate.day)\n          || (maxdate && dateY > maxdate.year && dateM > maxdate.month && dateD > maxdate.day)) {\n          daynode.classList.add(this.options.baseclass + '__day--disabled');\n        } else {\n          daynode.setAttribute(\"tabindex\", \"0\");\n          daynode.classList.add(this.options.baseclass + '__day--selectable');\n        }\n\n        if (datehelpers.compareDate(this.today, celldate) === 0)\n          daynode.classList.add(this.options.baseclass + '__day--today');\n\n        if (this.date && datehelpers.compareDate(this.date, celldate) === 0)\n          daynode.classList.add(this.options.baseclass + '__day--selected');\n\n        rownode.appendChild(daynode);\n        currentgriddate += 86400 * 1000;\n      }\n      calbody.appendChild(rownode);\n    }\n\n    return caltable;\n  }\n}\n\nclass Calendar2 extends CalendarTable {\n  constructor(options) {\n    super();\n    this.options = {\n      weeknumbers: false,\n      date: null,   // initial value\n      min: null,\n      max: null,\n      ...options\n    };\n    this.node = null;\n    this.tablenode = null;\n    this.yearspinner = null;\n    this.monthselectnode = null;\n    this.date = null; //selected date\n    this.keys = null;\n    this.focusednode = null;\n  }\n\n  _onYearMonthChange(evt) {\n    this.options.date = {\n      year: this.yearspinner.value,\n      month: this.monthselectnode.value,\n      day: this._currentdate ? this._currentdate.day : 1\n    };\n\n    this._currentdate.month = parseInt(this.monthselectnode.value);\n    this._currentdate.year = parseInt(this.yearspinner.value);\n\n    this.setMonthTable(this.options.date);\n  }\n\n  readDateNode() {\n    this.mindate = datehelpers.parseISODate(this._datenode.min, { nofail: true });\n    this.maxdate = datehelpers.parseISODate(this._datenode.max, { nofail: true });\n    this.date = datehelpers.parseISODate(this._datenode.value, { nofail: true });\n    const suggestion = datehelpers.parseISODate(this._datenode.dataset.suggestion, { nofail: true });\n    const max = datehelpers.parseISODate(this._datenode.max);\n    this.today = datehelpers.getLocalToday();\n\n    this.yearspinner.min = this.mindate ? this.mindate.year : 1901;\n    this.yearspinner.max = this.maxdate ? this.maxdate.year : 2099;\n\n    let showdate = this.date ?? suggestion ?? this.today;\n    if (this.mindate && datehelpers.makeJSUTCDate(showdate) < datehelpers.makeJSUTCDate(this.mindate))\n      showdate = this.mindate;\n    if (this.maxdate && datehelpers.makeJSUTCDate(showdate) > datehelpers.makeJSUTCDate(this.maxdate))\n      showdate = this.maxdate;\n\n    if (!this._currentdate)\n      this._currentdate = showdate;\n\n    this.setMonthTable(showdate);\n  }\n\n  _addMeToNode(container) {\n    this.node = container;\n\n    this.yearspinner = <input type=\"number\" class={`${this.options.baseclass}__yearselect`} step=\"1\" on={{ change: evt => this._onYearMonthChange(evt) }} />;\n    this.monthselectnode = <select class={`${this.options.baseclass}__monthselect`} on={{ change: evt => this._onYearMonthChange(evt) }} />;\n\n    this.readDateNode();\n\n    //build calendar interface:\n    const headernode = <div class={this.options.baseclass + \"__header\"}>\n      <div class={this.options.baseclass + \"__previous\"} onClick={evt => this.changeMonth(evt, -1)} />\n      {this.monthselectnode}\n      {this.yearspinner}\n      <div class={this.options.baseclass + \"__next\"} onClick={evt => this.changeMonth(evt, +1)} />\n    </div>;\n\n    //month pulldown\n    const selectedmonth = this._currentdate.month;\n    for (let m = 0; m < 12; ++m)\n      this.monthselectnode.appendChild(<option value={m + 1} selected={m === selectedmonth - 1}>{this._languagetexts[m + 2]}</option>);\n\n    this.node.append(headernode, this.tablenode);//, btnbarnode);\n\n    //looks like we're visible ! install a capturing\n    new KeyboardHandler(this.node, {\n      \"Enter\": ev => this.onKeyEnter(ev)\n    }\n      , { captureunsafekeys: true }\n    );\n\n    // Locale.addEvent(\"change\", this.onLanguageChange.bind(this));\n    this._startOverlayDismissCapture();\n    this._onYearMonthChange();\n  }\n\n  setMonthTable(showdate) {\n    this.yearspinner.value = showdate.year;\n    this.monthselectnode.value = showdate.month;\n\n    const newtable = this.getTable(showdate);\n\n    if (this.tablenode)\n      this.tablenode.replaceWith(newtable);\n    this.tablenode = newtable;\n\n    this.setFocus();\n  }\n\n  setFocus() {\n    if (!this.tablenode.clientWidth)\n      return;//Not (yet) visible\n\n    //Set focus on showdate or else first selectable date\n    let fnode;\n    if (this.date)\n      fnode = this.tablenode.querySelector(\"td[data-wh-datepicker-date='\" + datehelpers.formatISODate(this.date.year, this.date.month, this.date.day) + \"']\");\n    if (!fnode) //else pick first selectable day\n      fnode = this.tablenode.querySelector(\".\" + this.options.baseclass + '__day--selectable');\n    if (fnode)\n      fnode.focus();\n  }\n\n  onKeyEnter(ev) {\n    const daynode = ev.target.closest(\".\" + this.options.baseclass + '__day--selectable');\n    if (!daynode)\n      return;\n\n    this._onDayClick(ev);\n  }\n\n  _dismissOverlay() {\n    this.node.remove();\n    this._endOverlayDismissCapture();\n    this._owner.__closedDatepicker();\n  }\n\n  changeMonth(evt, direction) {\n    dompack.stop(evt);\n\n    let newyear = parseInt(this.yearspinner.value);\n    let newmonth = parseInt(this.monthselectnode.value) + direction;\n\n    if (newmonth > 12 || newmonth < 1) //wrap it\n    {\n      newyear += direction;\n      newmonth = direction > 0 ? 1 : 12;\n    }\n    this.setMonthTable({ year: newyear, month: newmonth });\n  }\n}\n\nclass DatePicker extends Calendar2 {\n  /** options.baseclass Base class to use for the elements in the date picker. Defaults to 'datepicker' */\n  constructor(owner) {\n    super({ ...owner.options, baseclass: owner._baseclass + '__picker' });\n    this._owner = owner;\n    this._datenode = owner._replacednode;\n    this.options = {\n      ...this.options,\n      language: null\n    };\n    //TODO limit by supportedlanguages and use gettid(\"~locale.datetimestrings\")\n    if (!this.options.language)\n      this.options.language = document.documentElement.lang ? document.documentElement.lang.split('-')[0].toLowerCase() : '';\n\n    this._languagetexts = (langcodes[this.options.language] || langcodes.en).split(';');\n\n    //we use the node to store our result, so verify it\n    //FIXME maybe this should be optional and you be allowed to create a datepicker without a corresponding node if you just manage getvalue/setvalue yourself, or maybe this glue code belongs outside us\n    //     if(node.nodeName !== 'INPUT' || node.getAttribute('type') !== 'date')\n    //       throw new Error(\"The DatePicker expects to be associated with a input[type=date]\");\n\n    //     this._node = node;\n    //     this._class = (options ? options.baseclass : '') || 'datepicker';\n    //     this._node.classList.add(this._class + \"--attached\");\n    // //\n    // this._node.addEventListener(\"wh:datepicker-request\");\n\n    this._anchornode = this._datenode.nextSibling;\n\n    this._calendarnode = dompack.create('div', { className: this.options.baseclass }); //tabindex:0 ?\n    this._addMeToNode(this._calendarnode);\n\n    this._items = this._calendarnode; //TODO bit ugly but keeps us compatible with selectlist.es\n\n    this._calendarnode.addEventListener(\"change\", ev => {\n      console.log(ev);\n    });\n\n    //Allow users to hook into the datepicker\n    dompack.dispatchCustomEvent(this._datenode, \"wh:datepicker-built\", { bubbles: true, cancelable: false, detail: { input: this._datenode, datepicker: this._calendarnode } });\n\n    //ADDME can we borrow positioning code from the dompack pulldown?\n    //for now, attach to bottom\n    document.body.appendChild(this._calendarnode);\n    const calendarnodesize = this._calendarnode.getBoundingClientRect();\n    const anchornode = this._anchornode.getBoundingClientRect();\n\n    //fits left aligned?\n    if (anchornode.left + calendarnodesize.width > window.innerWidth) { //doesn't fit left aligned, we must right align\n      this._calendarnode.style.right = '0px';\n    } else //left align\n    {\n      this._calendarnode.style.left = Math.ceil(anchornode.left) + 'px';\n    }\n\n    //fits top aligned?\n    if (anchornode.top + calendarnodesize.height > window.innerHeight) { //doesn't fit below, send above\n      let y = (window.innerHeight - anchornode.top);\n      if ((window.innerHeight - y) - calendarnodesize.height < 0) //Prevent calendar hiding behind top of window\n        y = window.innerHeight - calendarnodesize.height;\n      this._calendarnode.style.bottom = y + 'px';\n    } else //left align\n    {\n      this._calendarnode.style.top = Math.ceil(anchornode.bottom) + 'px';\n    }\n\n    this.setFocus();\n  }\n}\n\nexport default DatePicker;\n","import * as dompack from '@webhare/dompack';\nimport { type CaptchaProvider, type CaptchaSettings, captcharegistry } from \"@mod-publisher/js/captcha/api\";\n\n//recaptcha API: https://developers.google.com/recaptcha/docs/display\nlet recaptchaload: PromiseWithResolvers<void> | undefined;\n\ndeclare global {\n  interface Window {\n    $wh__ongooglerecaptchaloaded: () => void;\n    grecaptcha: {\n      render: (node: HTMLElement, options: { sitekey: string; callback: () => void }) => string;\n      getResponse: (id: string) => string;\n    };\n  }\n}\n\nwindow.$wh__ongooglerecaptchaloaded = function () {\n  recaptchaload!.resolve();\n};\n\nfunction makeRecaptchaLoadPromise() {\n  recaptchaload = Promise.withResolvers<void>();\n  document.querySelector<HTMLElement>(\"head,body\")!.append(<script src=\"https://www.google.com/recaptcha/api.js?onload=$wh__ongooglerecaptchaloaded&amp;render=explicit\" />);\n  return recaptchaload.promise;\n}\n\nexport async function runRecaptcha(provider: CaptchaProvider, injectInto: HTMLElement, settings: CaptchaSettings) {\n  const lock = dompack.flagUIBusy({ modal: true });\n  try {\n    await (recaptchaload ? recaptchaload.promise : makeRecaptchaLoadPromise());\n\n    const captchanode = <div class=\"wh-captcha__googlerecaptchaholder\"></div>;\n    injectInto.append(captchanode);\n\n    if (provider.apikey === 'mock') {\n      captchanode.appendChild(<label class=\"wh-captcha__mock\"><input type=\"checkbox\" on={{ click: () => settings.onResponse('mock') }} />I am a human, beep-bop</label>);\n    } else {\n      const recaptchaid = window.grecaptcha.render(captchanode, {\n        sitekey: provider.apikey, callback: () => {\n          const response = window.grecaptcha ? window.grecaptcha.getResponse(recaptchaid) : '';\n          settings.onResponse(response);\n        }\n      });\n    }\n  } finally {\n    lock.release();\n  }\n}\n\n\nexport function setupGoogleRecaptcha() {\n  if (captcharegistry[\"google-recaptcha\"])\n    throw new Error(\"Duplicate google recaptcha initialization\");\n\n  captcharegistry[\"google-recaptcha\"] = { initialize: runRecaptcha };\n}\n","import * as dompack from '@webhare/dompack';\nimport { type CaptchaProvider, type CaptchaSettings, captcharegistry } from \"@mod-publisher/js/captcha/api\";\n\n//friendly captcha API: https://developer.friendlycaptcha.com/docs/v2/sdk/configuration\nlet script = \"https://cdn.jsdelivr.net/npm/@friendlycaptcha/sdk@0.1.31/site.min.js\";\nlet endpoint: string | undefined;\nlet isLoaded = false;\n\nexport async function runFriendlyCaptcha(provider: CaptchaProvider, injectInto: HTMLElement, settings: CaptchaSettings): Promise<void> {\n  const captcha = document.createElement('div');\n  captcha.className = \"frc-captcha\";\n  captcha.dataset.sitekey = provider.apikey;\n  if (endpoint === \"eu\")\n    captcha.dataset.apiEndpoint = \"eu\"; //https://developer.friendlycaptcha.com/docs/v2/sdk/configuration#data-api-endpoint\n  captcha.addEventListener(\"frc:widget.complete\", ((evt: CustomEvent<{ response: string }>) => settings.onResponse(evt.detail.response)) as EventListener);\n\n  injectInto.append(captcha);\n\n  if (isLoaded) {\n    //@ts-expect-error -- undocumented but this seems to properly refresh the unit\n    window.frcaptcha.attach();\n  } else { //Now initialize it\n    using lock = dompack.flagUIBusy();\n    void (lock);\n    //TODO listen for widget.statechange - https://developer.friendlycaptcha.com/docs/v2/sdk/events#frcwidgetstatechange before releasing the lock\n    await dompack.loadScript(script, { module: true });\n    isLoaded = true;\n  }\n}\n\n/** Setup friendlycaptcha integration */\nexport function setupFriendlyCaptcha(options?: { script?: string; endpoint?: \"eu\" }) {\n  if (captcharegistry[\"friendly-captcha\"])\n    throw new Error(\"Duplicate friendly captcha initialization\");\n\n  if (options?.script)\n    script = options.script;\n  if (options?.endpoint)\n    endpoint = options.endpoint;\n\n  captcharegistry[\"friendly-captcha\"] = { initialize: runFriendlyCaptcha };\n}\n","/* PLEASE NOTE - including @mod-publisher/js/forms is considered including the 'legacy form api'. It comes\n   without tree shaking support and autoregisters forms\n\n   @webhare/forms provides a tree-shakable implementation (but requires more setup). To switch please see dev module forms.ts\n  setupForms();\n*/\n\nimport './internal/requiredstyles.css';\nimport * as merge from './internal/merge';\nimport { setFieldError, setupValidator } from './internal/customvalidation';\nimport FormBase, { type FormSubmitEmbeddedResult } from './formbase';\nimport RPCFormBase from './rpc';\nimport { setupForms, registerHandler } from '@webhare/forms';\nimport { isLive } from '@webhare/env';\nimport { setupFormAnalytics } from '@webhare/frontend/src/pxl';\n\nexport { FormBase, RPCFormBase, setFieldError, setupValidator, type FormSubmitEmbeddedResult };\n\nexport const registerMergeFormatter = merge.registerFormatter;\n\ntype LegacyFormHandlerFactory = (form: HTMLFormElement) => FormBase;\n\nfunction legacyRegisterFormHandler(handlername: string, handler: LegacyFormHandlerFactory) {\n  registerHandler(handlername, (form: HTMLFormElement) => {\n    const createdForm = handler(form);\n    if (!isLive && createdForm instanceof FormBase && !(createdForm instanceof RPCFormBase)) {\n      console.warn(`Form handler for '${handlername}' is deriving from @mod-publisher/js/forms#FormBase - it should derive from RPCFormBase (In WH5.7+, the FormBase exported by @webhare/forms will *be* the RPCFormBase)`);\n    }\n    return createdForm as RPCFormBase;\n  });\n}\n\n/** @deprecated setup() is no longer needed */\nexport function setup(options: unknown) {\n}\n\n// We explicitly bind the 'publisher:form' forms to FormBase. The modern version doesn't distinguish between these anymore (and we want to move away from that difference anyawy, RPCBase isn't that much different)\nsetupForms({\n  handlers: { \"publisher:form\": form => new FormBase(form) as RPCFormBase }\n});\n\n// We assume if you're importing @mod-publisher/js/forms you don't know about having to do setupFormAnalytics to keep analytics in WH 5.7+\nsetupFormAnalytics();\n\nexport { legacyRegisterFormHandler as registerHandler };\n","/* eslint-disable @typescript-eslint/no-floating-promises -- FIXME: needs API rework */\n\n/** Generic support for .wh-form .wh-rtd--forminput */\nimport * as dompack from 'dompack';\n\n//we delay load the RTE, but we still need its styling - we don't have a delayed load for SCSS yet.\nimport '@mod-tollium/web/ui/components/richeditor/styling';\n\nimport type * as RichEditor from '@mod-tollium/web/ui/components/richeditor';\nimport type FreeEditor from '@mod-tollium/web/ui/components/richeditor/internal/free-editor';\nimport type StructuredEditor from '@mod-tollium/web/ui/components/richeditor/internal/structurededitor';\nimport type { ExternalStructureDef } from '@mod-tollium/web/ui/components/richeditor/internal/parsedstructure';\nimport type { EditorBaseOptions } from '@mod-tollium/web/ui/components/richeditor/internal/editorbase';\nimport type RPCFormBase from '../../rpc';\nimport type { RTEWidget } from '@mod-tollium/web/ui/components/richeditor/internal/types';\nimport { JSFormElement } from '@webhare/forms/src/jsformelement';\n\n//FIXME  Are we sure we want to have one control handling both Free and Structured RTD? does the form RPC currently even support Free? might remove 'as' below if we dont eg insertVideo...\n\nexport interface RTDFieldOptions {\n  /** options.onInsertVideo: function (node) - should return a promise resolving to an instance if the insertion is successful, or resolve to null if cancelled. receives the html rteedit node on which we're invoked */\n  onInsertVideo?: (node: HTMLElement) => void;\n  hidebuttons?: string[];\n  rtdoptions?: EditorBaseOptions;\n}\n\nexport class RTDEditElement extends JSFormElement<string> {\n  rte: FreeEditor | StructuredEditor | null = null;\n  // options: RTDFieldOptions;\n  // _fieldgroup: HTMLElement | null;\n  node;\n  onInsertVideo?: (node: HTMLElement) => void;\n\n  constructor() {\n    super();\n    this.node = this;\n    //@ts-ignore cleanup registration\n    this.node.whRTDField = this;\n  }\n\n  async connectedCallback() {\n    const specifiedopts = JSON.parse(this.node.dataset.whRtdoptions || '{}') as { structure?: ExternalStructureDef };\n    const structure = specifiedopts.structure || null;\n    const hidebuttons = this.node.getAttribute(\"hidebuttons\")?.split(\" \") || [];\n\n    if (structure && !structure.blockstyles.some(style => style.type === \"table\"))\n      hidebuttons.push(\"table\");\n    hidebuttons.push('object-insert');\n    hidebuttons.push('action-showformatting');\n\n    // //We shouldn't be waiting to receive enable/disable until the RTD is there\n    // this._fieldgroup = this.node.closest(\".wh-form__fieldgroup\");\n    // if (this._fieldgroup) {\n    //   this.node.dataset.whFormStateListener = \"true\";\n    //   this.node.addEventListener('wh:form-enable', evt => this._handleEnable(evt));\n    // }\n\n    const rtdoptions: Partial<EditorBaseOptions> =\n    {\n      enabled: true,\n      readonly: false,\n      structure,\n      allowtags: null,//data.allowtags.length ? data.allowtags : null\n      hidebuttons: hidebuttons,\n      editembeddedobjects: false,\n      ...specifiedopts\n    };\n    //FIXME\n    //, onStatechange: this._onRTEStateChange.bind(this)\n    //FIXME\n    //, language: 'en'//parent.app.lang      // FIXME\n    //, log:true\n    //FIXME , structure: data.structure\n    //, csslinks: [data.cssurl]\n    //, cssinstance: data.cssinstance\n    //, breakupnodes: this.isemaileditor ? [ 'blockquote' ] : []\n    //, hidebuttons: hidebuttons\n    //, htmlclass: data.htmlclass\n    //, bodyclass: data.bodyclass\n    //, csscode: data.csscode\n\n    //Mark the UI as busy while we're loading the RTE\n    using lock = dompack.flagUIBusy();\n    void (lock);\n\n    const richeditor = await import('@mod-tollium/web/ui/components/richeditor') as typeof RichEditor;\n\n    this.rte = richeditor.createRTE(this.node, {\n      ...rtdoptions,\n      enabled: !this.disabled //initial enabled state\n    });\n\n    //@ts-ignore -- we need this for testframework-rte to support our RTD. (TODO reevaluate at some point if we can clean this up)\n    this.node.rte = this.rte;\n    //@ts-expect-error -- remove as soon as wh:richeditor-action is defined\n    this.node.addEventListener('wh:richeditor-action', evt => void this.executeAction(evt));\n    this.node.addEventListener('wh:richeditor-dirty', evt => dompack.dispatchCustomEvent(this.node, 'input', { bubbles: true, cancelable: false }));\n  }\n\n  get value(): string {\n    return this.rte ? this.rte.getValue() : this.node.innerHTML;\n  }\n\n  set value(newvalue: string) {\n    if (typeof newvalue !== 'string')\n      throw new Error(`Invalid value for RTE field: ${typeof newvalue}`);\n\n    if (this.rte)\n      this.rte.setValue(newvalue);\n    else\n      this.node.innerHTML = newvalue;\n  }\n\n  async executeAction(evt: CustomEvent<{ action: string }>) {\n    if (evt.detail.action === 'object-video' && this.onInsertVideo) {\n      evt.stopPropagation();\n      evt.preventDefault();\n      this.onInsertVideo(this.node);\n      return;\n    }\n  }\n\n  async insertVideoByURL(url: string) {\n    const formhandler = this.node.closest('form')?.propWhFormhandler;\n    if (!formhandler)\n      throw new Error(`RTE no longer associated with a form`);\n\n    const result = await (formhandler as RPCFormBase).invokeRPC(this.name + '.insertVideoByUrl', url) as { success: boolean; embeddedobject?: RTEWidget };\n    if (!result.success)\n      return { success: false, message: \"Video URL not understood\" };\n\n    (this.rte!.getEditor() as StructuredEditor).insertEmbeddedObject(result.embeddedobject!);\n    return { success: true };\n  }\n\n  set disabled(disable: boolean) {\n    super.disabled = disable;\n    this._updateEnabledStatus(!disable);\n  }\n  _updateEnabledStatus(nowenabled: boolean) {\n    this.rte?.setEnabled(nowenabled);\n    if (nowenabled)\n      this.node.removeAttribute(\"data-wh-form-disabled\");\n    else\n      this.node.setAttribute(\"data-wh-form-disabled\", \"\");\n  }\n\n  static getForNode(node: HTMLElement): RTDField | null {\n    //@ts-ignore cleanup registration\n    return (node.whRTDField as RTDField) || null;\n  }\n}\n\nexport default class RTDField {\n  constructor(node: HTMLElement, options?: RTDFieldOptions) {\n    const hidebuttons = options?.hidebuttons || [];\n    if (!options?.onInsertVideo)\n      hidebuttons.push('object-video');\n    if (hidebuttons.length)\n      node.setAttribute(\"hidebuttons\", hidebuttons.join(\" \"));\n\n    customElements.whenDefined(\"wh-rtdedit\").then(() => {\n      if (options?.onInsertVideo) //TODO cleaner, use event handlers? RTD already has some action-eventhandler stuff though..\n        (node as RTDEditElement).onInsertVideo = options.onInsertVideo;\n    });\n\n    if (!customElements.get(\"wh-rtdedit\"))\n      customElements.define(\"wh-rtdedit\", RTDEditElement);\n  }\n}\n","/* eslint-disable @typescript-eslint/no-misused-promises, @typescript-eslint/no-floating-promises -- FIXME: needs API rework  */\n\nimport * as dompack from '@webhare/dompack';\nimport * as dialogapi from 'dompack/api/dialog';\nimport type { RTDEditElement } from './index';\nimport RPCFormBase from '../../rpc';\nimport { getFormService } from \"@webhare/forms/src/formservice\";\nimport type { FormSubmitEmbeddedResult } from '../../formbase';\n\nclass EmbedVideoForm extends RPCFormBase {\n  constructor(node: HTMLFormElement, private dialog: dialogapi.DialogBase, private rtd: RTDEditElement) {\n    super(node);\n  }\n\n  async onSubmitSuccess(result: FormSubmitEmbeddedResult<{\n    video: {\n      network: string;\n      videoid: string;\n    };\n  }>) {\n    if (result.video) {\n      this.rtd.insertVideoByURL('x-wh-embedvideo:' + result.video.network + ':' + result.video.videoid);\n      this.dialog.resolve(null);\n    }\n  }\n}\n\nexport async function insertVideo(rtd: HTMLElement) {\n  const formloadlock = dompack.flagUIBusy();\n  const formhandler = rtd.closest('form')?.propWhFormhandler;\n  if (!formhandler) {\n    console.error(\"Cannot find formhandler for node\", rtd);\n    throw new Error(\"Cannot find formhandler for RTD node\");\n  }\n  const formdata = await getFormService().requestBuiltinForm((formhandler as RPCFormBase).getRPCFormIdentifier(), 'rtd', 'embedvideo');\n\n  const dialog = dialogapi.createDialog();\n  dialog.contentnode!.innerHTML = formdata.html;\n\n  new EmbedVideoForm(dompack.qR(dialog.contentnode!, 'form'), dialog, rtd as RTDEditElement);\n  formloadlock.release();\n\n  await dialog.runModal();\n}\n","/* eslint-disable */\n/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\nimport * as dompack from \"../../index\";\nimport SelectList from \"../internal/selectlist\";\nimport KeyboardHandler from \"../../extra/keyboard\";\n\nlet watchingreset = false;\n\nfunction onReset() {\n  const lock = dompack.flagUIBusy();\n  //reset doesn't invoke onchange, so we'll have to recheck every select after a form reset (but we'll need to wait for the default event processing to kick in after a timeout)\n  setTimeout(function () {\n    dompack.qSA('select').forEach(node => {\n      if (node._dompackValueUpdated)\n        node._dompackValueUpdated();\n    });\n    lock.release();\n  });\n}\n\nfunction setupMyValueProperty(select) {\n  Object.defineProperty(select, 'value', { configurable: true, get: mySelectGetValue, set: mySelectSetValue });\n}\nfunction setupMySelectedIndexProperty(select) {\n  Object.defineProperty(select, 'selectedIndex', { configurable: true, get: mySelectGetSelectedIndex, set: mySelectSetSelectedIndex });\n}\nfunction mySelectGetValue() {\n  //we're not using the original getter as that appears to be broken on IE (always returns empty string)\n  const selectedoption = this.options[this.selectedIndex];\n  return selectedoption ? selectedoption.value : '';\n}\nfunction mySelectSetValue(newvalue) {\n  this._flushObservations();\n\n  const origsetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), 'value').set;\n  if (origsetter) //this works on chrome, firefox and IE\n  {\n    origsetter.apply(this, [newvalue]);\n  } else {\n    //safari doesnt let us call the original setter. but we _can_ remove the value property and it will be restored\n    delete this.value;\n    this.value = newvalue;\n    setupMyValueProperty(this); //reset our custom property\n  }\n  this._dompackValueUpdated();\n}\nfunction mySelectGetSelectedIndex() {\n  const origgetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), 'selectedIndex').get;\n  if (origgetter)\n    return origgetter.apply(this, []);\n\n  //safari doesnt let us call the original setter. but we _can_ remove the value property and it will be restored\n  delete this.selectedIndex;\n  const retval = this.selectedIndex;\n  setupMySelectedIndexProperty(this); //reset our custom property\n  return retval;\n}\nfunction mySelectSetSelectedIndex(newvalue) {\n  const origsetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), 'selectedIndex').set;\n  if (origsetter) {\n    origsetter.apply(this, [newvalue]);\n  } else {\n    //safari doesnt let us call the original setter. but we _can_ remove the value property and it will be restored\n    delete this.selectedIndex;\n    this.selectedIndex = newvalue;\n    setupMySelectedIndexProperty(this); //reset our custom property\n  }\n  this._dompackValueUpdated();\n}\n\n\nexport default class Pulldown extends SelectList {\n  /** options.fixitemswidth Make the items container as wide as the pulldown. Defaults to true */\n  constructor(node, options?, old_options?) {\n    if (typeof options === 'string')\n      options = { ...old_options, baseclass: options };\n\n    super(options);\n    if (!window.MutationObserver)\n      return; //we cannot safely take over without a MutationObserver, so let's just abort and hope the native control stays in place due to not setting --replaced\n\n    if (!watchingreset) {\n      document.addEventListener('reset', onReset, true);\n      watchingreset = true;\n    }\n\n    this._replacednode = node;\n    this._replacednode.classList.add(this._class + \"--replaced\");\n    this._replacednode.addEventListener('change', evt => {\n      if (evt.detail && evt.detail.__norefresh)\n        return;\n      this.refresh();\n    });\n    this._replacednode.addEventListener('dompack:takefocus', evt => this._takeFocus(evt));\n\n    //replacements that allow us to track value & selectedIndex\n    setupMyValueProperty(this._replacednode);\n    setupMySelectedIndexProperty(this._replacednode);\n\n    this._replacednode._flushObservations = () => this.refresh({ generateitems: true });\n    this._replacednode._dompackValueUpdated = () => this.refresh();\n\n    /* creating this structure:\n\n       <div class=xxx\n         <div class=xxx__area\n           <div class=xxx__control\n             <div class=xxx__current\n             <div class=xxx__arrow\n           <div class=xxx__items\n             <div class=xxx_item\n             <div class=xxx_item\n             <div class=xxx_item\n    */\n\n    this._arrow = dompack.create('div', {\n      className: this._class + '__arrow'\n    });\n    this._control = dompack.create('div', {\n      className: this._class + '__control',\n      childNodes: [this._arrow]\n    });\n    this._area = dompack.create('div', {\n      className: this._class + '__area',\n      childNodes: [this._control, this._items]\n    });\n    this._anchornode = dompack.create('div', {\n      className: this._class,\n      childNodes: [this._area],\n      on: {\n        mousedown: evt => this._controlMouseDown(evt),\n        blur: evt => this._onBlur(evt)\n      },\n      tabIndex: 0\n    });\n\n    dompack.after(this._replacednode, this._anchornode);\n\n    this.refresh({ insertitems: true, generateitems: true });\n\n    this._observer = new MutationObserver(mutations => this._onObserve(mutations));\n    this._observer.observe(this._replacednode, { attributes: true, attributeFilter: ['disabled', 'class'], subtree: true, childList: true });\n\n    new KeyboardHandler(this._anchornode, {\n      \"ArrowUp\": evt => this._onArrow(evt, -1),\n      \"ArrowDown\": evt => this._onArrow(evt, +1),\n      \"Enter\": evt => this._onEnter(),\n      \" \": evt => this._onSpace(evt),\n      \"Escape\": evt => this._onEscape()\n    }, { \"onkeypress\": (event, key) => this._onKey(event, key) });\n  }\n\n  refresh(options) {\n    this._refreshNewnodeClasses();\n\n    if (options && options.generateitems)\n      this._generateItems();\n    else\n      this._updateItems();\n\n    if (options && options.insertitems)\n      this._area.appendChild(this._items);\n    this._updateDisplayValue();\n\n    if (!this._isOpen())\n      dompack.registerMissed(this._area);\n  }\n\n  /////////////////////////////\n  //\n  // Keyboard support\n  //\n  _onArrow(evt, direction) {\n    dompack.stop(evt);\n    if (!this._isOpen()) {\n      this._openSelectList();\n      return;\n    }\n\n    this._loopToItem(direction, null);\n  }\n  _activateCurrentItem() {\n    const selectitem = this._items.querySelector(`.${this._class}__item--selected`);\n    if (selectitem && this._doSelectItem(selectitem))\n      this.closeSelectList();\n  }\n\n  _onEnter() {\n    if (this._isOpen())\n      this._activateCurrentItem();\n  }\n  _onEscape() {\n    const allitems = Array.from(this._items.querySelectorAll(`.${this._class}__item`));\n    const selectidx = allitems.findIndex(node => node.classList.contains(this._class + '__item--selected'));\n    if (selectidx === this._replacednode.selectedIndex) //no change\n      return;\n    if (selectidx >= 0)\n      allitems[selectidx].classList.remove(this._class + '__item--selected');\n    if (this._replacednode.selectedIndex >= 0)\n      allitems[this._replacednode.selectedIndex].classList.add(this._class + '__item--selected');\n\n    this.closeSelectList();\n  }\n  _onSpace(evt) {\n    dompack.stop(evt);\n    if (this._isOpen())\n      this._activateCurrentItem();\n    else\n      this._openSelectList();\n  }\n  _loopToItem(direction, filter) {\n    const allitems = Array.from(this._items.querySelectorAll(`.${this._class}__item`));\n    let current = allitems.findIndex(node => node.classList.contains(this._class + '__item--selected'));\n    if (current < 0)\n      current = 0;\n\n    let selectidx = current;\n    //maxiterations protects against corner cases such as all items being disabled, or the filter function modifying the list.\n    for (let maxiterations = allitems.length; maxiterations > 0; --maxiterations) {\n      //go to next item, looping to first if needed\n      selectidx += direction;\n      if (selectidx === allitems.length)\n        selectidx = 0;\n      else if (selectidx < 0)\n        selectidx = allitems.length - 1;\n\n      if (selectidx === current) //back where we started?\n        return; //then no match\n\n      if (allitems[selectidx].classList.contains(this._class + '__item--disabled'))\n        continue; //disabled items never match\n\n      if (!filter || filter(allitems[selectidx])) //match!\n      {\n        if (this._isOpen()) {\n          allitems[current].classList.remove(this._class + '__item--selected');\n          allitems[selectidx].classList.add(this._class + '__item--selected');\n          this.scrollOptionIntoView(allitems[selectidx]);\n        } else {\n          this._doSelectItem(allitems[selectidx]); //this will trigger change immediately\n        }\n        return;\n      }\n    }\n  }\n  _onKey(event, key) {\n    if (key.length !== 1 || key === ' ') //special key\n      return true;\n\n    key = key.toUpperCase();\n    this._loopToItem(+1, node => {\n      const tc = node.textContent.trim();\n      return tc[0] && tc[0].toUpperCase() === key;\n    });\n    dompack.stop(event);\n  }\n\n  _onBlur() {\n    if (!dompack.debugflags.meo)\n      this.closeSelectList();\n  }\n\n  _takeFocus(evt) {\n    evt.preventDefault();\n    dompack.focus(this._anchornode);\n  }\n\n  _onObserve(mutations) {\n    const anyoptionchange = mutations.some(mutation => mutation.type === 'childList'\n      || (mutation.type === 'attributes'\n        && (mutation.attributeName === 'class' || mutation.attributeName === 'disabled')));\n\n    //TODO figure out what exactly changed and optimize, we can take the observer's records i think\n    this.refresh({ generateitems: anyoptionchange });\n    //testcode uses this. end users should not rely on it\n    dompack.dispatchCustomEvent(this._replacednode, 'dompack:-internal-refreshed', { bubbles: false, cancelable: false });\n  }\n\n  _refreshNewnodeClasses() {\n    dompack.toggleClass(this._anchornode, this._class + '--disabled', this._replacednode.disabled);\n  }\n\n  _generateOptions(childnodes, inoptgroup, idx) {\n    for (const opt of childnodes) {\n      if (!inoptgroup && opt.nodeName === 'OPTGROUP') {\n        const node = dompack.create('div', {\n          className: this._class + '__optgroup' + ' ' + opt.className,\n          textContent: opt.getAttribute(\"label\") || '\\u00a0',\n          dataset: {\n            ...opt.dataset,\n            dompackPulldownIndex: -1\n          },\n          _pulldownidx: -1\n        });\n        this._items.appendChild(node);\n        idx = this._generateOptions(opt.childNodes, true, idx);\n      } else if (opt.nodeName === 'OPTION') {\n        const node = dompack.create('div', {\n          className: this._class + '__item' + ' '\n            + (inoptgroup ? this._class + '__item--ingroup ' : '')\n            + opt.className,\n          textContent: opt.textContent || '\\u00a0',\n          dataset: {\n            ...opt.dataset,\n            dompackPulldownIndex: idx\n          },\n          _pulldownidx: idx\n        });\n\n        if (opt.disabled)\n          node.classList.add(this._class + '__item--disabled');\n        if (opt.selected)\n          node.classList.add(this._class + '__item--selected');\n\n        this._items.appendChild(node);\n        ++idx;\n      }\n    }\n    return idx;\n  }\n\n  _updateItems() {\n    //Fixup selection classes\n    dompack.qSA(this._items, '.' + this._class + '__item--selected').forEach(node => node.classList.remove(this._class + '__item--selected'));\n    if (this._replacednode.selectedIndex >= 0) {\n      const toselect = this._items.querySelector(`*[data-dompack-pulldown-index=\"${this._replacednode.selectedIndex}\"]`);\n      if (toselect)\n        toselect.classList.add(this._class + '__item--selected');\n    }\n\n    //Reenable any incorrectly disabled nodes\n    dompack.qSA(this._items, '.' + this._class + '__item--disabled').filter(node => !this._replacednode.options[node._pulldownidx].disabled).forEach(node => node.classList.remove(this._class + '__item--disabled'));\n    //Disable any incorrectly enabled nodes\n    Array.from(this._replacednode.options).forEach((option, idx) => {\n      if (option.disabled) {\n        const todisable = this._items.querySelector(`*[data-dompack-pulldown-index=\"${idx}\"]`);\n        if (todisable)\n          todisable.classList.add(this._class + '__item--disabled');\n      }\n    });\n  }\n\n  _generateItemNodes(options) {\n    this._generateOptions(this._replacednode.childNodes, false, 0);\n  }\n\n  _updateDisplayValue() {\n    const toshow = this._replacednode.options[this._replacednode.selectedIndex];\n    const newcurrent = dompack.create('div', {\n      className: this._class + '__current',\n      textContent: (toshow ? toshow.textContent : '') || '\\u00a0'\n    });\n    if (toshow) { //copy value and attributes\n      newcurrent.dataset.optionvalue = toshow.value;\n      Object.keys(toshow.dataset).forEach(key => newcurrent.dataset[\"option\" + key.substr(0, 1).toUpperCase() + key.substr(1)] = toshow.dataset[key]);\n    }\n\n    if (this._current)\n      this._control.replaceChild(newcurrent, this._current);\n    else\n      this._control.insertBefore(newcurrent, this._arrow);\n\n    this._current = newcurrent;\n\n    dompack.registerMissed(this._current);\n  }\n\n  closeSelectList() {\n    super.closeSelectList();\n    this._area.appendChild(this._items);\n  }\n\n  _controlMouseDown(evt) {\n    if (evt.button !== 0)\n      return; //only care about LMB\n    if (dompack.contains(this._items, evt.target))\n      return;//do not interfere with clicks inside the items area\n\n    const isopen = this._isOpen();\n    if (!isopen && this._replacednode.disabled)\n      return; //the original node is locked, thus so are we\n\n    this._anchornode.focus();\n\n    evt.preventDefault();\n    evt.stopPropagation();\n\n    if (isopen)\n      this.closeSelectList();\n    else\n      this._openSelectList();\n  }\n\n  _doSelectItem(selectitem) //return whether we can close the optionlist\n  {\n    if (this._replacednode.options[selectitem._pulldownidx].disabled)\n      return false; //do not close (and not a change)\n\n    if (this._replacednode.selectedIndex === selectitem._pulldownidx)\n      return true; //no change, but would have otherwise been a change, so close\n\n    this._replacednode.selectedIndex = selectitem._pulldownidx;\n\n    //fire the update event, but signal our change event not to refresh\n    dompack.fireModifiedEvents(this._replacednode, { detail: { __norefresh: true } });\n    return true; //change, close!\n  }\n}\n","/* eslint-disable */\n/// @ts-nocheck -- Bulk rename to enable TypeScript validation\n\nimport * as dompack from \"../../index\";\n\nexport default class SelectList {\n  constructor(options) {\n    this._class = (options ? options.baseclass : '') || 'selectlist';\n    this._fixitemswidth = !(options && !options.fixitemswidth);\n  }\n\n  ///Scrolls an option into view, override to control scrolling behaviour\n  scrollOptionIntoView(selection) {\n    selection.scrollIntoView();\n  }\n  _generateItems(options) {\n    if (this._items)\n      dompack.empty(this._items);\n    else\n      this._items = dompack.create('div', {\n        className: this._class + '__items',\n        on: {\n          mouseup: evt => this._clickItem(evt), //on 'up' we consider the selection good\n          mousedown: evt => this._preventFocusLoss(evt),\n          click: evt => this._clickItem(evt) //catches synthetic clicks (.click on element)\n        }\n      });\n    this._generateItemNodes(options);\n  }\n\n  _preventFocusLoss(evt) //prevent focus interference (and also mouse clicks)\n  {\n    evt.preventDefault();\n  }\n\n  _clickItem(evt) {\n    dompack.stop(evt);\n\n    const selectitem = evt.target.closest('.' + this._class + '__item');\n    if (selectitem && this._doSelectItem(selectitem))\n      this.closeSelectList();\n  }\n\n  _isOpen() {\n    return this._anchornode.classList.contains(this._class + '--open');\n  }\n\n  _openSelectList() {\n    if (this._isOpen())\n      return;\n\n    //fix the width, as we're removing our contents so they won't keep us at the proper width\n    const pulldowncoords = this._anchornode.getBoundingClientRect();\n    const itemscoords = this._items.getBoundingClientRect();\n\n    this._openbottom = true;\n    const bottomroom = window.innerHeight - pulldowncoords.bottom;\n    const toproom = pulldowncoords.top;\n\n    if (itemscoords.bottom > window.innerHeight) //the pulldown won't fit below us\n    {\n      //if we have at least half the room on the bottom as we do on top, still prefer bottom\n      this._openbottom = bottomroom >= toproom / 2; //TODO configurable policy?\n    }\n\n    //if we Math.ceil the width, we risk triggering a word wrapping on ourselves\n    this._anchornode.style.minWidth = pulldowncoords.width + 'px';\n    this._items.style.minWidth = pulldowncoords.width + 'px';\n    if (this._fixitemswidth)\n      this._items.style.width = this._items.style.minWidth;\n    this._anchornode.classList.add(this._class + '--open');\n    this._items.classList.add(this._class + '__items--open');\n\n    if (this._openbottom) {\n      this._items.style.maxHeight = bottomroom + 'px';\n    } else {\n      this._items.style.maxHeight = toproom + 'px';\n    }\n\n    //set up capturing handlers to kill our pulldowns asap when something else is clicked\n    if (!this._boundGlobalMouseDown)\n      this._boundGlobalMouseDown = evt => this._globalMouseDown(evt);\n\n    window.addEventListener(\"mousedown\", this._boundGlobalMouseDown, true);\n    window.addEventListener(\"touchstart\", this._boundGlobalMouseDown, true);\n\n    //we need to join the body, because even with fixed ignoring overflows, we can still be clipped by z-index\n    document.body.appendChild(this._items);\n    //make sure te selectionis in sight!\n    const selection = this._items.querySelector(`.${this._class}__item--selected`);\n    if (selection)\n      this.scrollOptionIntoView(selection);\n\n    this._lastpulldowncoords = {};\n    this._positionSelectList();\n\n    this._items.style.left = Math.ceil(pulldowncoords.left) + 'px';\n  }\n  _positionSelectList() {\n    if (!this._isOpen())\n      return;\n    //we need to copy it, getBCR is a weird object\n    const bcr = this._anchornode.getBoundingClientRect();\n    if (this._lastpulldowncoords.top !== bcr.top\n      || this._lastpulldowncoords.left !== bcr.left\n      || this._lastpulldowncoords.bottom !== bcr.bottom) { //we moved\n      this._lastpulldowncoords = bcr;\n      if (this._openbottom) {\n        //this._items.style.top = Math.ceil(pulldowncoords.bottom) + 'px';\n        this._items.style.top = Math.floor(bcr.bottom) + 'px';\n        this._items.style.bottom = '';\n      } else {\n        this._items.style.top = '';\n        this._items.style.bottom = Math.floor(window.innerHeight - bcr.top) + 'px';\n      }\n    }\n    requestAnimationFrame(() => this._positionSelectList());\n  }\n  _globalMouseDown(evt) {\n    if (!dompack.contains(this._anchornode, evt.target) && !dompack.contains(this._items, evt.target))\n      this.closeSelectList();\n  }\n  closeSelectList() {\n    if (!this._isOpen())\n      return;\n\n    window.removeEventListener(\"mousedown\", this._boundGlobalMouseDown, true);\n    window.removeEventListener(\"touchstart\", this._boundGlobalMouseDown, true);\n\n    if (!dompack.debugflags.meo) {\n      //remove fixed width\n      this._anchornode.style.minWidth = \"\";\n      this._items.style.minWidth = \"\";\n      if (this._fixitemswidth)\n        this._items.style.width = \"\";\n\n      this._anchornode.classList.remove(this._class + '--open');\n      this._items.classList.remove(this._class + '__items--open');\n    }\n  }\n}\n","import * as dompack from \"@webhare/dompack\";\nimport { SlimSelect } from \"@mod-utwente_design\";\nimport { setupValidator } from '@mod-publisher/js/forms';\nimport { getTid } from \"@webhare/gettid\";\nimport { requestGeoIP } from \"@mod-utwente_base/webdesigns/ws2016/src/shared/crm\";\nimport \"@mod-utwente_design/web/img/flags/flags.css\";\nimport \"./phone.scss\";\n\nclass PhoneField {\n  input: HTMLInputElement;\n  ss: SlimSelect;\n  phoneinput: HTMLInputElement;\n  countries: Array<{ code: string; title: string; phone: string }> = [];\n  mobileonly: boolean = false;\n\n  constructor(input: HTMLInputElement) {\n    this.input = input;\n    this.input.hidden = true;\n    this.mobileonly = this.input.dataset.mobileonly === \"1\";\n    this.input.addEventListener(\"input\", () => this.syncValueToCustomComponents());\n\n    const fieldgroup = this.input.closest(\".wh-form__fieldgroup\");\n    if (fieldgroup) // Mark fieldgroup so ut select pulldown is not applied\n      fieldgroup.classList.add(\"wh-form__fieldgroup--slimselect\");\n\n    const wrapper = <div class=\"phonefield-fieldswrapper\" />;\n    this.input.before(wrapper);\n\n    this.countries = JSON.parse(this.input.dataset.countries || '[]');\n    const countries = this.countries.map(country => ({\n      text: `${country.title} (+${country.phone})`,\n      value: country.code,\n      html: `<span class=\"utwente-flags utwente-flags-${country.code.toLowerCase()}\"></span><div class=\"title\">${country.title}</div><span class=\"phoneprefix\">+${country.phone}</span>`,\n    }));\n\n    const select = <select class=\"webform-utwente--phonefield__country\" /> as HTMLSelectElement;\n    wrapper.append(select);\n    this.ss = new SlimSelect({\n      select: select,\n      data: countries,\n      events: {\n        afterChange: () => this.syncValueFromCustomComponents()\n      },\n    });\n\n    this.phoneinput = <input type=\"tel\" class=\"webform-utwente--phonefield__input\" placeholder={this.input.placeholder} /> as HTMLInputElement;\n    this.phoneinput.value = this.input.value.replace(/[^0-9+\\s]/g, '').trim();\n    this.phoneinput.addEventListener(\"input\", () => this.syncValueFromCustomComponents());\n    this.phoneinput.addEventListener(\"change\", () => this.onChange());\n\n    if (this.input.value)\n      this.syncValueToCustomComponents();\n\n    wrapper.append(this.phoneinput);\n\n    setupValidator(this.input, inp => this.validatePhoneNumber(inp));\n\n    if (this.phoneinput.value === \"\")\n      void this.prefillCountryCode();\n    else\n      this.syncValueFromCustomComponents();\n  }\n\n  onChange() {\n    const matchcountry = this.countries.find(c => this.input.value.startsWith(`+${c.phone}`));\n    if (matchcountry) {\n      let phoneNumber = this.input.value.substring(matchcountry.phone.length + 1).trim();\n\n      if ([\"BE\", \"DE\", \"NL\"].includes(matchcountry.code)) {\n        while (phoneNumber.startsWith('0')) // Strip leading zeros, we will add one back later if needed\n          phoneNumber = phoneNumber.substring(1);\n        this.phoneinput.value = phoneNumber && !phoneNumber.startsWith('+') ? \"0\" + phoneNumber : phoneNumber;\n      } else {\n        this.phoneinput.value = phoneNumber;\n      }\n    }\n  }\n\n  validatePhoneNumber(inp: HTMLInputElement) {\n    const selectedCode = this.ss ? this.ss.getSelected() : [];\n    const countryCode = selectedCode.length ? selectedCode[0] : \"\";\n    const countryinfo = countryCode ? this.countries.find(c => c.code === countryCode) : \"\";\n    const phonePrefix = countryinfo ? `+${countryinfo.phone}` : '';\n    const digits = inp.value.replace(/[^0-9]/g, ''); // First check basic digit count\n\n    if (this.input.required) {\n      if (digits.length < 6 || digits.length > 15)\n        return getTid('utwente_base:frontend.ws2016.js.notavalidphonenumber');\n    } else {\n      if (phonePrefix !== \"\" && this.input.value === phonePrefix)\n        this.input.value = \"\";// Just country code, treat as empty\n\n      if (this.input.value !== \"\" && (digits.length < 6 || digits.length > 15))\n        return getTid('utwente_base:frontend.ws2016.js.notavalidphonenumber');\n    }\n\n    if (this.mobileonly && this.input.value !== \"\" && !this.isValidMobileNumber(countryCode, this.input.value))\n      return getTid('utwente_base:frontend.ws2016.js.notavalidmobilephonenumber');\n  }\n\n  isValidMobileNumber(countryCode: string, phoneNumber: string) {\n    // Just check for be,de,nl if mobileonly. See issue #2868\n    const chknumber = '+' + phoneNumber.replace(/[^0-9]/g, '');\n    if (countryCode === \"BE\") {\n      const regex = /^\\+324[56789]\\d{7}$/;\n      return regex.test(chknumber);\n    } else if (countryCode === \"DE\") {\n      const regex = /^\\+49[1-9]\\d{1,4}\\d{6,10}$/;\n      return regex.test(chknumber);\n    } else if (countryCode === \"NL\") {\n      const regex = /^\\+316\\d{8}$/;\n      return regex.test(chknumber);\n    }\n\n    return true; // For other countries we don't have specific rules, so just accept any number of digits\n  }\n\n  syncValueFromCustomComponents() {\n    const selectedCode = this.ss ? this.ss.getSelected() : [];\n    const countryCode = selectedCode.length ? selectedCode[0] : \"\";\n    const country = selectedCode.length ? this.countries.find(c => c.code === countryCode) : \"\";\n    let phonePrefix = country ? `+${country.phone}` : '';\n    let phoneNumber = this.phoneinput.value.replace(/[^0-9+\\s]/g, '').trim();\n    if (phoneNumber.startsWith('+')) {\n      const match = this.countries.find(c => phoneNumber.startsWith(`+${c.phone}`));\n      if (match) {\n        this.ss.setSelected(match.code, false);\n        phonePrefix = `+${match.phone}`;\n        phoneNumber = phoneNumber.substring(match.phone.length + 1).trim();\n        this.phoneinput.value = phoneNumber;\n      }\n    }\n\n    this.updatePlaceholderForCountry(countryCode);\n\n    if ([\"BE\", \"DE\", \"NL\"].includes(countryCode)) {\n      while (phoneNumber.startsWith('0')) // Strip leading zeros, we will add one back later if needed\n        phoneNumber = phoneNumber.substring(1);\n    }\n\n    const setValue = phoneNumber ? phonePrefix + phoneNumber : \"\";\n    if (this.input.value !== setValue)\n      dompack.changeValue(this.input, setValue);\n  }\n\n  updatePlaceholderForCountry(countryCode: string) {\n    if (countryCode === \"BE\")\n      this.phoneinput.placeholder = \"(0)470123456\";\n    else if (countryCode === \"DE\")\n      this.phoneinput.placeholder = \"(0)1701234567\";\n    else if (countryCode === \"NL\")\n      this.phoneinput.placeholder = \"(0)612345678\";\n  }\n\n  syncValueToCustomComponents() {\n    const matchcountry = this.countries.find(c => this.input.value.startsWith(`+${c.phone}`));\n    if (matchcountry) { //TODO deal with canada/us. do we have their country prefixes?\n      this.ss.setSelected(matchcountry.code, false);\n    } else {\n      this.syncValueFromCustomComponents();\n    }\n  }\n\n  async prefillCountryCode() {\n    const country = await requestGeoIP();\n    if (country && this.countries.find(c => c.code === country)) {\n      this.ss.selectEl.dataset.prefilledCountry = country;\n      this.ss.setSelected(country);\n    }\n  }\n}\n\ndompack.register<HTMLInputElement>(\".webform-utwente--phonefield input[name$='.phone'][data-countries]\", node => new PhoneField(node));\n","export default class CssClasses {\n  public main: string\n  // Placeholder\n  public placeholder: string\n\n  // Values\n  public values: string\n  public single: string\n  public max: string\n  public value: string\n  public valueText: string\n  public valueDelete: string\n  public valueOut: string\n\n  // Deselect\n  public deselect: string\n  public deselectPath: string // Not a class but whatever\n\n  // Arrow\n  public arrow: string\n  public arrowClose: string // Not a class but whatever\n  public arrowOpen: string // Not a class but whatever\n\n  // Content\n  public content: string\n  public contentOpen: string\n  public dirAbove: string\n  public dirBelow: string\n\n  // Search\n  public search: string\n  public searchHighlighter: string\n  public searching: string\n  public addable: string\n  public addablePath: string // Not a class but whatever\n\n  // List optgroups/options\n  public list: string\n\n  // Optgroup\n  public optgroup: string\n  public optgroupLabel: string\n  public optgroupLabelText: string\n  public optgroupActions: string\n  public optgroupSelectAll: string // optgroup select all\n  public optgroupSelectAllBox: string // Not a class but whatever\n  public optgroupSelectAllCheck: string // Not a class but whatever\n  public optgroupClosable: string\n\n  // Option\n  public option: string\n  public optionDelete: string // Not a class but whatever\n  public highlighted: string\n\n  // Misc\n  public mainOpen: string\n  public close: string\n  public selected: string\n  public error: string\n  public disabled: string\n  public hide: string\n\n  constructor(classes?: Partial<CssClasses>) {\n    if (!classes) {\n      classes = {}\n    }\n\n    let join = (a = '', b = '') => `${a} ${b}`.trim()\n\n    this.main = join('ss-main', classes.main)\n    this.placeholder = join('ss-placeholder', classes.placeholder)\n    this.values = join('ss-values', classes.values)\n    this.single = join('ss-single', classes.single)\n    this.max = join('ss-max', classes.max)\n    this.value = join('ss-value', classes.value)\n    this.valueText = join('ss-value-text', classes.valueText)\n    this.valueDelete = join('ss-value-delete', classes.valueDelete)\n    this.valueOut = join('ss-value-out', classes.valueOut)\n\n    this.deselect = join('ss-deselect', classes.deselect)\n    this.deselectPath = classes.deselectPath || 'M10,10 L90,90 M10,90 L90,10'\n    this.arrow = join('ss-arrow', classes.arrow)\n    this.arrowClose = classes.arrowClose || 'M10,30 L50,70 L90,30'\n    this.arrowOpen = classes.arrowOpen || 'M10,70 L50,30 L90,70'\n    this.content = join('ss-content', classes.content)\n    this.contentOpen = join('ss-open', classes.contentOpen)\n    this.dirAbove = join('ss-dir-above', classes.dirAbove)\n    this.dirBelow = join('ss-dir-below', classes.dirBelow)\n    this.search = join('ss-search', classes.search)\n    this.searchHighlighter = join('ss-search-highlight', classes.searchHighlighter)\n    this.searching = join('ss-searching', classes.searching)\n    this.addable = join('ss-addable', classes.addable)\n    this.addablePath = classes.addablePath || 'M50,10 L50,90 M10,50 L90,50'\n    this.list = join('ss-list', classes.list)\n    this.optgroup = join('ss-optgroup', classes.optgroup)\n    this.optgroupLabel = join('ss-optgroup-label', classes.optgroupLabel)\n    this.optgroupLabelText = join('ss-optgroup-label-text', classes.optgroupLabelText)\n    this.optgroupActions = join('ss-optgroup-actions', classes.optgroupActions)\n    this.optgroupSelectAll = join('ss-selectall', classes.optgroupSelectAll)\n    this.optgroupSelectAllBox = classes.optgroupSelectAllBox || 'M60,10 L10,10 L10,90 L90,90 L90,50'\n    this.optgroupSelectAllCheck = classes.optgroupSelectAllCheck || 'M30,45 L50,70 L90,10'\n    this.optgroupClosable = join('ss-closable', classes.optgroupClosable)\n    this.option = join('ss-option', classes.option)\n    this.optionDelete = classes.optionDelete || 'M10,10 L90,90 M10,90 L90,10'\n    this.highlighted = join('ss-highlighted', classes.highlighted)\n    this.mainOpen = join('ss-open', classes.mainOpen)\n    this.close = join('ss-close', classes.close)\n    this.selected = join('ss-selected', classes.selected)\n    this.error = join('ss-error', classes.error)\n    this.disabled = join('ss-disabled', classes.disabled)\n    this.hide = join('ss-hide', classes.hide)\n  }\n\n  public getFirst(name: keyof Omit<CssClasses, 'getFirst'>): string {\n    return this[name].split(' ')[0]\n  }\n}\n","// Generate an 8 character random string\nexport function generateID(): string {\n  return Math.random().toString(36).substring(2, 10)\n}\n\nexport function hasClassInTree(element: HTMLElement, className: string): HTMLElement | null {\n  function hasClass(e: HTMLElement, c: string) {\n    // If the element has the class return element\n    if (c && e && e.classList && e.classList.contains(c)) {\n      return e\n    }\n\n    // If the element has a dataset id of the class return element\n    if (c && e && e.dataset && e.dataset.id && e.dataset.id === className) {\n      return e\n    }\n\n    return null\n  }\n\n  function parentByClass(e: any, c: string): any {\n    if (!e || e === (document as any)) {\n      return null\n    } else if (hasClass(e, c)) {\n      return e\n    } else {\n      return parentByClass(e.parentNode, c)\n    }\n  }\n\n  return hasClass(element, className) || parentByClass(element, className)\n}\n\n// debounce will call the last requested function after the wait time\nexport function debounce<T extends (...args: any[]) => void>(func: T, wait = 50, immediate = false): () => void {\n  let timeout: any\n  return function (this: any, ...args: any[]): void {\n    const context = self\n    const later = () => {\n      timeout = null\n      if (!immediate) {\n        func.apply(context, args)\n      }\n    }\n    const callNow = immediate && !timeout\n    clearTimeout(timeout)\n    timeout = setTimeout(later, wait)\n    if (callNow) {\n      func.apply(context, args)\n    }\n  }\n}\n\nexport function isEqual(a: any, b: any): boolean {\n  return JSON.stringify(a) === JSON.stringify(b)\n}\n\nexport function kebabCase(str: string): string {\n  const result = str.replace(/[A-Z\\u00C0-\\u00D6\\u00D8-\\u00DE]/g, (match) => '-' + match.toLowerCase())\n  return str[0] === str[0].toUpperCase() ? result.substring(1) : result\n}\n","import { generateID } from './helpers'\n\nexport class Option {\n  id: string\n  value: string\n  text: string\n  html: string\n  defaultSelected: boolean\n  selected: boolean\n  display: boolean\n  disabled: boolean\n  placeholder: boolean\n  class: string\n  style: string\n  data: { [key: string]: string }\n  mandatory: boolean\n\n  constructor(option: Partial<Option>) {\n    this.id = !option.id || option.id === '' ? generateID() : option.id\n    this.value = option.value === undefined ? option.text || '' : option.value || ''\n    this.text = option.text || ''\n    this.html = option.html || ''\n    this.defaultSelected = option.defaultSelected !== undefined ? option.defaultSelected : false\n    this.selected = option.selected !== undefined ? option.selected : false\n    this.display = option.display !== undefined ? option.display : true\n    this.disabled = option.disabled !== undefined ? option.disabled : false\n    this.mandatory = option.mandatory !== undefined ? option.mandatory : false\n    this.placeholder = option.placeholder !== undefined ? option.placeholder : false\n    this.class = option.class || ''\n    this.style = option.style || ''\n    this.data = option.data || {}\n  }\n}\nexport class Optgroup {\n  public id: string\n  public label: string\n  public selectAll: boolean\n  public selectAllText: string\n  public closable: 'off' | 'open' | 'close'\n  public options: Partial<Option>[]\n\n  constructor(optgroup: Partial<Optgroup>) {\n    this.id = !optgroup.id || optgroup.id === '' ? generateID() : optgroup.id\n    this.label = optgroup.label || ''\n    this.selectAll = optgroup.selectAll === undefined ? false : optgroup.selectAll\n    this.selectAllText = optgroup.selectAllText || 'Select All'\n    this.closable = optgroup.closable || 'off'\n\n    // If options exist, loop through options and create new option class\n    // and set the options to the optgroup options field\n    this.options = []\n    if (optgroup.options) {\n      for (const o of optgroup.options) {\n        this.options.push(new Option(o))\n      }\n    }\n  }\n}\n\nexport default class Store {\n  private selectType: 'single' | 'multiple' = 'single'\n\n  // Main data set, never null\n  private data: (Option | Optgroup)[] = []\n  private selectedOrder: string[] = []\n\n  constructor(type: 'single' | 'multiple', data: (Partial<Option> | Partial<Optgroup>)[]) {\n    this.selectType = type\n    this.setData(data)\n  }\n\n  // Validate DataArrayPartial\n  public validateDataArray(data: (Partial<Option> | Partial<Optgroup>)[]): Error | null {\n    if (!Array.isArray(data)) {\n      return new Error('Data must be an array')\n    }\n\n    // Loop through each data object\n    for (let dataObj of data) {\n      if (!dataObj) continue\n\n      // Optgroup\n      if (dataObj instanceof Optgroup || 'label' in dataObj) {\n        if (!('label' in dataObj)) {\n          return new Error('Optgroup must have a label')\n        }\n\n        if ('options' in dataObj && dataObj.options) {\n          for (let option of dataObj.options) {\n            const validationError = this.validateOption(option)\n            if (validationError) {\n              return validationError\n            }\n          }\n        }\n      } else if (dataObj instanceof Option || 'text' in dataObj) {\n        const validationError = this.validateOption(dataObj)\n        if (validationError) {\n          return validationError\n        }\n      } else {\n        return new Error('Data object must be a valid optgroup or option')\n      }\n    }\n\n    return null\n  }\n\n  // Validate Option\n  public validateOption(option: Partial<Option>): Error | null {\n    if (!('text' in option)) {\n      return new Error('Option must have a text')\n    }\n\n    return null\n  }\n\n  public partialToFullData(data: (Partial<Option> | Partial<Optgroup>)[]): (Option | Optgroup)[] {\n    let dataFinal: (Option | Optgroup)[] = []\n    data.forEach((dataObj) => {\n      if (!dataObj) return\n\n      // Optgroup\n      if (dataObj instanceof Optgroup || 'label' in dataObj) {\n        let optOptions: Option[] = []\n        if ('options' in dataObj && dataObj.options) {\n          dataObj.options.forEach((option: Partial<Option>) => {\n            optOptions.push(new Option(option))\n          })\n        }\n\n        if (optOptions.length > 0) {\n          dataFinal.push(new Optgroup(dataObj as Partial<Optgroup>))\n        }\n      }\n\n      // Option\n      if (dataObj instanceof Option || 'text' in dataObj) {\n        dataFinal.push(new Option(dataObj as Partial<Option>))\n      }\n    })\n\n    return dataFinal\n  }\n\n  public setData(data: (Partial<Option> | Partial<Optgroup>)[], preserveSelected: boolean = false) {\n    // Convert new data to full data array\n    const newData = this.partialToFullData(data)\n\n    let selectedOptionsBeforeUpdate: Option[] = []\n\n    if (preserveSelected) {\n      // Get currently selected options before updating data\n      selectedOptionsBeforeUpdate = this.getSelectedOptions()\n\n      // Check which selected options are missing from new data\n      const missingSelected: (Option | Optgroup)[] = []\n      selectedOptionsBeforeUpdate.forEach((selectedOption) => {\n        let found = false\n\n        // Check if this selected option exists in new data\n        for (const newItem of newData) {\n          if (newItem instanceof Option && newItem.id === selectedOption.id) {\n            found = true\n            break\n          }\n          if (newItem instanceof Optgroup) {\n            for (const opt of newItem.options) {\n              if (opt.id === selectedOption.id) {\n                found = true\n                break\n              }\n            }\n          }\n        }\n\n        if (!found) {\n          missingSelected.push(selectedOption)\n        }\n      })\n\n      // Add missing selected options to the beginning of the data\n      this.data = [...missingSelected, ...newData]\n    } else {\n      this.data = newData\n    }\n\n    // Run this.data through setSelected by value\n    // to set the selected property and clean any wrong selected\n    if (this.selectType === 'single') {\n      // When search returns new data and user had nothing selected, don't auto-select first option\n      const allowEmptySelection = preserveSelected && selectedOptionsBeforeUpdate.length === 0\n      this.setSelectedBy('id', this.getSelected(), allowEmptySelection)\n    }\n  }\n\n  // Get data will return all the data\n  public getData(): Option[] | Optgroup[] {\n    return this.filter(null, true) as Option[] | Optgroup[]\n  }\n\n  // Get data options will return the data as a\n  // flat array of just options\n  public getDataOptions(): Option[] {\n    return this.filter(null, false) as Option[]\n  }\n\n  public addOption(option: Partial<Option>, addToStart: boolean = false) {\n    if (addToStart) {\n      let data = [new Option(option)] as (Option | Optgroup)[]\n      this.setData(data.concat(this.getData()))\n    } else {\n      this.setData(this.getData().concat(new Option(option)))\n    }\n  }\n\n  // Pass in an array of id that will loop through\n  // each option and set the selected property to true\n  // but also clean selected by determining selectType\n  // When allowEmptySelection is true (e.g. after search with no prior selection), single select will not auto-select the first option\n  public setSelectedBy(\n    selectedType: 'id' | 'value',\n    selectedValues: string[],\n    allowEmptySelection: boolean = false\n  ) {\n    let firstOption: Partial<Option> | null = null\n    let hasSelected = false\n    const selectedObjects: Partial<Option>[] = []\n\n    for (let dataObj of this.data) {\n      // Optgroup\n      if (dataObj instanceof Optgroup) {\n        for (let option of dataObj.options as Partial<Option>[]) {\n          if (!firstOption) {\n            firstOption = option\n          }\n\n          let optionValue = option[selectedType] || ''\n          option.selected = hasSelected ? false : selectedValues.includes(optionValue)\n\n          // If the option is selected, set hasSelected to true\n          // for single based selects\n          if (option.selected) {\n            selectedObjects.push(option)\n\n            if (this.selectType === 'single') {\n              hasSelected = true\n            }\n          }\n        }\n      }\n\n      // Option\n      if (dataObj instanceof Option) {\n        if (!firstOption) {\n          firstOption = dataObj\n        }\n\n        dataObj.selected = hasSelected ? false : selectedValues.includes(dataObj[selectedType])\n\n        // If the option is selected, set hasSelected to true\n        // for single based selects\n        if (dataObj.selected) {\n          selectedObjects.push(dataObj)\n\n          if (this.selectType === 'single') {\n            hasSelected = true\n          }\n        }\n      }\n    }\n\n    // If no options are selected, select the first option (unless allowEmptySelection, e.g. after search with no selection)\n    if (\n      this.selectType === 'single' &&\n      firstOption &&\n      !hasSelected &&\n      !allowEmptySelection\n    ) {\n      firstOption.selected = true\n      selectedObjects.push(firstOption)\n    }\n\n    // Put together a list of selected ids in the order of the selected values\n    const selectedIds = selectedValues.map((value) => {\n      return selectedObjects.find((option) => option[selectedType] === value)?.id || ''\n    })\n\n    this.selectedOrder = selectedIds\n  }\n\n  public getSelected(): string[] {\n    return this.getSelectedOptions().map((option) => option.id)\n  }\n\n  public getSelectedValues(): string[] {\n    return this.getSelectedOptions().map((option) => option.value)\n  }\n\n  public getSelectedOptions(): Option[] {\n    return this.filter((opt: Option) => {\n      return opt.selected\n    }, false) as Option[]\n  }\n\n  public getOptgroupByID(id: string): Optgroup | null {\n    // Loop through each data object\n    // and if optgroup is found, return it\n    for (let dataObj of this.data) {\n      if (dataObj instanceof Optgroup && dataObj.id === id) {\n        return dataObj\n      }\n    }\n\n    return null\n  }\n\n  public getOptionByID(id: string): Option | null {\n    let options = this.filter((opt: Option) => {\n      return opt.id === id\n    }, false) as Option[]\n\n    return options.length ? options[0] : null\n  }\n\n  public getSelectType(): string {\n    return this.selectType\n  }\n\n  public getFirstOption(): Option | null {\n    let option: Option | null = null\n    for (let dataObj of this.data) {\n      if (dataObj instanceof Optgroup) {\n        option = dataObj.options[0] as Option\n      } else if (dataObj instanceof Option) {\n        option = dataObj\n      }\n\n      if (option) {\n        break\n      }\n    }\n    return option\n  }\n\n  // Take in search string and return filtered list of values\n  public search(search: string, searchFilter: (opt: Option, search: string) => boolean): (Option | Optgroup)[] {\n    search = search.trim()\n\n    // If search is empty, return all data\n    if (search === '') {\n      return this.getData()\n    }\n\n    // Run filter with search function\n    return this.filter((opt: Option): boolean => {\n      return searchFilter(opt, search)\n    }, true)\n  }\n\n  // Filter takes in a function that will be used to filter the data\n  // This will also keep optgroups of sub options meet the filter requirements\n  public filter(filter: { (opt: Option): boolean } | null, includeOptgroup: boolean): (Option | Optgroup)[] {\n    const dataSearch: (Option | Optgroup)[] = []\n    this.data.forEach((dataObj: Option | Optgroup) => {\n      // Optgroup\n      if (dataObj instanceof Optgroup) {\n        let optOptions: Option[] = []\n        let options = dataObj.options as Option[]\n        options.forEach((option: Option) => {\n          if (!filter || filter(option as Option)) {\n            // If you dont want to include optgroups\n            // just push to the dataSearch array\n            if (!includeOptgroup) {\n              dataSearch.push(new Option(option))\n            } else {\n              optOptions.push(new Option(option))\n            }\n          }\n        })\n\n        // If we pushed any options to the optOptions array\n        // push the optgroup to the dataSearch array\n        if (optOptions.length > 0) {\n          // Create new optgroup with the new options\n          let optgroup = new Optgroup(dataObj)\n          optgroup.options = optOptions\n\n          // Push optgroup to dataSearch\n          dataSearch.push(optgroup)\n        }\n      }\n\n      // Option\n      if (dataObj instanceof Option) {\n        if (!filter || filter(dataObj)) {\n          dataSearch.push(new Option(dataObj))\n        }\n      }\n    })\n\n    return dataSearch\n  }\n\n  // Take in an array of options and reoder them based upon the selected order\n  public selectedOrderOptions(options: Option[]): Option[] {\n    const newOrder: Option[] = []\n    this.selectedOrder.forEach((id) => {\n      const option = options.find((opt) => opt.id === id)\n      if (option) {\n        newOrder.push(option)\n      }\n    })\n\n    // add any remaining options that were not in the selected order\n    options.forEach((option) => {\n      let isIn = false\n      newOrder.forEach((selectedOption) => {\n        if (option.id === selectedOption.id) {\n          isIn = true\n\n          return\n        }\n      })\n\n      if (!isIn) {\n        newOrder.push(option)\n      }\n    })\n\n    return newOrder\n  }\n}\n","import { debounce } from './helpers'\nimport Settings from './settings'\nimport Store, { Optgroup, Option } from './store'\nimport CssClasses from './classes'\n\nexport interface Callbacks {\n  open: () => void\n  close: () => void\n  addable?: (\n    value: string\n  ) => Promise<Partial<Option> | string> | Partial<Option> | string | false | undefined | null | Error\n  setSelected: (value: string | string[], runAfterChange: boolean) => void\n  addOption: (option: Option) => void\n  search: (search: string) => void\n  beforeChange?: (newVal: Option[], oldVal: Option[]) => boolean | void\n  afterChange?: (newVal: Option[]) => void\n}\n\nexport interface Main {\n  main: HTMLDivElement\n  values: HTMLDivElement\n  deselect: {\n    main: HTMLDivElement\n    svg: SVGSVGElement\n    path: SVGPathElement\n  }\n  arrow: {\n    main: SVGSVGElement\n    path: SVGPathElement\n  }\n}\n\nexport interface Content {\n  main: HTMLDivElement\n  search: Search\n  list: HTMLDivElement\n}\n\nexport interface Search {\n  main: HTMLDivElement\n  input: HTMLInputElement\n  addable?: {\n    main: HTMLDivElement\n    svg: SVGSVGElement\n    path: SVGPathElement\n  }\n}\n\nexport default class Render {\n  public settings: Settings\n  public store: Store\n  public callbacks: Callbacks\n\n  // Used to compute the range selection\n  private lastSelectedOption: Option | null\n  private lastRenderedOptions: Option[]\n\n  // Timeout tracking for cleanup\n  private closeAnimationTimeout: ReturnType<typeof setTimeout> | null = null\n\n  // Elements\n  public main: Main\n  public content: Content\n\n  // Classes\n  public classes: CssClasses\n\n  constructor(settings: Required<Settings>, classes: Required<CssClasses>, store: Store, callbacks: Callbacks) {\n    this.store = store\n    this.settings = settings\n    this.classes = classes\n    this.callbacks = callbacks\n    this.lastSelectedOption = null\n    this.lastRenderedOptions = []\n\n    this.main = this.mainDiv()\n    this.content = this.contentDiv()\n\n    // Add classes and styles to main/content\n    this.updateClassStyles()\n    this.updateAriaAttributes()\n\n    // Position content off-screen initially to prevent scrollbars\n    // This must be after updateClassStyles() since it removes all style attributes\n    // The main element isn't in the DOM yet, so getBoundingClientRect() would return zeros\n    // Once opened, moveContent() will position it correctly\n    if (this.settings.contentPosition !== 'relative') {\n      this.content.main.style.top = '-9999px'\n      this.content.main.style.left = '-9999px'\n      this.content.main.style.margin = '0'\n      this.content.main.style.width = 'auto'\n    }\n\n    // Add content to the content location settings\n    if (this.settings.contentLocation) {\n      this.settings.contentLocation.appendChild(this.content.main)\n    }\n  }\n\n  // Helper method to add classes that may contain spaces\n  // Splits by spaces and adds each class individually to avoid DOMException\n  private addClasses(element: HTMLElement | SVGElement, classValue: string): void {\n    if (!classValue || classValue.trim() === '') {\n      return\n    }\n    const classes = classValue.split(' ').filter((c) => c.trim() !== '')\n    for (const cls of classes) {\n      element.classList.add(cls.trim())\n    }\n  }\n\n  // Helper method to remove classes that may contain spaces\n  private removeClasses(element: HTMLElement | SVGElement, classValue: string): void {\n    if (!classValue || classValue.trim() === '') {\n      return\n    }\n    const classes = classValue.split(' ').filter((c) => c.trim() !== '')\n    for (const cls of classes) {\n      element.classList.remove(cls.trim())\n    }\n  }\n\n  // Remove disabled classes\n  public enable(): void {\n    // Remove disabled class\n    this.removeClasses(this.main.main, this.classes.disabled)\n    this.main.main.setAttribute('aria-disabled', 'false')\n\n    // Set search input to \"enabled\"\n    this.content.search.input.disabled = false\n  }\n\n  // Set disabled classes\n  public disable(): void {\n    // Add disabled class\n    this.addClasses(this.main.main, this.classes.disabled)\n    this.main.main.setAttribute('aria-disabled', 'true')\n\n    // Set search input to disabled\n    this.content.search.input.disabled = true\n  }\n\n  public open(): void {\n    this.main.arrow.path.setAttribute('d', this.classes.arrowOpen)\n    this.main.main.setAttribute('aria-expanded', 'true')\n\n    // Clear any pending close animation timeout to prevent race conditions\n    if (this.closeAnimationTimeout) {\n      clearTimeout(this.closeAnimationTimeout)\n      this.closeAnimationTimeout = null\n    }\n\n    // Set direction class on both main and content (persists, never removed)\n    const isAbove = this.settings.openPosition === 'up'\n    const dirClass = isAbove ? this.classes.dirAbove : this.classes.dirBelow\n    this.addClasses(this.main.main, dirClass)\n    this.addClasses(this.content.main, dirClass)\n\n    // Add open class to content to trigger open animation\n    this.addClasses(this.content.main, this.classes.contentOpen)\n\n    // Make search visible to screen readers when opened\n    this.content.search.input.removeAttribute('aria-hidden')\n\n    // move the content in to the right location\n    this.moveContent()\n\n    // Move to last selected option\n    const selectedOptions = this.store.getSelectedOptions()\n    if (selectedOptions.length) {\n      const selectedId = selectedOptions[selectedOptions.length - 1].id\n      const selectedOption = this.content.list.querySelector('[data-id=\"' + selectedId + '\"]') as HTMLElement\n      if (selectedOption) {\n        this.ensureElementInView(this.content.list, selectedOption)\n      }\n    }\n  }\n\n  public close(): void {\n    this.main.main.setAttribute('aria-expanded', 'false')\n    this.main.arrow.path.setAttribute('d', this.classes.arrowClose)\n\n    // Remove open class from content to trigger close animation\n    // Direction class (dirAbove/dirBelow) persists to maintain correct transform-origin\n    this.removeClasses(this.content.main, this.classes.contentOpen)\n\n    // Hide search from screen readers when closed\n    this.content.search.input.setAttribute('aria-hidden', 'true')\n\n    // Clear active descendant when closed\n    this.main.main.removeAttribute('aria-activedescendant')\n\n    // Remove direction class from main and content after animation is complete\n    const animationTiming = this.getAnimationTiming()\n    this.closeAnimationTimeout = setTimeout(() => {\n      this.removeClasses(this.main.main, this.classes.dirAbove)\n      this.removeClasses(this.main.main, this.classes.dirBelow)\n      this.removeClasses(this.content.main, this.classes.dirAbove)\n      this.removeClasses(this.content.main, this.classes.dirBelow)\n      this.closeAnimationTimeout = null\n    }, animationTiming)\n  }\n\n  private getAnimationTiming(): number {\n    const computedStyle = getComputedStyle(this.content.main)\n    const cssValue = computedStyle.getPropertyValue('--ss-animation-timing').trim()\n\n    if (cssValue) {\n      // Parse CSS time value (e.g., \"0.2s\" or \"200ms\")\n      if (cssValue.endsWith('ms')) {\n        return parseFloat(cssValue)\n      } else if (cssValue.endsWith('s')) {\n        return parseFloat(cssValue) * 1000\n      }\n    }\n\n    // Fall back to default 200ms\n    return 200\n  }\n\n  public updateClassStyles(): void {\n    // Clear all classes and styles\n    this.main.main.className = ''\n    this.main.main.removeAttribute('style')\n    this.content.main.className = ''\n    this.content.main.removeAttribute('style')\n\n    // Make sure main/content has its base class\n    this.addClasses(this.main.main, this.classes.main)\n    this.addClasses(this.content.main, this.classes.content)\n\n    // Add styles\n    if (this.settings.style !== '') {\n      this.main.main.style.cssText = this.settings.style\n      this.content.main.style.cssText = this.settings.style\n    }\n\n    // Add classes\n    if (this.settings.class.length) {\n      for (const c of this.settings.class) {\n        if (c.trim() !== '') {\n          this.main.main.classList.add(c.trim())\n          this.content.main.classList.add(c.trim())\n        }\n      }\n    }\n\n    // Misc classes\n    // Add content position class\n    if (this.settings.contentPosition === 'relative' || this.settings.contentPosition === 'fixed') {\n      this.content.main.classList.add('ss-' + this.settings.contentPosition)\n    }\n  }\n\n  public updateAriaAttributes() {\n    const listboxId = this.content.list.id\n\n    // Main combobox\n    this.main.main.role = 'combobox'\n    this.main.main.setAttribute('aria-haspopup', 'listbox')\n    this.main.main.setAttribute('aria-controls', listboxId)\n    this.main.main.setAttribute('aria-expanded', 'false')\n\n    this.content.list.setAttribute('role', 'listbox')\n    this.content.list.setAttribute('aria-label', this.settings.ariaLabel + ' listbox')\n\n    // Add aria-multiselectable for multiple selects\n    if (this.settings.isMultiple) {\n      this.content.list.setAttribute('aria-multiselectable', 'true')\n    }\n\n    // Search input should also control the listbox\n    this.content.search.input.setAttribute('aria-controls', listboxId)\n  }\n\n  public mainDiv(): Main {\n    // Create main container\n    const main = document.createElement('div')\n\n    // Add id to data-id\n    main.dataset.id = this.settings.id\n    // main.id = this.settings.id+'-main' // Remove for now as it is not needed and add duplicate id errors\n\n    // Add label\n    main.setAttribute('aria-label', this.settings.ariaLabel)\n\n    // Set tabable to allow tabbing to the element\n    main.tabIndex = 0\n\n    // Deal with keyboard events on the main div\n    // This is to allow for normal selecting\n    // when you may not have a search bar\n    main.onkeydown = (e: KeyboardEvent): boolean => {\n      // Convert above if else statemets to switch\n      switch (e.key) {\n        case 'ArrowUp':\n        case 'ArrowDown':\n          this.callbacks.open()\n          e.key === 'ArrowDown' ? this.highlight('down') : this.highlight('up')\n          return false\n        case 'Tab':\n          this.callbacks.close()\n          return true // Continue doing normal tabbing\n        case 'Enter':\n        case ' ':\n          this.callbacks.open()\n          const highlighted = this.content.list.querySelector(\n            '.' + this.classes.getFirst('highlighted')\n          ) as HTMLDivElement\n          if (highlighted) {\n            highlighted.click()\n          }\n          return false\n        case 'Escape':\n          this.callbacks.close()\n          return false\n      }\n\n      // Check if they type a-z, A-Z and 0-9\n      if (e.key.length === 1) {\n        this.callbacks.open()\n      }\n\n      return true\n    }\n\n    // Add onclick for main div\n    main.onclick = (e: Event): void => {\n      // Dont do anything if disabled\n      if (this.settings.disabled) {\n        return\n      }\n\n      this.settings.isOpen ? this.callbacks.close() : this.callbacks.open()\n    }\n\n    // Add values\n    const values = document.createElement('div')\n    this.addClasses(values, this.classes.values)\n    main.appendChild(values)\n\n    // Add deselect\n    const deselect = document.createElement('div')\n    this.addClasses(deselect, this.classes.deselect)\n\n    // Check if deselect is to be shown or not\n    const selectedOptions = this.store?.getSelectedOptions()\n    if (!this.settings.allowDeselect || (this.settings.isMultiple && selectedOptions && selectedOptions.length <= 0)) {\n      this.addClasses(deselect, this.classes.hide)\n    } else {\n      this.removeClasses(deselect, this.classes.hide)\n    }\n\n    // Add deselect onclick event\n    deselect.onclick = (e: Event) => {\n      e.stopPropagation()\n\n      // Dont do anything if disabled\n      if (this.settings.disabled) {\n        return\n      }\n\n      // By Default we will delete\n      let shouldDelete = true\n      const before = this.store.getSelectedOptions()\n      const after = [] as Option[]\n\n      // Add beforeChange callback\n      if (this.callbacks.beforeChange) {\n        shouldDelete = this.callbacks.beforeChange(after, before) === true\n      }\n\n      if (shouldDelete) {\n        if (this.settings.isMultiple) {\n          this.callbacks.setSelected([], false)\n          this.updateDeselectAll()\n        } else {\n          // Get first option and set it as selected\n          const firstOption = this.store.getFirstOption()\n          const id = firstOption ? firstOption.id : ''\n\n          this.callbacks.setSelected(id, false)\n        }\n\n        // Check if we need to close the dropdown\n        if (this.settings.closeOnSelect) {\n          this.callbacks.close()\n        }\n\n        // Run afterChange callback\n        if (this.callbacks.afterChange) {\n          this.callbacks.afterChange(this.store.getSelectedOptions())\n        }\n      }\n    }\n\n    // Add deselect svg\n    const deselectSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n    deselectSvg.setAttribute('viewBox', '0 0 100 100')\n    const deselectPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n    deselectPath.setAttribute('d', this.classes.deselectPath)\n    deselectSvg.appendChild(deselectPath)\n    deselect.appendChild(deselectSvg)\n    main.appendChild(deselect)\n\n    // Add arrow\n    const arrow = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n    this.addClasses(arrow, this.classes.arrow)\n    arrow.setAttribute('viewBox', '0 0 100 100')\n    const arrowPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n    arrowPath.setAttribute('d', this.classes.arrowClose)\n    if (this.settings.alwaysOpen) {\n      this.addClasses(arrow, this.classes.hide)\n    }\n    arrow.appendChild(arrowPath)\n    main.appendChild(arrow)\n\n    return {\n      main: main,\n      values: values,\n      deselect: {\n        main: deselect,\n        svg: deselectSvg,\n        path: deselectPath\n      },\n      arrow: {\n        main: arrow,\n        path: arrowPath\n      }\n    }\n  }\n\n  public mainFocus(eventType: string | null): void {\n    // Trigger focus but dont scroll to it\n    // Need for prevent refocus the element if event is not keyboard event.\n    // For example if event is mouse click or tachpad click this condition prevent refocus on element\n    // because click by mouse change focus position and not need return focus to element.\n    if (eventType !== 'click') {\n      this.main.main.focus({ preventScroll: true })\n    }\n  }\n\n  public placeholder(): HTMLDivElement {\n    // Figure out if there is a placeholder option\n    const placeholderOption = this.store.filter((o) => o.placeholder, false) as Option[]\n\n    // If there is a placeholder option use that\n    // If placeholder has an html value, use that\n    // If placeholder has a text, use that\n    // If nothing is set, use the placeholder text\n    let placeholderText = this.settings.placeholderText\n    if (placeholderOption.length) {\n      if (placeholderOption[0].html !== '') {\n        placeholderText = placeholderOption[0].html\n      } else if (placeholderOption[0].text !== '') {\n        placeholderText = placeholderOption[0].text\n      }\n    }\n\n    // Create placeholder div\n    const placeholder = document.createElement('div')\n    this.addClasses(placeholder, this.classes.placeholder)\n    placeholder.innerHTML = placeholderText\n    return placeholder\n  }\n\n  // Get selected values and append to multiSelected values container\n  // and remove those who shouldnt exist\n  public renderValues(): void {\n    // If single select set placeholder or selected value\n    if (!this.settings.isMultiple) {\n      this.renderSingleValue()\n      return\n    }\n\n    this.renderMultipleValues()\n\n    this.updateDeselectAll()\n  }\n\n  private renderSingleValue(): void {\n    const selected = this.store.filter((o: Option): boolean => {\n      return o.selected && !o.placeholder\n    }, false) as Option[]\n    const selectedSingle = selected.length > 0 ? selected[0] : null\n\n    // If nothing is seleected use settings placeholder text\n    if (!selectedSingle) {\n      this.main.values.innerHTML = this.placeholder().outerHTML\n    } else {\n      // Create single value container\n      const singleValue = document.createElement('div')\n      this.addClasses(singleValue, this.classes.single)\n      if (selectedSingle.html) {\n        singleValue.innerHTML = selectedSingle.html\n      } else {\n        singleValue.innerText = selectedSingle.text\n      }\n\n      // If there is a selected value, set a single div\n      this.main.values.innerHTML = singleValue.outerHTML\n    }\n\n    // If allowDeselect is false or selected value is empty just hide deselect\n    if (!this.settings.allowDeselect || !selected.length) {\n      this.addClasses(this.main.deselect.main, this.classes.hide)\n    } else {\n      this.removeClasses(this.main.deselect.main, this.classes.hide)\n    }\n  }\n\n  private renderMultipleValues(): void {\n    // Get various pieces of data\n    let currentNodes = this.main.values.childNodes as NodeListOf<HTMLDivElement>\n    let selectedOptions = this.store.filter((opt: Option) => {\n      // Only grab options that are selected and display is true\n      return opt.selected && opt.display\n    }, false) as Option[]\n\n    // If selectedOptions is empty set placeholder\n    if (selectedOptions.length === 0) {\n      this.main.values.innerHTML = this.placeholder().outerHTML\n      return\n    } else {\n      // If there is a placeholder, remove it\n      const placeholder = this.main.values.querySelector('.' + this.classes.getFirst('placeholder'))\n      if (placeholder) {\n        placeholder.remove()\n      }\n    }\n\n    // If selectedOptions is greater than maxItems, set maxValuesMessage\n    if (selectedOptions.length > this.settings.maxValuesShown) {\n      // Creating the element that shows the number of selected items\n      const singleValue = document.createElement('div')\n      this.addClasses(singleValue, this.classes.max)\n      singleValue.textContent = this.settings.maxValuesMessage.replace('{number}', selectedOptions.length.toString())\n\n      // If there is a selected value, set a single div\n      this.main.values.innerHTML = singleValue.outerHTML\n      return\n    } else {\n      // If there is a message, remove it\n      const maxValuesMessage = this.main.values.querySelector('.' + this.classes.getFirst('max'))\n      if (maxValuesMessage) {\n        maxValuesMessage.remove()\n      }\n    }\n\n    // Lets check for data selected order\n    if (this.settings.keepOrder) {\n      selectedOptions = this.store.selectedOrderOptions(selectedOptions)\n    }\n\n    // Loop through currentNodes and only include ones that are not in selectedIDs\n    let removeNodes: HTMLDivElement[] = []\n    for (let i = 0; i < currentNodes.length; i++) {\n      const node = currentNodes[i]\n      const id = node.getAttribute('data-id')\n      if (id) {\n        // Check if id is in selectedOptions\n        const found = selectedOptions.filter((opt: Option) => {\n          return opt.id === id\n        }, false)\n\n        // If not found, add to removeNodes\n        if (!found.length) {\n          removeNodes.push(node)\n        }\n      }\n    }\n\n    // Loop through and remove\n    for (const n of removeNodes) {\n      this.addClasses(n, this.classes.valueOut)\n      setTimeout(() => {\n        if (this.main.values.hasChildNodes() && this.main.values.contains(n)) {\n          this.main.values.removeChild(n)\n        }\n      }, 100)\n    }\n\n    // Add values that dont currently exist\n    currentNodes = this.main.values.childNodes as NodeListOf<HTMLDivElement>\n    for (let d = 0; d < selectedOptions.length; d++) {\n      let shouldAdd = true\n      for (let i = 0; i < currentNodes.length; i++) {\n        if (selectedOptions[d].id === String(currentNodes[i].dataset.id)) {\n          shouldAdd = false\n        }\n      }\n\n      // If shouldAdd, insertAdjacentElement it to the values container in the order of the selectedOptions\n      if (shouldAdd) {\n        // If keepOrder is true, we will just append it to the end\n        if (this.settings.keepOrder) {\n          this.main.values.appendChild(this.multipleValue(selectedOptions[d]))\n        } else {\n          // else we will insert it in the order of the selectedOptions\n          if (currentNodes.length === 0) {\n            this.main.values.appendChild(this.multipleValue(selectedOptions[d]))\n          } else if (d === 0) {\n            this.main.values.insertBefore(this.multipleValue(selectedOptions[d]), currentNodes[d])\n          } else {\n            currentNodes[d - 1].insertAdjacentElement('afterend', this.multipleValue(selectedOptions[d]))\n          }\n        }\n      }\n    }\n  }\n\n  public multipleValue(option: Option): HTMLDivElement {\n    const value = document.createElement('div')\n    this.addClasses(value, this.classes.value)\n    value.dataset.id = option.id\n\n    const text = document.createElement('div')\n    this.addClasses(text, this.classes.valueText)\n    text.textContent = option.text // For multiple values always use text\n    value.appendChild(text)\n\n    // Only add deletion if the option is not mandatory\n    if (!option.mandatory) {\n      // Create delete div element\n      const deleteDiv = document.createElement('div')\n      this.addClasses(deleteDiv, this.classes.valueDelete)\n      deleteDiv.setAttribute('tabindex', '0') // Make the div focusable for tab navigation\n\n      // Add delete onclick event\n      deleteDiv.onclick = (e: Event) => {\n        e.preventDefault()\n        e.stopPropagation()\n\n        // Dont do anything if disabled\n        if (this.settings.disabled) {\n          return\n        }\n\n        // By Default we will delete\n        let shouldDelete = true\n        const before = this.store.getSelectedOptions()\n        const after = before.filter((o) => {\n          return o.selected && o.id !== option.id\n        }, true)\n\n        // Check if minSelected is set and if after length so, return\n        if (this.settings.minSelected && after.length < this.settings.minSelected) {\n          return\n        }\n\n        // If there is a beforeDeselect function run it\n        if (this.callbacks.beforeChange) {\n          shouldDelete = this.callbacks.beforeChange(after, before) === true\n        }\n\n        if (shouldDelete) {\n          // Loop through after and append ids to a variable called selected\n          let selectedIds: string[] = []\n          for (const o of after) {\n            if (o instanceof Optgroup) {\n              for (const c of o.options) {\n                if (c.id) {\n                  selectedIds.push(c.id)\n                }\n              }\n            }\n\n            if (o instanceof Option) {\n              selectedIds.push(o.id)\n            }\n          }\n          this.callbacks.setSelected(selectedIds, false)\n\n          // Check if we need to close the dropdown\n          if (this.settings.closeOnSelect) {\n            this.callbacks.close()\n          }\n\n          // Run afterChange callback\n          if (this.callbacks.afterChange) {\n            this.callbacks.afterChange(after)\n          }\n\n          this.updateDeselectAll()\n        }\n      }\n\n      // Add delete svg\n      const deleteSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n      deleteSvg.setAttribute('viewBox', '0 0 100 100')\n      const deletePath = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n      deletePath.setAttribute('d', this.classes.optionDelete)\n      deleteSvg.appendChild(deletePath)\n      deleteDiv.appendChild(deleteSvg)\n\n      value.appendChild(deleteDiv)\n\n      // Add keydown event listener for keyboard navigation (Enter key)\n      deleteDiv.onkeydown = (e) => {\n        if (e.key === 'Enter') {\n          deleteDiv.click() // Trigger the click event when Enter is pressed\n        }\n      }\n    }\n\n    return value\n  }\n\n  public contentDiv(): Content {\n    const main = document.createElement('div')\n\n    // Add id to data-id\n    main.dataset.id = this.settings.id\n    // main.id = this.settings.id + '-content' // Remove for now as it is not needed and add duplicate id errors\n\n    // Add search\n    const search = this.searchDiv()\n    main.appendChild(search.main)\n\n    // Add list\n    const list = this.listDiv()\n    main.appendChild(list)\n\n    return {\n      main: main,\n      search: search,\n      list: list\n    }\n  }\n\n  public moveContent(): void {\n    // If contentPosition is relative, dont move the content anywhere other than below\n    if (this.settings.contentPosition === 'relative') {\n      this.moveContentBelow()\n      return\n    }\n\n    // If openContent is not auto set content\n    if (this.settings.openPosition === 'down') {\n      this.moveContentBelow()\n      return\n    } else if (this.settings.openPosition === 'up') {\n      this.moveContentAbove()\n      return\n    }\n\n    // Auto - Determine where to put the content\n    if (this.putContent() === 'up') {\n      this.moveContentAbove()\n    } else {\n      this.moveContentBelow()\n    }\n  }\n\n  public searchDiv(): Search {\n    const main = document.createElement('div')\n    const input = document.createElement('input')\n    const addable = document.createElement('div')\n    this.addClasses(main, this.classes.search)\n\n    // Setup search return object\n    const searchReturn: Search = {\n      main,\n      input\n    }\n\n    // We still want the search to be tabable but not shown\n    if (!this.settings.showSearch) {\n      this.addClasses(main, this.classes.hide)\n      input.readOnly = true\n    }\n\n    input.type = 'search'\n    input.placeholder = this.settings.searchPlaceholder\n    input.tabIndex = -1\n    input.setAttribute('aria-label', this.settings.searchPlaceholder)\n    input.setAttribute('aria-autocomplete', 'list')\n    input.setAttribute('autocapitalize', 'off')\n    input.setAttribute('autocomplete', 'off')\n    input.setAttribute('autocorrect', 'off')\n    // Hide from screen readers by default (shown when opened)\n    input.setAttribute('aria-hidden', 'true')\n\n    input.oninput = debounce((e: Event) => {\n      this.callbacks.search((e.target as HTMLInputElement).value)\n    }, 100)\n\n    // Deal with keyboard events on search input field\n    input.onkeydown = (e: KeyboardEvent): boolean => {\n      // Convert above if else statemets to switch\n      switch (e.key) {\n        case 'ArrowUp':\n        case 'ArrowDown':\n          e.key === 'ArrowDown' ? this.highlight('down') : this.highlight('up')\n          return false\n        case 'Tab':\n          // When tabbing close the dropdown\n          // which will also focus on main div\n          // and then continuing normal tabbing\n          this.callbacks.close()\n          return true // Continue doing normal tabbing\n        case 'Escape':\n          this.callbacks.close()\n          return false\n        case ' ':\n          const highlighted = this.content.list.querySelector(\n            '.' + this.classes.getFirst('highlighted')\n          ) as HTMLDivElement\n          if (highlighted) {\n            highlighted.click()\n            return false\n          }\n          return true\n        case 'Enter':\n          // Check if there's a highlighted option first\n          const highlightedEnter = this.content.list.querySelector(\n            '.' + this.classes.getFirst('highlighted')\n          ) as HTMLDivElement\n          if (highlightedEnter) {\n            // If an option is highlighted, select it (even if addable is enabled)\n            highlightedEnter.click()\n            return false\n          } else if (this.callbacks.addable) {\n            // If no option is highlighted and addable is enabled, add new item\n            addable.click()\n            return false\n          }\n          return true\n      }\n\n      return true // Allow normal typing\n    }\n\n    main.appendChild(input)\n\n    // If addable is enabled, add the addable div\n    if (this.callbacks.addable) {\n      // Add main class\n      this.addClasses(addable, this.classes.addable)\n\n      // Add svg icon\n      const plus = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n      plus.setAttribute('viewBox', '0 0 100 100')\n      const plusPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n      plusPath.setAttribute('d', this.classes.addablePath)\n      plus.appendChild(plusPath)\n      addable.appendChild(plus)\n\n      // Add click event to addable div\n      addable.onclick = (e: Event) => {\n        e.preventDefault()\n        e.stopPropagation()\n\n        // Do nothing if addable is not set\n        if (!this.callbacks.addable) {\n          return\n        }\n\n        // Grab input value\n        const inputValue = this.content.search.input.value.trim()\n        if (inputValue === '') {\n          this.content.search.input.focus()\n          return\n        }\n\n        // Run finish will be ran at the end of the addable function.\n        // Reason its in a function is so we can run it after the\n        // addable function is done for promise based addables\n        const runFinish = (oo: Partial<Option>) => {\n          let newOption = new Option(oo)\n\n          // Call addOption to add the new option\n          this.callbacks.addOption(newOption)\n\n          // set selected value for single and multiple\n          if (this.settings.isMultiple) {\n            let ids = this.store.getSelected()\n            ids.push(newOption.id)\n            this.callbacks.setSelected(ids, true)\n          } else {\n            this.callbacks.setSelected([newOption.id], true)\n          }\n\n          // Clear search\n          this.callbacks.search('')\n\n          // Close it only if closeOnSelect = true\n          if (this.settings.closeOnSelect) {\n            setTimeout(() => {\n              // Give it a little padding for a better looking animation\n              this.callbacks.close()\n            }, 100)\n          }\n        }\n\n        // Call addable callback\n        const addableValue = this.callbacks.addable(inputValue)\n\n        // If addableValue is false, undefined or null, do nothing\n        if (addableValue === false || addableValue === undefined || addableValue === null) {\n          return\n        }\n\n        // If addableValue is a promise, wait for it to resolve\n        if (addableValue instanceof Promise) {\n          addableValue.then((value) => {\n            if (typeof value === 'string') {\n              runFinish({\n                text: value,\n                value: value\n              })\n            } else if (addableValue instanceof Error) {\n              this.renderError(addableValue.message)\n            } else {\n              runFinish(value)\n            }\n          })\n        } else if (typeof addableValue === 'string') {\n          runFinish({\n            text: addableValue,\n            value: addableValue\n          })\n        } else if (addableValue instanceof Error) {\n          this.renderError(addableValue.message)\n        } else {\n          runFinish(addableValue)\n        }\n\n        return\n      }\n      main.appendChild(addable)\n\n      // Add the addable to the search return\n      searchReturn.addable = {\n        main: addable,\n        svg: plus,\n        path: plusPath\n      }\n    }\n\n    return searchReturn\n  }\n\n  public searchFocus(): void {\n    this.content.search.input.focus({ preventScroll: true })\n  }\n\n  public getOptions(notPlaceholder = false, notDisabled = false, notHidden = false): HTMLDivElement[] {\n    // Put together query string\n    let query = '.' + this.classes.getFirst('option')\n    if (notPlaceholder) {\n      query += ':not(.' + this.classes.getFirst('placeholder') + ')'\n    }\n    if (notDisabled) {\n      query += ':not(.' + this.classes.getFirst('disabled') + ')'\n    }\n    if (notHidden) {\n      query += ':not(.' + this.classes.getFirst('hide') + ')'\n    }\n\n    return Array.from(this.content.list.querySelectorAll(query))\n  }\n\n  // highlightUp is used to highlight the previous option in the list\n  public highlight(dir: 'up' | 'down'): void {\n    // Get full list of options in list\n    const options = this.getOptions(true, true, true)\n\n    // If there are no options, do nothing\n    if (options.length === 0) {\n      return\n    }\n\n    // If length is 1, highlight it\n    if (options.length === 1) {\n      // Check if option doesnt already have highlighted class\n      if (!options[0].classList.contains(this.classes.getFirst('highlighted'))) {\n        this.addClasses(options[0], this.classes.highlighted)\n        return\n      }\n    }\n\n    // Loop through options and see if there are no highlighted ones\n    let highlighted = false\n    for (const o of options) {\n      if (o.classList.contains(this.classes.getFirst('highlighted'))) {\n        highlighted = true\n      }\n    }\n\n    // If no highlighted, see if any are selected and if so highlight selected first one\n    if (!highlighted) {\n      for (const o of options) {\n        if (o.classList.contains(this.classes.getFirst('selected'))) {\n          this.addClasses(o, this.classes.highlighted)\n          break\n        }\n      }\n    }\n\n    // Loop through options and find the highlighted one\n    for (let i = 0; i < options.length; i++) {\n      // Found highlighted option\n      if (options[i].classList.contains(this.classes.getFirst('highlighted'))) {\n        const prevOption = options[i]\n        // Remove highlighted class from current one\n        this.removeClasses(prevOption, this.classes.highlighted)\n\n        // If previous option has parent classes ss-optgroup with ss-open then click it\n        const prevParent = prevOption.parentElement\n        if (prevParent && prevParent.classList.contains(this.classes.getFirst('mainOpen'))) {\n          const optgroupLabel = prevParent.querySelector('.' + this.classes.getFirst('optgroupLabel')) as HTMLDivElement\n          if (optgroupLabel) {\n            optgroupLabel.click()\n          }\n        }\n\n        // Highlight the next one\n        let selectOption =\n          options[dir === 'down' ? (i + 1 < options.length ? i + 1 : 0) : i - 1 >= 0 ? i - 1 : options.length - 1]\n        this.addClasses(selectOption, this.classes.highlighted)\n        this.ensureElementInView(this.content.list, selectOption)\n\n        // Update aria-activedescendant for screen readers\n        if (selectOption.id) {\n          this.main.main.setAttribute('aria-activedescendant', selectOption.id)\n        }\n\n        // If selected option has parent classes ss-optgroup with ss-close then click it\n        const selectParent = selectOption.parentElement\n        if (selectParent && selectParent.classList.contains(this.classes.getFirst('close'))) {\n          const optgroupLabel = selectParent.querySelector(\n            '.' + this.classes.getFirst('optgroupLabel')\n          ) as HTMLDivElement\n          if (optgroupLabel) {\n            optgroupLabel.click()\n          }\n        }\n\n        return\n      }\n    }\n\n    // If we get here, there is no highlighted option\n    // So we will highlight the first or last based upon direction\n    const firstHighlight = options[dir === 'down' ? 0 : options.length - 1]\n    this.addClasses(firstHighlight, this.classes.highlighted)\n\n    // Update aria-activedescendant for screen readers\n    if (firstHighlight.id) {\n      this.main.main.setAttribute('aria-activedescendant', firstHighlight.id)\n    }\n\n    // Scroll to highlighted one\n    this.ensureElementInView(this.content.list, firstHighlight)\n  }\n\n  // Create main container that options will reside\n  public listDiv(): HTMLDivElement {\n    const options = document.createElement('div')\n    this.addClasses(options, this.classes.list)\n\n    // Add id for ARIA controls reference\n    const listId = this.settings.id + '-list'\n    options.id = listId\n    options.dataset.id = listId\n\n    return options\n  }\n\n  public renderError(error: string) {\n    // Clear out innerHtml\n    this.content.list.innerHTML = ''\n\n    const errorDiv = document.createElement('div')\n    this.addClasses(errorDiv, this.classes.error)\n    errorDiv.textContent = error\n    this.content.list.appendChild(errorDiv)\n  }\n\n  public renderSearching() {\n    // Clear out innerHtml\n    this.content.list.innerHTML = ''\n\n    const searchingDiv = document.createElement('div')\n    this.addClasses(searchingDiv, this.classes.searching)\n    searchingDiv.textContent = this.settings.searchingText\n    this.content.list.appendChild(searchingDiv)\n  }\n\n  // Take in data and add options to\n  public renderOptions(data: (Option | Optgroup)[]): void {\n    this.lastRenderedOptions = data\n      .map((o) => (o instanceof Option ? [o] : o.options.map((po) => new Option(po))))\n      .flat()\n\n    // Clear out innerHtml\n    this.content.list.innerHTML = ''\n\n    // If no results show no results text\n    if (data.length === 0) {\n      const noResults = document.createElement('div')\n      this.addClasses(noResults, this.classes.search)\n\n      //\n      if (this.callbacks.addable) {\n        noResults.innerHTML = this.settings.addableText.replace('{value}', this.content.search.input.value)\n      } else {\n        noResults.innerHTML = this.settings.searchText\n      }\n      this.content.list.appendChild(noResults)\n      return\n    }\n\n    // If settings has allowDeselect and isSingle, add empty placeholder in the event they want to deselect\n    if (this.settings.allowDeselect && !this.settings.isMultiple) {\n      // Check if store options have a placeholder\n      const placeholderOption = this.store.filter((o) => o.placeholder, false) as Option[]\n      if (!placeholderOption.length) {\n        this.store.addOption(\n          new Option({\n            text: '',\n            value: '',\n            selected: false,\n            placeholder: true\n          }),\n          true\n        )\n      }\n    }\n\n    // Append individual options to div container\n    const fragment = document.createDocumentFragment()\n    for (const d of data) {\n      // Create optgroup\n      if (d instanceof Optgroup) {\n        // Create optgroup\n        const optgroupEl = document.createElement('div')\n        this.addClasses(optgroupEl, this.classes.optgroup)\n\n        // Create label\n        const optgroupLabel = document.createElement('div')\n        this.addClasses(optgroupLabel, this.classes.optgroupLabel)\n        optgroupEl.appendChild(optgroupLabel)\n\n        // Create label text div element\n        const optgroupLabelText = document.createElement('div')\n        this.addClasses(optgroupLabelText, this.classes.optgroupLabelText)\n        optgroupLabelText.textContent = d.label\n        optgroupLabel.appendChild(optgroupLabelText)\n\n        // Create options container\n        const optgroupActions = document.createElement('div')\n        this.addClasses(optgroupActions, this.classes.optgroupActions)\n        optgroupLabel.appendChild(optgroupActions)\n\n        // If selectByGroup is true and isMultiple then add click event to label\n        if (this.settings.isMultiple && d.selectAll) {\n          // Create new div to hold a checkbox svg\n          const selectAll = document.createElement('div')\n          this.addClasses(selectAll, this.classes.optgroupSelectAll)\n\n          // Check options and if all are selected, if so add class selected\n          let allSelected = true\n          for (const o of d.options) {\n            if (!o.selected) {\n              allSelected = false\n              break\n            }\n          }\n\n          // Add class if all selected\n          if (allSelected) {\n            this.addClasses(selectAll, this.classes.selected)\n          }\n\n          // Add select all text span\n          const selectAllText = document.createElement('span')\n          selectAllText.textContent = d.selectAllText\n          selectAll.appendChild(selectAllText)\n\n          // Create new svg for checkbox\n          const selectAllSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n          selectAllSvg.setAttribute('viewBox', '0 0 100 100')\n          selectAll.appendChild(selectAllSvg)\n\n          // Create new path for box\n          const selectAllBox = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n          selectAllBox.setAttribute('d', this.classes.optgroupSelectAllBox)\n          selectAllSvg.appendChild(selectAllBox)\n\n          // Create new path for check\n          const selectAllCheck = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n          selectAllCheck.setAttribute('d', this.classes.optgroupSelectAllCheck)\n          selectAllSvg.appendChild(selectAllCheck)\n\n          // Add click event listener to select all\n          selectAll.addEventListener('click', (e: MouseEvent) => {\n            e.preventDefault()\n            e.stopPropagation()\n\n            // Get the store current selected values\n            const currentSelected = this.store.getSelected()\n\n            // If all selected, remove all options from selected\n            // call setSelected and return\n            if (allSelected) {\n              // Put together new list minus all options in this optgroup\n              const newSelected = currentSelected.filter((s) => {\n                for (const o of d.options) {\n                  if (s === o.id) {\n                    return false\n                  }\n                }\n\n                return true\n              })\n\n              this.callbacks.setSelected(newSelected, true)\n              return\n            } else {\n              // Put together new list with all options in this optgroup\n              let optionIds = d.options.map((o) => o.id).filter((id) => id !== undefined)\n              const newSelected = currentSelected.concat(optionIds)\n\n              // Loop through options and if they don't exist in the store\n              // run addOption callback\n              for (const o of d.options) {\n                if (o.id && !this.store.getOptionByID(o.id)) {\n                  this.callbacks.addOption(new Option(o))\n                }\n              }\n\n              this.callbacks.setSelected(newSelected, true)\n              return\n            }\n          })\n\n          // Append select all to label\n          optgroupActions.appendChild(selectAll)\n        }\n\n        // If optgroup has collapsable\n        if (d.closable !== 'off') {\n          // Create new div to hold a checkbox svg\n          const optgroupClosable = document.createElement('div')\n          this.addClasses(optgroupClosable, this.classes.optgroupClosable)\n\n          // Create svg arrow\n          const optgroupClosableSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n          optgroupClosableSvg.setAttribute('viewBox', '0 0 100 100')\n          this.addClasses(optgroupClosableSvg, this.classes.arrow)\n          optgroupClosable.appendChild(optgroupClosableSvg)\n\n          // Create new path for arrow\n          const optgroupClosableArrow = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n          optgroupClosableSvg.appendChild(optgroupClosableArrow)\n\n          // If any options are selected or someone is searching, set optgroup to open\n          if (d.options.some((o) => o.selected) || this.content.search.input.value.trim() !== '') {\n            this.addClasses(optgroupClosable, this.classes.mainOpen)\n            optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen)\n          } else if (d.closable === 'open') {\n            this.addClasses(optgroupEl, this.classes.mainOpen)\n            optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen)\n          } else if (d.closable === 'close') {\n            this.addClasses(optgroupEl, this.classes.close)\n            optgroupClosableArrow.setAttribute('d', this.classes.arrowClose)\n          }\n\n          // Add click event listener to close\n          optgroupLabel.addEventListener('click', (e: MouseEvent) => {\n            e.preventDefault()\n            e.stopPropagation()\n\n            // If optgroup is closed, open it\n            if (optgroupEl.classList.contains(this.classes.getFirst('close'))) {\n              this.removeClasses(optgroupEl, this.classes.close)\n              this.addClasses(optgroupEl, this.classes.mainOpen)\n              optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen)\n            } else {\n              this.removeClasses(optgroupEl, this.classes.mainOpen)\n              this.addClasses(optgroupEl, this.classes.close)\n              optgroupClosableArrow.setAttribute('d', this.classes.arrowClose)\n            }\n          })\n\n          // Append close to label\n          optgroupActions.appendChild(optgroupClosable)\n        }\n\n        // Add optgroup label\n        optgroupEl.appendChild(optgroupLabel)\n\n        // Loop through options\n        for (const option of d.options) {\n          optgroupEl.appendChild(this.option(new Option(option)))\n          fragment.appendChild(optgroupEl)\n        }\n      }\n\n      // Create option\n      if (d instanceof Option) {\n        fragment.appendChild(this.option(d as Option))\n      }\n    }\n\n    // Append fragment to list\n    this.content.list.appendChild(fragment)\n  }\n\n  // Create option div element\n  public option(option: Option): HTMLDivElement {\n    // Add hidden placeholder\n    if (option.placeholder) {\n      const placeholder = document.createElement('div')\n      this.addClasses(placeholder, this.classes.option)\n      this.addClasses(placeholder, this.classes.hide)\n      return placeholder\n    }\n\n    // Create option\n    const optionEl = document.createElement('div')\n    optionEl.dataset.id = option.id // Dataset id for identifying an option\n    optionEl.id = this.settings.id + '-' + option.id // Unique ID for ARIA references\n    this.addClasses(optionEl, this.classes.option)\n    optionEl.setAttribute('role', 'option') // WCAG attribute\n    if (option.class) {\n      option.class.split(' ').forEach((dataClass: string) => {\n        optionEl.classList.add(dataClass)\n      })\n    }\n    if (option.style) {\n      optionEl.style.cssText = option.style\n    }\n\n    // Set option content\n    if (this.settings.searchHighlight && this.content.search.input.value.trim() !== '') {\n      optionEl.innerHTML = this.highlightText(\n        option.html !== '' ? option.html : option.text,\n        this.content.search.input.value,\n        this.classes.searchHighlighter\n      )\n    } else if (option.html !== '') {\n      optionEl.innerHTML = option.html\n    } else {\n      optionEl.textContent = option.text\n    }\n\n    // Set title attribute\n    if (this.settings.showOptionTooltips && optionEl.textContent) {\n      optionEl.setAttribute('title', optionEl.textContent)\n    }\n\n    // If option is disabled\n    if (!option.display) {\n      this.addClasses(optionEl, this.classes.hide)\n    }\n\n    // If allowed to deselect, null onclick and add disabled\n    if (option.disabled) {\n      this.addClasses(optionEl, this.classes.disabled)\n    }\n\n    // If option is selected and hideSelectedOption is true, hide it\n    if (option.selected && this.settings.hideSelected) {\n      this.addClasses(optionEl, this.classes.hide)\n    }\n\n    // If option is selected\n    if (option.selected) {\n      this.addClasses(optionEl, this.classes.selected)\n      optionEl.setAttribute('aria-selected', 'true')\n      this.main.main.setAttribute('aria-activedescendant', optionEl.id)\n    } else {\n      this.removeClasses(optionEl, this.classes.selected)\n      optionEl.setAttribute('aria-selected', 'false')\n    }\n\n    // Add click event listener\n    optionEl.addEventListener('click', (e: MouseEvent) => {\n      e.preventDefault()\n      e.stopPropagation()\n\n      // Setup variables\n      const selectedOptions = this.store.getSelected()\n      const element = e.currentTarget as HTMLDivElement\n      const elementID = String(element.dataset.id)\n      const isCmd = e.ctrlKey || e.metaKey // Cmd (Mac) or Ctrl (Windows/Linux)\n\n      // If the option is disabled, do nothing\n      if (option.disabled) {\n        return\n      }\n\n      // allowDeselect only applies to single-select mode\n      // In multi-select, you can always toggle options on/off\n      if (!this.settings.isMultiple && option.selected && !this.settings.allowDeselect) {\n        return\n      }\n\n      // Prevent deselection of mandatory options\n      if (option.selected && option.mandatory) {\n        return\n      }\n\n      // Check limit and do nothing if limit is reached and the option is not selected\n      // Also check reverse for min limit and is selected (allow Cmd to bypass minSelected)\n      if (\n        (this.settings.isMultiple && this.settings.maxSelected <= selectedOptions.length && !option.selected) ||\n        (this.settings.isMultiple && this.settings.minSelected >= selectedOptions.length && option.selected && !isCmd)\n      ) {\n        return\n      }\n\n      // Setup variables\n      let shouldUpdate = false\n      const before = this.store.getSelectedOptions()\n      let after = [] as Option[]\n\n      // If multiple - mimic native browser multi-select behavior\n      if (this.settings.isMultiple) {\n        const isCurrentlySelected = before.some((o: Option) => o.id === elementID)\n        const isShift = e.shiftKey\n\n        // Shift+Click: Select range from last clicked to current\n        if (isShift && this.lastSelectedOption) {\n          const options = this.lastRenderedOptions\n          const lastIndex = options.findIndex((o: Option) => o.id === this.lastSelectedOption!.id)\n          const currentIndex = options.findIndex((o: Option) => o.id === option.id)\n\n          if (lastIndex >= 0 && currentIndex >= 0) {\n            const startIndex = Math.min(lastIndex, currentIndex)\n            const endIndex = Math.max(lastIndex, currentIndex)\n            const rangeOptions = options.slice(startIndex, endIndex + 1)\n\n            // Check if range would exceed maxSelected\n            const newSelections = rangeOptions.filter((opt) => !before.find((b) => b.id === opt.id))\n            if (before.length + newSelections.length <= this.settings.maxSelected) {\n              // Add range to existing selections\n              after = before.concat(newSelections)\n            } else {\n              // Range too large, keep existing selections\n              after = before\n            }\n          } else {\n            after = before\n          }\n        }\n        // Cmd/Ctrl+Click: Toggle selection without affecting others (keeps dropdown open)\n        else if (isCmd) {\n          if (isCurrentlySelected) {\n            // Deselect this option\n            after = before.filter((o: Option) => o.id !== elementID)\n          } else {\n            // Add this option to selection\n            after = before.concat(option)\n          }\n          this.lastSelectedOption = option\n        }\n        // Regular Click: Toggle this option (add/remove), will close dropdown\n        else {\n          if (isCurrentlySelected) {\n            // Deselect this option\n            after = before.filter((o: Option) => o.id !== elementID)\n          } else {\n            // Add this option to selection\n            after = before.concat(option)\n          }\n          this.lastSelectedOption = option\n        }\n      }\n\n      // If single\n      if (!this.settings.isMultiple) {\n        if (option.selected) {\n          // If selected after would remove\n          after = []\n        } else {\n          // If not selected after would add\n          after = [option]\n        }\n      }\n\n      // If no beforeOnChange is set automatically update at end\n      if (!this.callbacks.beforeChange) {\n        shouldUpdate = true\n      }\n\n      if (this.callbacks.beforeChange) {\n        // Check if beforeChange returns false\n        if (this.callbacks.beforeChange(after, before) === false) {\n          shouldUpdate = false\n        } else {\n          shouldUpdate = true\n        }\n      }\n\n      if (shouldUpdate) {\n        // Check if the option exists in the store\n        // if not run addOption callback\n        if (!this.store.getOptionByID(elementID)) {\n          this.callbacks.addOption(option)\n        }\n\n        // Get values from after and set as selected\n        this.callbacks.setSelected(\n          after.map((o: Option) => o.id),\n          false\n        )\n\n        // Close dropdown unless using modifier keys in multi-select\n        // (mimics native multi-select behavior where you can keep selecting)\n        const isModifierKey = e.ctrlKey || e.metaKey || e.shiftKey // Cmd/Ctrl or Shift\n        const shouldClose = this.settings.closeOnSelect && !(this.settings.isMultiple && isModifierKey)\n\n        if (shouldClose) {\n          this.callbacks.close()\n        }\n\n        // callback that the value has changed\n        if (this.callbacks.afterChange) {\n          this.callbacks.afterChange(after)\n        }\n      }\n    })\n\n    return optionEl\n  }\n\n  public destroy(): void {\n    // Clear any pending timeouts\n    if (this.closeAnimationTimeout) {\n      clearTimeout(this.closeAnimationTimeout)\n      this.closeAnimationTimeout = null\n    }\n\n    // Remove main\n    this.main.main.remove()\n\n    // Remove content\n    this.content.main.remove()\n  }\n\n  private highlightText(str: string, search: any, className: string) {\n    const searchTerm = search.trim()\n    if (searchTerm === '') {\n      return str\n    }\n\n    // Escape special regex characters in the search term to prevent regex injection\n    const escapedSearch = searchTerm.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n    // Create a temporary div to parse HTML and work with text nodes only\n    const tempDiv = document.createElement('div')\n    tempDiv.innerHTML = str\n\n    // Function to recursively process text nodes\n    const highlightTextNodes = (node: Node) => {\n      if (node.nodeType === Node.TEXT_NODE) {\n        const text = node.textContent || ''\n        const regex = new RegExp('(' + escapedSearch + ')', 'i')\n\n        if (regex.test(text)) {\n          // Create a temporary container for the highlighted content\n          const wrapper = document.createElement('span')\n          const parts = text.split(regex)\n\n          parts.forEach((part, index) => {\n            if (part && regex.test(part)) {\n              // This is the matched part - wrap it in mark\n              const mark = document.createElement('mark')\n              mark.className = className\n              mark.textContent = part\n              wrapper.appendChild(mark)\n            } else if (part) {\n              // This is not the matched part - keep as text\n              wrapper.appendChild(document.createTextNode(part))\n            }\n          })\n\n          // Replace the text node with the wrapper\n          node.parentNode?.replaceChild(wrapper, node)\n        }\n      } else if (node.nodeType === Node.ELEMENT_NODE) {\n        // Recursively process child nodes\n        Array.from(node.childNodes).forEach((child) => highlightTextNodes(child))\n      }\n    }\n\n    // Process all text nodes in the temporary div\n    Array.from(tempDiv.childNodes).forEach((node) => highlightTextNodes(node))\n\n    return tempDiv.innerHTML\n  }\n\n  private setContentDirection(direction: 'above' | 'below'): void {\n    const isAbove = direction === 'above'\n    const addClass = isAbove ? this.classes.dirAbove : this.classes.dirBelow\n    const removeClass = isAbove ? this.classes.dirBelow : this.classes.dirAbove\n\n    // Set direction classes on both main and content\n    this.removeClasses(this.main.main, removeClass)\n    this.addClasses(this.main.main, addClass)\n    this.removeClasses(this.content.main, removeClass)\n    this.addClasses(this.content.main, addClass)\n\n    // Set margin to position content\n    if (isAbove) {\n      const mainHeight = this.main.main.offsetHeight\n      const contentHeight = this.content.main.offsetHeight\n      this.content.main.style.margin = '-' + (mainHeight + contentHeight - 1) + 'px 0px 0px 0px'\n    } else {\n      this.content.main.style.margin = '-1px 0px 0px 0px'\n    }\n  }\n\n  private setContentPosition(): void {\n    if (this.settings.contentPosition === 'relative') {\n      return\n    }\n\n    // getBoundingClientRect() returns viewport-relative coordinates.\n    const containerRect = this.main.main.getBoundingClientRect()\n    let top: number\n    let left: number\n\n    if (this.settings.contentPosition === 'fixed') {\n      // position:fixed is relative to the viewport, so viewport coords work directly.\n      top = containerRect.top + containerRect.height\n      left = containerRect.left\n    } else {\n      // position:absolute is relative to the containing block. By default the content\n      // is appended to document.body (static), so the containing block is the initial\n      // containing block (document origin). We must convert viewport coords to document\n      // coords by adding scroll offsets. Using offsetParent subtraction was unreliable\n      // because offsetParent for body children varies across browsers (body vs html)\n      // and body margin caused misalignment.\n      top = containerRect.top + window.scrollY + containerRect.height\n      left = containerRect.left + window.scrollX\n    }\n\n    this.content.main.style.top = top + 'px'\n    this.content.main.style.left = left + 'px'\n\n    // Apply content width based on contentWidth setting\n    // \"\"           → width matches trigger (default/current behavior)\n    // \"500px\"      → exact width of 500px\n    // \">500px\"     → min-width of 500px, width auto (content can grow)\n    // \"<500px\"     → max-width of 500px, width auto (content can shrink)\n    const cw = this.settings.contentWidth\n    this.content.main.style.width = ''\n    this.content.main.style.minWidth = ''\n    this.content.main.style.maxWidth = ''\n\n    if (!cw) {\n      // Default: match trigger width exactly\n      this.content.main.style.width = containerRect.width + 'px'\n    } else if (cw.startsWith('>')) {\n      // Min-width mode: at least this wide, can grow to fit content\n      this.content.main.style.minWidth = cw.slice(1)\n    } else if (cw.startsWith('<')) {\n      // Max-width mode: no wider than this, content wraps if longer\n      this.content.main.style.maxWidth = cw.slice(1)\n    } else {\n      // Exact width\n      this.content.main.style.width = cw\n    }\n\n    // If content overflows the right side of the viewport, shift it left so the right edge\n    // lines up with the trigger (or stays inside the viewport). Use rAF so we measure after\n    // layout (and after width:auto / min-width have been applied).\n    const padding = 20\n    const viewportRight = window.innerWidth - padding\n\n    const applyOverflowShift = (): void => {\n      const contentRect = this.content.main.getBoundingClientRect()\n      const contentRight = contentRect.right\n      if (contentRight <= viewportRight) return\n\n      const overflow = contentRight - viewportRight\n      const currentLeft = parseFloat(this.content.main.style.left) || 0\n\n      if (this.settings.contentPosition === 'fixed') {\n        const newLeft = Math.max(padding, currentLeft - overflow)\n        this.content.main.style.left = newLeft + 'px'\n      } else {\n        const newLeft = Math.max(window.scrollX + padding, currentLeft - overflow)\n        this.content.main.style.left = newLeft + 'px'\n      }\n    }\n\n    // First rAF: layout done (width/min-width applied). Second rAF: catch scrollbar etc.\n    requestAnimationFrame(() => {\n      applyOverflowShift()\n      requestAnimationFrame(applyOverflowShift)\n    })\n  }\n\n  public moveContentAbove(): void {\n    this.setContentDirection('above')\n    this.setContentPosition()\n  }\n\n  public moveContentBelow(): void {\n    this.setContentDirection('below')\n    this.setContentPosition()\n  }\n\n  public ensureElementInView(container: HTMLElement, element: HTMLElement): void {\n    // Determine container top and bottom\n    const cTop = container.scrollTop + container.offsetTop // Make sure to have offsetTop\n    const cBottom = cTop + container.clientHeight\n\n    // Determine element top and bottom\n    const eTop = element.offsetTop\n    const eBottom = eTop + element.clientHeight\n\n    // Check if out of view\n    if (eTop < cTop) {\n      container.scrollTop -= cTop - eTop\n    } else if (eBottom > cBottom) {\n      container.scrollTop += eBottom - cBottom\n    }\n  }\n\n  public putContent(): 'up' | 'down' {\n    // Get main and content height\n    const mainHeight = this.main.main.offsetHeight\n    const mainRect = this.main.main.getBoundingClientRect()\n    const contentHeight = this.content.main.offsetHeight\n\n    // From bottom of mainHeight figure out if content will fit below without going below the window\n    const spaceBelow = window.innerHeight - (mainRect.top + mainHeight)\n\n    // If space below is less than content height\n    if (spaceBelow <= contentHeight) {\n      // If space above is more than content height\n      if (mainRect.top > contentHeight) {\n        // Move content above\n        return 'up'\n      } else {\n        // Move content below\n        return 'down'\n      }\n    }\n\n    // Move content below\n    return 'down'\n  }\n\n  // Updates deselect based on item count and allowDeselect setting\n  public updateDeselectAll(): void {\n    if (!this.store || !this.settings) {\n      return\n    }\n    const selected = this.store.getSelectedOptions()\n    const hasSelectedItems = selected && selected.length > 0\n    const isMultiple = this.settings.isMultiple\n    const allowDeselect = this.settings.allowDeselect\n\n    const deselectButton = this.main.deselect.main\n    const hideClass = this.classes.hide\n\n    if (allowDeselect && !(isMultiple && !hasSelectedItems)) {\n      this.removeClasses(deselectButton, hideClass)\n    } else {\n      this.addClasses(deselectButton, hideClass)\n    }\n  }\n}\n","import { kebabCase, hasClassInTree } from './helpers'\nimport { Optgroup, Option } from './store'\n\nexport default class Select {\n  public select: HTMLSelectElement\n\n  // Mutation observer fields\n  public onValueChange?: (value: Option[]) => void\n  public onClassChange?: (classes: string[]) => void\n  public onDisabledChange?: (disabled: boolean) => void\n  public onOptionsChange?: (data: (Option | Optgroup)[]) => void\n  public onLabelClick?: () => void\n\n  // Change observers\n  private listen: boolean = false\n  private observer: MutationObserver | null = null\n  private isUpdating: boolean = false\n  private pendingOptionsChange: (Option | Optgroup)[] | null = null\n\n  // Event handlers for preventing native select behavior (especially on iOS Safari)\n  private preventNativeSelect: ((e: Event) => void) | null = null\n  private preventNativeSelectMousedown: ((e: Event) => void) | null = null\n  private preventNativeSelectFocus: ((e: Event) => void) | null = null\n\n  constructor(select: HTMLSelectElement) {\n    this.select = select\n\n    this.valueChange = this.valueChange.bind(this)\n    // Add change event listener\n    this.select.addEventListener('change', this.valueChange, {\n      // allow bubbling of event\n      passive: true\n    })\n\n    // Initiate mutation observer\n    this.observer = new MutationObserver(this.observeCall.bind(this))\n\n    // Start listening for changes\n    this.changeListen(true)\n  }\n\n  public enable(): void {\n    this.select.disabled = false\n  }\n\n  public disable(): void {\n    this.select.disabled = true\n  }\n\n  public hideUI(): void {\n    this.select.tabIndex = -1\n    // Visually hide but keep focusable for form validation\n    // Use 1px dimensions so browser validation popup can display\n    this.select.style.position = 'absolute'\n    this.select.style.width = '1px'\n    this.select.style.height = '1px'\n    this.select.style.opacity = '0'\n    this.select.style.overflow = 'hidden'\n    this.select.style.pointerEvents = 'none'\n    // Remove any spacing or borders that could affect layout\n    this.select.style.margin = '0'\n    this.select.style.padding = '0'\n    this.select.style.borderWidth = '0'\n    // Clip to completely hide the 1px\n    this.select.style.clip = 'rect(0 0 0 0)'\n    this.select.setAttribute('aria-hidden', 'true')\n\n    // Prevent native select from opening when label is clicked (especially on iOS Safari)\n    // iOS Safari programmatically focuses/clicks the select when label is clicked,\n    // bypassing pointer-events: none, so we need to prevent these events\n    // Only add listeners if they haven't been added yet\n    if (!this.preventNativeSelect) {\n      this.preventNativeSelect = (e: Event) => {\n        e.preventDefault()\n        e.stopPropagation()\n        e.stopImmediatePropagation()\n      }\n\n      this.preventNativeSelectMousedown = (e: Event) => {\n        e.preventDefault()\n        e.stopPropagation()\n        e.stopImmediatePropagation()\n      }\n\n      this.preventNativeSelectFocus = (e: Event) => {\n        e.preventDefault()\n        e.stopPropagation()\n        e.stopImmediatePropagation()\n      }\n\n      // Add event listeners with capture phase to catch events before they reach the select\n      this.select.addEventListener('click', this.preventNativeSelect, { capture: true, passive: false })\n      this.select.addEventListener('mousedown', this.preventNativeSelectMousedown, { capture: true, passive: false })\n      this.select.addEventListener('focus', this.preventNativeSelectFocus, { capture: true, passive: false })\n    }\n  }\n\n  public showUI(): void {\n    this.select.removeAttribute('tabindex')\n    // Reset visual hiding styles\n    this.select.style.position = ''\n    this.select.style.width = ''\n    this.select.style.height = ''\n    this.select.style.opacity = ''\n    this.select.style.overflow = ''\n    this.select.style.pointerEvents = ''\n    this.select.style.margin = ''\n    this.select.style.padding = ''\n    this.select.style.borderWidth = ''\n    this.select.style.clip = ''\n    this.select.removeAttribute('aria-hidden')\n\n    // Remove event listeners that prevent native select behavior\n    if (this.preventNativeSelect) {\n      this.select.removeEventListener('click', this.preventNativeSelect, { capture: true })\n      this.preventNativeSelect = null\n    }\n    if (this.preventNativeSelectMousedown) {\n      this.select.removeEventListener('mousedown', this.preventNativeSelectMousedown, { capture: true })\n      this.preventNativeSelectMousedown = null\n    }\n    if (this.preventNativeSelectFocus) {\n      this.select.removeEventListener('focus', this.preventNativeSelectFocus, { capture: true })\n      this.preventNativeSelectFocus = null\n    }\n  }\n\n  public changeListen(listen: boolean) {\n    this.listen = listen\n\n    // Start listening for changes\n    if (listen) {\n      if (this.observer) {\n        this.observer.observe(this.select, {\n          subtree: true, // subtree for optgroups options\n          childList: true, // children changes\n          attributes: true // attributes changes\n        })\n      }\n    }\n\n    // Stop listening for changes\n    if (!listen) {\n      if (this.observer) {\n        this.observer.disconnect()\n      }\n    }\n  }\n\n  // This function get triggers when the select value changes\n  // and will call the onValueChange function if it exists\n  public valueChange(ev: Event): boolean {\n    if (this.listen && this.onValueChange) {\n      this.onValueChange(this.getSelectedOptions())\n    }\n\n    // Allow bubbling back to other change event listeners\n    return true\n  }\n\n  private observeCall(mutations: MutationRecord[]): void {\n    // If we are not listening, do nothing.\n    if (!this.listen) {\n      return\n    }\n\n    let classChanged = false\n    let disabledChanged = false\n    let optgroupOptionChanged = false\n    let selectionChanged = false\n\n    // Loop through mutations and check various things\n    for (const m of mutations) {\n      // Check if its the select\n      if (m.target === this.select) {\n        // Check if disabled has changed\n        if (m.attributeName === 'disabled') {\n          disabledChanged = true\n        }\n\n        // Check if class has changed\n        if (m.attributeName === 'class') {\n          classChanged = true\n        }\n\n        if (m.type === 'childList') {\n          for (const n of Array.from(m.addedNodes)) {\n            if (n.nodeName === 'OPTION' && (<HTMLOptionElement>n).value === this.select.value) {\n              // we added a new option that's now the select value\n              selectionChanged = true\n              break\n            }\n          }\n\n          // options changed, so we need the optionsChange event to fire\n          optgroupOptionChanged = true\n        }\n      }\n\n      // Check if its an optgroup or option\n      if (m.target.nodeName === 'OPTGROUP' || m.target.nodeName === 'OPTION') {\n        optgroupOptionChanged = true\n      }\n    }\n\n    // If class has changed then call the class change function\n    if (classChanged && this.onClassChange) {\n      this.onClassChange(this.select.className.split(' '))\n    }\n\n    // If disabled has changed then call the disabled change function\n    if (disabledChanged && this.onDisabledChange) {\n      this.changeListen(false)\n      this.onDisabledChange(this.select.disabled)\n      this.changeListen(true)\n    }\n\n    // If optgroup or option has changed then call the select change function\n    if (optgroupOptionChanged && this.onOptionsChange) {\n      // If we're currently updating, queue this change to process after update completes\n      if (this.isUpdating) {\n        // Only queue if the select element actually has options (not empty from updateOptions clearing)\n        // Check the select element directly, not getData() which might return stale data\n        if (this.select.options.length > 0) {\n          const currentData = this.getData()\n          // Only queue if we have actual data\n          if (currentData.length > 0) {\n            this.pendingOptionsChange = currentData\n          }\n        }\n        if (selectionChanged) {\n          this.select.dispatchEvent(new Event('change'))\n        }\n        return\n      }\n\n      this.changeListen(false)\n      this.onOptionsChange(this.getData())\n      this.changeListen(true)\n    }\n\n    if (selectionChanged) {\n      this.select.dispatchEvent(new Event('change'))\n    }\n  }\n\n  // From the select element pull optgroup and options into data\n  public getData(): (Option | Optgroup)[] {\n    let data = []\n\n    // Loop through nodes and get data\n    const nodes = this.select.childNodes as any as HTMLOptGroupElement[] | HTMLOptionElement[]\n    for (const n of nodes) {\n      // Optgroup\n      if (n.nodeName === 'OPTGROUP') {\n        data.push(this.getDataFromOptgroup(n as HTMLOptGroupElement))\n      }\n\n      // Option\n      if (n.nodeName === 'OPTION') {\n        data.push(this.getDataFromOption(n as HTMLOptionElement))\n      }\n    }\n\n    return data\n  }\n\n  public getDataFromOptgroup(optgroup: HTMLOptGroupElement): Optgroup {\n    let data = {\n      id: optgroup.id,\n      label: optgroup.label,\n      selectAll: optgroup.dataset ? optgroup.dataset.selectall === 'true' : false,\n      selectAllText: optgroup.dataset ? optgroup.dataset.selectalltext : 'Select all',\n      closable: optgroup.dataset ? optgroup.dataset.closable : 'off',\n      options: []\n    } as Optgroup\n\n    const options = optgroup.childNodes as any as HTMLOptionElement[]\n    for (const o of options) {\n      if (o.nodeName === 'OPTION') {\n        data.options!.push(this.getDataFromOption(o as HTMLOptionElement))\n      }\n    }\n\n    return data\n  }\n\n  // From passed in option pull pieces of usable information\n  public getDataFromOption(option: HTMLOptionElement): Option {\n    return {\n      id: option.id,\n      value: option.value,\n      text: option.text,\n      html: option.dataset && option.dataset.html ? option.dataset.html : '',\n      defaultSelected: option.defaultSelected,\n      selected: option.selected,\n      display: option.style.display !== 'none',\n      disabled: option.disabled,\n      mandatory: option.dataset ? option.dataset.mandatory === 'true' : false,\n      placeholder: option.dataset.placeholder === 'true',\n      class: option.className,\n      style: option.style.cssText,\n      data: option.dataset\n    } as Option\n  }\n\n  public getSelectedOptions(): Option[] {\n    let options = []\n\n    // Loop through options and set selected\n    const opts = this.select.childNodes as any as (HTMLOptGroupElement | HTMLOptionElement)[]\n    for (const o of opts) {\n      if (o.nodeName === 'OPTGROUP') {\n        const optgroupOptions = o.childNodes as any as HTMLOptionElement[]\n        for (const oo of optgroupOptions) {\n          if (oo.nodeName === 'OPTION') {\n            const option = oo as HTMLOptionElement\n            if (option.selected) {\n              options.push(this.getDataFromOption(option))\n            }\n          }\n        }\n      }\n\n      if (o.nodeName === 'OPTION') {\n        const option = o as HTMLOptionElement\n        if (option.selected) {\n          options.push(this.getDataFromOption(option))\n        }\n      }\n    }\n\n    return options\n  }\n\n  public getSelectedValues(): string[] {\n    return this.getSelectedOptions().map((option) => option.value)\n  }\n\n  public setSelected(ids: string[]): void {\n    // Stop listening to changes\n    this.changeListen(false)\n\n    // Loop through options and set selected\n    const options = this.select.childNodes as any as (HTMLOptGroupElement | HTMLOptionElement)[]\n    for (const o of options) {\n      if (o.nodeName === 'OPTGROUP') {\n        const optgroup = o as HTMLOptGroupElement\n        const optgroupOptions = optgroup.childNodes as any as HTMLOptionElement[]\n        for (const oo of optgroupOptions) {\n          if (oo.nodeName === 'OPTION') {\n            const option = oo as HTMLOptionElement\n            option.selected = ids.includes(option.id)\n          }\n        }\n      }\n\n      if (o.nodeName === 'OPTION') {\n        const option = o as HTMLOptionElement\n        option.selected = ids.includes(option.id)\n      }\n    }\n\n    // Stop listening to changes\n    this.changeListen(true)\n  }\n\n  // Set selected options by value instead of id\n  // This is useful when the id is not known\n  // and only the value is known\n  // but the value is not unique and can be duplicated\n  public setSelectedByValue(values: string[]): void {\n    // Stop listening to changes\n    this.changeListen(false)\n\n    // Loop through options and set selected\n    const options = this.select.childNodes as any as (HTMLOptGroupElement | HTMLOptionElement)[]\n    for (const o of options) {\n      if (o.nodeName === 'OPTGROUP') {\n        const optgroup = o as HTMLOptGroupElement\n        const optgroupOptions = optgroup.childNodes as any as HTMLOptionElement[]\n        for (const oo of optgroupOptions) {\n          if (oo.nodeName === 'OPTION') {\n            const option = oo as HTMLOptionElement\n            option.selected = values.includes(option.value)\n          }\n        }\n      }\n\n      if (o.nodeName === 'OPTION') {\n        const option = o as HTMLOptionElement\n        option.selected = values.includes(option.value)\n      }\n    }\n\n    // Stop listening to changes\n    this.changeListen(true)\n  }\n\n  public updateSelect(id?: string, style?: string, classes?: string[]): void {\n    // Stop listening to changes\n    this.changeListen(false)\n\n    // Update id, only if the id isnt already set\n    if (id) {\n      this.select.dataset.id = id\n    }\n\n    // Update style\n    if (style) {\n      this.select.style.cssText = style\n    }\n\n    // Update classes\n    if (classes) {\n      this.select.className = ''\n      classes.forEach((c) => {\n        if (c.trim() !== '') {\n          this.select.classList.add(c.trim())\n        }\n      })\n    }\n\n    // Start listening to changes\n    this.changeListen(true)\n  }\n\n  public updateOptions(data: (Option | Optgroup)[]): void {\n    // Don't update if data is empty (prevents clearing select when no data)\n    if (!data || data.length === 0) {\n      return\n    }\n\n    // Set updating flag FIRST to prevent mutation observer from processing during update\n    // This must be set before stopping listening so any queued mutations see the flag\n    this.isUpdating = true\n    this.pendingOptionsChange = null\n\n    // Stop listening to changes\n    this.changeListen(false)\n\n    // Clear out select\n    this.select.innerHTML = ''\n\n    for (const d of data) {\n      if (d instanceof Optgroup) {\n        this.select.appendChild(this.createOptgroup(d))\n      }\n\n      if (d instanceof Option) {\n        this.select.appendChild(this.createOption(d))\n      }\n    }\n\n    // Trigger change event on original select\n    this.select.dispatchEvent(new Event('change', { bubbles: true }))\n\n    // Start listening to changes\n    this.changeListen(true)\n\n    // Clear updating flag\n    this.isUpdating = false\n\n    // Process any pending options change that was queued during the update\n    // Only process if it has data (don't process empty data from innerHTML clearing)\n    if (this.pendingOptionsChange !== null) {\n      const pending: (Option | Optgroup)[] = this.pendingOptionsChange\n      if (pending.length > 0 && this.onOptionsChange) {\n        this.pendingOptionsChange = null\n        // Process the queued change\n        this.changeListen(false)\n        this.onOptionsChange(pending)\n        this.changeListen(true)\n      } else {\n        // Clear pending if it was empty\n        this.pendingOptionsChange = null\n      }\n    }\n  }\n\n  public createOptgroup(optgroup: Optgroup): HTMLOptGroupElement {\n    const optgroupEl = document.createElement('optgroup')\n    optgroupEl.id = optgroup.id\n    optgroupEl.label = optgroup.label\n    if (optgroup.selectAll) {\n      optgroupEl.dataset.selectAll = 'true'\n    }\n    if (optgroup.closable !== 'off') {\n      optgroupEl.dataset.closable = optgroup.closable\n    }\n    if (optgroup.options) {\n      for (const option of optgroup.options) {\n        optgroupEl.appendChild(this.createOption(option as Option))\n      }\n    }\n    return optgroupEl\n  }\n\n  public createOption(info: Option): HTMLOptionElement {\n    const optionEl = document.createElement('option')\n    optionEl.id = info.id\n    optionEl.value = info.value\n    optionEl.textContent = info.text\n    if (info.html !== '') {\n      optionEl.setAttribute('data-html', info.html)\n    }\n    optionEl.defaultSelected = info.defaultSelected\n    optionEl.selected = info.selected // Explicitly set selected because defaultSelected: true sets selected to true\n    if (info.disabled) {\n      optionEl.disabled = true\n    }\n    if (!info.display) {\n      optionEl.style.display = 'none'\n    }\n    if (info.placeholder) {\n      optionEl.setAttribute('data-placeholder', 'true')\n    }\n    if (info.mandatory) {\n      optionEl.setAttribute('data-mandatory', 'true')\n    }\n    if (info.class) {\n      info.class.split(' ').forEach((optionClass: string) => {\n        optionEl.classList.add(optionClass)\n      })\n    }\n    if (info.data && typeof info.data === 'object') {\n      Object.keys(info.data).forEach((key) => {\n        optionEl.setAttribute('data-' + kebabCase(key), info.data[key])\n      })\n    }\n\n    return optionEl\n  }\n\n  // Find and handle labels associated with this select\n  public setupLabelHandlers(): void {\n    const labels: HTMLLabelElement[] = []\n\n    // Find labels that point to this select via 'for' attribute\n    const selectId = this.select.id\n    if (selectId) {\n      const labelsByFor = document.querySelectorAll<HTMLLabelElement>(`label[for=\"${selectId}\"]`)\n      labelsByFor.forEach((label) => labels.push(label))\n    }\n\n    // Find labels that wrap this select (label contains select)\n    let parent = this.select.parentElement\n    while (parent && parent !== document.body) {\n      if (parent.tagName === 'LABEL') {\n        labels.push(parent as HTMLLabelElement)\n        break\n      }\n      parent = parent.parentElement\n    }\n\n    // Remove duplicates\n    const uniqueLabels = Array.from(new Set(labels))\n\n    uniqueLabels.forEach((label) => {\n      // Skip if already handled\n      if ((label as any).__slimSelectLabelHandler) {\n        return\n      }\n\n      // Add click handler to label\n      const labelClickHandler = (e: MouseEvent) => {\n        const target = e.target as HTMLElement\n\n        // Check if click is on SlimSelect UI elements (main div or content)\n        const isSlimSelectElement = hasClassInTree(target, this.select.dataset.id!)\n\n        // Prevent default label behavior (focusing the select)\n        // This needs to happen for all clicks on the label or its children\n        // to prevent the browser from focusing the hidden select\n        e.preventDefault()\n        // e.stopPropagation() // dont stop propagation\n\n        // Only trigger the toggle if the click is NOT on SlimSelect elements\n        // This allows clicking label text/children to toggle, while wrapped SlimSelect handles its own clicks\n        if (!isSlimSelectElement && this.onLabelClick) {\n          this.onLabelClick()\n        }\n      }\n\n      // Store the handler on the label for cleanup later\n      ;(label as any).__slimSelectLabelHandler = labelClickHandler\n      label.addEventListener('click', labelClickHandler, { capture: true, passive: false })\n    })\n  }\n\n  // Remove label handlers\n  public removeLabelHandlers(): void {\n    const labels: HTMLLabelElement[] = []\n\n    // Find labels that point to this select via 'for' attribute\n    const selectId = this.select.id\n    if (selectId) {\n      const labelsByFor = document.querySelectorAll<HTMLLabelElement>(`label[for=\"${selectId}\"]`)\n      labelsByFor.forEach((label) => labels.push(label))\n    }\n\n    // Find labels that wrap this select\n    let parent = this.select.parentElement\n    while (parent && parent !== document.body) {\n      if (parent.tagName === 'LABEL') {\n        labels.push(parent as HTMLLabelElement)\n        break\n      }\n      parent = parent.parentElement\n    }\n\n    // Remove duplicates\n    const uniqueLabels = Array.from(new Set(labels))\n\n    uniqueLabels.forEach((label) => {\n      const handler = (label as any).__slimSelectLabelHandler\n      if (handler) {\n        label.removeEventListener('click', handler, { capture: true })\n        delete (label as any).__slimSelectLabelHandler\n      }\n    })\n  }\n\n  public destroy() {\n    this.changeListen(false)\n\n    // Remove event change listener\n    this.select.removeEventListener('change', this.valueChange)\n\n    // Remove event listeners that prevent native select behavior\n    if (this.preventNativeSelect) {\n      this.select.removeEventListener('click', this.preventNativeSelect, { capture: true })\n      this.preventNativeSelect = null\n    }\n    if (this.preventNativeSelectMousedown) {\n      this.select.removeEventListener('mousedown', this.preventNativeSelectMousedown, { capture: true })\n      this.preventNativeSelectMousedown = null\n    }\n    if (this.preventNativeSelectFocus) {\n      this.select.removeEventListener('focus', this.preventNativeSelectFocus, { capture: true })\n      this.preventNativeSelectFocus = null\n    }\n\n    // Disconnect observer and null\n    if (this.observer) {\n      this.observer.disconnect()\n      this.observer = null\n    }\n\n    // Remove label handlers\n    this.removeLabelHandlers()\n\n    // Remove dataset id from original select\n    delete this.select.dataset.id\n\n    // Show the original select\n    this.showUI()\n  }\n}\n","import { generateID } from './helpers'\n\nexport default class Settings {\n  public id: string = '' // Primary ID for the select\n  public style: string = '' // Style attribute from the select element\n  public class: string[] = [] // Class attribute from the select element\n\n  // Dynamic settings\n  public isMultiple: boolean = false\n  public isOpen: boolean = false\n  public isFullOpen: boolean = false\n  public intervalMove: ReturnType<typeof setInterval> | null = null\n\n  // Fields set from constructor\n  public disabled: boolean\n  public alwaysOpen: boolean\n  public showSearch: boolean\n  public focusSearch: boolean\n  public keepSearch: boolean\n  public ariaLabel: string\n  public searchPlaceholder: string\n  public searchText: string\n  public searchingText: string\n  public searchHighlight: boolean\n  public closeOnSelect: boolean\n  public contentLocation: HTMLElement | null\n  public contentPosition: 'relative' | 'absolute' | 'fixed'\n  public contentWidth: string\n  public openPosition: 'auto' | 'up' | 'down'\n  public placeholderText: string\n  public allowDeselect: boolean\n  public hideSelected: boolean\n  public keepOrder: boolean\n  public showOptionTooltips: boolean\n  public minSelected: number\n  public maxSelected: number\n  public timeoutDelay: number\n  public maxValuesShown: number\n  public maxValuesMessage: string\n  public addableText: string\n\n  constructor(settings?: Partial<Settings>) {\n    if (!settings) {\n      settings = {}\n    }\n\n    this.id = 'ss-' + generateID()\n    this.style = settings.style || ''\n    this.class = settings.class || []\n\n    this.disabled = settings.disabled !== undefined ? settings.disabled : false\n    this.alwaysOpen = settings.alwaysOpen !== undefined ? settings.alwaysOpen : false\n    this.showSearch = settings.showSearch !== undefined ? settings.showSearch : true\n    this.focusSearch = settings.focusSearch !== undefined ? settings.focusSearch : true\n    this.keepSearch = settings.keepSearch !== undefined ? settings.keepSearch : false\n    this.ariaLabel = settings.ariaLabel || 'Combobox'\n    this.searchPlaceholder = settings.searchPlaceholder || 'Search...'\n    this.searchText = settings.searchText || 'No Results'\n    this.searchingText = settings.searchingText || 'Searching...'\n    this.searchHighlight = settings.searchHighlight !== undefined ? settings.searchHighlight : false\n    this.closeOnSelect = settings.closeOnSelect !== undefined ? settings.closeOnSelect : true\n    this.contentLocation = settings.contentLocation || document.body\n    this.contentPosition = settings.contentPosition || 'absolute'\n    this.contentWidth = settings.contentWidth || ''\n    this.openPosition = settings.openPosition || 'auto' // options: auto, up, down\n    this.placeholderText = settings.placeholderText !== undefined ? settings.placeholderText : 'Select Value'\n    this.allowDeselect = settings.allowDeselect !== undefined ? settings.allowDeselect : false\n    this.hideSelected = settings.hideSelected !== undefined ? settings.hideSelected : false\n    this.keepOrder = settings.keepOrder !== undefined ? settings.keepOrder : false\n    this.showOptionTooltips = settings.showOptionTooltips !== undefined ? settings.showOptionTooltips : false\n    this.minSelected = settings.minSelected || 0\n    this.maxSelected = settings.maxSelected || 1000\n    this.timeoutDelay = settings.timeoutDelay || 200\n    this.maxValuesShown = settings.maxValuesShown || 20\n    this.maxValuesMessage = settings.maxValuesMessage || '{number} selected'\n    this.addableText = settings.addableText || 'Press \"Enter\" to add {value}'\n  }\n}\n","import CssClasses from './classes'\nimport { debounce, hasClassInTree, isEqual } from './helpers'\nimport Render from './render'\nimport Select from './select'\nimport Settings from './settings'\nimport Store, { Option, Optgroup } from './store'\n\n// Export classes\nexport { Settings, Option, Optgroup }\n\n// Export interfaces from render\nexport type { Main, Content, Search } from './render'\n\nexport interface Config {\n  select: string | Element\n  data?: (Partial<Option> | Partial<Optgroup>)[]\n  settings?: Partial<Settings>\n  cssClasses?: Partial<CssClasses>\n  events?: Events\n}\n\nexport interface Events {\n  search?: (\n    searchValue: string,\n    currentData: (Option | Optgroup)[]\n  ) => Promise<(Partial<Option> | Partial<Optgroup>)[]> | (Partial<Option> | Partial<Optgroup>)[]\n  searchFilter?: (option: Option, search: string) => boolean\n  addable?: (\n    value: string\n  ) => Promise<Partial<Option> | string> | Partial<Option> | string | false | null | undefined | Error\n  beforeChange?: (newVal: Option[], oldVal: Option[]) => boolean | void\n  afterChange?: (newVal: Option[]) => void\n  beforeOpen?: () => void\n  afterOpen?: () => void\n  beforeClose?: () => void\n  afterClose?: () => void\n  error?: (err: Error) => void\n}\n\nexport default class SlimSelect {\n  public selectEl: HTMLSelectElement\n\n  // Classes\n  public settings!: Settings\n  public cssClasses!: CssClasses\n  public select!: Select\n  public store!: Store\n  public render!: Render\n\n  // Timeout tracking for cleanup\n  private openTimeout: ReturnType<typeof setTimeout> | null = null\n  private closeTimeout: ReturnType<typeof setTimeout> | null = null\n\n  // Events\n  public events = {\n    search: undefined,\n    searchFilter: (opt: Option, search: string) => {\n      return opt.text.toLowerCase().indexOf(search.toLowerCase()) !== -1\n    },\n    addable: undefined,\n    beforeChange: undefined,\n    afterChange: undefined,\n    beforeOpen: undefined,\n    afterOpen: undefined,\n    beforeClose: undefined,\n    afterClose: undefined\n  } as Events\n\n  constructor(config: Config) {\n    // Make sure you get the right element\n    this.selectEl = (\n      typeof config.select === 'string' ? document.querySelector(config.select) : config.select\n    ) as HTMLSelectElement\n    if (!this.selectEl) {\n      if (config.events && config.events.error) {\n        config.events.error(new Error('Could not find select element'))\n      }\n      return\n    }\n    if (this.selectEl.tagName !== 'SELECT') {\n      if (config.events && config.events.error) {\n        config.events.error(new Error('Element isnt of type select'))\n      }\n      return\n    }\n\n    // If select already has a slim select id on it lets destroy it first\n    if (this.selectEl.dataset.ssid) {\n      this.destroy()\n    }\n\n    // Set settings\n    this.settings = new Settings(config.settings)\n\n    // Set CSS classes\n    this.cssClasses = new CssClasses(config.cssClasses)\n\n    // Set events\n    const debounceEvents = ['beforeOpen', 'afterOpen', 'beforeClose', 'afterClose']\n    for (const key in config.events) {\n      // Check if key exists in events\n      if (!config.events.hasOwnProperty(key)) {\n        continue\n      }\n\n      // Check if key is in debounceEvents\n      if (debounceEvents.indexOf(key) !== -1) {\n        ;(this.events as { [key: string]: any })[key] = debounce((config.events as { [key: string]: any })[key], 100)\n      } else {\n        ;(this.events as { [key: string]: any })[key] = (config.events as { [key: string]: any })[key]\n      }\n    }\n\n    // Upate settings with type, style and classname\n    this.settings.disabled = config.settings?.disabled ? config.settings.disabled : this.selectEl.disabled\n    this.settings.isMultiple = this.selectEl.multiple\n    this.settings.style = this.selectEl.style.cssText\n    this.settings.class = this.selectEl.className.split(' ')\n\n    // Set select class\n    this.select = new Select(this.selectEl)\n    // Ensure the select has an id for label associations\n    if (!this.selectEl.id) {\n      this.selectEl.id = this.settings.id\n    }\n    this.select.updateSelect(this.settings.id, this.settings.style, this.settings.class)\n    this.select.hideUI() // Hide the original select element\n\n    // Add select listeners\n    this.select.onValueChange = (options: Option[]) => {\n      // Run set selected from the values given\n      this.setSelected(options.map((option) => option.id))\n    }\n    this.select.onClassChange = (classes: string[]) => {\n      // Update settings with new class\n      this.settings.class = classes\n\n      // Run render updateClassStyles\n      this.render.updateClassStyles()\n    }\n    this.select.onDisabledChange = (disabled: boolean) => {\n      if (disabled) {\n        this.disable()\n      } else {\n        this.enable()\n      }\n    }\n    this.select.onOptionsChange = (data: (Option | Optgroup)[]) => {\n      // Process the data (including empty data for clearing all options)\n      // Empty data is safe to process here because if we were updating, the change would be queued\n      // and onOptionsChange wouldn't be called directly\n      this.setData(data || [])\n    }\n    // Set up label click handler to toggle SlimSelect\n    // This allows clicking the label to open/close, matching the main div behavior\n    this.select.onLabelClick = () => {\n      if (!this.settings.disabled) {\n        this.settings.isOpen ? this.close() : this.open()\n      }\n    }\n\n    // Set store class\n    const data = config.data ? config.data : this.select.getData()\n    this.store = new Store(this.settings.isMultiple ? 'multiple' : 'single', data)\n\n    // If data is passed update the original select element\n    if (config.data) {\n      this.select.updateOptions(this.store.getData())\n    }\n\n    // Set render renderCallbacks\n    const renderCallbacks = {\n      open: this.open.bind(this),\n      close: this.close.bind(this),\n      addable: this.events.addable ? this.events.addable : undefined,\n      setSelected: this.setSelected.bind(this),\n      addOption: this.addOption.bind(this),\n      search: this.search.bind(this),\n      beforeChange: this.events.beforeChange,\n      afterChange: this.events.afterChange\n    }\n\n    // Setup render class\n    this.render = new Render(this.settings, this.cssClasses, this.store, renderCallbacks)\n    this.render.renderValues()\n    this.render.renderOptions(this.store.getData())\n\n    // Add aria-label or aria-labelledby if exists\n    const selectAriaLabel = this.selectEl.getAttribute('aria-label')\n    const selectAriaLabelledBy = this.selectEl.getAttribute('aria-labelledby')\n\n    if (selectAriaLabel) {\n      this.render.main.main.setAttribute('aria-label', selectAriaLabel)\n    } else if (selectAriaLabelledBy) {\n      this.render.main.main.setAttribute('aria-labelledby', selectAriaLabelledBy)\n    }\n\n    // Add render after original select element\n    if (this.selectEl.parentNode) {\n      this.selectEl.parentNode.insertBefore(this.render.main.main, this.selectEl.nextSibling)\n    }\n\n    // Add window resize listener to moveContent if window size changes\n    window.addEventListener('resize', this.windowResize, false)\n\n    // If the user wants to show the content forcibly on a specific side,\n    // there is no need to listen for scroll events\n    if (this.settings.openPosition === 'auto') {\n      window.addEventListener('scroll', this.windowScroll, false)\n    }\n\n    // Add window visibility change listener to closeContent if window is hidden\n    document.addEventListener('visibilitychange', this.windowVisibilityChange)\n\n    // If disabled lets call it\n    if (this.settings.disabled) {\n      this.disable()\n    }\n\n    // If alwaysOpnen then open it\n    if (this.settings.alwaysOpen) {\n      this.open()\n    }\n\n    // Set up label handlers to open SlimSelect when label is clicked\n    this.select.setupLabelHandlers()\n\n    // Add SlimSelect to select element\n    ;(this.selectEl as any).slim = this\n  }\n\n  // Set to enabled and remove disabled classes\n  public enable(): void {\n    this.settings.disabled = false\n\n    this.select.enable()\n    this.render.enable()\n  }\n\n  // Set to disabled and add disabled classes\n  public disable(): void {\n    this.settings.disabled = true\n\n    this.select.disable()\n    this.render.disable()\n  }\n\n  public getData(): Option[] | Optgroup[] {\n    return this.store.getData()\n  }\n\n  public setData(data: (Partial<Option> | Partial<Optgroup>)[]): void {\n    // Get original selected values\n    const selected = this.store.getSelected()\n\n    // Validate data\n    const err = this.store.validateDataArray(data)\n    if (err) {\n      if (this.events.error) {\n        this.events.error(err)\n      }\n      return\n    }\n\n    // Update the store\n    this.store.setData(data)\n    const dataClean = this.store.getData()\n\n    // Update original select element\n    this.select.updateOptions(dataClean)\n\n    // Update the render\n    this.render.renderValues()\n    this.render.renderOptions(dataClean)\n\n    // Trigger afterChange event, if it doesnt equal the original selected values\n    if (this.events.afterChange && !isEqual(selected, this.store.getSelected())) {\n      this.events.afterChange(this.store.getSelectedOptions())\n    }\n  }\n\n  public getSelected(): string[] {\n    let options = this.store.getSelectedOptions()\n    if (this.settings.keepOrder) {\n      options = this.store.selectedOrderOptions(options)\n    }\n    return options.map((option) => option.value)\n  }\n\n  // Will take in a string or array of strings and set the selected by either the id or value\n  public setSelected(values: string | string[], runAfterChange = true): void {\n    // Get original selected values\n    const selected = this.store.getSelected()\n    const options = this.store.getDataOptions()\n    values = Array.isArray(values) ? values : [values]\n    const ids = []\n\n    // for back-compatibility support both, set by id and set by value\n    for (const value of values) {\n      if (options.find((option) => option.id == value)) {\n        ids.push(value)\n        continue\n      }\n\n      // if option with given id is not found try to search by value\n      for (const option of options.filter((option) => option.value == value)) {\n        ids.push(option.id)\n      }\n    }\n\n    // Update the store\n    this.store.setSelectedBy('id', ids)\n    const data = this.store.getData()\n\n    // Update the select element\n    this.select.updateOptions(data)\n\n    // Update the render\n    this.render.renderValues()\n\n    // If there is a search input value lets run through the search again\n    // Otherwise we will just render the options from store data\n    if (this.render.content.search.input.value !== '') {\n      this.search(this.render.content.search.input.value)\n    } else {\n      this.render.renderOptions(data)\n    }\n\n    // Trigger afterChange event, if it doesnt equal the original selected values\n    if (runAfterChange && this.events.afterChange && !isEqual(selected, this.store.getSelected())) {\n      this.events.afterChange(this.store.getSelectedOptions())\n    }\n  }\n\n  public addOption(option: Partial<Option>): void {\n    // Get original selected values\n    const selected = this.store.getSelected()\n\n    // Add option to store if it does not already include the option\n    if (!this.store.getDataOptions().some((o) => o.value === (option.value ?? option.text))) {\n      this.store.addOption(option)\n    }\n    const data = this.store.getData()\n\n    // Update the select element\n    this.select.updateOptions(data)\n\n    // Update the render\n    this.render.renderValues()\n    this.render.renderOptions(data)\n\n    // Trigger afterChange event, if it doesnt equal the original selected values\n    if (this.events.afterChange && !isEqual(selected, this.store.getSelected())) {\n      this.events.afterChange(this.store.getSelectedOptions())\n    }\n  }\n\n  public open(): void {\n    // Dont open if disabled\n    // Dont do anything if the content is already open\n    if (this.settings.disabled || this.settings.isOpen) {\n      return\n    }\n\n    // Clear any pending close timeout to prevent race conditions\n    if (this.closeTimeout) {\n      clearTimeout(this.closeTimeout)\n      this.closeTimeout = null\n    }\n\n    // Run beforeOpen callback\n    if (this.events.beforeOpen) {\n      this.events.beforeOpen()\n    }\n\n    // Tell render to open\n    this.render.open()\n\n    // Focus on input field only if search is enabled\n    if (this.settings.showSearch && this.settings.focusSearch) {\n      this.render.searchFocus()\n    }\n\n    this.settings.isOpen = true\n    // setTimeout is for animation completion\n    this.openTimeout = setTimeout(() => {\n      // Run afterOpen callback\n      if (this.events.afterOpen) {\n        this.events.afterOpen()\n      }\n\n      // Update settings\n      // Prevent overide if user close fast without wait full open\n      // For detail see issue https://github.com/brianvoe/slim-select/issues/397\n      if (this.settings.isOpen) {\n        this.settings.isFullOpen = true\n      }\n\n      // Add onclick listener to document to closeContent if clicked outside\n      document.addEventListener('click', this.documentClick)\n    }, this.settings.timeoutDelay)\n\n    // Start an interval to check if main has moved\n    // in order to keep content close to main\n    if (this.settings.contentPosition === 'absolute') {\n      if (this.settings.intervalMove) {\n        clearInterval(this.settings.intervalMove)\n      }\n      this.settings.intervalMove = setInterval(this.render.moveContent.bind(this.render), 500)\n    }\n  }\n\n  public close(eventType: string | null = null): void {\n    // Dont do anything if the content is already closed\n    // Dont do anything if alwaysOpen is true\n    if (!this.settings.isOpen || this.settings.alwaysOpen) {\n      return\n    }\n\n    // Clear any pending open timeout to prevent race conditions\n    if (this.openTimeout) {\n      clearTimeout(this.openTimeout)\n      this.openTimeout = null\n    }\n\n    // Run beforeClose calback\n    if (this.events.beforeClose) {\n      this.events.beforeClose()\n    }\n\n    // Tell render to close\n    this.render.close()\n\n    // Clear search only if not empty and keepSearch is false\n    if (!this.settings.keepSearch && this.render.content.search.input.value !== '') {\n      this.search('') // Clear search\n    }\n\n    // If we arent tabbing focus back on the main element\n    this.render.mainFocus(eventType)\n\n    // Update settings\n    this.settings.isOpen = false\n    this.settings.isFullOpen = false\n\n    // Reset the content below\n    this.closeTimeout = setTimeout(() => {\n      // Run afterClose callback\n      if (this.events.afterClose) {\n        this.events.afterClose()\n      }\n\n      // Add onclick listener to document to closeContent if clicked outside\n      document.removeEventListener('click', this.documentClick)\n    }, this.settings.timeoutDelay)\n\n    if (this.settings.intervalMove) {\n      clearInterval(this.settings.intervalMove)\n    }\n  }\n\n  // Take in string value and search current options\n  public search(value: string): void {\n    // If the passed in value is not the same as the search input value\n    // then lets update the search input value\n    if (this.render.content.search.input.value !== value) {\n      this.render.content.search.input.value = value\n    }\n\n    // If value is empty then render all options\n    if (value === '') {\n      this.render.renderOptions(this.store.getData())\n      return\n    }\n\n    // If no search event run regular search\n    if (!this.events.search) {\n      // If value is empty then render all options\n      const searchResults = value === '' ? this.store.getData() : this.store.search(value, this.events.searchFilter!)\n      this.render.renderOptions(searchResults)\n      return\n    }\n\n    // Search event exists so lets render the searching text\n    this.render.renderSearching()\n\n    // Based upon the search event deal with the response\n    const searchResp = this.events.search(value, this.store.getSelectedOptions())\n\n    // If the search event returns a promise\n    if (searchResp instanceof Promise) {\n      searchResp\n        .then((data: (Partial<Option> | Partial<Optgroup>)[]) => {\n          // Update store data with search results, preserving selected options\n          this.store.setData(data, true)\n\n          // Update original select element\n          this.select.updateOptions(this.store.getData())\n\n          // Render the updated data\n          this.render.renderOptions(this.store.getData())\n        })\n        .catch((err: Error | string) => {\n          // Update the render with error\n          this.render.renderError(typeof err === 'string' ? err : err.message)\n        })\n\n      return\n    } else if (Array.isArray(searchResp)) {\n      // Update store data with search results, preserving selected options\n      this.store.setData(searchResp, true)\n\n      // Update original select element\n      this.select.updateOptions(this.store.getData())\n\n      // Render the updated data\n      this.render.renderOptions(this.store.getData())\n    } else {\n      // Update the render with error\n      this.render.renderError('Search event must return a promise or an array of data')\n    }\n  }\n\n  public destroy(): void {\n    // Clear any pending timeouts\n    if (this.openTimeout) {\n      clearTimeout(this.openTimeout)\n      this.openTimeout = null\n    }\n    if (this.closeTimeout) {\n      clearTimeout(this.closeTimeout)\n      this.closeTimeout = null\n    }\n    if (this.settings.intervalMove) {\n      clearInterval(this.settings.intervalMove)\n      this.settings.intervalMove = null\n    }\n\n    // Remove all event listeners\n    document.removeEventListener('click', this.documentClick)\n    window.removeEventListener('resize', this.windowResize, false)\n    if (this.settings.openPosition === 'auto') {\n      window.removeEventListener('scroll', this.windowScroll, false)\n    }\n    document.removeEventListener('visibilitychange', this.windowVisibilityChange)\n\n    // Delete the store data\n    this.store.setData([])\n\n    // Remove the render\n    this.render.destroy()\n\n    // Show the original select element\n    this.select.destroy()\n  }\n\n  private windowResize: (e: Event) => void = debounce(() => {\n    if (!this.settings.isOpen && !this.settings.isFullOpen) {\n      return\n    }\n\n    this.render.moveContent()\n  })\n\n  // Event listener for window scrolling\n  private windowScroll: (e: Event) => void = debounce(() => {\n    // If the content is not open, there is no need to move it\n    if (!this.settings.isOpen && !this.settings.isFullOpen) {\n      return\n    }\n\n    this.render.moveContent()\n  })\n\n  // Event listener for document click\n  private documentClick: (e: Event) => void = (e: Event) => {\n    // If the content is not open, there is no need to close it\n    if (!this.settings.isOpen) {\n      return\n    }\n\n    // Check if the click was on the content by looking at the parents\n    if (e.target && !hasClassInTree(e.target as HTMLElement, this.settings.id)) {\n      this.close(e.type)\n    }\n  }\n\n  // Event Listener for window visibility change\n  private windowVisibilityChange: (e: Event) => void = () => {\n    if (document.hidden) {\n      this.close()\n    }\n  }\n}\n","function getTrigrams(str: string): string[] {\n  str = ` ${str.replace(/ +/g, \" \").trim().toLowerCase()} `;\n\n  const trigrams: string[] = [];\n  for (let i = 0; i < str.length - 2; ++i) {\n    const trigram = str.substring(i, i + 3);\n    if (trigram[1] === ' ')\n      continue;\n    trigrams.push(trigram);\n  }\n  return trigrams;\n}\n\nexport class TrigramMatcher {\n  private total;\n  private trigram_occ = new Map<string, number>();\n  private l = new Array<{ str: string; trigrams: string[] }>;\n\n  constructor(public strs: string[]) {\n    this.total = strs.length;\n\n    for (const str of strs) {\n      const trigrams = getTrigrams(str);\n      const s = new Set(trigrams);\n      for (const ut of s) {\n        const occ = this.trigram_occ.get(ut) || 0;\n        this.trigram_occ.set(ut, occ + 1);\n      }\n      const v = { str, trigrams };\n      this.l.push(v);\n    }\n  }\n\n  score(str: string) {\n    // for scoring, we ignore end-of-word trigrams, because we assume users don't complete their words\n    const trigrams = getTrigrams(str).filter(s => s[2] !== ' ');\n    const retval: Array<{ str: string; score: number }> = [];\n\n    for (const v of this.l) {\n      let score = 0;\n      for (const t of trigrams) {\n        const i = v.trigrams.indexOf(t);\n        if (i !== -1)\n          score += this.total / (this.trigram_occ.get(t) || 999999);\n      }\n      retval.push({ str: v.str, score });\n    }\n    return retval.toSorted((a, b) => (b.score - a.score)); //highest score first\n  }\n}\n\n/*\nconst prep = prepareMatcher([\n  `csg dingstede`,\n  `landstede`\n]);\n\n//console.log(scoreStuff(prep, 'lamdstede'));\n*/\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n/*\n   https://gitlab.webhare.com/utwente/utwente_base/-/issues/1076\n\n   hyperlinks in forms after the first question but before submission, should open in a new window\n*/\n\nfunction shouldOpenInNewWindow(link) {\n  const page = link.closest(\".wh-form__page\");\n  if (!page)\n    return false;\n  if (page.dataset.whFormPagerole === \"thankyou\")\n    return false; //this is the conclusion, stay on page\n  if (page.parentNode.querySelectorAll(\".wh-form__page\")[0] !== page)\n    return true; //we are not the first page, so open in new window!\n\n  //we are on the first page... is there any question before our text ?\n  const ourtextnode = link.closest(\".wh-form__fieldgroup\");\n  if (!ourtextnode)\n    return false; //confused about where this link came from\n\n  for (let node = ourtextnode; node; node = node.previousElementSibling) {\n    //is this a fieldgroup but not RTE/grouphader?\n    if (node.classList.contains(\"wh-form__fieldgroup\")\n      && !node.classList.contains(\"wh-form__fieldgroup--richtext\")\n      && !node.classList.contains(\"wh-form__fieldgroup--group\"))\n      return true; //then we're after a question.. so new window is a go!\n  }\n\n  return false;\n}\nfunction checkNewWindowLink(link) {\n  if (shouldOpenInNewWindow(link))\n    link.target = \"_blank\";\n}\n\ndompack.register(\"form.wh-form a[href]\", checkNewWindowLink);\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport * as $wh from \"@mod-system/js/wh/integration\";\n\n\nlet colorschemeNode;\nlet animDelay = 0; // delay used on first animation (to sync with previous visited page)\nlet animFirstActivated;\n\nconst animDuration = $wh.config.site.colorscheme.length * 10;\n\n\n// Sync animations upon starting\nwindow.addEventListener(\"animationstart\", onAnimationStart);\n\n\nfunction onAnimationStart(evt) {\n  //console.log(evt.target, evt.animationName);\n\n  if ([\n    \"colorscheme-background\",\n    \"colorscheme-color\",\n    \"colorscheme-fill\",\n    \"colorscheme-color-border\",\n    \"colorscheme-cta-color\",\n    \"colorscheme-cta-background\",\n    \"colorscheme-cta-hover-background\",\n    \"colorscheme-cta-hover-color\",\n    \"colorscheme-cta-hover-color-border\"\n  ].indexOf(evt.animationName) == -1)\n    return;\n\n  //console.log(\"Anim timestamp\", evt.timeStamp);\n  //console.log(\"Current expected\", getExpectedAnimTime());\n\n  //setAnimation(evt.target, evt.animationName);\n  setAnimationDelay(evt.target, evt.animationName);\n}\n\n\n\nfunction getExpectedAnimTime() {\n  let totalDelay;\n  if (!animFirstActivated) {\n    animFirstActivated = new Date().getTime();\n    totalDelay = animDelay * 1000;\n  } else {\n    const timediff = new Date().getTime() - animFirstActivated;\n    totalDelay = (animDelay * 1000) - timediff;\n  }\n  return totalDelay;\n}\n\n\nexport function setAnimation(node, name) {\n  const style = getAnimationStyle(name);\n  //console.log(\"setAnimation\", node.className, totalDelay, style);\n  node.style.animation = style;\n  //node.style.outline = \"1px solid #F00\";\n}\n\nfunction getAnimationStyle(name) {\n  const totalDelay = getExpectedAnimTime() % (animDuration * 1000);\n\n  const playState = dompack.debugflags.unc ? \"paused\" : \"\";\n\n  return `${name} ${animDuration}s steps(${animDuration * 2}, end) ${totalDelay}ms infinite ${playState}`;\n}\n\n\nfunction setAnimationDelay(node, name) {\n  const totalDelay = getExpectedAnimTime() % (animDuration * 1000);\n\n  const style = `${totalDelay}ms`;\n  //console.log(\"setAnimationDelay\", node.className, totalDelay, style);\n\n  node.style.animationDelay = style;\n  node.style.animationDuration = animDuration + \"s\";\n}\n\n\n\ndompack.register(\".docstate\", node => {\n  if (colorschemeNode) // prevent double initialization\n    return;\n\n  if (localStorage[\"ucs-start\"]) {\n    let saveStart = parseInt(localStorage[\"ucs-start\"], 10);\n    if (!isNaN(saveStart)) {\n      saveStart = (Date.now() - saveStart) % (animDuration * 1000);\n      if (saveStart > 0)\n        animDelay = -Math.floor(saveStart / 1000);\n    }\n  } else {\n    localStorage[\"ucs-start\"] = Date.now();\n  }\n\n  colorschemeNode = node;\n\n  if ($wh.config.site.animatethemecolor && $wh.config.site.colorscheme.length > 1) {\n    document.documentElement.classList.add(\"animatedcolorscheme\");\n\n    setAnimation(colorschemeNode, \"colorscheme-background\");\n\n    const bg_targets =\n      [\n        \".themecolor--bg\",\n        \".docstate\"\n      ];\n\n    const fg_targets =\n      [\n        \".themecolor--fg\",\n        \".inlinecta__icon\",\n        \".rtdinset__icon\"\n      ];\n\n    const fgbr_targets =\n      [\".themecolor--fg.themecolor--br\"];\n\n    const bg_cta_targets =\n      [\n        \".cta--transparent\", // CTA in the header top-right (currently only on toplevelhome but also other headers in the future)\n        \".cta-themecolor--bg\"\n      ];\n\n    const fgbr_cta_targets =\n      [\".cta-themecolor--fg.cta-themecolor--br\"];\n\n    // These will get a CTA color or background animation\n    const buttons =\n      [\n        \".wh-form__button:not(.wh-form__button--previous)\",\n        \".cta__button\",       // Header CTA\n        \".inlinecta__button\"\n      ];\n\n    dompack.register(bg_targets.join(\",\"), node => setAnimation(node, \"colorscheme-background\"));\n    dompack.register(fg_targets.join(\",\"), node => setAnimation(node, \"colorscheme-color\"));\n    dompack.register(fgbr_targets.join(\",\"), node => setAnimation(node, \"colorscheme-color-border\"));\n    dompack.register(buttons.join(\",\"), node => setButtonAnimation(node));\n    dompack.register(bg_cta_targets.join(\",\"), node => setAnimation(node, \"colorscheme-cta-background\"));\n    dompack.register(fgbr_cta_targets.join(\",\"), node => setAnimation(node, \"colorscheme-cta-color-border\"));\n\n    // Search result highlights are styled through a ::before pseudo-element, which cannot be styled directly, so we'll add\n    // a style block to animate the background color\n    const searchhighlights =\n      [\".ut-querymatch\"];\n    document.head.appendChild(\n      <style>\n        {\n          searchhighlights.join(`::before\n        {\n          animation: ${getAnimationStyle(\"colorscheme-background\")};\n        })`) + `::before\n        {\n          animation: ${getAnimationStyle(\"colorscheme-background\")};\n        }`\n        }\n      </style>\n    );\n  }\n});\n\n\nfunction setButtonAnimation(node) {\n  const cta_header = node.closest(\".cta--transparent\");\n  if (cta_header)\n    setAnimation(node, \"colorscheme-cta-color\");\n  else\n    setAnimation(node, \"colorscheme-cta-background\");\n}\n\n// Make sure all replaced and dynamically added buttons recieve their animations\nwindow.addEventListener(\"load\", evt => dompack.registerMissed(document.body));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\nfunction handleNewWindow(event) {\n  event.preventDefault();\n  const size = this.getAttribute(\"data-windowopen\").split(\",\");\n  window.open(this.href, \"\", `width=${size[0]},height=${size[1]},scrollbars=yes`);\n}\n\ndompack.register(\"[data-windowopen]\", link => {\n  link.addEventListener(\"click\", handleNewWindow.bind(link));\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport * as $wh from \"@mod-system/js/wh/integration\";\nimport * as coloranim from \"../theme/colorschemeanimation\";\nimport promiseXMLHttpRequest from \"../components/promisexmlhttprequest\";\nimport SlideShow from \"../shared/slideshow\";\n\n//import \"./header_sync-alignment\";\nimport \"./header.scss\";\nimport \"./header_cta\";\nimport \"./header_cta.scss\";\nimport \"./header_overlay.scss\";\nimport \"./header_stickyctabar\";\nimport \"./header_ctabelow.scss\";\n\nlet univActive = false, univElement = null;\nconst svgHeaders = [];\nlet colorschemeNode;\nlet syncPathColor = false;\n\nconst animDelay = 0; // delay used on first animation (to sync with previous visited page)\nconst animDuration = $wh.config.site.colorscheme.length * 10;\nlet headeranimation_paused = false; // carrousel and slideshow will perform badly (understatement) if they can't pause the header animation\n\n\n// Don't show the universe header if the 'unh' debug flag is set, or if this page is displayed within an iframe\n//ADDME: Disable header for specific browser/platform combinations (e.g. Firefox on Android)?\nconst activateHeader = !dompack.debugflags.unh\n  && !document.documentElement.classList.contains(\"ws2016--iframed\");\n\n\n\n\n\n/** @short load the element (animated vector graphics in the background)\n*/\nasync function loadElement(containerNode) {\n  // Get the element to load\n  let element = containerNode.getAttribute(\"data-element\");\n  if (element == \"-none-\") {\n    return false; // No element\n  } else {\n    if (element) {\n      // An certain element is specified\n      const elements = $wh.config.site.universeelements.filter(el => el.filename == element);\n      element = elements.length ? elements[0] : null;\n    }\n    if (!element) {\n      // Use a random element, but not the one shown previously\n      const prevElement = localStorage[\"ucs-element\"] || \"\";\n      const elements = $wh.config.site.universeelements.filter(el => el.filename != prevElement);\n      if (elements.length) {\n        element = elements[Math.floor(Math.random() * elements.length)];\n      }\n    }\n  }\n  if (element) {\n    // Store the current element, so it's not shown again next time\n    localStorage[\"ucs-element\"] = element.filename;\n\n    // If the animation color is not applied to the path element (i.e. this is IE11), we have to sync the color manually\n    syncPathColor = await new Promise(resolve => {\n      // Create a temporary SVG with a path\n      const tmpSvg = document.createElement(\"svg\");\n      const tmpPath = document.createElement(\"path\");\n      coloranim.setAnimation(tmpSvg, \"colorscheme-fill\");\n      tmpSvg.appendChild(tmpPath);\n      document.body.appendChild(tmpSvg);\n      // Give the animation a chance to be applied\n      setTimeout(() => {\n        requestAnimationFrame(() => {\n          // Check the path's fill color, it should not be black\n          const pathColor = getComputedStyle(tmpPath).fill;\n          //console.log(pathColor);\n          document.body.removeChild(tmpSvg);\n          resolve(pathColor == \"black\" || pathColor == \"rgb(0, 0, 0)\");\n        });\n      }, 1);\n    });\n\n    // Load the SVG document\n    const svgDoc = await promiseXMLHttpRequest($wh.config.imgroot + \"elements/\" + element.filename, { responseType: \"xml\" });\n    if (svgDoc) {\n      // Remove the custom 'style' block\n      for (const styleNode of Array.from(svgDoc.getElementsByTagName(\"style\")))\n        styleNode.parentNode.removeChild(styleNode);\n      // Store the <svg> node, so it can be imported into the document\n      element.svg = svgDoc.documentElement;\n      return element;\n    } else\n      return false; // Element unavailable\n  }\n  return false; // No element to show\n}\n\n\nfunction pauseHeaderAnimation() {\n  //console.log(\"pauseHeaderAnimation\");\n  headeranimation_paused = true;\n  if (!dompack.debugflags.unc)\n    svgHeaders.forEach(nodes => {\n      nodes.colorPathNode.style[\"animationPlayState\"] = \"paused\";\n    });\n}\n\nfunction unPauseHeaderAnimation() {\n  //console.log(\"unPauseHeaderAnimation\");\n  headeranimation_paused = false;\n  if (!dompack.debugflags.unc)\n    svgHeaders.forEach(nodes => {\n      nodes.colorPathNode.style.animationPlayState = \"\";\n    });\n}\nwindow.pauseHeaderAnimation = pauseHeaderAnimation;\nwindow.unPauseHeaderAnimation = unPauseHeaderAnimation;\n\n\n\nfunction onRotate(event, node) {\n  if (dompack.debugflags.unr)\n    return;\n  if (event && event.currentTarget != event.target)\n    return;\n  if (event)\n    node = event.target;\n\n  // Just toggle the class to reverse the transition\n  node.classList.toggle(\"header__universe-container--rotate\");\n}\n\nfunction syncColor() {\n  if (!colorschemeNode)\n    colorschemeNode = document.body.querySelector(\".docstate\");\n\n  if (!headeranimation_paused && colorschemeNode)\n    svgHeaders.forEach(nodes => {\n      nodes.colorPathNode.style.fill = getComputedStyle(colorschemeNode).backgroundColor;\n    });\n}\n\n\n\n\n\nif (activateHeader) {\n  // If this page has a universe header or contains a widgetsblock, initialize the universe container\n  dompack.register(\".header__universe, .widgetsblock\", function () {\n    if (!univActive) {\n      univActive = true;\n    }\n  });\n}\n\ndompack.register(\".header__universe-container\", async function (containerNode) {\n  if (!univActive)\n    return;\n\n  const initializing = univElement === null; // null: uninitialized, false: no element to show\n  if (initializing)\n    univElement = await loadElement(containerNode);\n\n  if (univElement) {\n    // Insert the SVG into the container\n    const svgNode = document.importNode(univElement.svg, true);\n    containerNode.insertBefore(svgNode, containerNode.firstChild);\n\n    const colorPathNode = svgNode.querySelector(\".header__universe-color\");\n    svgHeaders.push({ containerNode, svgNode, colorPathNode });\n\n    if (univElement.reverse)\n      containerNode.classList.add(\"header__universe-container--counterclockwise\");\n    else\n      containerNode.classList.add(\"header__universe-container--clockwise\");\n    containerNode.addEventListener(\"transitionend\", onRotate);\n\n    if (univElement.width)\n      svgNode.style.width = `${univElement.width}px`;\n    if (univElement.top)\n      svgNode.style.marginTop = `${univElement.top}px`;\n    //svgNode.style.backfaceVisibility = \"hidden\"; // to speed up when using translate3D\n\n    // Force a style recompute after the SVG was inserted, so the transition will work properly\n    svgNode._wsTmpTransform = getComputedStyle(svgNode).transform;\n\n    svgNode.style.marginLeft = `${Math.round(-svgNode.clientWidth / 2) + (univElement.left || 0)}px`;\n\n    if (!syncPathColor && $wh.config.site.animatethemecolor)\n      coloranim.setAnimation(colorPathNode, \"colorscheme-fill\");\n\n    onRotate(null, containerNode);\n  }\n\n  if (initializing) {\n    // Check if the element's path fill should be animated manually\n    if (univElement && syncPathColor) {\n      if ($wh.config.site.animatethemecolor) {\n        console.warn(\"Fallback for svg path animation active\");\n        setInterval(syncColor, 500); // Sync scheme color every .5 seconds\n        syncColor();\n      }\n    }\n  }\n});\n\ndompack.register(\".header\", node => {\n  // Initialize the header photo slideshow\n  new SlideShow(node.querySelectorAll(\".header__slide\"), {\n    dotNodes: node.querySelectorAll(\".header__sliderdot\"),\n    pauseNode: node\n  });\n\n  window.addEventListener(\"scroll\", () => {\n    if (window.pageYOffset > 0)\n      document.documentElement.classList.add(\"html__scrolled\");\n    else\n      document.documentElement.classList.remove(\"html__scrolled\");\n  });\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nconst globalRequest = new XMLHttpRequest();\n\nexport default function promiseXMLHttpRequest(url, options) {\n  // responseType \"xml\" is non-standard, but is used here to return responseXML when the promise resolves\n  options = {\n    timeout: 0,\n    responseType: \"text\", // \"arraybuffer\", \"blob\", \"document\", \"json\", \"text\", or \"xml\"\n    reuseRequest: true,\n    method: \"GET\", // request method, usually \"GET\" or \"POST\"\n    requestHeaders: [], // { header, value }\n    data: null, // data to send with the request\n    ...options\n  };\n\n  return new Promise((resolve, reject) => {\n    let request;\n    if (options.reuseRequest) {\n      // Use the global request object\n      request = globalRequest;\n\n      // If the request is active, abort the current request\n      if (request.readyState !== XMLHttpRequest.UNSENT && request.readyState !== XMLHttpRequest.DONE) {\n        request.abort();\n        if (request._reject)\n          request._reject(Error(\"abort\")); // Reject with status 0 to signal abort\n      }\n    } else {\n      // Create a new request object\n      request = new XMLHttpRequest();\n    }\n\n    // Store the reject handler, so it can be called when the request is aborted\n    request._reject = reject;\n\n    // Set the ready state change handler\n    request.onreadystatechange = () => {\n      // Check if the request is complete\n      if (request.readyState !== XMLHttpRequest.DONE)\n        return;\n\n      // Check the request status\n      if (request.status !== 200) {\n        // Status is 0 for both abort and timeout, both of which are rejected elsewhere\n        if (request.status)\n          reject(Error(`status:${request.status}`));\n        return;\n      }\n\n      // Return the response\n      resolve(options.responseType === \"xml\" ? request.responseXML : request.response);\n    };\n\n    // Set the timeout handler\n    request.ontimeout = () => {\n      reject(Error(\"status:408\"));\n    };\n\n    // Perform the request\n    request.open(options.method, url, true);\n    request.timeout = options.timeout;\n    request.responseType = options.responseType === \"xml\" ? \"\" : options.responseType;\n    for (const header of options.requestHeaders)\n      request.setRequestHeader(header.header, header.value);\n    if (options.data)\n      request.send(options.data);\n    else\n      request.send();\n  });\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport utwenteCookies from \"@mod-utwente_design/js/cookiebar\";\nimport * as dompack from \"dompack\";\nimport * as videotools from \"../components/video\";\nimport SwipeDetect from \"../components/swipedetect\";\n\n\nexport default class SlideShow {\n  constructor(nodes, options) {\n    this.nodes = [];\n    this.players = [];\n    this.dotNodes = [];\n    this.curSlide = -1;\n\n    this.options = {\n      timeout: 5000,\n      dotNodes: null,\n      pauseNode: null,\n      enableswipe: true, ...options\n    };\n\n    // Make a list of nodes\n    for (const node of nodes) {\n      node.addEventListener(\"transitionend\", this.onSlide.bind(this));\n      if (this.nodes.length) {\n        // Set z-index of slides not currently visible to 0\n        node.classList.add(\"slideshow--slidein\");\n        node.style.zIndex = 0; // Not visible\n      } else {\n        this.containerNode = node.parentNode;\n        this.containerNode.style.zIndex = 0; // Reset z-index\n        node.style.zIndex = 2; // Currently visible\n      }\n      this.nodes.push(node);\n      // Set visibility to visible (slides are hidden initially)\n      node.style.display = \"block\";\n    }\n\n    // No need to slide\n    if (!this.nodes.length)\n      return;\n    if (this.nodes.length === 1) {\n      // There is one slide, maybe it contains a video?\n      const node = this.nodes[0];\n      if (node.hasAttribute(\"data-video\"))\n        this.initializeVideoSlide(node, 0, false);\n      return;\n    }\n\n    if (this.containerNode && this.options.enableswipe) {\n      new SwipeDetect(this.containerNode);\n      this.containerNode.addEventListener('wh:swipe', function (ev) {\n        if (ev.detail.direction === 'w') {\n          const nextSlide = this.curSlide + 1;\n          this.nextNode(nextSlide >= this.nodes.length ? 0 : nextSlide, false);\n        } else if (ev.detail.direction === 'e') {\n          const nextSlide = this.curSlide - 1;\n          this.nextNode(nextSlide < 0 ? this.nodes.length - 1 : nextSlide, true);\n        }\n      }.bind(this));\n    }\n\n    // Pause on hover, if requested\n    if (this.options.pauseNode) {\n      this.options.pauseNode.addEventListener(\"mouseover\", this.pause.bind(this));\n      this.options.pauseNode.addEventListener(\"mouseout\", this.play.bind(this));\n    }\n\n    // Make a list of dots\n    if (this.options.dotNodes)\n      Array.from(this.options.dotNodes).forEach((dot, idx) => {\n        this.dotNodes.push(dot);\n        dot.addEventListener(\"click\", event => {\n          this.nextNode(idx);\n          // If the slideshow was stopped, resume it\n          this.resume();\n        });\n      });\n\n    // Show the first slide\n    this.nextNode();\n  }\n\n  nextNode(nextindex, moveleft) {\n    // Show the next slide after 'timeout' ms\n    clearTimeout(this.nextTimeout);\n    if (!this.paused)\n      this.nextTimeout = setTimeout(this.nextNode.bind(this), this.options.timeout);\n\n    // Run the actual animation within an animation frame, so the animation only continues if the browser is actually showing\n    // the animation\n    if (this.slideTimeout)\n      cancelAnimationFrame(this.slideTimeout);\n    this.slideTimeout = requestAnimationFrame(() => {\n      if (typeof nextindex !== 'undefined') {\n        if (nextindex === this.curSlide)\n          return;\n\n        this.nextSlide = nextindex;\n\n        if (this.prevNode && this.prevNode.classList.contains(\"slideshow--slideout\")) {\n          this.prevNode.style.zIndex = 0; // Not visible\n          this.prevNode.classList.remove(\"slideshow--slideout\");\n          this.prevNode.classList.add(\"slideshow--slidein\");\n        }\n      }\n\n      // Keep a reference to the previous slide\n      this.prevNode = this.curSlide < 0 ? null : this.nodes[this.curSlide];\n\n      // Select the next slide\n      this.containerNode.classList.remove(\"slideshow--slideleft\");\n      if (typeof this.nextSlide !== 'undefined' && this.nextSlide !== null) {\n        if (this.nextSlide < this.curSlide && typeof moveleft !== 'boolean' || moveleft)\n          this.containerNode.classList.add(\"slideshow--slideleft\");\n\n        this.curSlide = this.nextSlide;\n        this.nextSlide = null;\n      } else\n        ++this.curSlide;\n\n      if (this.curSlide >= this.nodes.length)\n        this.curSlide = 0;\n      const curNode = this.nodes[this.curSlide];\n\n      if (curNode.hasAttribute(\"data-video\")) {\n        curNode.addEventListener(\"click\", event => this.initializeVideoSlide(curNode, this.curSlide, true));\n      }\n\n      this.slideTimeout = null;\n\n      // If there is a previous slide, insert the new slide and start the transition\n      if (this.prevNode) {\n        // Update z-index of current and next slide\n        this.prevNode.style.zIndex = 1; // About to slide out\n        curNode.style.zIndex = 2; // About to slide in\n        // Start the transition\n        this.prevNode.classList.add(\"slideshow--slideout\");\n        curNode.classList.remove(\"slideshow--slidein\");\n      }\n\n      // Update the active slider dot\n      this.dotNodes.forEach((dot, idx) => {\n        // Cannot use classList.toggle with second parameter as it's not supported by IE11\n        if (idx === this.curSlide)\n          dot.classList.add(\"slideshow--activedot\");\n        else\n          dot.classList.remove(\"slideshow--activedot\");\n      });\n\n      dompack.dispatchCustomEvent(window, \"ws:nextslide\", {\n        bubbles: true,\n        cancelable: false,\n        detail: {\n          target: this,\n          idx: this.curSlide\n        }\n      });\n    });\n  }\n\n  initializeVideoSlide(node, idx, startplay) {\n    if (!utwenteCookies.getConsent())\n      return;\n\n    if (!videotools.isVideoNodeInitialized(node)) {\n      videotools.initializeVideoNode(node).then(player => {\n        this.players[idx] = player;\n\n        // Hide poster image and play button\n        node.classList.remove(\"widget__photoslide--poster\");\n\n        // Stop the slideshow when the video starts playing\n        node.addEventListener(\"video:play\", event => this.stop());\n        // Show the slider dots when the video is paused (they're hidden again\n        // when the video resumes which triggers a video:play event)\n        node.addEventListener(\"video:pause\", event => this.toggleDotNodes(true));\n        // If the video has finished playing, resume the slideshow\n        node.addEventListener(\"video:finish\", event => this.resume());\n\n        // If the player is ready, start it\n        if (startplay)\n          node.addEventListener(\"video:ready\", event => player.play());\n      });\n    } else if (this.players[idx]) {\n      // Hide poster image and play button\n      node.classList.remove(\"widget__photoslide--poster\");\n\n      // Resume/replay the video\n      this.players[idx].play();\n    }\n  }\n\n  // Pause the slideshow on hover\n  pause() {\n    this.paused = true;\n    if (this.nextTimeout) {\n      clearTimeout(this.nextTimeout);\n      this.nextTimeout = null;\n      this.dotNodes.forEach((dot, idx) => {\n        if (idx === this.curSlide)\n          dot.classList.add(\"slideshow--paused\");\n      });\n    }\n  }\n\n  // Play the slideshow again after mouseout, unless it's stopped\n  play() {\n    if (this.stopped)\n      return;\n\n    this.paused = false;\n    if (!this.nextTimeout) {\n      this.nextTimeout = setTimeout(this.nextNode.bind(this), this.options.timeout / 2);\n    }\n    this.dotNodes.forEach(dot => dot.classList.remove(\"slideshow--paused\"));\n  }\n\n  // Stop the slideshow until it's resumed\n  stop() {\n    this.pause();\n    this.stopped = true;\n    this.toggleDotNodes(false);\n  }\n\n  // Start playing the slideshow again\n  resume() {\n    this.stopped = false;\n    this.toggleDotNodes(true);\n    for (const node of this.nodes)\n      node.classList.add(\"widget__photoslide--poster\");\n    this.play();\n  }\n\n  toggleDotNodes(show) {\n    this.dotNodes.forEach(dot => dot.style.display = show ? \"\" : \"none\");\n  }\n\n  onSlide(event) {\n    // Check if this is the slide that is no longer active\n    if (event.target === event.currentTarget\n      && event.target.classList.contains(\"slideshow--slideout\")) {\n      // Reset z-index and classes\n      event.target.style.zIndex = 0; // Not visible\n      event.target.classList.remove(\"slideshow--slideout\");\n      event.target.classList.add(\"slideshow--slidein\");\n    }\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\nconst videoNodeInitialized = Symbol();\nconst vimeoFrameLoaded = Symbol();\n\nconst default_video_playback =\n{\n  autoplay: false,\n  muted: false, // don't play audio by default (to enable autostart on iOS 10+, currently only supported for videofile)\n  controls: true,  // use the controls the video networks provide\n  loop: false, // only supported in Vimeo\n  poster: \"\"    // poster image, currently only supported for videofile\n};\n\n/** @short generate a video player to play the specified video with the specified settings\n    @cell video\n    @cell video.network 'youtube', 'vimeo', 'youku', 'videofile' (experimental)\n    @cell video.id\n    @cell playback\n    @cell playback.autoplay\n    @cell playback.api make sure we can interact with the video (FIXME: current always done on YouTube)\n    @cell playback.muted\n    @cell playback.start\n    @cell playback.end\n    @cell playback.controls\n    @cell playback.loop\n    @cell playback.background (Vimeo play video in background. This hides controls but this activates: loop, mute, autoplay)\n*/\nfunction generateVideoNode(video, playback) {\n  const mergedoptions = Object.assign(default_video_playback, playback); // make a clone, so we don't edit the original options object\n  playback = Object.assign(mergedoptions, playback);\n\n  let playernode;\n  const args = [];\n\n  switch (video.network) {\n    case \"youtube\":\n\n      // https://developers.google.com/youtube/player_parameters\n      args.push(\"autoplay=\" + (playback.autoplay ? \"1\" : \"0\"));\n\n      if (video.starttime)\n        args.push(\"start=\" + Math.floor(video.starttime)); // seconds, whole integer (YouTube also uses t= in the shorturl??)\n\n      if (video.endtime)\n        args.push(\"end=\" + Math.floor(video.endtime));\n\n      if (!playback.controls)\n        args.push(\"controls=0\");\n\n      if (playback.loop) {\n        args.push(\"loop=1\");\n        args.push(\"playlist=\" + video.id); // not sure if required in HTML5 player or only in AS3 player\n      }\n\n      args.push(\"rel=0\"); // disable 'related video's'\n\n      args.push(\"enablejsapi=1\");\n      args.push(\"origin=\" + location.protocol + \"//\" + location.hostname);\n\n      //args.push(\"showinfo=0\"); // deprecated\n\n      // Try to hide some stuff (not much is possible anymore)\n      args.push(\"iv_load_policy=3\"); // don't show video annotations\n      args.push(\"modestbranding=1\");\n\n      // ADDME: playsinline parameter for inline or fullscreen playback on iOS\n      /*\n      YouTube\n\n      - hl=(languagecode ISO 639-1 or fully specifiedlocale such as fr-ca)\n\n      -   start=\n        & end=\n        & controls=0\n        & modestbranding=0\n        & rel=0  (don't show related videos from outside the channel)\n      */\n\n      let youtube_url = \"//www.youtube.com/embed/\" + video.id;\n      if (args.length > 0)\n        youtube_url += \"?\" + args.join(\"&\");\n\n      playernode = __getPlayerFrame();\n      playernode.src = youtube_url;\n      return playback.api ? getYouTubePlayer(playernode) : getStaticVideoPlayer(playernode);\n\n    case \"vimeo\":\n\n      // http://developer.vimeo.com/player/embedding\n      args.push(\"autoplay=\" + (playback.autoplay ? \"1\" : \"0\"));\n\n      if (video.endtime)\n        console.warn(\"setting an endtime doesn't work for Vimeo video's\");\n\n      if (!playback.controls)\n        console.warn(\"disabling video controls not possible for Vimeo video's\");\n\n      if (playback.loop)\n        args.push(\"loop=1\");\n\n      if (playback.background)\n        args.push(\"background=1\");\n\n      let vimeo_url = \"//player.vimeo.com/video/\" + video.id;\n      if (args.length > 0)\n        vimeo_url += \"?\" + args.join(\"&\");\n\n      if (video.starttime) {\n        // #t=3m28s\n        const t = video.starttime;\n        const minutes = Math.floor(t / 60);\n        const seconds = t % 60;\n        vimeo_url += \"#t=\" + minutes + \"m\" + seconds + \"s\";\n      }\n\n\n      // title=0 - hides the title\n\n      playernode = __getPlayerFrame();\n\n      // Set vimeoFrameLoaded to true on load (detect if the iframe contents is loaded before the vimeo player script is)\n      playernode[vimeoFrameLoaded] = false;\n      playernode.addEventListener(\"load\", event => playernode[vimeoFrameLoaded] = true);\n\n      playernode.src = vimeo_url;\n      return playback.api ? getVimeoPlayer(playernode) : getStaticVideoPlayer(playernode);\n\n\n\n    case \"yuja\":\n      {\n        // Convert the parameters into a full playback URL\n        const params = new URL(\"https://www.example.org/?\" + video.id).searchParams;\n        const host = params.get(\"h\");\n        const videoid = params.get(\"v\");\n        const authorizationkey = params.get(\"a\");\n        // let playback_url = `//{host}/V/Video?v={videoid}&a={authorizationkey}`;\n        let playback_url = `//${host}/V/Video`;\n\n        args.push(\"v=\" + encodeURIComponent(videoid));\n        args.push(\"a=\" + encodeURIComponent(authorizationkey));\n\n\n        /*\n        // https://support.yuja.com/hc/en-us/articles/360051850373-Enabling-Auto-Start-for-a-Video-s-Direct-Link-Embed-Code\n        // FIXME: for now we disabled this, because it'll start playback muted ... which will confuse users\n        if (playback.autoplay)\n          args.push(\"autostart=1\");\n          // args.push(\"isPlaying=true\");\n        */\n\n        if (playback.starttime)\n          args.push(\"starttime=\" + playback.starttime);\n\n        if (playback.endtime)\n          console.warn(\"setting an endtime doesn't work for Yuja video's\");\n\n        if (!playback.controls)\n          console.warn(\"disabling video controls not possible for Yuja video's\");\n\n        if (playback.loop)\n          console.warn(\"loop isn't supported for Yuja video's\");\n\n        if (args.length > 0)\n          playback_url += \"?\" + args.join(\"&\");\n\n        playernode = __getPlayerFrame();\n        playernode.src = playback_url;\n        // return playback.api ? getYouTubePlayer(playernode) : getStaticVideoPlayer(playernode);\n        return getYujaPlayer(playernode);\n\n        break;\n      }\n\n    case \"videofile\":\n      playernode = document.createElement(\"video\");\n      playernode.loop = Boolean(playback.loop);\n      playernode.controls = Boolean(playback.controls);\n      playernode.muted = Boolean(playback.muted);\n      if (playback.poster)\n        playernode.poster = playback.poster;\n      playernode.style.width = \"100%\";\n      playernode.style.height = \"100%\";\n      playernode.src = video.id;\n      return playback.api ? getHtml5Player(playernode) : getStaticVideoPlayer(playernode);\n\n    default:\n      console.error(\"Unknown video type\");\n      break;\n  }\n\n  return playernode;\n}\n\nfunction __getPlayerFrame() {\n  const ifrm = document.createElement(\"iframe\");\n  ifrm.style.width = \"100%\";\n  ifrm.style.height = \"100%\";\n  ifrm.frameBorder = 0;\n  ifrm.allowFullscreen = true;\n  ifrm.setAttribute(\"allow\", \"autoplay\"); // new in 2018, see https://developers.google.com/web/updates/2017/09/autoplay-policy-changes\n  return ifrm;\n}\n\nfunction isVideoNodeInitialized(node) {\n  return Boolean(node[videoNodeInitialized]);\n}\n\n// Returns a Promise that resolves with a VideoPlayer object\nfunction initializeVideoNode(node, options) {\n  if (node[videoNodeInitialized])\n    return;\n\n  node.innerHTML = \"\";\n  node[videoNodeInitialized] = true;\n\n  const video = JSON.parse(node.getAttribute(\"data-video\"));\n  let opts = node.hasAttribute(\"data-video-options\") ? JSON.parse(node.getAttribute(\"data-video-options\")) : {};\n  opts = Object.assign(opts, options);\n\n  return new Promise((resolve, reject) => {\n    generateVideoNode(video, opts).then(player => {\n      node.appendChild(player.node);\n      resolve(player);\n    });\n  });\n}\n\n\n\nclass StaticVideoPlayer {\n  constructor(node) {\n    this.node = node;\n    this.network = \"static\";\n  }\n\n  /// Play the video\n  play() {\n  }\n\n  /// Pause the video\n  pause() {\n  }\n\n  /// Is the player currently paused?\n  getPaused() {\n    return Promise.resolve();\n  }\n\n  /// Has the player finished playing?\n  getFinished() {\n    return Promise.resolve();\n  }\n\n  /// Play the video in a loop\n  setLoop(loop) {\n  }\n\n  /// Seek to the given position in the video, in seconds\n  seekTo(seconds) {\n  }\n\n  /// Get the current playback position, in seconds\n  getCurrentTime() {\n    return Promise.resolve();\n  }\n\n  /// Get the total length of the video, in seconds\n  getDuration() {\n    return Promise.resolve();\n  }\n\n  /// Set the playback volume, range 0-100\n  setVolume(volume) {\n  }\n\n  /// Get the current playback volume, range 0-100\n  getVolume() {\n    return Promise.resolve();\n  }\n\n  /// Get a URL for the video\n  getVideoUrl() {\n    return Promise.resolve();\n  }\n\n  /// When the player is ready to play, a bubbling \"video:ready\" event is\n  /// dispatched on the player node\n  onReady() {\n    dompack.dispatchCustomEvent(this.node, \"video:ready\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n\n  /// When the player starts playing, a bubbling \"video:play\" event is\n  /// dispatched on the player node\n  onPlay() {\n    dompack.dispatchCustomEvent(this.node, \"video:play\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n\n  /// When the playback is paused, a bubbling \"video:pause\" event is dispatched\n  /// on the player node\n  onPause() {\n    dompack.dispatchCustomEvent(this.node, \"video:pause\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n\n  /// When the player has finished playing the video, a bubbling \"video:play\"\n  /// event is dispatched on the player node\n  onFinish() {\n    dompack.dispatchCustomEvent(this.node, \"video:finish\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n}\n\n// https://developers.google.com/youtube/iframe_api_reference\nclass YouTubeVideoPlayer extends StaticVideoPlayer {\n  constructor(node) {\n    super(node);\n    this.network = \"youtube\";\n    this.player = new YT.Player(this.node,\n      {\n        events: {\n          onReady: this.onReady.bind(this),\n          onStateChange: this.onStateEvent.bind(this)\n        }\n      });\n  }\n\n  play() {\n    this.player.playVideo();\n  }\n\n  pause() {\n    this.player.pauseVideo();\n  }\n\n  getPaused() {\n    return Promise.resolve(this.player.getPlayerState() === YT.PlayerState.PAUSED);\n  }\n\n  getFinished() {\n    return Promise.resolve(this.player.getPlayerState() === YT.PlayerState.ENDED);\n  }\n\n  setLoop(loop) {\n    this.player.setLoop(Boolean(loop));\n  }\n\n  seekTo(seconds) {\n    this.player.seekTo(seconds, true);\n  }\n\n  getCurrentTime() {\n    return Promise.resolve(this.player.getCurrentTime());\n  }\n\n  getDuration() {\n    return Promise.resolve(this.player.getDuration());\n  }\n\n  setVolume(volume) {\n    this.player.setVolume(volume);\n  }\n\n  getVolume() {\n    return Promise.resolve(this.player.getVolume());\n  }\n\n  getVideoUrl() {\n    return Promise.resolve(this.player.getVideoUrl());\n  }\n\n  onStateEvent(event) {\n    if (event.data === YT.PlayerState.PLAYING)\n      this.onPlay();\n    else if (event.data === YT.PlayerState.PAUSED)\n      this.onPause();\n    else if (event.data === YT.PlayerState.ENDED)\n      this.onFinish();\n  }\n}\n\n// https://developer.vimeo.com/player/js-api\n// https://github.com/vimeo/player.js\nclass VimeoVideoPlayer extends StaticVideoPlayer {\n  constructor(node) {\n    super(node);\n    this.network = \"vimeo\";\n    if (this.node[vimeoFrameLoaded]) // iframe is already loaded\n      this.initPlayer();\n    else // wait for iframe to load\n      this.node.addEventListener(\"load\", this.initPlayer.bind(this));\n  }\n\n  initPlayer() {\n    this.player = new Vimeo.Player(this.node);\n    this.player.ready().then(this.onReady.bind(this));\n    this.player.on(\"play\", this.onPlay.bind(this));\n    this.player.on(\"pause\", this.onPause.bind(this));\n    this.player.on(\"ended\", this.onFinish.bind(this));\n  }\n\n  play() {\n    if (!this.player)\n      return;\n    this.player.play();\n  }\n\n  pause() {\n    if (!this.player)\n      return;\n    this.player.pause();\n  }\n\n  getPaused() {\n    if (!this.player)\n      return Promise.reject();\n    return this.player.getPaused();\n  }\n\n  getFinished() {\n    if (!this.player)\n      return Promise.reject();\n    return this.player.getFinished();\n  }\n\n  setLoop(loop) {\n    if (!this.player)\n      return Promise.reject();\n    this.player.setLoop(loop);\n  }\n\n  seekTo(seconds) {\n    if (!this.player)\n      return Promise.reject();\n    this.player.setCurrentTime(seconds);\n  }\n\n  getCurrentTime() {\n    if (!this.player)\n      return Promise.reject();\n    return this.player.getCurrentTime();\n  }\n\n  getDuration() {\n    if (!this.player)\n      return Promise.reject();\n    return this.player.getDuration();\n  }\n\n  setVolume(volume) {\n    if (!this.player)\n      return Promise.reject();\n    this.player.setVolume(volume / 100);\n  }\n\n  getVolume() {\n    if (!this.player)\n      return Promise.reject();\n    return this.player.getVolume().then(volume => volume * 100);\n  }\n\n  getVideoUrl() {\n    if (!this.player)\n      return Promise.reject();\n    return this.player.getVideoUrl();\n  }\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement\n// https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events\nclass Html5VideoPlayer extends StaticVideoPlayer {\n  constructor(node) {\n    super(node);\n    this.network = \"html5\";\n    this.node.addEventListener(\"loadedmetadata\", this.onReady.bind(this));\n    this.node.addEventListener(\"play\", this.onPlay.bind(this));\n    this.node.addEventListener(\"pause\", this.onPause.bind(this));\n    this.node.addEventListener(\"ended\", this.onFinish.bind(this));\n  }\n\n  play() {\n    this.node.play();\n  }\n\n  pause() {\n    this.node.pause();\n  }\n\n  getPaused() {\n    return Promise.resolve(this.node.paused);\n  }\n\n  getFinished() {\n    return Promise.resolve(this.node.ended);\n  }\n\n  setLoop(loop) {\n    this.node.loop = Boolean(loop);\n  }\n\n  seekTo(seconds) {\n    this.node.currentTime = seconds;\n  }\n\n  getCurrentTime() {\n    return Promise.resolve(this.node.currentTime);\n  }\n\n  getDuration() {\n    return Promise.resolve(this.node.duration);\n  }\n\n  setVolume(volume) {\n    this.node.volume = volume / 100;\n  }\n\n  getVolume() {\n    return Promise.resolve(this.node.volume * 100);\n  }\n\n  getVideoUrl() {\n    return Promise.resolve(this.node.src);\n  }\n}\n\n\n\n\nclass YuJaVideoPlayer {\n  constructor(node) {\n    this.node = node;\n    this.network = \"static\";\n\n    this.node_parent = node.parentNode;\n  }\n\n  /// Play the video\n  play() {\n    console.info(\"asking to play\");\n    // this.node.postMessage({ name: \"Play\" }, \"*\");\n    this.node.contentWindow.postMessage(JSON.stringify({ name: \"Play\" }), \"*\");\n    return Promise.resolve();\n  }\n\n  /// Pause the video\n  pause() {\n    console.info(\"asking to pause\");\n    // this.node.postMessage({ name: \"Pause\" }, \"*\");\n    this.node.contentWindow.postMessage(JSON.stringify({ name: \"Pause\" }), \"*\");\n    return Promise.resolve();\n  }\n\n  /// Is the player currently paused?\n  getPaused() {\n    return Promise.resolve();\n  }\n\n  /// Has the player finished playing?\n  getFinished() {\n    return Promise.resolve();\n  }\n\n  /// Play the video in a loop\n  setLoop(loop) {\n  }\n\n  /// Seek to the given position in the video, in seconds\n  seekTo(seconds) {\n  }\n\n  /// Get the current playback position, in seconds\n  getCurrentTime() {\n    return Promise.resolve();\n  }\n\n  /// Get the total length of the video, in seconds\n  getDuration() {\n    return Promise.resolve();\n  }\n\n  /// Set the playback volume, range 0-100\n  setVolume(volume) {\n  }\n\n  /// Get the current playback volume, range 0-100\n  getVolume() {\n    return Promise.resolve();\n  }\n\n  /// Get a URL for the video\n  getVideoUrl() {\n    return Promise.resolve();\n  }\n\n  /// When the player is ready to play, a bubbling \"video:ready\" event is\n  /// dispatched on the player node\n  onReady() {\n    dompack.dispatchCustomEvent(this.node, \"video:ready\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n\n  /// When the player starts playing, a bubbling \"video:play\" event is\n  /// dispatched on the player node\n  onPlay() {\n    dompack.dispatchCustomEvent(this.node, \"video:play\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n\n  /// When the playback is paused, a bubbling \"video:pause\" event is dispatched\n  /// on the player node\n  onPause() {\n    dompack.dispatchCustomEvent(this.node, \"video:pause\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n\n  /// When the player has finished playing the video, a bubbling \"video:play\"\n  /// event is dispatched on the player node\n  onFinish() {\n    dompack.dispatchCustomEvent(this.node, \"video:finish\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { player: this }\n    });\n  }\n}\n\n\n\n\n\n// A video player without API\nfunction getStaticVideoPlayer(node) {\n  return Promise.resolve(new StaticVideoPlayer(node, \"static\"));\n}\n\n// A list of player API scripts with status\nconst playerScripts = {};\n\n// This function is called by the loaded YouTube API script\nwindow.onYouTubeIframeAPIReady = function () {\n  playerScripts.youtube.ready = true;\n  for (const waiter of playerScripts.youtube.waiters)\n    waiter.deferred.resolve(new YouTubeVideoPlayer(waiter.node));\n};\n\nfunction getYouTubePlayer(node) {\n  if (!playerScripts.youtube) {\n    playerScripts.youtube = {\n      ready: false,\n      waiters: []\n    };\n\n    const script = document.createElement(\"script\");\n    script.src = \"//www.youtube.com/iframe_api\";\n    script.async = true;\n    document.head.appendChild(script);\n  }\n\n  if (!playerScripts.youtube.ready) {\n    const deferred = dompack.createDeferred();\n    if (!playerScripts.youtube.waiters)\n      playerScripts.youtube.waiters = [];\n    playerScripts.youtube.waiters.push({ deferred, node });\n    return deferred.promise;\n  } else\n    return Promise.resolve(new YouTubeVideoPlayer(node));\n}\n\nfunction getVimeoPlayer(node) {\n  if (!playerScripts.vimeo) {\n    playerScripts.vimeo = {\n      ready: false,\n      waiters: []\n    };\n\n    const script = document.createElement(\"script\");\n    script.src = \"//player.vimeo.com/api/player.js\";\n    script.async = true;\n    script.addEventListener(\"load\", event => {\n      playerScripts.vimeo.ready = true;\n      for (const waiter of playerScripts.vimeo.waiters)\n        waiter.deferred.resolve(new VimeoVideoPlayer(waiter.node));\n    });\n    document.head.appendChild(script);\n  }\n\n  if (!playerScripts.vimeo.ready) {\n    const deferred = dompack.createDeferred();\n    if (!playerScripts.vimeo.waiters)\n      playerScripts.vimeo.waiters = [];\n    playerScripts.vimeo.waiters.push({ deferred, node });\n    return deferred.promise;\n  } else\n    return Promise.resolve(new VimeoVideoPlayer(node));\n}\n\nfunction getYujaPlayer(node) {\n  return Promise.resolve(new YuJaVideoPlayer(node));\n}\n\n\nfunction getHtml5Player(node) {\n  return Promise.resolve(new Html5VideoPlayer(node));\n}\n\n\n\nexport {\n  initializeVideoNode,\n  isVideoNodeInitialized\n};\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\nexport default class SwipeDetect {\n  constructor(node, options) {\n    if (!node)\n      return;\n\n    this.options = {\n      threshold_distance: 15,\n      threshold_speed: 0.3,\n      enablemouseswipe: true, ...options\n    };\n\n    this.swipeinfo = null;\n    this.node = node;\n\n    if (this.options.enablemouseswipe) {\n      node.addEventListener(\"mousedown\", event => this.onTouchStart(event));\n      node.addEventListener(\"mousemove\", event => this.onTouchMove(event));\n      node.addEventListener(\"mouseup\", event => this.onTouchEnd(event));\n    }\n    if (this.touchEnabled()) {\n      node.addEventListener(\"touchstart\", event => this.onTouchStart(event));\n      node.addEventListener(\"touchmove\", event => this.onTouchMove(event));\n      node.addEventListener(\"touchend\", event => this.onTouchEnd(event));\n    }\n  }\n\n  touchEnabled() {\n    return (\"createTouch\" in document);\n  }\n\n  onTouchStart(ev) {\n    this.swipeinfo = {\n      starttime: new Date().getTime(),\n      endtime: -1,\n      start: { x: ev.pageX, y: ev.pageY },\n      end: { x: ev.pageX, y: ev.pageY },\n      target: ev.target,\n      direction: \"\"\n    };\n  }\n\n  onTouchMove(ev) {\n    if (!this.swipeinfo)\n      return;\n    this.swipeinfo.end = { x: ev.pageX, y: ev.pageY };\n  }\n\n  onTouchEnd(ev) {\n    if (!this.swipeinfo)\n      return;\n\n    const dx = this.swipeinfo.end.x - this.swipeinfo.start.x;\n    const dy = this.swipeinfo.end.y - this.swipeinfo.start.y;\n\n    this.swipeinfo.endtime = new Date().getTime();\n\n    const abs_x = Math.abs(dx);\n    const abs_y = Math.abs(dy);\n\n    if (abs_x > this.options.threshold_distance && abs_x / (this.swipeinfo.endtime - this.swipeinfo.starttime) > this.options.threshold_speed)\n      this.swipeinfo.direction += dx > 0 ? \"e\" : \"w\";\n\n    if (abs_y > this.options.threshold_distance && abs_y / (this.swipeinfo.endtime - this.swipeinfo.starttime) > this.options.threshold_speed)\n      this.swipeinfo.direction += dy > 0 ? \"s\" : \"n\";\n\n    if (this.swipeinfo.direction !== \"\") {\n      dompack.dispatchCustomEvent(this.node, \"wh:swipe\", {\n        bubbles: true,\n        cancelable: false,\n        detail: this.swipeinfo\n      });\n\n    }\n\n    this.swipeinfo = null;\n  }\n\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n/*\nB-Lex 2013-2017\n\n\n\nHow to use\n- Give the container a width\n- The browser will render breaking lines at the container's widget,\n  unless there are words which cannot be broken in the specified width.\n  By using the\n  - \"node_measurewidth\" we can be sure to get the full text width even if it overflows it's container\n  - \"node_measureheight\" we can check the combined height of the text and for example a button for a CTA panel\n  - \"node_applystyle\"\n\n\n2019 update\n- stylecontainer is now \"node_applystyle\"\n- container replaced by mandatory \"node_measurewidth\" and \"node_measureheight\" fields\n- commented out support for \"verticalalign\",\n  because this can be done through CSS nowadays\n- removed maxwidth/maxheight \"detect\" setting - keep it simple, move this logic to the caller\n\n2017/2018\n- removed use of Mootools from designfiles wh.layout.autofit version\n\n\n\noptions:\n- minfontsize (default 5)\n- maxfontsize (default 100)\n- maxwidth - if null=no restriction, \"detect\" -> use size of container (inner size, so the available space within the padding and borders)\n- maxheight - if null=no restriction, \"detect\" -> use size of container\n- verticalalign - true / false / \"top\" / \"middle\" / \"bottom\"\n- lineheight - to fix the lineheight for the determined fontsize (best to use a % size, for example: '100%')\n\n- node_measurewidth\n- node_measureheight\n- node_applystyle - which node to manipulate the font-size and line-height properties on\n\n\nUse cases:\n- stretch to fill up container -> maxheight: \"detect\"\n- make sure a element doesn't get too high by auto-sizing text within a given element -> container: ..., maxheight: ...px\n\nOther notes:\n- vertical alignment can be done either by\n  option 1) giving the container a :before with display: inline-block; height: <height to align in>\n  option 2) use the vertical align option\n\n\n\nADDME: maybe play a little with letter-spacing?\nADDME: maybe an option to, when possible, use transform: scale() and fall back to font-size if nessecary, so both text + other content within the textcontainer can be scaled\n\nPlans for V2:\n- combine $wh.makeTextFit and $wh.applyEllipsisToText into a single library\n- add a option applyellipsis, so ellipsis is applied when even a minfontsize the text still does not fit\n- ability to batch instructions?\n- let the user handle vertical alignment using CSS (remove our alignment code)\n*/\n\nexport default function makeTextFit(container_or_elements, options) {\n  if (!options)\n    options = {};\n\n  if (options.debug) {\n    //    console.group(\"$wh.makeTextFit\");\n    //console.info(container_or_elements);\n  }\n\n  const sourcetype = typeof (container_or_elements);\n\n  /*\n  document.getElementsByClassName() is an HTMLCollection, and is live.\n  document.getElementsByTagName() is an HTMLCollection, and is live.\n  document.getElementsByName() is a NodeList and is live.\n  document.querySelectorAll() is a NodeList and is not live.\n  HTMLCollections appear to always be live\n  */\n\n  //var multiple = sourcetype == /*MooTools*/\"elements\" || sourcetype == /*HTML*/\"collection\";\n  const multiple = container_or_elements instanceof NodeList       // querySelectorAll / getElementsByName\n    || container_or_elements instanceof HTMLCollection // live nodelist (GetElementsByTagName / GetElementsByClass)\n    || container_or_elements instanceof Array;         // normal array with (hopefully) HTML nodes\n\n  const elements = multiple ? container_or_elements : [container_or_elements]; // FIXME: or use Array.from() ?\n\n  for (let idx = 0; idx < elements.length; idx++) {\n    const container = elements[idx];\n    __makeTextFit(container, options);\n  }\n\n  // if (options.debug)\n  //  console.groupEnd();\n}\n\nfunction __makeTextFit(textcontainer, options) {\n  let maxwidth,\n    maxheight;\n\n  if (!textcontainer) {\n    console.error(\"No textcontainer specified.\");\n    return;\n  }\n\n  const node_applystyle = \"node_applystyle\" in options ? options.node_applystyle : textcontainer;\n  const node_measurewidth = \"node_measurewidth\" in options ? options.node_measurewidth : textcontainer;\n  const node_measureheight = \"node_measureheight\" in options ? options.node_measureheight : textcontainer;\n\n  /*\n  if (textcontainer.getStyle(\"display\") != \"inline\")\n  {\n    //console.warn(\"maxlines ellipsis only works on inline elements.\");\n    range = document.createRange();\n    range.selectNode(container.childNodes[0]);\n    measureme = range;\n  }\n  */\n\n  if (options.lineheight)\n    node_applystyle.style.lineHeight = options.lineheight; // FIXME\n\n\n  if (options.debug) {\n    if (options.container)\n      console.log(\"Using specified container to determine max size of text\");\n    else\n      console.log(\"Using parentnode of text to determine max size of text\");\n  }\n\n  //console.log(textcontainer.parentNode, container.clientWidth);\n  //console.log(container);\n\n  if (options.maxwidth)\n    maxwidth = options.maxwidth;\n\n  if (options.maxheight)\n    maxheight = options.maxheight;\n\n  /*\n  if (options.maxwidth)\n  {\n    if (options.maxwidth == \"detect\")\n      maxwidth = container.clientWidth;\n    else\n      maxwidth = options.maxwidth;\n  }\n\n  if (options.maxheight)\n  {\n    if (options.maxheight == \"detect\")\n      maxheight = container.clientHeight;\n    else\n      maxheight = options.maxheight;\n  }\n  */\n\n  if (!(\"minfontsize\" in options))\n    options.minfontsize = 5;\n\n  if (!(\"maxfontsize\" in options))\n    options.maxfontsize = 100;\n\n  // experimental\n  if (!(\"fontsizethreshold\" in options)) {\n    options.fontsizethreshold = (options.maxfontsize - options.minfontsize) / 10;\n  }\n  if (options.fontsizethreshold < 0.1)\n    options.fontsizethreshold = 0.1;\n\n\n\n  let tcontent = textcontainer.textContent;\n  if (tcontent === undefined)\n    tcontent = textcontainer.innerText;\n\n  // Nodes used for measuring the size\n  if (options.debug) {\n    console.groupCollapsed(\"$wh.makeTextFit\", tcontent.substr(0, 64));\n    console.dir({\n      textcontainer: textcontainer,\n      node_applystyle: node_applystyle,\n      node_measurewidth: node_measurewidth,\n      node_measureheight: node_measureheight,\n      maxwidth: maxwidth,\n      maxheight: maxheight\n    });\n  }\n\n\n\n  if (tcontent == \"\") {\n    console.warn(\"Empty text, no need to resize.\"); // not even a EOL char\n    //return; // FIXME: skip resizing code, directly move to vertical alignment code\n  }\n\n\n  // If the text isn't visual or there isn't any text we cannot perform calculations on it.\n  const textbounds = textcontainer.getBoundingClientRect();\n\n\n  //console.log(textsize);\n  let textwidth;\n  let textheight = textbounds.bottom - textbounds.top;\n  if (textheight == 0) {\n    console.warn(\"No text, specified textcontainer is inline or display is set to none on textcontainer or it's parents.\");\n\n    if (options.debug)\n      console.groupEnd();\n  }\n\n  // FIXME: are there any smarter ways to quickly determine the correct size?\n  // alternate options:\n  // - try to determine the correlation between fontsize changes and the textwrapper size to make smarter guesses on which size would be best to use/test next\n  let size_ok;\n\n  // get the average fontsize of the min and max\n  let largest_known_fitting_fontsize = options.minfontsize;\n  let smallest_known_too_large_fontsize = options.maxfontsize;\n  let optimal_fontsize;\n\n  let bounds_h, bounds_v;\n\n  // find the largest font-size which still fits\n  let steps_used = 0;\n  do {\n    const current_fontsize = largest_known_fitting_fontsize + (smallest_known_too_large_fontsize - largest_known_fitting_fontsize) / 2;\n\n    node_applystyle.style.fontSize = current_fontsize.toFixed(2) + \"px\";\n\n    /*\n        bounds_h = node_measurewidth.getBoundingClientRect();\n        if (node_measureheight == node_measurewidth)\n          bounds_v = bounds_h;\n        else\n          bounds_v = node_measureheight.getBoundingClientRect();\n    \n        textwidth = bounds_h.right - bounds_h.left;\n        textheight = bounds_v.bottom - bounds_v.top;\n    */\n    textwidth = node_measurewidth.scrollWidth;\n    textheight = node_measureheight.offsetHeight;\n\n\n    if (options.debug)\n      console.log(\"font-size \" + current_fontsize.toFixed(2) + \" results in \" + textwidth.toFixed(2) + \" x \" + textheight.toFixed(2));\n\n    if ((!maxwidth || textwidth <= maxwidth)\n      && (!maxheight || textheight <= maxheight)\n    ) {\n      // note that this fontsize still fits\n      if (current_fontsize > largest_known_fitting_fontsize)\n        largest_known_fitting_fontsize = current_fontsize;\n    } else {\n      if (current_fontsize < smallest_known_too_large_fontsize)\n        smallest_known_too_large_fontsize = current_fontsize;\n    }\n\n    const fontsize_diff = (smallest_known_too_large_fontsize - largest_known_fitting_fontsize);\n\n    /*\n    console.log(\"Next fontsize to check is between \"+largest_known_fitting_fontsize+\" and \"+smallest_known_too_large_fontsize);\n    console.log(\"fontsize_diff: \"+fontsize_diff);\n    */\n    //if (fontsize_diff < 1 && fontsize_diff > -1)\n    if (fontsize_diff < options.fontsizethreshold && fontsize_diff > -options.fontsizethreshold)\n      optimal_fontsize = largest_known_fitting_fontsize;\n\n    steps_used++;\n  }\n  while (steps_used < 100 && !optimal_fontsize);\n\n  // FIXME: contine and use the current fontsize?\n  if (steps_used == 100)\n    console.error(\"Could not determine an optimal fontsize or got stuck in a loop.\");\n\n  if (options.debug)\n    console.log(\"Optimal fontsize \" + optimal_fontsize + \" determined in \" + steps_used + \" steps.\");\n\n  node_applystyle.style.fontSize = optimal_fontsize.toFixed(2) + \"px\";\n\n  /*\n  // now we can apply vertical alignment\n  if (options.verticalalign === true || options.verticalalign === \"middle\")\n  {\n    textsize = node_measurewidth.getBoundingClientRect();\n    textheight = textsize.bottom - textsize.top;\n\n    //var verticaloffset = (container.clientHeight - textcontainer.scrollHeight) / 2;\n    var verticaloffset = (maxheight - textheight) / 2;\n\n    if (options.debug)\n      console.log(\"Vertical aligning with a margin-top of \", verticaloffset, \"px. (\"+maxheight+\"-\"+textheight+\")/2\");\n\n    textcontainer.style.marginTop = verticaloffset+\"px\";\n  }\n  else if (options.verticalalign === false || options.verticalalign === \"top\")\n  {\n    textcontainer.style.marginTop = 0;\n  }\n  else if (options.verticalalign === \"bottom\")\n  {\n    //textcontainer.style.marginTop = (container.clientHeight - textcontainer.scrollHeight)+\"px\";\n    textsize = node_measurewidth.getBoundingClientRect();\n    textheight = textsize.bottom - textsize.top;\n    textcontainer.style.marginTop = (container.clientHeight - textheight)+\"px\";\n  }\n  */\n\n  if (options.debug)\n    console.groupEnd();\n}\n\n//})(document.id);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport makeTextFit from \"../shared/wh.layout.autofit\";\n// import * as resizelistener from \"../shared/resizelistener\";\n// import * as dompack from \"dompack\";\n\n\nlet scaleheadercta = false;\n\nwindow.addEventListener(\"ws:responsivemode\", checkWindowSize);\nwindow.addEventListener(\"resize\", scaleHeaderCTA);\nwindow.addEventListener(\"load\", scaleHeaderCTA); // after custom lead has loaded\n\n// dompack.onDomReady(scaleHeaderCTA);\n\n\nfunction checkWindowSize(event) {\n  const flatcta =\n    ([\n      \"xxsmall\",     // <= 320px (0)\n      \"xsmall\",      // > 320px (1)\n      \"small\",       // > 480px (2)\n      \"medium\"\n    ].indexOf(event.detail.mode) > -1);\n\n  scaleheadercta = !flatcta;\n\n  // console.log(\"FLATCTA\", flatcta);\n\n  if (flatcta) {\n    const ctanode = document.querySelector(\".cta__title\");\n    if (!ctanode)\n      return;\n\n    ctanode.style.fontSize = \"\";\n    ctanode.style.lineHeight = \"\";\n    return;\n  }\n}\n\n// make the text fit\nfunction scaleHeaderCTA() {\n  const ctatitle = document.querySelector(\".cta__title\");\n  if (!ctatitle)\n    return;\n\n  const headercta = document.querySelector(\".headercta\");\n\n  if (!scaleheadercta)\n    return;\n\n  const hdrheight = document.querySelector(\".header__content\").clientHeight;\n\n  const hdrtitle = document.querySelector(\".header__title\");\n\n  let maxheight;\n  if (hdrtitle) { // Universe or photos/slideshow header\n    const hdrtitleheight = hdrtitle.clientHeight;\n    maxheight = hdrheight - hdrtitleheight - 80;\n    /*\n    console.log( { hdrheight:      hdrheight\n                 , hdrtitleheight: hdrtitleheight\n                 , maxheight:      maxheight\n                 });\n    */\n  } else { // Toplevelhome has no title\n    maxheight = hdrheight - 40;\n    /*\n    console.log( { hdrheight: hdrheight\n                 , maxheight: maxheight\n                 });\n    */\n  }\n\n  makeTextFit(ctatitle,\n    {\n      maxwidth: 280,       // 320 - 2 * 20 (padding)\n      maxheight: maxheight,\n\n      node_applystyle: ctatitle,\n      node_measurewidth: ctatitle,  // The final (possible overflowing) width of text (if we measure using header CTA, we don't detect overflow due to unbreakable lines/words)\n      node_measureheight: headercta, // The final height of text + CTA determines whether this is a fit\n\n      minfontsize: 20,\n      maxfontsize: 40,\n      fontsizethreshold: 1,\n      lineheight: \"100%\"\n\n      //, debug:              true\n    }\n  );\n}\n//window.scaleheadercta = scaleHeaderCTA;\n","import * as dompack from \"@webhare/dompack\";\nimport * as dialogapi from 'dompack/api/dialog';\nimport type { UTDialog } from \"../shared/dialog\";\nimport \"./header_stickyctabar.scss\";\n\nclass StickyCTAbar {\n  node: HTMLElement;\n  y: number = 0;\n  isSticky: boolean = false;\n  largescreen: MediaQueryList;\n  ctablock: HTMLElement | null = null;\n  managedcta: HTMLElement | null = null;\n  ctabar: HTMLElement | null = null;\n  ctabtns: HTMLElement[] = [];\n\n  constructor(node: HTMLElement) {\n    this.node = node;\n    this.largescreen = window.matchMedia(\"(min-width: 1280px)\");\n\n    window.addEventListener(\"scroll\", () => this.onScroll(), { passive: true });\n    window.addEventListener(\"load\", () => this.onResize());\n    window.addEventListener(\"resize\", () => this.onResize());\n    document.addEventListener(\"ws:programmedetailsheader-toggle\", () => this.onResize());\n    document.fonts.ready.then(() => this.onResize()).catch(e => console.error(e));\n    this.onResize();\n\n    this.ctabar = dompack.qS(\".header-ctabar\");\n    this.ctablock = dompack.qS(\".header-ctablock\");\n    if (this.ctablock) {\n      this.ctabtns = dompack.qSA(this.ctablock, \".header-cta__button\");\n      this.managedcta = dompack.qS(this.ctablock, \".managedcta\");\n\n      this.checkCTAVisibility();\n\n      new MutationObserver(() => this.checkCTAVisibility()).observe(this.ctablock, { subtree: false, attributes: true, characterData: false });\n      if (this.managedcta)\n        new MutationObserver(() => this.checkCTAVisibility()).observe(this.managedcta, { subtree: false, attributes: true, characterData: false });\n    } else if (this.ctabar) {\n      this.ctabar.classList.add(\"header-ctabar--showprimary\");\n    }\n  }\n\n  checkCTAVisibility() {\n    if (this.managedcta && this.ctablock) {\n      this.ctablock.hidden = false; // set visible first to measure correctly\n      this.ctablock.hidden ||= this.managedcta.offsetParent === null; // Check if managedcta is hidden\n    }\n\n    if (this.ctabar) {\n      let btnvisible = false;\n      if (!this.ctablock!.hidden) {\n        this.ctabtns.forEach(btn => {\n          btnvisible ||= btn.offsetParent !== null;\n          if (btn.closest(\".has-expired-countdown\") && btn.closest(\".header-countdown-inprogress\"))\n            btnvisible = false;\n        });\n      }\n\n      this.ctabar.classList.toggle(\"header-ctabar--showprimary\", !btnvisible);\n    }\n  }\n\n  onResize() {\n    this.node.classList.remove(\"header-ctabar--sticky\"); // first reset\n    this.isSticky = false;\n    this.y = this.node.getBoundingClientRect().top + window.scrollY;\n    if (this.largescreen.matches)\n      this.y -= 60; // below main nav\n\n    this.onScroll();\n  }\n\n  onScroll() {\n    const sticky = window.scrollY > this.y;\n    if (sticky === this.isSticky) return;\n\n    this.isSticky = sticky;\n    this.node.classList.toggle(\"header-ctabar--sticky\", sticky);\n  }\n}\n\n// Catch clicks on brochure request buttons to open the dialog with the form\ndompack.register<HTMLTemplateElement>(\"#dialog-brochurerequestform-template\", template => {\n  const brochurewidget = dompack.qS(template.content, \".brochurerequestform-container\");\n  if (brochurewidget) {\n    dompack.qSA(brochurewidget, \".wh-form\").forEach(form => form.classList.add(\"largedialog\")); // make sure forms in the template are visible for screenreaders\n    dompack.qSA(\".header-ctabar__button--brochure\").forEach(btn => {\n      btn.addEventListener(\"click\", () => {\n        const dialog = dialogapi.createDialog({ allowcancel: true, borrow: brochurewidget }) as UTDialog;\n        dialog.contentnode?.classList.add(\"ut-dialog--large\");\n        void dialog.runModal();\n      });\n    });\n  } else {\n    const formwidget = dompack.qS(template.content, \".widget-wh-form\");\n    if (formwidget) {\n      formwidget.classList.add(\"largedialog\"); // make sure forms in the template are visible for screenreaders\n      dompack.qSA(\".header-ctabar__button--brochure\").forEach(btn => {\n        btn.addEventListener(\"click\", () => {\n          const dialog = dialogapi.createDialog({ allowcancel: true, borrow: formwidget }) as UTDialog;\n          dialog.contentnode?.classList.add(\"ut-dialog--large\");\n          void dialog.runModal();\n        });\n      });\n    }\n  }\n});\n\ndompack.register(\".header-ctabar\", node => new StickyCTAbar(node));\n","/* xeslint-disable */\n// x@ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport SmoothScroll from \"../components/smoothscroll\";\nimport scrollListener from \"../components/scrolllistener\";\nimport { openFoldableContent } from \"../widgets/embeddedobjects\";\nimport { getCSSVariable } from \"./layout-tools\";\nimport { getTid } from \"@webhare/gettid\";\n\n// make some widgets stick to eachother or automatically get or lose borders\n// when they are next to each other.\nimport { activateSmartLayout } from \"./smartlayout\";\nimport \"./smartlayout.scss\";\n\n/*\n.ut--notfoldable\n    This element will be left in it's position in the DOM and not folded into an accordion item.\n    (Initial commet from Arnold (ocrt 2016) about this: \"Stop folden bij eerste element met .ut--notfoldable\")\n    - This element isn't allowed to be \"folded\". Instead it will be always be merged into a deeplink container.\n\n.ut--dontfoldcontent\n    This element must be merged into a accordion item in it's entirity. (it's H2's won't be folder).\n\n.hasfoldabledeeplink\n    This element contains content divided into an accordion using the H2's.\n*/\n\nlet windowMode: null | \"small\" | \"wide\" = null;\n\n// Page scroll duration\nconst scrollDuration = 300;\n\n// Record initial hash\nconst initialhash = location.hash;\n\nfunction openFoldableDeepLink(node: HTMLElement) {\n  node.classList.add(\"foldabledeeplink--open\");\n\n  const container = node.querySelector<HTMLElement>(\".foldabledeeplink__foldcontainer\");\n  if (!container) // If there wasn't content between this h2 and the next, no foldercontainer will have been created\n    return;\n\n  container.style.height = \"auto\";\n  container.style.overflow = \"inherit\";\n}\n\nfunction checkWindowMode(mode: \"small\" | \"wide\") {\n  if (mode !== windowMode) {\n    windowMode = mode;\n    if (windowMode === \"small\") {\n      const hash = document.location.hash.replace(\"#\", \"\");\n      // Enable foldable content\n      for (const node of document.querySelectorAll<HTMLElement>(\".foldabledeeplink\")) {\n        if (hash) {\n          //NOTE: This will not work if the id clashes with an id in the design (e.g. \"menu\") as the foldable id will be\n          //      rewritten (e.g. to \"menu-1\")\n          const idnode = node.querySelector(\"[id]\");\n          if (idnode && idnode.id === hash) { //If hash in url is equal to id, show container content\n            openFoldableDeepLink(node);\n          }\n        }\n        node.classList.remove(\"foldabledeeplink--disabled\");\n      }\n    } else {\n      // Disable foldable content\n      for (const node of document.querySelectorAll(\".foldabledeeplink\"))\n        node.classList.add(\"foldabledeeplink--disabled\");\n    }\n  }\n}\n\n/*\nShow the user where they are on the page\n- Update the visible deeplinks to show where you currently are in the page\n- Update the hash on the URL\n*/\nfunction checkHiglightDeeplink() {\n  // Find the deeplink containing our current content\n  let besthref = '', bestdeeplink;\n  const deeplinklist = dompack.qSA(\".main__deeplink\");\n  for (const deeplink of deeplinklist) {\n    const href = deeplink.getAttribute(\"href\") || '';\n    if (!href.startsWith('#'))\n      continue;\n\n    let target = document.getElementById(href.substr(1));\n    if (!target)\n      continue;\n\n    // If this is an <a> anchor link, switch to the parent <h2>\n    // <h2><a class=\"wh-rtd__anchor\" id=\"\"/></h2>\n    if (target.classList.contains(\"wh-rtd__anchor\") || target.classList.contains(\"wh-anchor\"))\n      target = target.closest(\"h2\") || target;\n\n    if (target.getBoundingClientRect().y <= window.innerHeight / 3) { //this one is at top or outside\n\n      bestdeeplink = deeplink;\n      besthref = href;\n    }\n\n  }\n\n  if (bestdeeplink && bestdeeplink.classList.contains(\"isvisible\"))\n    return; //already best one in sight\n\n  const currentvisible = dompack.qS(\".main__deeplink.isvisible\");\n  if (!bestdeeplink && !currentvisible)\n    return; //already no selected link\n\n  if (currentvisible)\n    currentvisible.classList.remove(\"isvisible\");\n\n  if (bestdeeplink) {\n    bestdeeplink.classList.add(\"isvisible\");\n    let isbefore = true;\n    for (const deeplink of deeplinklist) {\n      if (deeplink === bestdeeplink)\n        isbefore = false;\n\n      if (isbefore)\n        deeplink.classList.add(\"isbefore\");\n      else\n        deeplink.classList.remove(\"isbefore\");\n    }\n\n    //set hash on url\n    if (history.replaceState) {\n      //small timeout because some browsers (like safari) jump to anchor directly after loading page\n      setTimeout(function () { history.replaceState(null, \"\", document.location.href.split(\"#\")[0] + besthref); }, 10);\n    }\n  } else {\n    //remove hash from url\n    if (history.replaceState) {\n      //small timeout because some browsers (like safari) jump to anchor directly after loading page\n      setTimeout(function () { history.replaceState(null, \"\", document.location.href.split(\"#\")[0]); }, 10);\n    }\n  }\n}\n\n\n/* In a CSS grid layout, floating elements don't escape their grid line, which in effect causes each paragraph to clear any\n   floating elements. If an empty paragraph contains a floating image, the image is displayed on its own, without the text of\n   the next paragraph floating around it. To get around this limitation, we'll wrap consecutive paragraphs into one node, so\n   images can float within that node, which gets aligned to the CSS grid.\n   To activate this functionality for a container that has a grid layout and paragraph children that might contain floating\n   images, add the 'ut-wrapfloats' class to the container node.\n\n   Containers:\n   - .contentpart__main (wrapper when the page hasn't been rearranged serverside for the mobile accordeon)\n   - .wh-form__richtext (richtext field in form page)\n   - .ut-wrapfloats (opt-in for grids container elements containing RTD content (direct children)\n   - .ut-rtd-blocks__body (blocks of RTD content generated serverside to use as mobile accordeon)\n*/\nfunction combineFloatParagraphs() {\n  // Process the main content node and any node that opts in\n  for (const container of document.querySelectorAll(\".contentpart__main, .wh-form__richtext, .ut-wrapfloats, .ut-rtd-blocks__body\")) {\n    // Skip this container if it doesn't have children containing floating images\n    if (!container.querySelector(\":scope > p > img.wh-rtd__img--floatleft, :scope > p > img.wh-rtd__img--floatright\"))\n      continue;\n\n    let toCombine = [];\n    let child = container.firstElementChild;\n    while (child) {\n      // Keep a reference to the next child node, as we might move the current child to another parent\n      const nextChild = child.nextElementSibling;\n      // If this is a paragraph with a floating image, or if we already have paragraphs to combine, add it to the list\n      if (child.nodeName === \"P\" && (toCombine.length || child.querySelector(\":scope > img.wh-rtd__img--floatleft, :scope > img.wh-rtd__img--floatright\"))) {\n        toCombine.push(child);\n      } else {\n        // If there are multiple paragraphs, wrap them into one section, so floating images can span paragraphs\n        if (toCombine.length > 1) {\n          const section = <section class=\"ut-floatwrapper\" />;\n          section.append(...toCombine);\n          // Insert the section before the current (non-paragraph) child node\n          child.before(section);\n        }\n        toCombine = [];\n      }\n      child = nextChild;\n    }\n    // If there are multiple paragraphs left, wrap them and append to the container\n    if (toCombine.length > 1) {\n      const section = <section class=\"ut-floatwrapper\" />;\n      section.append(...toCombine);\n      container.append(section);\n    }\n  }\n}\n\nfunction convertDetailSummaries() {\n  dompack.qSA(\"details:not(.ut-no-refold) > summary\").forEach(summary => {\n    const details = summary.parentElement as HTMLDetailsElement;\n    details.removeChild(summary); //prevent <summary> from being cloned into the foldcontainer\n    details.replaceWith(<div class=\"foldablecontent\">\n      <div class=\"foldablecontent__title\">{Array.from(summary.childNodes)}</div>\n      <div class=\"foldablecontent__foldcontainer\"><div class=\"foldablecontent__text\">{Array.from(details.childNodes)}</div></div>\n    </div>);\n  });\n}\n\n\n\nfunction doChangesToRichtextContent() {\n  // To ensure allowing multiple paragraphs to flow around an floating image we\n  // need to combine these paragraphs. Otherwise a new paragraph won't wrap around the float\n  // due to our richtext nodes being part of a grid.\n  combineFloatParagraphs();\n\n  // before we reorder the DOM into foldabledeeplinks\n  // we want to preserve the information on what type of content (p, widget type)\n  // are next to eachother so we can implement special rules for spacing which require us to know bordering content.\n  activateSmartLayout();\n\n  // Convert <details><summary> elements into our own DOM so we have more control on layout and animation\n  convertDetailSummaries();\n\n  checkJumpIntoDeeplink();\n\n  //don't collapse inside NEO in desktop mode (487 or 535 pixels), https://gitlab.webhare.com/utwente/utwente_base/-/issues/1262\n  if (document.documentElement.dataset.nodeeplinks)\n    return;\n\n  if (document.documentElement.classList.contains(\"ws2016--iframed\")) {\n    if ((window.innerWidth >= 483 && window.innerWidth <= 490) || (window.innerWidth >= 530 && window.innerWidth <= 540))\n      return;\n  }\n\n  setupDeepLinks();\n}\n\nfunction setupDeepLinks() {\n  // Ensure tables aren't devided into deeplinks AND get absorbed into\n  for (const tablenode of dompack.qSA(\".wh-rtd__tablewrap\"))\n    tablenode.classList.add(\"ut--dontfoldcontent\");\n\n  const headings = [];\n  for (const h2 of dompack.qSA(\"h2:not([data-ut-ignore-deeplink]):not(.wh-form__grouptitle)\")) {\n    if (h2.closest(\".wh-details__container\"))\n      continue; //Ignore if already inside a foldable container, utwente/utwente_base#1962\n    // if (h2.closest(\".ut-no-refold\"))\n    //   continue; //Ignore if inside a modernized page\n\n    const formpage = h2.closest(\".wh-form__page\");\n    if (formpage && formpage.previousElementSibling && formpage.previousElementSibling.classList.contains(\"wh-form__page\"))\n      continue; //Skip if h2 is inside followup page inside forms\n\n    // FIXME: maybe we could add the H2's from the table to the deeplinks, but not fold them.\n    //        To do this we would need to replace the array \"target\" (with all h2's to both add to the list and fold) into two lists.\n    if (h2.closest(\".wh-rtd__tablecell\"))\n      continue; //dont create folds in tables, utwente/utwente_base#1136\n\n\n    let anchor;\n    if (h2.id)\n      anchor = h2;\n\n    const linkanchor = h2.querySelector(\"a[id]\");\n    if (linkanchor)\n      anchor = linkanchor;\n\n    if (!anchor)\n      continue; //skip any h2 without an anchor\n\n    // If a deeplink has the same name as another element on the page (e.g. \"menu\"), rename the id\n    if (document.querySelectorAll(`*[id='${anchor.id}']`).length > 1) {\n      let i = 1;\n      let newid = anchor.id + \"-\" + i;\n      while (document.getElementById(newid))\n        newid = anchor.id + \"-\" + ++i;\n      anchor.id = newid;\n    }\n\n    //Note title attribute is also used for ellipsis of link text (fn ellipsisDeeplinks)\n    headings.push(<li class=\"main__deeplinkitem\"><a class=\"main__deeplink\" title={h2.textContent} propTarget={h2} href={\"#\" + anchor.id}>{h2.textContent}</a></li>);\n  }\n  if (headings.length <= 1) //no deeplinks if we only have one (utwente/itcwebsite#112)\n    return;\n\n  const deeplinksNode =\n    <nav class=\"main__deeplinks\" aria-label={getTid(\"utwente_base:frontend.ws2016.js.landmark-deeplinks-arialabel\")}>\n      <ul class=\"main__deeplinklist\">{headings}</ul>\n    </nav>;\n\n  let activateDeeplinksMedia;\n  dompack.qS('main')?.prepend(\n    <div class=\"contentpart__deeplinks\">\n      {deeplinksNode}\n    </div>);\n\n  void getCSSVariable(\"--breakpoint-deeplinks\").then(breakpoint_deeplinks => {\n    // Read the breakpoint CSS variable and get a MediaQueryList\n    activateDeeplinksMedia = matchMedia(`(max-width: ${breakpoint_deeplinks})`);\n    // Directly check the query\n    checkWindowMode(activateDeeplinksMedia.matches ? \"small\" : \"wide\");\n    // Setup an onchange listener to activate/deactivate the deeplinks\n    activateDeeplinksMedia.addEventListener(\"change\", event => checkWindowMode(event.matches ? \"small\" : \"wide\"));\n  });\n\n  // Initialize smooth scrolling for the deeplinks\n  const deeplinks = dompack.qSA(deeplinksNode, \".main__deeplink\");\n  new SmoothScroll(deeplinks, { duration: scrollDuration });\n  scrollListener.addNodes(deeplinks);\n\n  //Watch scrolls/resize and check deeplink to highlight after such a change\n  checkHiglightDeeplink();\n  window.addEventListener(\"scroll\", checkHiglightDeeplink);\n  window.addEventListener(\"ws:resize\", checkHiglightDeeplink);\n\n  const targets = [];\n  deeplinks.forEach(deeplink => {\n    const href = deeplink.getAttribute(\"href\") || '';\n    if (!href.startsWith('#'))\n      return;\n\n    let target = document.getElementById(href.substr(1));\n    if (!target)\n      return;\n\n    // If this is an <a> anchor link, switch to the parent <h2>\n    // <h2><a class=\"wh-rtd__anchor\" id=\"\"/></h2>\n    if (target.classList.contains(\"wh-rtd__anchor\") || target.classList.contains(\"wh-anchor\"))\n      target = target.closest(\"h2\") || target;\n\n    // Prepend the target to the list of targets\n    targets.unshift(target);\n  });\n\n  ellipsisDeeplinks(deeplinks);\n  window.addEventListener(\"load\", () => ellipsisDeeplinks(deeplinks));//font loaded\n  window.addEventListener(\"ws:resize\", () => ellipsisDeeplinks(deeplinks)); //Incase deeplinks where hidden\n}\n\nfunction checkJumpIntoDeeplink() {//Check if the hash is inside a deeplink\n  let target;\n\n  if (initialhash && initialhash.length > 1) {\n    target = document.getElementById(initialhash.substr(1)); //not supporting <a name>, deprecated since html4 anyway\n    if (target)\n      doJumpIntoDeeplink(target);\n  }\n\n  window.addEventListener(\"hashchange\", () => {\n    if (location.hash.length <= 1)\n      return;\n\n    const target2 = document.getElementById(location.hash.substr(1));\n    if (target2)\n      doJumpIntoDeeplink(target2);\n  });\n}\n\n/** @short make sure all containers of the specified target are opened\n    @long This handles opening foldable deeplinks (which are meant for mobile) and foldable content\n*/\nexport function doJumpIntoDeeplink(target: HTMLElement | null) {\n  //console.info(\"doJumpIntoDeeplink\", target);\n\n  //Expand all my parents!\n  let checkexpand = target;\n  const expandlist = [];\n\n  // If the specified target is a foldable\n  if (target?.matches(\".foldablecontent, .foldabledeeplink\"))\n    expandlist.unshift(target);\n\n  while (true) {\n    // checkexpand = checkexpand.parentNode.closest(\".foldablecontent__foldcontainer, .foldabledeeplink__foldcontainer\");\n    checkexpand = checkexpand?.parentElement?.closest(\".foldablecontent, .foldabledeeplink\") || null;\n    if (!checkexpand)\n      break;\n\n    expandlist.unshift(checkexpand);\n  }\n\n  //console.log(\"to reach\",target,\"we must expand\",expandlist);\n\n  // open the \"__foldcontainer\"'s\n  expandlist.forEach(toexpand => {\n    if (toexpand.classList.contains('foldabledeeplink')) {\n      //we can open this by clicking the parent .foldabledeeplink\n      openFoldableDeepLink(toexpand);\n    } else if (toexpand.classList.contains('foldablecontent')) {\n      openFoldableContent(toexpand);\n    } else {\n      console.log(\"don't know how to open \", toexpand);\n    }\n  });\n}\n\nfunction ellipsisDeeplinks(deeplinks: HTMLElement[]) {\n  deeplinks.forEach((deeplink) => {\n    let txt = deeplink.title;\n    let i = txt.length;\n    deeplink.textContent = txt;//Put back original text\n\n    const wrapper_h = deeplink.parentElement?.clientHeight || 0;\n    let txt_h = deeplink.clientHeight;\n    while (txt_h > wrapper_h && i > 0) {\n      txt = txt.substring(0, i - 1);\n      deeplink.textContent = txt;\n      txt_h = deeplink.clientHeight;\n      --i;\n    }\n\n    //Check for max width (in case of long words)\n    const wrapper_w = deeplink.parentElement?.clientWidth || 0;\n    while (deeplink.clientWidth > wrapper_w) {\n      txt = txt.substring(0, i - 1);\n      deeplink.textContent = txt;\n      txt_h = deeplink.clientHeight;\n      --i;\n    }\n\n    if (deeplink.title !== txt) //Ellipsis, then add ... at end\n      deeplink.textContent = txt.substring(0, i - 4) + \"...\";\n  });\n}\n\ndompack.onDomReady(doChangesToRichtextContent);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n// CSS Smooth scroll based on: http://wibblystuff.blogspot.in/2014/04/in-page-smooth-scroll-using-css3.html\n// With improvements from: http://codepen.io/kayhadrin/pen/KbalA\nexport default class SmoothScroll {\n  constructor(nodes, options) {\n    this.options = { translateAnchor: null, ...options };\n    for (const node of nodes) {\n      let href = node.getAttribute(\"href\");\n      if (href.indexOf(\"#\") >= 0) {\n        if (this.options.translateAnchor)\n          href = this.options.translateAnchor(href);\n\n        if (href) {\n          const target = document.getElementById(href.substr(href.indexOf(\"#\") + 1));\n          if (target) {\n            node.addEventListener(\"click\", event => {\n              event.preventDefault();\n              target.scrollIntoView({ block: \"start\", behavior: \"smooth\" });\n            });\n            target.setAttribute(\"data-scrollevent\", \"0\");\n          }\n        }\n      }\n    }\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n\n\n/*\n  Scrolllistener is used to trigger loading/animations when selected elements get inside/outside the viewport.\n  Use attribute 'data-scrollevent' to bind event 'wh:visibilitychange' to element\n  With the data-scrollevent an threshold can be set like data-scrollevent=\"100\".\n  Then event will be triggered when at least 100px of element gets visible or is hidden.\n  (On first time 'onload' all thresholds are 0)\n  Extras: data-scrollparallax and data-scrollzoom for parallax/zoom effect while scrolling\n  value of these attributes are the factors of the parallax speed / zoom factor\n\n*/\nclass ScrollListener {\n  constructor() {\n    this.scrollactions = [];//contains nodes with active functions during scrolling\n    this.elements = [];\n\n    this.scrollfn = this.onScroll.bind(this);//bind to functions so we can remove listener if all elements are visible\n    this.resizefn = this.onResize.bind(this);\n\n    window.addEventListener(\"scroll\", this.scrollfn);\n    window.addEventListener(\"resize\", this.resizefn);\n\n    this.isinit = true;\n    this.onResize();\n\n    dompack.onDomReady(() => {\n      this.addNodes(document.querySelectorAll(\"[data-scrollevent]\"));\n    });\n  }\n\n  // Add nodes to listen to\n  addNodes(selnodes) {\n    if (!selnodes.length)\n      return;\n\n    for (let i = 0; i < selnodes.length; ++i) {\n      let treshhold = selnodes[i].getAttribute(\"data-scrollevent\");\n      treshhold = !treshhold ? 0 : parseInt(treshhold);\n\n      const nodeinfo = {\n        \"state\": \"\",\n        \"node\": selnodes[i],\n        \"treshhold\": treshhold,\n        \"boundingrect\": null,\n        \"actions\": [],\n        \"data\": null,\n        \"measure\": \"\"\n      };\n\n      const scrollvisibleclass = selnodes[i].getAttribute(\"data-scrollvisibleclass\");\n      if (scrollvisibleclass)\n        selnodes[i].addEventListener(\"wh:visibilitychange\", () => selnodes[i].classList.add(scrollvisibleclass));\n\n      const measuremethod = selnodes[i].getAttribute(\"data-scrolleventmeasure\");\n      if (measuremethod != \"\")\n        nodeinfo.measure = measuremethod;\n\n\n      const parallax = selnodes[i].getAttribute(\"data-scrollparallax\");\n      if (typeof parallax === \"string\") {\n        const free = selnodes[i].hasAttribute(\"data-scrollparallaxfree\"); // if used, we won't limit the amount the element can be shifted based on how much clipped content there is\n\n        // let innernode = selnodes[i].querySelector(\":first-child\");\n        const innernode = selnodes[i].firstElementChild;\n        if (innernode) {\n          const factor = Number(parallax);//movement factor\n          nodeinfo.data = {\n            innernode: innernode,\n            parallax: factor || 0.2,\n            limitparallax: !free\n          };\n          nodeinfo.actions.push(\"parallax\");\n          this.scrollactions.push(nodeinfo);\n        }\n      }\n\n      const zoom = selnodes[i].getAttribute(\"data-scrollzoom\");\n      if (typeof zoom === \"string\") {\n        // let innernode = selnodes[i].querySelector(\":first-child\");\n        const innernode = selnodes[i].firstElementChild;\n        if (innernode) {\n          //let factor = 1*zoom;//zoom factor\n          nodeinfo.data = {\n            innernode: innernode,\n            zoom: zoom !== 0 ? Math.abs(zoom) : 1\n          };\n          nodeinfo.actions.push(\"zoom\");\n          this.scrollactions.push(nodeinfo);\n        }\n      }\n      this.elements = this.elements.filter(info => info.node != selnodes[i]);\n      this.elements.push(nodeinfo);\n    }\n  }\n\n  onScrollActions() {\n    for (let i = 0; i < this.scrollactions.length; i++) {\n      const action = this.scrollactions[i];\n\n      if (action.state != \"visible\")\n        continue;\n\n      //Parallax\n      if (action.actions.indexOf(\"parallax\") != -1) {\n        const elementheight = action.data.innernode.clientHeight;\n        if (action.data.limitparallax && !elementheight) {\n          // if we cannot measure the content (absolute positioned content within the innernode?)\n          // we cannot limit the parallax.\n          continue;\n        }\n\n        const containerheight = action.node.clientHeight;\n\n        // determine how much larger the element to animate is compared to it's container\n        const overflowsize = elementheight - containerheight;\n\n        const p = 2 * (action.boundingrect.bottom / (this.viewport_height + containerheight) - 0.5);//range -1 .. 1\n        const center = overflowsize * -0.5;\n\n        let factor = action.data.parallax; // range of the parallax motion (how much it moves up to counter the page scroll)\n\n        // By default prevent the image moving outside of the container (leaving a gap)\n        if (action.data.limitparallax && Math.abs(factor) > overflowsize) // is the amount of movement (in px) specified on the element larger than the amount the image inside has larger?\n          factor = factor < 0 ? -overflowsize : overflowsize;\n\n\n        if (!action.data.innernode.style.transform) {\n          //first time: set top/bottom on auto\n          action.data.innernode.style.top = \"auto\";//(center + p * factor ) + \"px\";\n          action.data.innernode.style.bottom = \"auto\";\n        }\n\n        action.data.innernode.style.transform = \"translate(0,\" + (center + p * factor) + \"px)\";\n      }\n\n      //Zoom effect\n      if (action.actions.indexOf(\"zoom\") != -1) {\n        if (action.boundingrect.top <= 0) //start zoom effect if container starts to hide in top\n        {\n          const containerheight = action.node.clientHeight;\n          const p = -action.boundingrect.top / containerheight;\n\n          const factor = 1 + p * action.data.zoom;\n          action.data.innernode.style.transform = \"scale(\" + factor + \",\" + factor + \")\";\n          action.data.innernode.style.opacity = 1 - p;\n        } else {\n          action.data.innernode.style.transform = \"scale(1,1)\";\n          action.data.innernode.style.opacity = 1;\n        }\n      }\n\n    }\n  }\n\n  onScroll(ev) {\n    const scrollpos = window.scrollY;\n    this.isscrollup = this.lastscroll ? this.lastscroll > scrollpos : false;\n    this.lastscroll = scrollpos;\n\n    this.checkElementsVisibility();\n\n    this.onScrollActions();\n  }\n\n  checkElementsVisibility() { //check if elements getting visible or hides\n    for (let i = this.elements.length - 1; i >= 0; --i) {\n      let visible = false;\n\n      const treshhold = this.isinit ? 0 : this.elements[i].treshhold;\n      let rect;\n\n      //console.log(\"Check visibility\", this.elements[i]);\n\n      // This was added for elements which itself cannot be measured correctly.\n      // (either because of use display: contents; of childnodes overflowing)\n      if (this.elements[i].measure == \"content\") {\n        let node = this.elements[i].node.firstElementChild;\n        while (node) {\n          rect = node.getBoundingClientRect();\n          if (rect.height > 0) {\n            // FIXME: if we want to support scroll effects we also need to combine the clientrects\n            //        of children and set this.elements[i].boundingrect = rect;\n            visible = (rect.top >= treshhold && this.viewport_height - rect.top >= treshhold) || (rect.bottom > treshhold && this.viewport_height - rect.bottom > treshhold);\n            if (visible)\n              break; // stop checking elements, part of the element is visible anyway\n          }\n\n          node = node.nextElementSibling;\n        }\n      } else {\n        rect = this.elements[i].node.getBoundingClientRect();\n        if (rect.height == 0) // currently not visible\n          continue;\n\n        this.elements[i].boundingrect = rect;\n        visible = (rect.top >= treshhold && this.viewport_height - rect.top >= treshhold) || (rect.bottom > treshhold && this.viewport_height - rect.bottom > treshhold);\n      }\n\n      if (visible) {\n        if (this.elements[i].state != \"visible\") {\n          this.elements[i].state = \"visible\";\n          dompack.dispatchCustomEvent(this.elements[i].node, \"wh:visibilitychange\", {\n            bubbles: true,\n            cancelable: false,\n            detail: {\n              scrolldirection: this.isinit ? \"\" : (this.isscrollup ? \"up\" : \"down\"),\n              target: this.elements[i],\n              visible: true,\n              nodebounds: rect\n            }\n          });\n        }\n      } else {\n        if (this.elements[i].state == \"visible\") {\n          this.elements[i].state = \"hide\";\n          dompack.dispatchCustomEvent(this.elements[i].node, \"wh:visibilitychange\", {\n            bubbles: true,\n            cancelable: false,\n            detail: {\n              scrolldirection: this.isinit ? \"\" : (this.isscrollup ? \"up\" : \"down\"),\n              target: this.elements[i],\n              visible: false,\n              nodebounds: rect\n            }\n          });\n        }\n      }\n    }\n\n    this.isinit = false;\n  }\n\n  onResize(ev) {\n    const win_height = window.innerHeight;\n    if (this.viewport_height && this.viewport_height == win_height)\n      return;\n\n    this.viewport_height = win_height;\n\n    this.onScroll();\n  }\n\n}\n\nconst scrollListener = new ScrollListener();\nexport default scrollListener;\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n//import * as consenthandler from '@mod-publisher/js/analytics/consenthandler';\n\nimport \"./carrousel\";\nimport \"./photoalbum\";\nimport \"./slideshow\";\nimport \"./progress\";   // progress / admission widget\nimport \"./timeline\";\nimport \"./timetable\";\nimport \"./course_overview\";\nimport \"./managed-cta\";\nimport \"./publicationslist\";\n\nimport \"./embeddedobjects.scss\";\nimport \"./embeddedobjects-cta.scss\";\n\nimport \"./banner\";\nimport \"./linkspercategory_colors\";\nimport \"./linkspercategory_tabs\";\nimport \"./linkswithimage\";\nimport \"./newsandevents\";\nimport \"./pagenavigation\";\nimport \"./richtext-ff\";\n\nimport \"../figures\";\n\n\nfunction initWideImage() {\n  window.addEventListener(\"resize\", checkWideImage);\n  checkWideImage();\n}\n\nfunction checkWideImage() { //replace wide image with large (desktop) version if window > 640\n  if (window.innerWidth <= 640)\n    return;\n\n  const wideimages = document.querySelectorAll(\".embeddedobject.imageblock > img[data-wide]\");\n  let imgcount = wideimages.length;\n  for (const node of wideimages) {\n    const widelink = node.getAttribute(\"data-wide\");\n    if (widelink)\n      node.src = widelink;\n    node.removeAttribute(\"data-wide\");\n    imgcount--;\n  }\n  if (imgcount <= 0)\n    window.removeEventListener(\"resize\", checkWideImage);\n}\n\nlet dragging = 0;\nconst dragThreshold = 3;\n\n\n/*\nUsed CSS classes:\n- --disabled\n- --open                  - the foldable content is expanded (not collapsed)\n- __foldcontainer--active - means it's being animated\n*/\n\nexport function openFoldableContent(node, className = \"foldablecontent\") {\n  node.classList.add(className + \"--open\");\n\n  // we are forced to do this because we have custom classnames for all foldable content\n  const foldcontainernode = node.querySelector(\".\" + className + \"__foldcontainer\");\n  foldcontainernode.style.height = \"auto\";\n  foldcontainernode.style.overflow = \"inherit\";\n}\n\nexport function initFoldableContent(className = \"foldablecontent\") {\n  // Nodes having a \"--active\" class are already initialized\n  for (const node of document.querySelectorAll(\".\" + className + \":not(.\" + className + \"--active)\")) {\n    node.classList.add(className + \"--active\");\n    // titlenode = the node that toggles the foldable content\n    const titlenode = node.querySelector(\".\" + className + \"__title\");\n    // foldcontainernode = the node that is resized when opening/closing\n    const foldcontainernode = node.querySelector(\".\" + className + \"__foldcontainer\");\n    // textnode = the node that holds the actual content\n    const textnode = node.querySelector(\".\" + className + \"__text\");\n\n    if (!foldcontainernode) {\n      console.warn(\"No expandable content for\", node);\n      continue;\n    }\n\n    const setHandler = event => {\n      //console.log(\"setHandler\", event, node.classList);\n\n      if (event.detail.open) {\n        openFoldableContent(node, className);\n      } else {\n        node.classList.remove(className + \"--open\");\n        foldcontainernode.style.height = \"\";\n      }\n    };\n\n\n    const toggleHandler = event => {\n      //console.log(\"toggleHandler\", event, node.classList);\n\n      if (event.type == \"touchend\")\n        event.preventDefault(); // Don't fire click event as well\n      if (dragging >= dragThreshold)\n        return;\n      if (node.classList.contains(className + \"--disabled\"))\n        return;\n\n      // Toggle the open state\n      if (node.classList.toggle(className + \"--open\")) {\n        // Explicitly set height to zero\n        foldcontainernode.style.height = 0;\n\n        // Activate transition\n        foldcontainernode.classList.add(className + \"__foldcontainer--active\");\n\n        // Set height to content height to start the transition\n        foldcontainernode.style.height = textnode.getBoundingClientRect().height + \"px\";\n      } else {\n        // set overflow to css value (overflow=hidden)\n        foldcontainernode.style.overflow = \"\";\n\n        // Explicitly set height to current height\n        foldcontainernode.style.height = textnode.getBoundingClientRect().height + \"px\";\n        foldcontainernode._wsTmpHeight = getComputedStyle(foldcontainernode).height;\n\n        // Activate transition\n        foldcontainernode.classList.add(className + \"__foldcontainer--active\");\n\n        // Set height to 0 to start the transition\n        foldcontainernode.style.height = \"0\";\n      }\n\n      dompack.dispatchCustomEvent(node, \"ws:foldable-status\",\n        {\n          bubbles: true,\n          cancelable: false,\n          detail: { open: node.classList.contains(className + \"--open\") }\n        });\n    };\n\n    titlenode.addEventListener(\"click\", toggleHandler);\n    node.addEventListener(\"ws:foldable-toggle\", toggleHandler);\n    node.addEventListener(\"ws:foldable-set\", setHandler);\n\n    // Use touch events for mobile, because the first click only activates the hover effect\n    // Only activate toggle and prevent default when a certain number of move events have occurred\n    titlenode.addEventListener(\"touchstart\", () => dragging = 0, { passive: true });\n    titlenode.addEventListener(\"touchmove\", () => ++dragging, { passive: true });\n    titlenode.addEventListener(\"touchend\", toggleHandler);\n\n    foldcontainernode.addEventListener(\"transitionend\", event => {\n      if (event.currentTarget == event.target) {\n        // Deactivate the transition\n        foldcontainernode.classList.remove(className + \"__foldcontainer--active\");\n\n        // reset height and overflow back to what the stylesheet defines\n        //foldcontainernode.style.height = \"\";\n        //foldcontainernode.style.overflow = \"\";\n\n        // Set height to 'auto' when open (natural content height) or clear when closed (css default)\n        // and disable overflow so hover effects on items inside container can get outside container\n        if (node.classList.contains(className + \"--open\")) {\n          // we are forced to do this because we have custom classnames for all foldable content\n          foldcontainernode.style.height = \"auto\";\n          foldcontainernode.style.overflow = \"inherit\";\n        } else {\n          foldcontainernode.style.height = \"\";\n        }\n      }\n    });\n  }\n}\n\n\nfunction toggleStudyFinderSpecializations(ev) {\n  if (ev && !ev.target.closest(\".togglespecializations\"))\n    return;\n\n  if (ev)\n    ev.preventDefault();\n\n  const itemnode = ev.target.closest(\".studyfinder__programme\");\n  if (!itemnode)\n    return;\n\n  const spnode = itemnode.querySelector(\".programme_specializations\");\n  if (!spnode)\n    return;\n\n  if (spnode.classList.contains(\"show\")) {\n    spnode.style.height = spnode.clientHeight + \"px\";\n    void (spnode.clientWidth); //force css update\n    spnode.classList.remove(\"show\");\n    spnode.style.height = \"0px\";\n  } else {\n    spnode.style.height = spnode.children[0].clientHeight + \"px\";\n    void (spnode.clientWidth); //force css update\n    spnode.classList.add(\"show\");\n    setTimeout(function () {\n      if (spnode.classList.contains(\"show\"))\n        spnode.style.height = \"auto\";\n    }, 300);\n  }\n}\n\n\n\nfunction activateStudyfinderWidget(widgetnode) {\n  console.info(\"Initializing StudyFinder widget\", widgetnode);\n\n  // Studyfinder widget 'show all' button\n  const showallnode = widgetnode.querySelector(\".sfwidget__showall\");\n  if (showallnode)\n    showallnode.addEventListener(\"click\", evt => expandStudyfinderWidget(evt));\n\n  widgetnode.addEventListener(\"click\", toggleStudyFinderSpecializations);\n}\n\nfunction expandStudyfinderWidget(evt) {\n  console.log(dompack);\n  const widget = evt.target.closest(\".embeddedobject\");\n  widget.classList.add(\"sfwidget--expand\");\n}\n\ndompack.register(\".embeddedobject__studyfinder\", node => activateStudyfinderWidget(node));\n\n//cleanup empty paragraph between embedded objects\ndompack.register(\".embeddedobject\", node => {\n  const prevnode = node.previousElementSibling;\n  if (prevnode\n    && (prevnode.nodeName == \"P\"\n      || prevnode.nodeName == \"H2\"\n      || prevnode.nodeName == \"H3\"\n      || prevnode.nodeName == \"H4\")\n    && (prevnode.innerHTML == \"\"\n      || prevnode.innerHTML == \"<br>\")) { //empty paragraph or heading\n    //now check if element is between embedded objects\n    const prevembobjectnode = prevnode.previousElementSibling;\n    if (prevembobjectnode && prevembobjectnode.classList.contains(\"embeddedobject\"))\n      node.parentElement.removeChild(prevnode);//delete empty paragraph\n  }\n});\n\n\n//ADDME: Rewrite to dompack.register?\ndompack.onDomReady(function () {\n  initWideImage();\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport Carrousel from \"@webhare/dompack-carrousel\";\nimport * as videotools from \"../../../components/video\";\nimport \"./carrousel-shared.css\";\nimport \"./carrousel.scss\";\n\nlet whitespace;\nconst carrouselwidgets = [];\n\nwindow.carrouselwidgets = carrouselwidgets;\n\n//window.videotools = videotools;\n\nfunction getContentBlank(widgetnode) {\n  let measure_element = widgetnode.previousElementSibling || widgetnode.nextElementSibling;\n  let computed;\n  let measureself;\n\n  // Due to JS reordering/grouping to support anchors in mobile, we might not have any content above or below us.\n  // In this case (ab)use the widget's node to measure paddings.\n  if (!measure_element) {\n    // use the widget itself to measure by temporary disabling the fullwidth\n    measureself = true;\n    measure_element = widgetnode;\n    widgetnode.classList.remove(\".main__contents--fullwidth\");\n  }\n\n  computed = window.getComputedStyle(measure_element);\n  // NOTE: If this clientWidth isn't requested here, reading the properties of computed sometimes fails on IE11. Requesting\n  //       this clientWidth (the measure_element.offsetWidth may work too) forces the browser to get the proper computed\n  //       styles.\n  const fullwidth = (document.querySelector(\".main__contents\") || document.querySelector(\".contentpart__main\")).clientWidth;\n\n  const rec =\n  {\n    spaceLeft: parseInt(computed.marginLeft, 10) + parseInt(computed.paddingLeft, 10),\n    spaceRight: parseInt(computed.marginRight, 10) + parseInt(computed.paddingRight, 10),\n    contentWidth: measure_element.offsetWidth - parseInt(computed.paddingLeft, 10) - parseInt(computed.paddingRight, 10),\n    fullwidth: fullwidth\n  };\n\n  rec.spaceRight = rec.fullwidth - rec.spaceLeft - rec.contentWidth;\n\n  if (measureself)\n    widgetnode.classList.add(\".main__contents--fullwidth\");\n\n  return rec;\n}\n\nfunction doPauseHeaderAnimation(evt) {\n  window.pauseHeaderAnimation();\n}\nfunction doUnpauseHeaderAnimation(evt) {\n  window.unPauseHeaderAnimation();\n}\n\n\n\nfunction refreshAllCarousels() {\n  // console.info(\"refreshAllCarousels\");\n  //console.log(\"paddingLeft\", paddingLeft);\n\n  for (const widget of carrouselwidgets) {\n    const whitespace = getContentBlank(widget.node);\n\n    fixCarrouselWidgetMinHeight(widget);\n\n    const carrclass = widget.carrousel;\n    carrclass.setOptions({\n      paddingLeft: whitespace.spaceLeft,\n      paddingRight: whitespace.spaceRight\n    });\n    //ADDME: __refreshSlidesLayout doesn't exist? carrclass.__refreshSlidesLayout();\n    carrclass.refresh();\n  }\n}\n\nfunction remeasureSlides() {\n  //console.info(\"Carrousel widget, remeasuring slides, document state is \", document.readyState);\n\n  for (const widget of carrouselwidgets)\n    widget.carrousel.relayoutSlides();\n\n  refreshAllCarousels();\n}\n\n\n/** @short set a minwidth to stretch the carrousel widget to have enough\n           room below the carrousel images to have the navigation buttons\n           not overlap the images.\n*/\nfunction fixCarrouselWidgetMinHeight(widget) {\n  const carrclass = widget.carrousel;\n\n  const nextbutton = widget.node.querySelector(\".carrousel__next\");\n  if (!nextbutton || nextbutton.clientHeight == 0) {\n    widget.node.style.minHeight = \"\"; // no need to make room for the nav buttons\n    return;\n  }\n\n  // Use minheight to make sure there's enough room for the navigation buttons\n  const firstimage = carrclass.nodes.viewport.querySelector(\".carrousel__cell-image\");\n  if (firstimage) {\n    const carrouselrect = widget.node.getBoundingClientRect(); //carrclass.nodes.viewport.getBoundingClientRect();\n    const firstimagerect = firstimage.getBoundingClientRect();\n\n    const minheight = firstimagerect.bottom - carrouselrect.top + 60 + 20 + 20;\n    //console.log(\"Need at least\" + minheight + \"px\");\n    widget.node.style.minHeight = minheight + \"px\";\n  }\n}\n\nfunction doCheckForCarouselVideoTrigger(event) {\n  const widget = event.target.closest(\".carrouselwidget\");\n  if (!widget)\n    return;\n\n  const slidecontainer = event.target.closest(\".carrousel__cell\");\n  if (!slidecontainer)\n    return;\n\n  if (event.target.closest(\".carrousel__cell-playbutton\")) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    const videocontainer = slidecontainer.querySelector(\"[data-video]\");\n    if (videocontainer) {\n      slidecontainer.classList.add(\"active\");\n\n      if (videotools.isVideoNodeInitialized(videocontainer))\n        slidecontainer._wsVideoPlayer.play();\n      else\n        videotools.initializeVideoNode(videocontainer).then(player => slidecontainer._wsVideoPlayer = player);\n    }\n  } else if (event.target.closest(\".video-close\")) {\n    event.preventDefault();\n    event.stopPropagation();\n\n    slidecontainer.classList.remove(\"active\");\n    slidecontainer._wsVideoPlayer.pause();\n  }\n\n  const anchor = event.target.closest(\"a\");\n  if (anchor) {\n    // Get the X translation\n    const style = getComputedStyle(slidecontainer);\n    const transform = style.transform || style.webkitTransform || style.mozTransform;\n    let mat = transform.match(/^matrix3d\\((.+)\\)$/);\n    let xpos = -1;\n    if (mat)\n      xpos = parseFloat(mat[1].split(', ')[12]); // The 'tx' from matrix3d(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1)\n    else {\n      mat = transform.match(/^matrix\\((.+)\\)$/);\n      if (mat)\n        xpos = parseFloat(mat[1].split(', ')[4]); // The 'tx' from matrix(a, b, c, d, tx, ty)\n    }\n\n    // Get he current slide width\n    const width = parseInt(style.width);\n\n    // Get the carrousel viewport width\n    let findwidget = carrouselwidgets.filter(carrwidget => carrwidget.node == widget);\n    findwidget = findwidget.length ? findwidget[0] : null;\n    const viewport = findwidget.carrousel.nodes.viewport.getBoundingClientRect();\n\n    // Go to the link if this slide is completely visible (or if it doesn't fit but is currently active)\n    if ((xpos >= 0 && (xpos + width) < viewport.width) || slidecontainer.classList.contains(\"carrousel__cell--aligned\"))\n      location.href = anchor.href;\n\n    event.preventDefault();\n    event.stopPropagation();\n  }\n}\n\nfunction doOnlyAllowSlideImageLinksOnActiveSlides(evt) {\n  // we only want to follow links in active slides... we could either\n  // 1. cancel when the click is fired directly after a drag action\n  // 2. handle the anchor upon a 'iscroll tap event' if needed and cancel normal click events (we chose this route because 'tap' is fired much quicker resulting in a more responsive UI)\n  evt.preventDefault();\n  return;\n  /*\n  let cell = evt.target.closest(\".carrousel__cell\");\n  if (!cell)\n    return;\n\n  // only block links on the slide's image\n  if (!evt.target.closest(\".carrousel__cell-image\"))\n    return;\n\n  if (!cell.classList.contains(\"carrousel__cell--aligned\"))\n    evt.preventDefault();\n  */\n}\n\n\n\ndompack.register(\".carrouselwidget\", (node, idx) => {\n  if (!idx)\n    whitespace = getContentBlank(node);\n\n  const carrousel =\n    new Carrousel(node, {\n      paddingLeft: whitespace.spaceLeft,\n      paddingRight: whitespace.spaceRight\n      //, contentWidth: whitespace.contentWidth\n    });\n\n  const widget =\n  {\n    node: node,\n    carrousel: carrousel,\n    islarge: node.classList.contains(\"carrouselwidget--large\")\n  };\n\n  carrouselwidgets.push(widget);\n\n  fixCarrouselWidgetMinHeight(widget);\n\n  // iScroll replacement for \"click\", for quick response and it won't be triggered during a drag/swipe\n  node.addEventListener(\"tap\", doCheckForCarouselVideoTrigger);\n\n  node.addEventListener(\"click\", doOnlyAllowSlideImageLinksOnActiveSlides);\n\n  //var vpnode = carrousel.nodes.viewport;\n  if (carrousel.iscroll) {\n    carrousel.iscroll.on(\"scrollStart\", () => doPauseHeaderAnimation(\"scrollStart\"));\n    //carrousel.iscroll.on(\"beforeScrollStart\", () => doPauseHeaderAnimation(\"beforeScrollStart\"));\n    //carrousel.iscroll.on(\"scrollCancel\",      () => doUnpauseHeaderAnimation(\"scrollCancel\"));\n    carrousel.iscroll.on(\"flick\", () => doUnpauseHeaderAnimation(\"flick\"));\n    carrousel.iscroll.on(\"scrollEnd\", () => doUnpauseHeaderAnimation(\"scrollEnd\"));\n  }\n\n  if (!idx) {\n    window.addEventListener(\"resize\", refreshAllCarousels);\n    window.__carrouselwidgets = carrouselwidgets;\n\n    document.addEventListener(\"DOMContentLoaded\", remeasureSlides); // may help, but at this time the event might already have fired\n    window.addEventListener(\"load\", remeasureSlides); // Fix/workaround Safari reporting the wrong height for the first slide\n  }\n}, { afterdomready: true });\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport { JustifiedImageGrid } from \"@webhare/dompack-justifiedcontentgrid\";\nimport * as fsslideshow from \"./fullscreen-slideshow\";\n\nimport \"../../../shared/hoversupport\";\nimport \"./photoalbum.css\";\n\n\nconst __photoalbum_grids = [];\n\n\n///////////////////////////////////////////////////////////////////////////////////\n//\n//  Photoalbum overview (justified image grid)\n//\n\nfunction refreshAllPhotoAlbums() {\n  for (const grid of __photoalbum_grids) {\n    const defaultoptions = getDefaultGridOptions(grid.container); // FIXME: is 'container' public?\n    grid.setOptions(defaultoptions);\n    grid.refresh();\n  }\n}\n\nfunction doCheckForImageSelection(evt) {\n  const item = evt.target.closest(\".photoalbumwidget__item\");\n  if (!item)\n    return;\n\n  //console.log(\"Item\", item);\n\n  const grid = evt.target.closest(\".photoalbumwidget\");\n  const instanceid = grid.getAttribute(\"data-instanceid\");\n  //console.log(\"Grid\", grid);\n\n  let items = grid.querySelectorAll(\".photoalbumwidget__item\");\n  //items = Array.prototype.slice.call(items); // convert [Object] to [Array]\n  items = Array.from(items);\n  //console.log(\"All items\", items);\n\n  //console.log(typeof items);\n\n  const itemidx = items.indexOf(item);\n  if (itemidx === -1)\n    return;\n\n  //console.log(\"Opening carrousel slideshow at #\"+itemidx);\n\n  const headeranim = document.querySelector(\".header__universe\");\n  if (headeranim)\n    headeranim.style.display = \"none\";\n\n  fsslideshow.doActivateSlideshow(instanceid, itemidx);\n}\n\nfunction getDefaultGridOptions(node) {\n  //console.log(\"getDefaultGridOptions\", node);\n  let dpr = window.devicePixelRatio;\n  if (!dpr)\n    dpr = 1; // fallback for IE10\n\n  const contentWidth = node.clientWidth;\n\n  // WARNING: setting the row_height higher may cause some rows not to fit two images,\n  //          blowing up a single image to fill a row (which looks blurry)\n  const defaultoptions =\n  {\n    width: Math.round(contentWidth * dpr) / dpr,\n    row_height: Math.round(contentWidth / 2.75 * dpr) / dpr,\n    gutter_x: Math.round(contentWidth * dpr / 50) / dpr,\n    gutter_y: Math.round(contentWidth * dpr / 50) / dpr\n  };\n\n  return defaultoptions;\n}\n\n\n\ndompack.register(\".photoalbumwidget\", (node, idx) => {\n  const gridnode = node.querySelector(\".justifiedmediagrid\");\n\n  const defaultoptions = getDefaultGridOptions(gridnode);\n  const grid = new JustifiedImageGrid(gridnode, defaultoptions);\n\n  __photoalbum_grids.push(grid);\n\n  grid.refresh();\n\n  gridnode.addEventListener(\"click\", doCheckForImageSelection);\n\n  if (!idx) {\n    window.addEventListener(\"resize\", refreshAllPhotoAlbums);\n    window.addEventListener(\"load\", refreshAllPhotoAlbums);\n  }\n}, { afterdomready: true });\n","import * as dompack from \"dompack\";\n\n\nexport class JustifiedContentGrid\n{\n  constructor(container, options)\n  {\n    this.container = null;\n    this.gridcontainer = null;\n    this.items = [];\n\n    // vars for auto update in case image dimensions have to be determines and updated on the fly\n    this.newinforefreshtimer = null;\n    this.waitingforimagecount = 0;\n\n    this.options =\n      { width:              0\n      , height:             0\n\n      , row_height:         256 // used for direction: \"horizontal\"\n      , column_width:       256 // used for direction: \"vertical\"\n\n\n      // the amount of rows(if direction=\"horizontal\") or columns if direction=\"vertical\"\n      // if set and the track's size is fixed, any images which do not fit in the specified amount of tracks won't be shown\n      //, tracks:             4 // FIXME: not implemented\n\n      // \"keep\" - keep original ordering\n      // \"bestfit\" - order in such a way as to get equal sized tracks\n      //, ordering:           \"keep\" // FIXME: not implemented\n\n      , gutter_x:           2\n      , gutter_y:           2\n\n      , debug:              false\n      , debug_layout:       false\n\n      , fill_last_strip_threshold: 40\n      };\n\n    //this.setOptions(options);\n    this.options = {...this.options, ...options};\n\n    //this.gridcontainer = new Element(\"div\", { styles: { position: \"relative\" } });\n    this.gridcontainer = document.createElement(\"div\");\n    this.gridcontainer.style.position = \"relative\";\n\n    if (typeof this.container == \"string\")\n      this.container = document.querySelector(container);\n    else// if node\n      this.container = container;\n  }\n\n  setOptions(options)\n  {\n    Object.assign(this.options, options);\n  }\n\n  /** @short relayout\n  */\n  refresh()\n  {\n    this.refreshHorizontal();\n  }\n\n  refreshHorizontal()\n  {\n    var strip_width = this.options.width; // container width\n    var strip_height = this.options.row_height;\n\n    if (strip_width == 0)\n    {\n      strip_width = this.container.clientWidth;\n\n      if (strip_width == 0)\n      {\n        console.warn(\"Cannot draw, the clientWidth of the specified container is 0 (display: none; ?).\");\n        return;\n      }\n    }\n\n    var img_idx = 0;\n    var img_count = this.items.length;\n\n    var current_width = 0\n      , current_width_next = 0\n      , row = 0\n      , ypos = 0;\n\n    this.options.debug = this.options.debug || this.options.debug_layout;\n\n    if (this.options.debug)\n    {\n      if (console.groupCollapsed)\n        console.groupCollapsed(\"JustifiedContentGrid refresh\");\n      else\n        console.group(\"JustifiedContentGrid refresh\");\n\n      console.log(img_count, \"images\");\n\n      if (!this.options.debug_layout)\n        console.log(\"You can also use debug_layout for more information.\");\n    }\n\n    if (this.options.debug_layout)\n      console.log(\"strip_width:\", strip_width);\n\n    var maxiterations = 999;\n    var maxrows = 999;\n    while(img_idx < img_count && row < maxrows && maxiterations > 0)\n    {\n      maxiterations--;\n\n      var column = 0;\n      var current_width = 0;\n      var current_width_next = 0;\n\n      if (row > 0)\n        ypos += this.options.gutter_y;\n\n      // determine how many items can fit\n      var img_this_strip = [];\n      var item = null;\n      while(img_idx < img_count && current_width_next < strip_width)\n      {\n        item = this.items[img_idx];\n\n        // determine width we need to get the height to exactly fit\n        var resized_width = Math.ceil(item.width * (strip_height / item.height));\n        item.width_apply = resized_width;\n\n        /*\n        console.log({ width:   item.width\n                    , height:  item.height\n                    , width_r: item.width_apply\n                    });\n        */\n\n        current_width_next += item.width_apply + (column == 0 ? 0 : this.options.gutter_x);\n\n        if (current_width_next < strip_width)\n        {\n          current_width = current_width_next;\n          img_this_strip.push(item);\n          img_idx++;\n        }\n\n        column++;\n      }\n      column--;\n\n      //console.info(\"img_this_strip\", img_this_strip);\n\n      // the total amount of pixels to add or substract from images in this strip\n      var compensatex = 0;\n\n      // Determine what strategy would be the best for getting content\n      // nicely justified (with the less amount of stretching or shrinking)\n      // (unless we fit exactly)\n      if (current_width != strip_width)\n      {\n        var grow_if_no_extra_image = strip_width - current_width; // how many pixels do items have to grow to fit?\n        var shrink_if_extra_image = current_width_next - strip_width; // if we add one extra image (and overflow), how many pixels do items have to shrink to fit?\n\n        //console.log(img_idx, img_count);\n        //console.log(row);\n\n        if (img_this_strip.length == 0) // single wide (panoramic) image\n        {\n          img_this_strip.push(item);\n          column++; // (for debugging or if we want to store the column and row in the array)\n\n          // Scale the image to fill the width & height of this strip\n          var scale_to_fill_width  = strip_width  / item.width;\n          var scale_to_fill_height = strip_height / item.height;\n          var scale_to_fill_both   = scale_to_fill_width > scale_to_fill_height ? scale_to_fill_width : scale_to_fill_height;\n\n          // For blowing up the items a little we center on the middle and\n          var result_width = Math.ceil(item.width * scale_to_fill_both);\n          var result_height = Math.ceil(item.height * scale_to_fill_both);\n\n          item.width_apply = result_width;\n\n          /*\n          console.log({ scale_w: scale_to_fill_width\n                      , scale_h: scale_to_fill_height\n                      , scale_final: scale_to_fill_both\n                      , result_width: result_width\n                      , result_height: result_height\n                      });\n          */\n\n          item.node_applied = { left:   0\n                              , top:    ypos\n                              , width:  strip_width\n                              , height: strip_height\n                              };\n\n          // update the clipping node\n          item.node.style.left   = \"0\";\n          item.node.style.top    = ypos+\"px\";\n          item.node.style.width  = strip_width+\"px\";\n          item.node.style.height = strip_height+\"px\";\n\n          // FIXME: positioning can happen in non-rounded pixels...\n          //        prevent this by increasing the scale_to_fill_both a tiny bit so we can Math.floor ?\n\n          item.img_applied =  { left:  (strip_width - result_width) / 2\n                              , top:   (strip_height - result_height) / 2\n                              , width: item.width_apply\n                              };\n\n          // update the image\n          item.img.style.width = item.width_apply+\"px\";\n          item.img.style.left = item.img_applied.left + \"px\";\n          item.img.style.top = item.img_applied.top + \"px\";\n\n          column++; // (for debugging or if we want to store the column and row in the array)\n          img_idx++;\n\n          row++;\n          ypos += strip_height;\n\n          if (this.options.debug_layout)\n            console.log(img_idx, \"will fill it's own row (panoramic)\");\n\n          continue;\n        }\n        if (img_idx == img_count && this.options.fill_last_strip_threshold < grow_if_no_extra_image)\n        {\n          img_this_strip.push(item);\n          column++; // (for debugging or if we want to store the column and row in the array)\n\n          if (this.options.debug_layout)\n            console.log(img_idx, \"last image but no need to grow (fill_last_strip_threshold lower than empty space\");\n        }\n        else if (grow_if_no_extra_image < shrink_if_extra_image)\n        {\n          // 1. grow the items which fit to fill up all space\n          compensatex = grow_if_no_extra_image;\n\n          if (this.options.debug_layout)\n            console.log(img_idx, \"will distribute\", compensatex, \"to items in row\");\n        }\n        else // also get the current image into this column\n        {\n          // 2. shrink the items to fit\n          compensatex = -shrink_if_extra_image;\n          img_this_strip.push(item);\n\n          if (this.options.debug_layout)\n            console.log(img_idx, \"will shrink\", compensatex, \"to make a last image fit in the row\");\n\n          column++; // (for debugging or if we want to store the column and row in the array)\n          img_idx++;\n        }\n      }\n\n      if (this.options.debug_layout)\n        console.info(\"Row #\"+row+\" contains \", img_this_strip.length, \"images\");\n\n\n      // if (compensatex != 0)\n      var add_each_item = Math.floor(compensatex / column);\n      var add_last_item = compensatex - add_each_item * column;\n\n      if (this.options.debug_layout)\n      {\n        console.info(\"We need to grow\"); //, distributing\", compensatex, \" over\", column, \"columns.\");\n        console.info(\n            { compensatex:   compensatex\n            , columns:       column\n            , add_each_item: add_each_item\n            , add_last_item: add_last_item\n            });\n      }\n\n      var xpos = 0;\n      for (var col_idx = 0; col_idx < column; col_idx++)\n      {\n        //console.log(col_idx);\n        var item = img_this_strip[col_idx];\n\n        item.width_apply_orig = item.width_apply;\n\n        // apply extra pixels\n        if (compensatex != 0)\n        {\n          item.width_apply += add_each_item;\n          if (col_idx == column - 1)\n            item.width_apply += add_last_item;\n        }\n\n        // styles for the container/cropping node\n        item.node_applied = { left: xpos\n                            , top:  ypos\n                            , width: item.width_apply\n                            , height: strip_height\n                            };\n\n        if (compensatex > 0)\n        {\n          // For blowing up the items a little we center on the middle and\n          // cut off a little at the top and bottom\n          var expected_height = item.height * (item.width_apply / item.width);\n          /*\n          console.log({ img: item.img\n                      , width: item.width\n                      , width_scaled: item.width_apply_orig\n                      , width_scaled_justified: item.width_apply\n                      , expected_height: item.expected_height\n                      , left: 0\n                      , top:  (strip_height - expected_height) / 2\n                      });\n          */\n\n          item.img_applied =  { left: 0\n                              , top:  Math.round((strip_height - expected_height) / 2)\n                              , width: item.width_apply\n                              };\n        }\n        else if (compensatex < 0) // < 0, because == 0 is already handled\n        {\n          // Shrinking items has to be done by cutting off pixels at the sides\n          // (because we resize to exactly fit in the height, so if we zoom out whe'll have empty border)\n\n          item.img_applied =  { left: Math.round((item.width_apply - item.width_apply_orig) / 2)\n                              , top:  0\n                              , width: item.width_apply_orig\n                              };\n\n        }\n        else if (compensatex == 0)\n        {\n          item.img_applied =  { left:  0\n                              , top:   0\n                              , width: item.width_apply_orig\n                              };\n        }\n\n        // update the container/clipping node\n        item.node.style.left   = item.node_applied.left+\"px\";\n        item.node.style.top    = item.node_applied.top+\"px\";\n        item.node.style.width  = item.node_applied.width+\"px\";\n        item.node.style.height = item.node_applied.height+\"px\";\n\n        // update the image\n        item.img.style.left    = item.img_applied.left+\"px\";\n        item.img.style.top     = item.img_applied.top+\"px\";\n        item.img.style.width   = item.img_applied.width+\"px\";\n\n        xpos += item.width_apply + this.options.gutter_x;\n      }\n\n      /*\n      if (item.node_applied)\n        console.log(item.node_applied.width + \"x\" + item.node_applied.height + \" at \" + item.node_applied.left + \"x\" + item.node_applied.top);\n      else\n        console.log(\"no node_applied for item\");\n      */\n\n      row++;\n      ypos += strip_height;\n    }\n\n    this.gridcontainer.style.width = this.options.width+\"px\";\n    this.gridcontainer.style.height = ypos+\"px\";\n\n    if (this.options.debug)\n    {\n      console.log(\"The grid consists of\", row, \"rows\");\n      console.groupEnd();\n    }\n  }\n\n\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n//\n//  Private functions\n//\n\n  importItems(items)\n  {\n    var frag = document.createDocumentFragment();\n\n    for (var tel=0; tel < items.length; tel++)\n    {\n      var item = items[tel];\n\n      //var clip_node = new Element(\"div\", { styles: { position: \"absolute\", overflow: \"hidden\" } });\n      var clip_node = document.createElement(\"div\");\n      clip_node.style.cssText = \"position: absolute; overflow: hidden;\";\n      clip_node.appendChild(item.contentnode);\n\n      frag.appendChild(clip_node);\n\n      item.node = clip_node;\n    }\n\n    this.gridcontainer.appendChild(frag);\n  }\n};\n\n\nexport class JustifiedImageGrid extends JustifiedContentGrid\n{\n  /** @short import images from the specified node\n  */\n  constructor(container, options)\n  {\n    super(container, options);\n\n    //var images = container.getElements(\"IMG\");\n    var items = container.children;\n    var imgcount = items.length;\n\n    var new_items = [];\n\n    for(var img_idx = 0; img_idx < imgcount; img_idx++)\n    {\n      // 1. preferred method is when the HTML author specified the dimensions\n      var img = items[img_idx];\n      //console.log(\"Importing \", img);\n\n      var contentnode;\n      // assume these are anchors/containers with the image inside them\n      if (img.tagName != \"IMG\")\n      {\n        contentnode = img;\n        //img = $(contentnode).getElement(\"img\"); // $() needed for IE<9\n        img = img.querySelector(\"img\");\n        if (!img)\n        {\n          console.warn(\"missing image node\");\n          continue;\n        };\n      }\n      else\n      {\n        contentnode = img;\n      };\n\n      img.style.position = \"absolute\";\n\n      var imgwidth = img.getAttribute(\"data-width\");\n      var imgheight = img.getAttribute(\"data-height\");\n\n      // 2. otherwise check whether the browsers already has access to at least the size of the image\n      if (imgwidth === null)\n        imgwidth = img.naturalWidth;\n      else\n        imgwidth = parseInt(imgwidth);\n\n      if (imgheight === null)\n        imgheight = img.naturalHeight;\n      else\n        imgheight = parseInt(imgheight);\n\n      // remove width & height attributes so they won't interfere\n      // FIXME: or should we always set our height in the inline styles?\n      img.removeAttribute(\"width\");\n      img.removeAttribute(\"height\");\n\n      // store the known data on the image\n      var imgdesc =\n          { img:    img\n          , contentnode: contentnode // the node to be imported in the clipping node\n          , node:   null             // clipping node, to be set in the JustifiedContentGrid::importNode() function\n          , width:  imgwidth\n          , height: imgheight\n          };\n      new_items.push(imgdesc);\n\n      // if no image dimensions available yet (image not loaded) resort to updating this info later\n      if (imgwidth == 0 || imgheight == 0)\n      {\n        this.waitingforimagecount++;\n        img.addEventListener(\"load\", this.__onImageLoad.bind(this, imgdesc));\n      }\n    };\n\n    this.importItems(new_items);\n\n    //this.items.append(new_items);\n    this.items = this.items.concat(new_items);\n\n    this.container.appendChild(this.gridcontainer);\n  }\n\n  /** @short add images by passiging an array with image information\n      @param images\n      @cell images.url\n      @cell images.width\n      @cell images.height\n, addImages: function(images)\n  {\n    // ADDME: validate?\n\n    // now append in a single operation\n    this.items.append(images);\n  }\n  */\n\n  __onImageLoad(item_ref, evt)\n  {\n    if (this.options.debug)\n      console.log(\"Updating image size\");\n\n    var imgnode = evt.target;\n    item_ref.width = imgnode.naturalWidth;\n    item_ref.height = imgnode.naturalHeight;\n\n    imgnode.dataset.width = item_ref.width;\n    imgnode.dataset.height = item_ref.height;\n\n    this.waitingforimagecount--;\n    if (this.waitingforimagecount == 0)\n    {\n      // this was the last image we needed, we can cancel the timer and directly force an refresh\n      clearTimeout(this.newinforefreshtimer);\n      this.__forceRefresh();\n    }\n    else if (!this.newinforefreshtimer)\n    {\n      // update on a timer to make sure we don't update for every single image\n      this.newinforefreshtimer = setTimeout(() => this.__forceRefresh(), 250);\n    }\n  }\n\n  __forceRefresh()\n  {\n    this.newinforefreshtimer = null;\n    this.refresh();\n  }\n};\n","import * as dompack from \"dompack\";\nimport * as browser from 'dompack/extra/browser';\n\ndompack.onDomReady(() => {\n  const ios = browser.getPlatform() === \"ios\";\n  document.documentElement.classList.add(ios ? \"nohover\" : \"allowhover\");\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./carrousel.scss\";\nimport \"./slideshow.scss\";\nimport * as dompack from \"dompack\";\n//import CarrouselSlideshow from \"@webhare/dompack-carrousel-slideshow\";\nimport CarrouselSlideshow from \"./dompack-carrousel-slideshow\";\nimport * as videotools from \"../../../components/video\";\n\n\nwindow.__widget_slideshow = [];\n\n\nclass SlideshowWidget {\n  constructor(widgetnode) {\n    this.widgetnode = widgetnode;\n\n    if (widgetnode.classList.contains(\"slideshowwidget--multipleslides\")) {\n      this.slideinfonodes = widgetnode.querySelectorAll(\".slideshowwidget__slideinfo\");\n\n      const btn_prev = widgetnode.querySelector(\".slideshowwidget__previousbutton\");\n      const btn_next = widgetnode.querySelector(\".slideshowwidget__nextbutton\");\n\n      // NOTE: Make sure we have a .carrousel__dragarea in the DOM to prevent\n      //       the whole widget triggering dragging of the slideshow.\n      this.slideshow =\n        new CarrouselSlideshow(this.widgetnode\n          , {\n            jumpbuttons: \".slideshowwidget__slidedot\",\n            jumpbutton_selectedclass: \"slideshow--activedot\",\n            autoplay: true,\n            eventPassthrough: true,\n            buttonprevious: btn_prev,\n            buttonnext: btn_next,\n            transitionDuration: 500 // see config.scss for $slideshow-duration\n          });\n\n      // Pause the slideshow when hovering over it, completely stop it when clicking one of the buttons\n      this.widgetnode.addEventListener(\"mouseenter\", () => this.pauseSlideshow());\n      this.widgetnode.addEventListener(\"mouseleave\", () => this.resumeSlideshow());\n      btn_prev.addEventListener(\"click\", () => this.stopSlideshow());\n      btn_next.addEventListener(\"click\", () => this.stopSlideshow());\n\n      window.__widget_slideshow.push(\n        {\n          node: widgetnode,\n          widget: this,\n          slideshow: this.slideshow\n        });\n\n      widgetnode.addEventListener(\"wh:activeslidechange\", evt => this.onSlideChange(evt));\n\n      // iScroll replacement for \"click\", for quick response and it won't be triggered during a drag/swipe\n      widgetnode.addEventListener(\"tap\", evt => this.doCheckForSlideshowVideoTrigger(evt));\n    } else {\n      widgetnode.addEventListener(\"click\", evt => this.doCheckForSlideshowVideoTrigger(evt));\n    }\n  }\n\n  onSlideChange(evt) {\n    //console.log(\"onSlideChange\", evt);\n\n    this.slideinfonodes[evt.detail.previousactiveidx].classList.remove(\"active\");\n    this.slideinfonodes[evt.detail.nextactiveidx].classList.add(\"active\");\n\n    if (evt.detail.previousactivenode)\n      this.deactivateSlide(evt.detail.previousactivenode);\n  }\n\n  pauseSlideshow() {\n    if (!this.deactivated) {\n      this.slideshow.scrolling = false; // FIXME: a tap should cancel scrolling state within the slideshow code itself\n      this.slideshow.pause();\n      this.widgetnode.classList.add(\"slideshow--paused\");\n    }\n  }\n\n  resumeSlideshow() {\n    if (!this.deactivated) {\n      this.slideshow.play();\n      this.widgetnode.classList.remove(\"slideshow--paused\");\n    }\n  }\n\n  stopSlideshow() {\n    this.slideshow.scrolling = false; // FIXME: a tap should cancel scrolling state within the slideshow code itself\n    this.slideshow.pause();\n    this.deactivated = true;\n    this.widgetnode.classList.remove(\"slideshow--paused\");\n  }\n\n  stopVideoSlide(slidecontainer) {\n    console.log(\"stopCarrouselVideo\", slidecontainer);\n\n    this.passBlockPointerEvents(false);\n\n\n    //slidecontainer.classList.remove(\"carrousel__cell--active\");\n    try {\n      if (slidecontainer._wsVideoPlayer)\n        slidecontainer._wsVideoPlayer.pause();\n    } catch (err) // happens if the YouTube API isn't running on https\n    {\n      /*\n      let frame = slidecontainer.querySelector(\"iframe\");\n      if (frame)\n      {\n        slidecontainer._wsVideoFrame = frame;\n        frame.parentNode.removeChild(frame);\n      }\n      */\n    }\n\n    if (this.slideshow)\n      this.slideshow.play();\n  }\n\n\n  deactivateSlide(slidenode) {\n    if (slidenode._wsVideoPlayer)\n      this.stopVideoSlide(slidenode);\n\n    this.widgetnode.classList.remove(\"slideshowwidget--videoplaying\");\n\n    slidenode.classList.remove(\"active\");\n  }\n\n\n  passBlockPointerEvents(pass) {\n    if (this.slideshow)\n      this.slideshow.carrousel.iscroll.options.preventDefault = !pass;\n  }\n\n\n  doCheckForSlideshowVideoTrigger(event) {\n    const widget = event.target.closest(\".slideshowwidget\");\n    if (!widget)\n      return;\n\n    const slidecontainer = event.target.closest(\".carrousel__cell\");\n    if (!slidecontainer)\n      return;\n\n    const videocontainer = slidecontainer.querySelector(\"[data-video]\");\n    if (!videocontainer)\n      return;\n\n    //If playing video, set slideshow over deeplinks\n    this.widgetnode.classList.add(\"main__contents--overdeeplinks\");\n\n    if (event.target.closest(\".video-close\")) {\n      event.preventDefault();\n      event.stopPropagation();\n      this.deactivateSlide(slidecontainer);\n    } else {\n      event.preventDefault();\n      event.stopPropagation();\n\n      slidecontainer.classList.add(\"active\");\n\n      if (videotools.isVideoNodeInitialized(videocontainer)) {\n        this.widgetnode.classList.add(\"slideshowwidget--videoplaying\");\n\n        if (this.slideshow) {\n          this.slideshow.scrolling = false; // FIXME: a tap should cancel scrolling state within the slideshow code itself\n          this.slideshow.pause();\n        }\n\n        this.passBlockPointerEvents(true); // Allow interaction with the video and it's controls\n        slidecontainer._wsVideoPlayer.play();\n      } else\n        videotools.initializeVideoNode(videocontainer).then(player => {\n          this.passBlockPointerEvents(true); // Allow interaction with the video and it's controls\n          this.widgetnode.classList.add(\"slideshowwidget--videoplaying\");\n\n          if (this.slideshow) {\n            this.slideshow.scrolling = false; // FIXME: a tap should cancel scrolling state within the slideshow code itself\n            this.slideshow.pause();\n          }\n\n          slidecontainer._wsVideoPlayer = player;\n        });\n    }\n  }\n}\n\n\ndompack.register(\".slideshowwidget\",\n  widgetnode => new SlideshowWidget(widgetnode)\n);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport Carrousel from \"@webhare/dompack-carrousel\";\n\n\nwindow.__dompack_cslideshow_idx = 0;\nwindow.__dompack_cslideshows = [];\n\n\n\nlet __observer;\nif (window.IntersectionObserver)\n  __observer = new IntersectionObserver(checkSlideshowVisibility);\n\ndocument.addEventListener(\"visibilitychange\", onDocumentVisibilityChange);\n\n\nfunction onDocumentVisibilityChange() {\n  for (const slideshow of window.__dompack_cslideshows)\n    slideshow.__handleVisibilityChange();\n}\n\nfunction checkSlideshowVisibility(entries, observer) {\n  //console.log(\"checkSlideshowVisibility\");\n  //console.info(entries);\n\n  const visible = [];\n  const invisible = [];\n  for (const entry of entries) {\n    if (entry.isIntersecting)\n      visible.push(entry.target);\n    else\n      invisible.push(entry.target);\n  }\n\n  for (const slideshow of window.__dompack_cslideshows) {\n    const isvisible = visible.indexOf(slideshow.node) > -1;\n    if (!isvisible && invisible.indexOf(slideshow.node) === -1)\n      continue; //node should be at least in one of the lists, else ignore.\n\n    slideshow.inviewport = isvisible;\n    slideshow.__handleVisibilityChange();\n  }\n}\n\n\n\n\nexport default class CarrouselSlideshow {\n  constructor(node, options) {\n    if (!node) {\n      console.error(\"CarrouselSlideshow got null as node.\");\n      return;\n    }\n\n    window.__dompack_cslideshow_idx++; // used for anonymous this.option.name\n    window.__dompack_cslideshows.push(this);\n\n    const domoptions = dompack.getJSONAttribute(node, \"data-carrousel-options\");\n\n    this.node = node;\n    this.inviewport = this.__determineInViewport(node);\n    this.lastautoslidetime = null;\n    this.scrolling = false;\n    this.ignore_scroll = false; // ignore_scroll caused by our own resizes/relayouts\n\n    this.options = {\n      autoplay: true,\n      autoplay_initialdelay: 0,       // delay the first start of autoplay to prevent having a lot of slideshows run in sync\n      autoplay_freezeslideduration: 6000, // how long to keep the slide still (FIXME: should be after the transition) before going to the next\n      //, autoplay_staypausedfor        // amount of time to keep frozen after a mouseover\n      transitionDuration: 1500,\n\n      eventPassthrough: true,    // makes vertical scrolling keep on working (however at the moment it can cause textual selections)\n      updateviewportheight: false,\n\n      jumpbuttons: \".carrousel__jumpbutton\", // FIXME\n      jumpbutton_selectedclass: \"active\", // FIXME\n      buttonprevious: null,\n      buttonnext: null,\n      debug: false,\n      autoresize: true,\n      name: \"slideshow\" + window.__dompack_cslideshow_idx, ...domoptions, ...options\n    };\n\n    if (this.options.debug)\n      console.log(\"CarrouselSlideshow options\", this.options);\n\n    this.autoplaytimer = null;\n    this.playing = this.options.autoplay;\n\n\n    const carrousel_options =\n    {\n      transitionDuration: this.options.transitionDuration,\n      eventPassthrough: this.options.eventPassthrough,\n      gap: 0,\n      updateviewportheight: this.options.updateviewportheight\n    };\n\n    if (\"items\" in this.options)\n      carrousel_options.items = this.options.items;\n\n    if (this.options.debug)\n      console.info(\"Carrousel options\", carrousel_options);\n\n    this.carrousel = new Carrousel(node, carrousel_options);\n\n\n\n    const dragarea = this.carrousel.nodes.dragarea;\n\n    // For Firefox we need to cancel dragstart (otherwise <A> will be draggable)\n    dragarea.addEventListener(\"dragstart\", evt => this.doHandleDragStart(evt));\n\n    // We have cancel clicks and rely on iScroll's tap event,\n    // because clicks can be fired after scrolling.\n    dragarea.addEventListener(\"click\", evt => this.doHandleLinkClick(evt));\n    dragarea.addEventListener(\"tap\", evt => this.doHandleLinkTap(evt));\n\n\n\n    this.jumpbuttonnodes = [];\n    if (typeof this.options.jumpbuttons === \"string\")\n      this.jumpbuttonnodes = this.node.querySelectorAll(this.options.jumpbuttons);\n    else\n      this.jumpbuttonnodes = this.options.jumpbuttons; // assume an array, live nodelist or static nodelist\n\n    // ADDME: use tap if in carrousel viewport or click if outside\n    for (let idx = 0; idx < this.jumpbuttonnodes.length; idx++) {\n      // outside an iScroll container\n      this.jumpbuttonnodes[idx].addEventListener(\"click\", evt => this.__doJumpToSlide(idx, evt));\n\n      // when within an iScroll container\n      this.jumpbuttonnodes[idx].addEventListener(\"tap\", evt => this.__doJumpToSlide(idx, evt));\n    }\n\n    if (this.options.buttonprevious)\n      this.options.buttonprevious.addEventListener(\"click\", this.__handlePrevButton.bind(this));\n\n    if (this.options.buttonnext)\n      this.options.buttonnext.addEventListener(\"click\", this.__handleNextButton.bind(this));\n\n    /*\n    // iScroll replacement for \"click\", for quick response and it won't be triggered during a drag/swipe\n    node.addEventListener(\"tap\", doCheckForCarouselVideoTrigger);\n\n    node.addEventListener(\"click\", doOnlyAllowSlideImageLinksOnActiveSlides)\n    */\n\n    this.node.addEventListener(\"wh:activeslidechange\", this.onSlideChange.bind(this));\n\n    // Prevent autoplay overriding user-actions AND the autoscroll to a new slide\n    // (such as dragging, flicking, keyboard navigation etc...)\n    if (this.carrousel.iscroll) {\n      this.carrousel.iscroll.on(\"scrollStart\", this.__onScrollStart.bind(this));\n      this.carrousel.iscroll.on(\"scrollEnd\", this.__onScrollEnd.bind(this));\n    }\n\n    if (this.options.autoresize) {\n      if (this.options.debug)\n        console.info(\"AUTORESIZE enabled\");\n\n      this.bindedrefresh = this.relayoutSlides.bind(this);\n      window.addEventListener(\"resize\", this.bindedrefresh);\n      document.addEventListener(\"DOMContentLoaded\", this.bindedrefresh); // may help, but at this time the event might already have fired\n      window.addEventListener(\"load\", this.bindedrefresh); // Fix/workaround Safari reporting the wrong height for the first slide\n    }\n\n    if (__observer)\n      __observer.observe(node);\n\n    if (this.playing)\n      this.__applyCurrentAutoplay(this.options.autoplay_initialdelay);\n  }\n\n\n\n  doHandleDragStart(evt) {\n    // dragging stuff from inside a slideshow doesn't seem like a good thing to do\n    evt.preventDefault();\n  }\n\n  // Cancel the default browser click event, because it may fire during or after dragging using iScroll\n  doHandleLinkClick(evt) {\n    const anchor = evt.target.closest(\"a\");\n    if (!anchor)\n      return;\n\n    evt.preventDefault();\n  }\n\n  // When iScroll reports it was a tap (not a drag action) we can safely trigger the anchor\n  doHandleLinkTap(evt) {\n    // Are we in a link?\n    const anchor = evt.target.closest(\"a\");\n    if (!anchor)\n      return;\n\n    window.open(anchor.href, \"_blank\");\n  }\n\n\n  destroy() {\n    clearTimeout(this.autoplaytimer);\n    this.autoplaytimer = null;\n    this.playing = false;\n\n    if (this.bindedrefresh) {\n      window.removeEventListener(\"resize\", this.bindedrefresh);\n      document.removeEventListener(\"DOMContentLoaded\", this.bindedrefresh);\n      window.removeEventListener(\"load\", this.bindedrefresh);\n    }\n\n    this.carrousel.destroy();\n  }\n\n  __determineInViewport(node) {\n    const viewport = document.body.getBoundingClientRect();\n    const viewportheight = viewport.height;\n    const slideshowbounds = node.getBoundingClientRect();\n    return slideshowbounds.bottom >= 0 || slideshowbounds.top <= viewportheight;\n  }\n\n  __handlePrevButton() {\n    this.carrousel.previousSlide();\n  }\n\n  __handleNextButton() {\n    this.carrousel.nextSlide();\n  }\n\n  relayoutSlides() {\n    if (this.options.debug)\n      console.info(\"relayoutSlides\");\n\n    this.ignore_scroll = true;\n    this.carrousel.relayoutSlides();\n    this.carrousel.refresh();\n    this.ignore_scroll = false;\n  }\n\n\n  pause() {\n    this.playing = false;\n    this.__applyCurrentAutoplay();\n  }\n\n  play() {\n    this.playing = true;\n    this.__applyCurrentAutoplay();\n  }\n\n\n  refresh() {\n    this.relayoutSlides();\n    /*\n        console.info(\"refresh\");\n        this.ignore_scroll = true;\n        this.carrousel.refresh();\n        this.ignore_scroll = false;\n    */\n  }\n\n  onSlideChange(evt) {\n    const count = this.jumpbuttonnodes.length;\n\n    if (count > evt.detail.previousactiveidx)\n      this.jumpbuttonnodes[evt.detail.previousactiveidx].classList.remove(this.options.jumpbutton_selectedclass);\n\n    if (count > evt.detail.nextactiveidx)\n      this.jumpbuttonnodes[evt.detail.nextactiveidx].classList.add(this.options.jumpbutton_selectedclass);\n  }\n\n  __handleVisibilityChange() {\n    if (this.options.debug) {\n      console.info(this.options.name,\n        \"Page visible: \", !document.hidden,\n        \"Slideshow in viewport\", this.inviewport\n      );\n    }\n\n    this.__applyCurrentAutoplay();\n  }\n\n  __onScrollStart(evt) {\n    if (this.ignore_scroll)\n      return;\n\n    this.scrolling = true;\n    //this.__pauseAutoplay();\n  }\n\n  __onScrollEnd(evt) {\n    if (this.ignore_scroll)\n      return;\n\n    this.scrolling = false;\n    /*\n        // don't unpause if the document is hidden\n        if (document.hidden)\n          return;\n\n        this.__unpauseAutoplay();\n    */\n  }\n\n  __doJumpToSlide(idx, evt) {\n    evt.preventDefault();\n\n    // FIXME: animation disabled, the carrousel should offer the ability to find the closes path to the image (forward or backwards) or the animation will look like crap\n    //this.carrousel.jumpToSlide(idx, true, true);\n    this.carrousel.jumpToSlide(idx);\n  }\n\n  __applyCurrentAutoplay(delay) {\n    if (this.options.debug)\n      console.log(\"__applyCurrentAutoplay\");\n\n    if (!delay)\n      delay = 0;\n\n    // During scrolling we must finish the scroll.\n    // After the scroll has finished this function will be called again to schedule a slide change if needed.\n    if (this.scrolling) {\n      if (this.options.debug)\n        console.log(\"Not scheduling or cancelling a slide during scrolling.\");\n      return;\n    }\n\n    //console.log(this.__nextSlideByTimer);\n    if (this.playing && !document.hidden && this.inviewport) {\n      if (!this.autoplaytimer) {\n        if (this.options.debug)\n          console.log(\"Setting new timer for auto slide\");\n\n        this.autoplaytimer = setTimeout(this.__nextSlideByTimer.bind(this), this.options.autoplay_freezeslideduration + delay);\n      } else if (this.options.debug)\n        console.log(\"Timer already running...\");\n    } else {\n      if (this.options.debug)\n        console.log(\"No autoplay\", { play: this.playing, dochidden: document.hidden, inviewport: this.inviewport });\n\n      if (this.autoplaytimer) {\n        clearTimeout(this.autoplaytimer);\n        this.autoplaytimer = null;\n      }\n    }\n  }\n\n  __nextSlideByTimer() {\n    if (!this.options.autoplay) // did a timer event still get through?\n      return;\n\n    this.lastautoslidetime = new Date().getTime();\n\n    this.carrousel.nextSlide();\n\n    this.autoplaytimer = setTimeout(this.__nextSlideByTimer.bind(this), this.options.autoplay_freezeslideduration);\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./progress.scss\";\nimport * as dompack from \"dompack\";\n\nlet activestep;\n\ndompack.register(\".embeddedobject--progress\", node => {\n  // don't restore the scroll position from before reloading the page,\n  // we want to explicitly jump to the current progress/step.\n  if (\"scrollRestoration\" in history)\n    history.scrollRestoration = 'manual'; // Chr46+, FF46+, SF. Not IE or Edge yet.\n\n  const builder = new URL(location.href);\n\n  const steptags = builder.searchParams.get(\"step\") || '';\n  const parts = steptags.split(\"/\");\n  const steptag = parts[0];\n  const stepstate = parts.length > 1 ? parts[1] : \"\";\n\n  const activeoptions_str = builder.searchParams.get(\"activesteps\");\n  let activeoptions = [];\n  if (activeoptions_str)\n    activeoptions = activeoptions_str.split(\",\");\n\n  const allsteps = Array.from(node.querySelectorAll(\".progress__item\"));\n\n  activestep = node.querySelector('[data-progresstag=\"' + steptag + '\"]');\n\n  const activestepidx = allsteps.indexOf(activestep);\n\n  // Mark all steps up till the active step as passed\n  for (let idx = 0; idx <= activestepidx; idx++) {\n    const currentstep = allsteps[idx];\n\n    if (idx < activestepidx)\n      currentstep.classList.add(\"progress__item--passed\");\n    else {\n      if (stepstate === \"passed\" || stepstate === \"\")\n        activestep.classList.add(\"progress__item--passed\");\n      else if (stepstate === \"conditional\")\n        activestep.classList.add(\"progress__item--conditional\");\n      else\n        activestep.classList.add(\"progress__item--failed\");\n\n      activestep.classList.add(\"progress__item--currentitem\");\n    }\n\n    const tag = currentstep.getAttribute(\"data-progresstag\");\n\n    if (activeoptions.indexOf(tag) > -1 || currentstep === activestep)\n      currentstep.classList.add(\"progress__item--active\"); // activate an optional step\n  }\n\n  // Expand the active step\n  // foldablecontent is initialized onload (so as the last thing to initialize)\n  // in /src/widgets/embeddedobjects.js ....\n  // This is a hack to open the panel without needing to wait to after onload\n  // (we need to seperate .add because IE doesn't handle adding multiple classes at once)\n  if (activestep) {\n    // !! don't add --active, it's used to indicate that the foldablecontent events have been initialized on the node\n    activestep.classList.add(\"foldablecontent--open\");\n    activestep.querySelector(\".foldablecontent__foldcontainer\").style.cssText = \"height:auto;overflow:inherit;\";\n\n    /*\n    The \"proper\" way of opening the panel.. But it works only after the window load event:\n\n    dompack.dispatchCustomEvent(activestep, \"ws:foldable-set\",\n          { bubbles: true\n          , cancelable: false\n          , detail: { open: true }\n          });\n    */\n  }\n});\n\n\nfunction jumpToActiveStep() {\n  if (activestep) {\n    const node = document.querySelector(\".embeddedobject--progress\");\n\n    // We scroll to the widget because ideally we want to see the whole\n    // progress up to where we are now (activestep).\n    node.scrollIntoView();\n\n    // If the viewport is too small to see both the top of the widget\n    // and the active step, whe'll need to scroll further to the active step.\n    if (activestep.scrollIntoViewIfNeeded) // Chrome & Safari\n      activestep.scrollIntoViewIfNeeded();\n    else\n      activestep.scrollIntoView(); // Firefox\n  }\n}\n\n\nwindow.addEventListener(\"DOMContentLoaded\", jumpToActiveStep);\n\nwindow.addEventListener(\"load\", function () {\n  jumpToActiveStep();\n\n  // For Edge which restores the position, but doesn't support history.scrollRestoration yet\n  if (!(\"scrollRestoration\" in history))\n    setTimeout(jumpToActiveStep, 100);\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./timeline.scss\";\nimport \"./video-playbutton.scss\";\nimport * as dompack from \"dompack\";\nimport FilteredOverview from \"../../../filteredoverview\";\n\n// The updated masonry has some support for defining margins between different\n// types of content (headings, normal items, wide items)\n//import Masonry           from \"dompack-masonry\";\nimport Masonry from \"./dompack-masonry-update\";\n\nimport SmoothScroll from \"../../../components/smoothscroll\";\nimport * as videotools from \"../../../components/video\";\n\nwindow.__timelines = [];\n\nconst bookmark_offsety = -60;\n\nclass TimelinePageFilter extends FilteredOverview {\n  constructor(options) {\n    super({ ...options, filterpagetype: 'timeline' });\n\n    this.itemscontainer = document.querySelector(\".timeline__items\");\n\n    const items = this.itemscontainer.querySelectorAll(\".timeline__item\");\n\n    //this.setFeedback(items.length);\n\n    // keep an internal list of all items AND\n    // generate the list view based on content of the normal view\n    this.items = [];\n    for (const node of items) {\n      this.items.push({\n        node: node,\n        data: JSON.parse(node.dataset.filterdata)\n      });\n    }\n\n    if (this.isFilterActive())\n      this.doFilter();\n  }\n\n\n  showResults() {\n    //let activefilters = Object.keys(this.filters).length;\n    let totalfound = 0;\n\n    const yearsinresults = []; // In which years are the visible items?\n\n    for (const item of this.items) {\n      let doesnotmatch = false;\n\n      for (const key in this.filters) {\n        if (!(key in item.data)) {\n          if (this.debug_search)\n            console.log(\"Cannot find search key '\" + key + \"'\");\n          continue;\n        }\n\n        const itemvalue = item.data[key];\n        const searchvalue = this.filters[key];\n\n        if (this.debug_search)\n          console.log(\"Looking for\", searchvalue, \"in\", itemvalue);\n\n        if (Array.isArray(searchvalue) && Array.isArray(itemvalue)) // Find multiple values in multiple values\n        {\n          for (let i = 0; i < searchvalue.length; ++i) {\n            let found = false;\n            if (itemvalue.indexOf(this.filters[key][i]) > -1) {\n              found = true;\n              break;\n            }\n\n            if (!found)\n              doesnotmatch = true;\n          }\n        } else if (Array.isArray(itemvalue)) {\n          // lookup single value (pulldown or text) in array\n          if (itemvalue.indexOf(this.filters[key]) === -1)\n            doesnotmatch = true;\n        } else {\n          // lookup single value (pulldown or text) in a non-array (number of string)\n          const matchvalue = (typeof itemvalue === \"number\" ? parseInt(this.filters[key]) : this.filters[key]);\n          if (itemvalue !== matchvalue)\n            doesnotmatch = true;\n        }\n      }\n\n      const ismatch = !doesnotmatch;\n\n      item.node.classList[ismatch ? \"remove\" : \"add\"](\"timeline__item--hide\");\n\n      if (ismatch) {\n        if (yearsinresults.indexOf(item.data.year) === -1)\n          yearsinresults.push(item.data.year);\n\n        ++totalfound;\n      }\n\n      if (this.debug_search)\n        console.groupEnd();\n    }\n\n    this.setFeedback(totalfound);\n\n    for (const tlwidget of window.__timelines) {\n      tlwidget.widgetnode.classList[totalfound === 0 ? \"add\" : \"remove\"](\"embeddedobject--timeline--noresults\");\n\n      tlwidget.yearsinresults = yearsinresults;\n      tlwidget.refreshYearBookmarks(); // content of some years might not be visible anymore\n\n      tlwidget.refresh();\n    }\n  }\n}\n\n\nclass TimelineWidget {\n  constructor(widgetnode) {\n    window.__timelines.push(this);\n\n    this.widgetnode = widgetnode;\n    this.masonrynode = widgetnode.querySelector(\".timeline__items\");\n    this.masonry = null; // initialized on demand\n\n    this.preprocessItems();\n\n    window.addEventListener(\"load\", evt => this.refresh(evt));\n    window.addEventListener(\"resize\", evt => this.refresh(evt));\n    window.addEventListener(\"scroll\", evt => this.onScroll());\n\n    this.refresh();\n\n    this.createYearBookmarks();\n    this.refreshYearBookmarks();\n\n    widgetnode.addEventListener(\"click\", evt => this.doCheckForVideoTrigger(evt));\n\n    this.scroller = new SmoothScroll([]\n      , {\n        sethash: false,\n        offsety: bookmark_offsety\n      });\n  }\n\n  onScroll() {\n    this.refreshYearBookmarks();\n  }\n\n  preprocessItems() {\n    // keep an internal list of all items AND\n    // generate the list view based on content of the normal view\n    const items = this.widgetnode.querySelectorAll(\".timeline__item,.timeline__header,.timeline__break\");\n\n    this.items = [];\n\n    this.years = [];\n    this.yearsinresults = [];\n\n    for (const node of items) {\n      if (node.classList.contains(\"timeline__break\")) {\n        continue;\n      } else if (node.classList.contains(\"timeline__header\")) {\n        const year = parseInt(node.dataset.year);\n\n        this.years.push({\n          bookmarknode: null,\n          headernode: node,\n          year: year\n        });\n        this.yearsinresults.push(year);\n      } else {\n        this.items.push({\n          node: node,\n          data: JSON.parse(node.dataset.filterdata)\n        });\n      }\n    }\n\n    for (const itemnode of items) {\n      const labelnode = itemnode.nextElementSibling;\n\n      if (labelnode && labelnode.classList.contains(\"timeline__item__label\"))\n        itemnode.labelnode = labelnode;\n    }\n  }\n\n\n  onYearBookmarkClick(evt, year) {\n    evt.preventDefault();\n    evt.stopPropagation();\n\n    // find the first visible item for the given year\n    for (const item of this.items) {\n      if (item.data.year > year)\n        continue; // keep on looking\n\n      if (item.node.classList.contains(\"timeline__item--hide\"))\n        continue;\n\n      if ('scrollBehavior' in document.documentElement.style) {\n        const viewportrect = document.documentElement.getBoundingClientRect(); // document.scrollElement.\n        const itemrect = item.node.getBoundingClientRect();\n        const topy = itemrect.top - viewportrect.top + bookmark_offsety;\n        window.scrollTo({ behavior: \"smooth\", top: topy });\n      } else\n        this.scroller.scrollTo(item.node, evt);\n\n      return;\n    }\n  }\n\n\n  refresh(event) {\n    let options = {};\n\n\n    // Retrieve current settings from CSS /////////////////////////////////////////////////\n    const comp = window.getComputedStyle(this.masonrynode, '::before');\n    let layout = comp.content;\n\n    // remove the \" some browsers add (Safari doesn't add quotes)\n    if (layout !== \"\" && layout.substring(0, 1) === '\"')\n      layout = layout.substring(1, layout.length - 1); // remove the \"'s around the string\n\n    if (layout !== \"none\") {\n      const parts = layout.split(\":\");\n\n      options = {\n        columns: parseInt(parts[0]),\n        gutter_y: parseInt(parts[1]),\n        margin_header_top: parseInt(parts[2]),\n        margin_header_bottom: parseInt(parts[3])\n      };\n\n      if (parts.length > 3) {\n        // don't use masonrynode for measuring, the masonry will set the width when columnwidth is used.\n        if (options.columns > 1) {\n          options.columnwidth = this.masonrynode.clientWidth * 0.42;\n          options.gutter_x = this.masonrynode.clientWidth - options.columnwidth * options.columns / (options.columns - 1);\n        } else {\n          options.columnwidth = this.masonrynode.clientWidth;\n          options.gutter_x = 0;\n        }\n      } else\n        options.columnwidth = null;\n    } else {\n      // fallback values\n      options = {\n        columns: 2,\n        gutter_y: 50,\n        gutter_y_header: 35,\n        columnwidth: null\n      };\n    }\n    ////////////////////////////////////////////////////////////////////////////////////////\n\n\n    if (!this.masonry) {\n      this.masonry = new Masonry(this.masonrynode\n        , {\n          ...options,\n          items: \".timeline__item,.timeline__header\",\n          ignoreclass: \"timeline__item--hide\",\n          breakclass: \"timeline__header\"\n        });\n      this.masonry.refresh();\n    } else {\n      this.masonry.setOptions(options);\n      this.masonry.refresh();\n    }\n\n\n    this.repositionLabels();\n\n    /*\n    if (renderinfo.visiblewidgetscount == 0)\n      container.classList.add(\"masonry--noitems\");\n    else\n      container.classList.remove(\"masonry--noitems\");\n    */\n  }\n\n  repositionLabels() {\n    // Enhance the masonry rendering with indicator lines\n    const renderinfo = this.masonry.getLastRenderInfo();\n\n    for (let idx = 0; idx < renderinfo.items.length; idx++) {\n      const item = renderinfo.items[idx];\n\n      item.node.classList[item.col === 0 ? \"add\" : \"remove\"](\"timeline__content--leftside\");\n      item.node.classList[item.col !== 0 ? \"add\" : \"remove\"](\"timeline__content--rightside\");\n\n      if (item.node.labelnode) {\n        item.node.labelnode.classList[item.col === 0 ? \"add\" : \"remove\"](\"timeline__item__label--leftside\");\n        item.node.labelnode.classList[item.col !== 0 ? \"add\" : \"remove\"](\"timeline__item__label--rightside\");\n        item.node.labelnode.style.top = item.top + \"px\";\n      }\n    }\n  }\n\n\n  determineVisibleYears() {\n    const viewportrect = document.documentElement.getBoundingClientRect();\n\n    const visibleyears = [];\n\n    for (const item of this.items) {\n      if (visibleyears.indexOf(item.data.year) > -1)\n        continue; // skip we already have this year anyway\n\n      if (item.node.classList.contains(\"timeline__item--hide\"))\n        continue; // animating away or invisible\n\n      const itemrect = item.node.getBoundingClientRect();\n\n      if (itemrect.bottom > 0 && itemrect.top < viewportrect.height)\n        visibleyears.push(item.data.year);\n    }\n\n    return visibleyears;\n  }\n\n  createYearBookmarks() {\n    // The items should be ordered by date\n\n    // The positioning container for bookmarks\n    const bookmarkcontainer = document.createElement(\"div\");\n    bookmarkcontainer.className = \"timeline__bookmarks\";\n    this.bookmarkcontainer = bookmarkcontainer;\n\n    // Container to take content out of the flow\n    // (so it cannot push any content)\n    const bookmarkcontainer2 = document.createElement(\"div\");\n    bookmarkcontainer2.className = \"timeline__bookmarks__inner\";\n    this.bookmarkcontainer2 = bookmarkcontainer2;\n    this.bookmarkcontainer.appendChild(bookmarkcontainer2);\n\n    //let maincontentnode = document.getElementById(\"main\");\n    //maincontentnode.insertBefore(bookmarkcontainer, maincontentnode.firstChild);\n    this.widgetnode.insertBefore(bookmarkcontainer, this.widgetnode.firstChild);\n\n    for (const year of this.years) {\n      const bookmark = document.createElement(\"div\");\n      bookmark.className = \"timeline__bookmarks__item\";\n      bookmark.appendChild(document.createTextNode(year.year));\n      bookmark.addEventListener(\"click\", evt => this.onYearBookmarkClick(evt, year.year));\n      bookmarkcontainer2.appendChild(bookmark);\n\n      year.bookmarknode = bookmark;\n    }\n  }\n\n\n  refreshYearBookmarks() {\n    const visibleyears = this.determineVisibleYears();\n\n    for (const year of this.years) {\n      if (this.yearsinresults.indexOf(year.year) === -1) {\n        year.bookmarknode.classList.add(\"timeline__bookmarks__item--hide\");\n        year.bookmarknode.classList.remove(\"timeline__bookmarks__item--inview\");\n        year.headernode.classList.add(\"timeline__item--hide\");\n      } else {\n        year.bookmarknode.classList.remove(\"timeline__bookmarks__item--hide\");\n        year.headernode.classList.remove(\"timeline__item--hide\");\n\n        const inview = visibleyears.indexOf(year.year) > -1;\n        year.bookmarknode.classList[inview ? \"add\" : \"remove\"](\"timeline__bookmarks__item--inview\");\n      }\n    }\n  }\n\n\n  doCheckForVideoTrigger(event) {\n    const itemnode = event.target.closest(\".timeline__item\");\n\n\n    // Did we click on the close video button?\n    if (event.target.closest(\".generic_videocontainer__closevideo\")) {\n      event.preventDefault();\n      event.stopPropagation();\n\n      if (itemnode._wsVideoPlayer) {\n        itemnode._wsVideoPlayer.pause();\n        itemnode.classList.remove(\"genericvideoplayeractive\");\n      }\n\n      return;\n    }\n\n\n    // Did we click on a video play button?\n    if (!event.target.closest(\".timeline__item__playbutton\"))\n      return; // no? nothing to do then.\n\n\n    const videocontainer = itemnode.querySelector(\"[data-video]\");\n    if (!videocontainer)\n      return;\n\n\n    event.preventDefault();\n    event.stopPropagation();\n\n    if (videotools.isVideoNodeInitialized(videocontainer)) {\n      itemnode.classList.add(\"genericvideoplayeractive\");\n      itemnode._wsVideoPlayer.play();\n    } else {\n      videotools.initializeVideoNode(videocontainer).then(player => {\n        itemnode.classList.add(\"genericvideoplayeractive\");\n        itemnode._wsVideoPlayer = player;\n      });\n    }\n  }\n}\n\n\ndompack.register(\".embeddedobject--timeline\", node => new TimelineWidget(node));\n\n\ndompack.onDomReady(() => {\n  // This filterclass is meant for the Timeline Page\n  if (!document.documentElement.classList.contains(\"page--timeline\"))\n    return;\n\n  window.filteredoverview = new TimelinePageFilter({ itemsselector: \".timeline__item\" });\n});\n","/* eslint-disable */\n/// @ts-nocheck -- Rename to enable TypeScript validation\n\nimport * as whintegration from \"@mod-system/js/wh/integration\";\nimport * as dompack from '@webhare/dompack';\nimport UTAutoComplete from '@mod-utwente_base/webdesigns/ws2016/src/components/autocompleter2/autocompleter';\nimport \"../site.lang.json\";\nimport { getTid } from \"@webhare/gettid\";\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\nimport { SearchIndex } from \"./searchindex\";\nimport { debugFlags } from \"@webhare/env\";\nimport { pushToDataLayer } from \"@webhare/frontend\";\n\n/// fields for which we don't want to create a tag\nconst filtertags_ignorefields = [\"words\", \"query\"];\nconst filter_lastsettings: Filters = {};\nlet filter_lastseenkeys: string[] = [];\n\ntype ActiveFilterValue = {\n  name: string;\n  value: string | string[];\n  title: string | string[];\n};\n\n//Filters can be an array if they're a checkbox\ntype Filters = Record<string, string | string[]> & {\n  query?: string;\n};\n\ntype FilterItem = {\n  node: HTMLElement;\n  filterdata: Record<string, unknown> | null;\n  title: HTMLElement | null;\n  description: HTMLElement | null;\n};\n\ninterface FilteredOverviewHeaderOptions {\n  getResultsTeaserText?: typeof getResultsFeedbackText;\n  getResultsFeedbackText?: typeof getResultsFeedbackText;\n}\n\ninterface FilteredOverviewOptions extends FilteredOverviewHeaderOptions {\n  filterpagetype: string;\n  additionalform?: HTMLFormElement;\n}\n\n\n/** get default \"X results\" text. Also usefull to for pages with custom filtering\n *         or custom feedback bar to standardize on the same text as the Filtered Overview feedback bar.\n *  @param totalfound - amount of results\n *  @param totalshown - amount of results shown on the page\n *  @param allitemscount - amount of items there are without any filters active\n */\nexport function getResultsFeedbackText(totalfound: number, totalshown?: number) {\n  if (totalshown && totalshown < totalfound)\n    return getTid('utwente_base:frontend.ws2016.js.filteredoverview.feedbackbar-resultslimited', totalfound, totalshown);\n  else if (totalfound === 1)\n    return getTid('utwente_base:frontend.ws2016.js.filteredoverview.feedbackbar-result', totalfound);\n  else if (totalfound > 1)\n    return getTid('utwente_base:frontend.ws2016.js.filteredoverview.feedbackbar-results', totalfound);\n  else\n    return getTid(\"utwente_base:frontend.ws2016.js.filteredoverview.feedbackbar-noresults\");\n}\n\nexport function getResultsTeaserText(totalfound: number) {\n  if (totalfound === 1)\n    return getTid('utwente_base:frontend.ws2016.js.filteredoverview.tease-result', totalfound);\n  else if (totalfound > 1)\n    return getTid('utwente_base:frontend.ws2016.js.filteredoverview.tease-results', totalfound);\n  else\n    return getTid(\"utwente_base:frontend.ws2016.js.filteredoverview.tease-noresults\");\n}\n\n/** Basic filtered overview support for pages which already handle stuff themselves.\n\n    - Header toggle\n    - API for expanding/collapsing the header filters\n    - API to set 'X results' teaser for mobile screens\n*/\nexport class FilteredOverviewHeader {\n  debug = debugFlags[\"ut-filters\"];\n  form: HTMLFormElement;\n  resultscountnode: HTMLElement | null = null;\n  options: FilteredOverviewHeaderOptions;\n  resultscountcontainer: HTMLElement | null = null;\n\n  constructor(options: FilteredOverviewHeaderOptions) {\n    this.options = { ...options };\n    this.form = dompack.qR<HTMLFormElement>(\".filteredoverview__form\");\n\n    this.hideFiltersMaybe();\n\n\n    for (const node of document.body.querySelectorAll<HTMLElement>(\".filteredoverview__toggleaction\")) {\n      // NOTE: We use mouseup to fire before (and be able to prevent) focus\n      //       This way we can prevent the focus ring on mouse events, but keep it for keyboard navigation\n      node.addEventListener(\"mousedown\", evt => evt.preventDefault()); // prevent getting focus\n      node.addEventListener(\"mouseup\", () => this.toggleFiltersExpanded());\n      node.addEventListener(\"keydown\", evt => this.toggleFiltersExpandedIfEnter(evt));\n    }\n  }\n\n  /// Set whether the filters are expanded or collapsed\n  setFiltersExpanded(visible: boolean) {\n    document.documentElement.classList.toggle(\"showfilters\", visible);\n\n    const fieldnodes = this.form.querySelectorAll(\"input[name], select[name]\");\n\n    for (let idx = 0; idx < fieldnodes.length; idx++) {\n      if (visible)\n        fieldnodes[idx].removeAttribute(\"tabindex\");\n      else\n        fieldnodes[idx].setAttribute(\"tabindex\", \"-1\"); // disable ability to focus\n    }\n\n    this.checkNeedToShowTeaserBar();\n  }\n\n  toggleFiltersExpandedIfEnter(evt: KeyboardEvent) {\n    if (evt.key === \"Enter\")\n      this.toggleFiltersExpanded();\n  }\n\n  toggleFiltersExpanded() {\n    this.setFiltersExpanded(!document.documentElement.classList.contains(\"showfilters\"));\n  }\n\n  isFilterBarExpanded() {\n    return document.documentElement.classList.contains(\"showfilters\");\n  }\n\n\n  hideFiltersMaybe() {\n    if (this.debug)\n      console.log(\"[ut-filters] hideFiltersMaybe\");\n\n    // header filters not initialized through the normal route?\n    if (!whintegration.config.obj.filteredoverview) {\n      console.warn(\"No filteredoverview settings found.\");\n      return;\n    }\n\n    const expandwhen = whintegration.config.obj.filteredoverview.expandwhen;\n    if (this.debug)\n      console.log(\"[ut-filters] expandwhen\", expandwhen);\n\n    // NOTE: even though in the template we add the \"showfilters\" to the <html> node,\n    //       we must use setFiltersExpanded to correctly initialize behaviour (and disable/enable tabindex) of elements\n\n    switch (expandwhen) {\n      case \"openfirstvisit\":\n        {\n          if (!(\"whfsid\" in whintegration.config.obj.filteredoverview))\n            console.warn(\"Cannot determine expand state for filteredoverview, no filteredoverview.whfsid specified.\");\n          else {\n            const pagekey = \"pageseen\" + whintegration.config.obj.filteredoverview.whfsid;\n            const firstvisitinsession = !(pagekey in sessionStorage);\n\n            this.setFiltersExpanded(firstvisitinsession);\n\n            sessionStorage[pagekey] = \"true\"; // mark this page as seen for this session\n          }\n          break;\n        }\n      case \"alwaysopen\":\n        {\n          this.setFiltersExpanded(true); // explicitly to also update tabindex of hidden filters\n          break;\n        }\n      case \"defaultclosed\":\n        {\n          this.setFiltersExpanded(false); // explicitly to also update tabindex of hidden filters\n          break;\n        }\n    }\n  }\n\n  setTeaserResultCount(totalfound: number, totalshown: number) {\n    if (!this.resultscountnode)\n      this.__createResultsCountNode();\n\n    const gettextfunc = this.options.getResultsTeaserText ?? getResultsTeaserText;\n    this.resultscountnode!.textContent = gettextfunc(totalfound, totalshown);\n  }\n\n  __createResultsCountNode() {\n    const node = document.createElement(\"a\");\n    node.className = \"filteredoverview__teaser\";\n    node.href = \"#results\";\n\n    const contentnode = document.createElement(\"div\");\n    contentnode.className = \"filteredoverview__teaser__content\";\n    node.appendChild(contentnode);\n\n    //node.addEventListener(\"click\", this.scrollToResults());\n    //contentnode.addEventListener(\"click\", this.scrollToResults());\n\n    //contentnode.addEventListener(\"mousedown\", this.scrollToResults());\n\n    document.body.appendChild(node);\n\n    this.resultscountcontainer = node;\n    this.resultscountnode = contentnode;\n\n    window.addEventListener(\"resize\", () => this.checkNeedToShowTeaserBar());\n    document.addEventListener(\"scroll\", () => this.checkNeedToShowTeaserBar());\n    this.checkNeedToShowTeaserBar();\n  }\n\n  setHoveringFeedbackText(text: string) {\n    if (this.resultscountnode)\n      this.resultscountnode.textContent = text;\n  }\n\n\n  checkNeedToShowTeaserBar() {\n    if (!this.resultscountcontainer)\n      return;\n\n    const viewportheight = document.body.getBoundingClientRect().height;\n\n    const resultsanchor = document.querySelector('#results, a[name=\"results\"]');\n    if (!resultsanchor) {\n      if (this.debug)\n        console.warn(\"Missing results anchor\");\n      return;\n    }\n\n    const feedbackbartop = resultsanchor.getBoundingClientRect().top;\n    const results_out_of_view = feedbackbartop > viewportheight;\n\n    // The feedback bar also tells the amount of results AND it means whe're almost at the results.\n    // So if we reach the top of the feedback bar we can hide the teaser bar.\n    this.resultscountcontainer.classList.toggle(\"filteredoverview__teaser--aboveresults\", results_out_of_view);\n  }\n}\n\n\n\n/** - The class you make MUST use doFilter() or doFilterForce() to trigger a refresh\n    - The class you make may offer a showResults() which uses this.filters to change the content on the page\n*/\nexport default class FilteredOverview extends FilteredOverviewHeader {\n  filters: Filters = {};\n  filters_titles: Record<string, string | string[]> = {};\n  gotfiltersfromurl = false;\n  feedbackcontainer: HTMLElement;\n  feedbacknode: HTMLElement;\n  resultsnode: HTMLElement;\n  declare options: FilteredOverviewOptions;\n  resetnode: HTMLElement | null;\n  oldfilterstr = '';\n\n  constructor(options: FilteredOverviewOptions) {\n    super(options);\n\n    if (!this.options.filterpagetype)\n      console.error(\"Please set the filterpagetype for this page (for tracking)\");\n    else\n      pushToDataLayer({ filterpagetype: this.options.filterpagetype });\n\n\n    this.feedbackcontainer = dompack.qS(\".filteredoverview__feedbackandviewbar\");\n    this.feedbacknode = dompack.qS(\".filteredoverview__feedback\");\n    this.resultsnode = dompack.qS(\".filteredoverview__results\");\n\n    if (this.debug) {\n      this.form.classList.add(\"filteredoverview--debugmode\");\n\n      console.log(\"[ut-filters]\", {\n        fbc: this.feedbackcontainer,\n        fbn: this.feedbacknode,\n        rsn: this.resultsnode\n      });\n    }\n\n\n\n    // Check for removing tags on pages which show selected filters as tags\n    const filtertagscontainer = document.querySelector(\".filtertags__items\");\n    if (filtertagscontainer)\n      filtertagscontainer.addEventListener(\"click\", evt => this.doCheckForTagRemoval(evt));\n\n    this.__attachChangeEvents();\n    this.__initFiltersFromURL();\n\n    this.prefillFormWithFilterValues(this.filters);\n\n    this.resetnode = this.form.querySelector(\".filteredoverview__resetfilters\");\n    if (this.resetnode)\n      this.resetnode.addEventListener(\"click\", evt => this.resetFilters());\n\n\n    // ADDME: setting an onunload(??) event may force the browser to reload the page\n\n\n    // NOTE: only Webkit browsers fire this?\n    // NOTE: Only Safari returns evt.persisted\n    // NOTE: Safari only fires pageshow once\n    // NOTE: ... setting an unload event might force Safari to not use the back-forward cache\n    window.addEventListener(\"pageshow\", evt => this.collapseFilterIfReturned(evt));\n\n\n    if (this.debug)\n      console.log(\"[ut-filters] FilteredOverview clientside mode\", this.form);\n\n    // submit (by enter, 'go' on virtual keyboard or click on a submit button) must force a refilter\n    this.form.addEventListener(\"submit\", evt => {\n      evt.preventDefault();\n      this.doFilter(evt);\n    });\n  }\n\n  filternodes?: Array<HTMLInputElement | HTMLSelectElement>;\n  __attachChangeEvents() {\n    // Apply the settings from the URL to the filters bar\n    this.filternodes = dompack.qSA<HTMLInputElement | HTMLSelectElement>(this.form, \"input[name], select[name]\");\n\n    if (this.options.additionalform) {\n      const additionalfields = dompack.qSA<HTMLInputElement | HTMLSelectElement>(this.options.additionalform, \"input[name], select[name]\");\n      this.filternodes = [...this.filternodes, ...additionalfields];\n    }\n\n    for (const node of this.filternodes)\n      node.addEventListener(\"change\", ev => this.onFilterChange(ev));\n  }\n\n  __initFiltersFromURL() {\n    this.oldfilterstr = \"\";\n    this.filters = this.getFiltersFromURL();\n\n    // The automatically open/closing of the filterbar upon page load\n    // is based on whether an URL to specific filters were used.\n    if (Object.keys(this.filters).length > 0)\n      this.gotfiltersfromurl = true;\n\n    if (this.debug)\n      console.log(\"[ut-filters] Filters from URL\", this.filters);\n\n    //force all languages checked (if option is available and not already set)\n    if (!this.filters.language) {\n      for (const optnode of this.form.querySelectorAll(\"input[name='language']\")) {\n        if (!this.filters.language)\n          this.filters.language = [];\n        this.filters.language.push(optnode.value);\n      }\n    }\n\n    //Set filters from url as oldfilter to detect changes for utwente_courses\n    if (document.documentElement.classList.contains(\"coursefinderpage\"))\n      this.oldfilterstr = JSON.stringify(this.filters);\n  }\n\n\n  collapseFilterIfReturned(evt) {\n    if (evt.persisted)\n      this.setFiltersExpanded(false);\n  }\n\n\n\n  isFilterActive() {\n    return Object.keys(this.filters).length;\n  }\n\n  getFiltersFromURL() {\n    const filters = {};\n\n    //get url params if set\n    const urlparamsdone = [];\n    for (const node of this.filternodes) {\n      const val = urlparamsdone.indexOf(node.name) === -1 ? this.getUrlParam(node.name) : \"\";\n      if (val !== \"\") {\n        // Do we have a mapping?\n        // We can use this to convert the value in field \"tag\" to the value in field \"value\".\n        const inptype = node.nodeName === \"INPUT\" ? node.getAttribute(\"type\") : \"\";\n        if (inptype === \"checkbox\") {\n          const vals = val.split(\",\");\n\n          filters[node.name] = vals;\n        } else if (inptype === \"radio\")\n          filters[node.name] = val;\n        else if (node.nodeName === \"SELECT\")\n          filters[node.name] = val;\n        else\n          filters[node.name] = val;\n\n        urlparamsdone.push(node.name);\n      }\n    }\n\n    this.processFiltersFromURL();\n\n    return filters;\n  }\n\n  prefillFormWithFilterValues(filters) {\n    if (this.debug)\n      console.log(\"[ut-filters] Apply filters to DOM\", filters);\n\n    for (const node of this.filternodes) {\n      const inptype = node.nodeName === \"INPUT\" ? node.getAttribute(\"type\") : \"\";\n      if (inptype === \"checkbox\")\n        node.checked = filters[node.name] && filters[node.name].indexOf(node.value) > -1;\n      else if (inptype === \"radio\")\n        node.checked = filters[node.name] === node.value; // ? true : false;\n      else if (filters[node.name])\n        node.value = filters[node.name];\n    }\n  }\n\n  // Set filter parameters in url\n  applyFiltersToURL() {\n    if (this.debug)\n      console.log(\"[ut-filters] Apply filters to URL\", this.filters);\n\n    if (!history.replaceState)\n      return;\n\n    const url = new URL(location.href);\n    for (const name of Object.keys(this.filters)) {\n      const val = this.filters[name];\n\n      if (typeof val === \"string\") {\n        if (val !== \"\")\n          url.searchParams.set(name, val);\n      } else if (typeof val === \"boolean\") {\n        if (val)\n          url.searchParams.set(name, \"\");\n      } else if (Array.isArray(val)) {\n        if (val.length > 0)\n          url.searchParams.set(name, val.join(\",\"));\n      }\n    }\n\n    // FIXME: workaround for Studyfinder / Coursefinder, find a cleaner way to do this\n    if (typeof this.isdetailsview !== \"undefined\") {\n      if (!this.isdetailsview)\n        url.hash = \"#listview\";\n    }\n\n    history.replaceState(null, \"\", url);\n\n\n    ////////////////////////////////////////////////////////////////////////////////////////////////////\n    // For pages which reload or go to a different URL for another view (such as the PDC services pages)\n    // we need to update the anchor to contain the current filtersettings.\n    // (otherwise the user would loose all filters when switching between views)\n\n    // IE is the only browser not supporting the URL API\n    // (and some very old devices such as iPad1 and iPhone4)\n\n    // using the URL API we update the search query part of the URL\n    // of links to pages which also use the same filters\n    const anchors = document.querySelectorAll<HTMLAnchorElement>(\"a.filteredoverview__updatelinkquery\");\n    for (const anchor of anchors) {\n      // For URL API docs see: https://developer.mozilla.org/en-US/docs/Web/API/URL\n      const url2 = new URL(anchor.href);\n      url2.search = search;\n      anchor.href = url2.href;\n    }\n    ///////////////////////////////////////////////////////////////////////////////////////////////////\n  }\n\n  onFilterChange(evt) {\n    this.doFilter(evt);\n  }\n\n  updateFilters(evt?: Event) {\n    const interactivechange = Boolean(evt);\n    // FIXME: we should change to this.filters = { name: \"\", title: \"\", allselected: true }\n    this.filters = {};\n    this.filters_titles = {};\n\n    for (const node of this.filternodes) {\n      if (node.nodeName === \"SELECT\") { //node.value != \"\") // <select> (pulldown) or <input type=\"text\" />\n\n        if (node.value !== \"\") {\n          this.filters[node.name] = node.value;\n          // FIXME: we could use .selectedOptions, but it might fail on IE11 ?\n          this.filters_titles[node.name] = node.options[node.selectedIndex].text; // node.value;\n        }\n      } else if (node.nodeName === \"INPUT\") {\n        const inptype = node.getAttribute(\"type\");\n\n        if (inptype === \"checkbox\") {\n          if (!node.checked)\n            continue;\n\n          if (!this.filters[node.name]) {\n            this.filters[node.name] = [];\n            this.filters_titles[node.name] = [];\n          }\n\n          this.filters[node.name].push(node.value);\n\n          let title = \"\";\n\n          if (node.id !== \"\") {\n            const labelnode = document.querySelector('label[for=\"' + node.id + '\"]:not(:empty)');\n\n            if (labelnode)\n              title = labelnode.textContent;\n            else\n              title = \"??\"; // no label or there's a typo in the label's for attribute\n          }\n\n          this.filters_titles[node.name].push(title);\n        } else if (inptype === \"radio\") {\n          if (!node.checked)\n            continue;\n\n          if (node.value !== \"\") // ignore invalid (placeholder) or 'show all' settings\n            this.filters[node.name] = node.value; //checked;\n\n          let title = \"\";\n          if (node.id !== \"\") {\n            const labelnode = document.querySelector('label[for=\"' + node.id + '\"]');\n            if (labelnode)\n              title = labelnode.textContent;\n            else\n              title = \"??\"; // no label or there's a typo in the label's for attribute\n          }\n          this.filters_titles[node.name] = title;\n        } else {// assume textual (\"text\", \"search\")\n          if (node.value !== \"\") {\n            this.filters[node.name] = node.value;\n            this.filters_titles[node.name] = node.value;\n          }\n        }\n      }\n    }\n\n    this.sendCurrentFiltersToDataLayer(interactivechange);\n\n    this.onFormFiltersUpdate(this.filters, evt);\n\n    // Exception for language selection in the (Master) studyfinder.\n    // When all languages are selected, treat this as 'filter not used'.\n    if (document.documentElement.classList.contains(\"page--studyfinder\") && this.filters.language) {\n      // All languages selected?\n      if (this.form.language.length === this.filters.language.length)\n        delete this.filters.language;\n    }\n  }\n\n  sendCurrentFiltersToDataLayer(interactivechange) {\n    if (interactivechange) {\n      const dlevent: Record<string, string> = {};\n      Object.keys(this.filters_titles).forEach(key => {\n        let val = this.filters_titles[key];\n        if (Array.isArray(val))\n          val = val.join(', ');\n\n        dlevent['filter_' + key] = val;\n\n        if (!filter_lastsettings[key] || filter_lastsettings[key] !== val) { //also send an explicit event for just this filter\n          filter_lastsettings[key] = val;\n          pushToDataLayer({ event: 'set_filter', filtername: key, filtervalue: val });\n        }\n      });\n      filter_lastseenkeys.filter(key => !(key in this.filters_titles)).forEach(key => { //this key went away\n        pushToDataLayer({ event: 'set_filter', filtername: key, filtervalue: '' });\n      });\n      pushToDataLayer({ event: \"set_filters\", ...dlevent });\n    }\n    filter_lastseenkeys = Object.keys(this.filters_titles);\n  }\n\n  // The study finder resets the other filters when searching for words\n  resetFilters(keepwords) {\n    for (const node of this.filternodes) {\n      if (keepwords && node.name === \"words\")\n        continue;\n      const inptype = node.nodeName === \"INPUT\" ? node.getAttribute(\"type\") : \"\";\n      if (inptype === \"checkbox\" || inptype === \"radio\")\n        node.checked = node.name === \"language\";//check if is language filter else uncheck\n      else\n        node.value = \"\";\n    }\n\n    this.doFilter();\n  }\n\n\n  doFilter(evt?: Event) {\n    this.doFilterInternal(evt);\n  }\n\n  doFilterForced() {\n    this.doFilterInternal(null, true);\n  }\n\n  refreshFilterFeedbackUI() {\n    this.syncFilterTags();\n\n    // Only show reset button if there is an active filter\n    let nrfilters = Object.keys(this.filters).length;\n    if (nrfilters === 1 && this.filters.language && this.filters.language.length === this.languagescount)\n      --nrfilters;//ignore of all languages are selected\n\n    this.form.classList[nrfilters > 0 ? \"add\" : \"remove\"](\"filteredoverview--filteractive\");\n\n    if (this.feedbackcontainer)\n      this.feedbackcontainer.classList[nrfilters > 0 ? \"add\" : \"remove\"](\"filteredoverview--filteractive\");\n  }\n\n\n  //doFilter( forcerefresh )\n  async doFilterInternal(evt, forcerefresh = false) {\n    if (this.debug)\n      console.log(\"[ut-filters] FilteredOverview:doFilter\", { evt: evt });\n\n    this.updateFilters(evt);\n\n    const filterstr = JSON.stringify(this.filters);\n\n    if (filterstr === this.oldfilterstr && !forcerefresh)\n      return;\n\n    this.oldfilterstr = filterstr;\n\n\n    this.refreshFilterFeedbackUI();\n\n    this.applyFiltersToURL();\n\n\n\n\n\n    // Used by Studyfinder / Coursefinder\n    // FIXME: move to StudyfinderFilter class in utwente_education !! HOWEVER only coursefinder actually implements _SearchWords RPC so... this rpc stuff should go to coursefinder ?\n    if (typeof this.filters.words !== \"undefined\" && this.filters.words !== \"\") {\n      if (this.rpccache && this.rpccache.words === this.filters.words) {\n        this.showResults();\n      } else {\n        // this.rpc.request( \"SearchWords\", [ this.filters.words ], this.onRpcResult.bind(this) );\n        const result = await this.doSearchWords(this.filters.words);\n        this.rpccache = result;\n        if (this.debug)\n          console.log(\"rpccache\", result);\n        this.showResults();\n      }\n\n      return;\n    }\n    this.rpccache = null;\n\n    this.showResults();\n  }\n\n  async doSearchWords(words: string) {\n    if (!this.rpc)\n      this.rpc = new JSONRPC();\n    return await this.rpc.async('SearchWords', words);\n  }\n\n  showNoResults(noresults: boolean) {\n    if (noresults)\n      document.documentElement.classList.add(\"filteredoverview--noresults\");\n    else\n      document.documentElement.classList.remove(\"filteredoverview--noresults\");\n  }\n\n\n\n\n\n  // override me\n  // @short after reading the URL and before updating the form field values, this function allows you use or change values in the filters\n  processFiltersFromURL() {\n    if (this.debug)\n      console.log(\"[ut-filters] processFiltersFromURL not used.\");\n  }\n\n  // override me to check/change/delete filters before new results are calculated\n  onFormFiltersUpdate(filters, evt?: Event) {\n  }\n\n\n\n  ////////////////////////////////////////////////////////////////////////////////////////////\n  //\n  //  Tags\n  //\n\n  doCheckForTagRemoval(evt) {\n    const tagnode = evt.target.closest(\".filtertags__item\");\n    if (!tagnode)\n      return;\n\n    evt.preventDefault();\n\n    const fieldname = tagnode.getAttribute(\"data-name\");\n    const fieldvalue = tagnode.getAttribute(\"data-value\");\n\n    /*\n    FIXME: uncomment when there is a need for it again\n    if (this.onRemoveTag)\n      this.onRemoveTag({ name: fieldname, value: fieldvalue });\n    */\n\n    if (!this.form[fieldname]) {\n      console.error(\"Failed to find field/option belonging to the removed tag\", fieldname, fieldvalue);\n      return;\n    }\n    if (this.form[fieldname] instanceof RadioNodeList) { // Both Checkbox and Radiobuttons\n      // In a collection (checkboxes or radiobuttons), lookup the option with the\n      // value we want to remove and remove it's checked state\n      //let field = this.form.querySelector('[name=\"'+fieldname+'\"][value=\"'+fieldvalue+'\"]');\n      //field.checked = false;\n      for (const field of this.form[fieldname] as unknown as HTMLInputElement[]) {\n        if (field.value === fieldvalue)\n          field.checked = false;\n      }\n    } else { // SELECT, input type=\"text\"/\"hidden\"\n      (this.form[fieldname] as HTMLSelectElement).value = \"\";\n    }\n\n    this.doFilter();\n  }\n\n  getFlatActiveFilterValuesList(): ActiveFilterValue {\n    // Compile a list of all selected filter values\n    const tags: ActiveFilterValue[] = [];\n    for (const key in this.filters) {\n      if (filtertags_ignorefields.indexOf(key) > -1)\n        continue; // don't show a free text query as tag\n\n      tags.push({\n        name: key,\n        value: this.filters[key],\n        title: this.filters_titles[key]\n      });\n    }\n    return tags;\n  }\n\n  currenttags: Record<string, {\n    isnew: boolean;\n    isused: boolean;\n    title: string;\n    name: string;\n    value: string;\n    node: HTMLElement | null;\n  }> = {};\n\n  syncFilterTags() {\n    const filtertagscontainer = document.querySelector(\".filtertags__items\");\n    if (!filtertagscontainer)\n      return;\n\n    // FIXME: would have been nicer if updateFilters returned an array\n    //        with { name:, selectedvalues:, selectedvaluetitles: }\n\n    for (const key of Object.keys(this.currenttags)) {\n      this.currenttags[key].isnew = false;\n      this.currenttags[key].isused = false;\n    }\n\n\n    let tags = this.getFlatActiveFilterValuesList();\n\n    // Present the oppertunity to merge tags\n    // For example status=graduated+graduationyear=2018 could be mapped to graduationyear=2018 with title \"Completed in 2018\"\n    if (this.onMapFilterTags) {\n      tags = this.onMapFilterTags(tags, this.filters);\n      //console.info(\"TAGS after mapping\", {...tags});\n    }\n\n    for (const tag of tags) {\n      if (Array.isArray(tag.value)) { // result of a checkbox (or pulldown multiselect??)\n        for (let idx = 0; idx < tag.value.length; idx++) {\n          const rowkey = \"_\" + tag.name + \"=\" + tag.value[idx];\n          if (!this.currenttags[rowkey])\n            this.currenttags[rowkey] = {\n              title: tag.title[idx],\n              name: tag.name,\n              value: tag.value[idx],\n              isnew: true,\n              node: null\n            };\n\n          this.currenttags[rowkey].isused = true;\n        }\n      } else {\n        const rowkey = \"_\" + tag.name + \"=\" + tag.value;\n        if (!this.currenttags[rowkey])\n          this.currenttags[rowkey] =\n          {\n            title: tag.title,\n            name: tag.name,\n            value: tag.value,\n            isnew: true,\n            node: null\n          };\n\n        this.currenttags[rowkey].isused = true;\n      }\n    }\n\n    // Update (create or delete) the list of tags in the DOM\n    for (const key of Object.keys(this.currenttags)) {\n      const tag = this.currenttags[key];\n\n      if (tag.isnew) {\n        const item = document.createElement(\"div\");\n        item.className = \"filtertags__item\";\n        item.setAttribute(\"data-name\", tag.name);\n        item.setAttribute(\"data-value\", tag.value);\n\n        const title = document.createElement(\"div\");\n        title.className = \"filtertags__item__title\";\n        title.textContent = tag.title;\n\n        const remove = document.createElement(\"div\");\n        remove.className = \"filtertags__item__remove UT-icon-UT_icon_47_cross-16px\";\n        //remove.textContent = \"x\";\n\n        item.appendChild(title);\n        item.appendChild(remove);\n        filtertagscontainer.appendChild(item);\n\n        item.__tag = tag;\n\n        this.currenttags[key].node = item;\n      }\n    }\n\n    const feedbacknode = document.querySelector(\".filteredoverview__feedbackandviewbar\");\n    if (feedbacknode)\n      feedbacknode.classList.toggle(\"filteredoverview__filtertags--active\", tags.length > 0);\n\n    document.clientWidth;\n\n    for (const key of Object.keys(this.currenttags)) {\n      const tag = this.currenttags[key];\n      if (tag.isnew) {\n        tag.node.clientWidth;\n        tag.node.classList.add(\"visible\");\n      }\n      if (!tag.isused) {\n        tag.node.classList.remove(\"visible\");\n        setTimeout(() => tag.node?.remove(), 200); //we're not trusting transitionend to fire - it won't fire if the whole filter section is removed\n        delete this.currenttags[key];\n      }\n    }\n  }\n\n\n  ////////////////////////////////////////////////////////////////////////////////////////////\n  //\n  //  Misc helper functions\n  //\n\n  getUrlParam(name) {\n    const urlparamstr = location.search.replace(/\\+/g, \"%20\");\n    if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(urlparamstr))\n      return decodeURIComponent(name[1]);\n    return \"\";\n  }\n\n  setFeedback(totalfound: number, totalshown?: number, allitemscount?: number) {\n    this.showNoResults(totalfound === 0);\n\n    if (this.feedbacknode) {\n      const gettextfunc = this.options.getResultsFeedbackText ?? getResultsFeedbackText;\n      this.feedbacknode.textContent = gettextfunc(totalfound, totalshown);\n    }\n\n    this.setTeaserResultCount(totalfound, totalshown);\n  }\n}\n\n\n\n/** FilteredOverview which automatically handles filtering based on JSON encoded\n    values specified in the data-filterdata attribute of each item\n*/\nexport class ClientSideFilteredOverview extends FilteredOverview {\n  items: FilterItem[] = [];\n  itemscontainer: HTMLElement;\n  searchIndex = new SearchIndex();\n\n  constructor(options) {\n    super(options);\n    const itemsselector = options?.itemsselector || \"\";\n    this.itemscontainer = dompack.qR(\".filteredoverview__items\");\n    if (this.debug)\n      console.log(\"[ut-filters]\", {\n        form: this.form,\n        itemscontainer: this.itemscontainer\n      });\n\n    const items = this.itemscontainer.querySelectorAll(itemsselector);\n    if (items.length === 0)\n      console.error(\"No items in filteredoverview? selector = \");\n    else if (this.debug)\n      console.log(\"[ut-filters] Filteredoverview with \" + items.length + \" items\");\n\n    this.setFeedback(items.length, items.length, items.length);\n\n    // keep an internal list of all items AND\n    // generate the list view based on content of the normal view\n    this.items = [];\n    for (const node of items) {\n      this.items.push({\n        node: node,\n        filterdata: node.dataset.filterdata ? JSON.parse(node.dataset.filterdata) : null,\n        title: node.querySelector(\"[data-autocompletesource-title]\"),\n        description: node.querySelector(\"[data-autocompletesource-description]\")\n        //, \"title\":   node.querySelector(\"h3\").textContent.toLowerCase()\n      });\n    }\n    this._initClientsideAutosuggest();\n\n    if (this.isFilterActive())\n      this.doFilter();\n  }\n\n  _initClientsideAutosuggest() {\n    // A slightly modified version of initSearchSuggestions to highlight matches within suggestions, not just the first x characters\n    const searchnode = this.form.querySelector<HTMLElement>(\"input[data-autocomplete-clientside]\"); //should all switch to -clientside for clarity\n    if (searchnode) {\n      this._initClientsideSearchIndex();\n\n      UTAutoComplete({\n        input: searchnode,\n        className: 'ut-autocomplete',\n        preventSubmit: 1,\n        fetch: async (text, update) => {\n          const suggestions = this.searchIndex.suggest(text).slice(0, 10);\n\n          update(suggestions.map(_ => { return { label: _, value: _ }; }));\n        },\n        onSelect: (item) => {\n          searchnode.value = item.value;\n          this.doFilter();\n        }\n      });\n    }\n  }\n\n  _initClientsideSearchIndex() {\n    this.searchIndex.searchFields = [\"title\", \"description\"];\n    this.searchIndex.completeSuggestFields = [\"title\"];\n\n    for (const item of this.items) {\n      this.searchIndex.indexItem(\n        {\n          node: item.node,\n          title: item.title?.textContent ?? '',\n          description: item.description?.textContent ?? '',\n          titleNode: item.title,\n          descriptionNode: item.description\n        });\n    }\n  }\n\n  isMatch(node) {\n    if (this.searchIndexMatch) { //was the search set ?\n      const matchingentry = this.searchIndexMatch.items.filter(_ => _.node === node)[0];\n      if (!matchingentry)\n        return false;\n    }\n\n    for (const filtername of Object.keys(this.filters)) {\n      if (node.hasAttribute(`data-filter-${filtername}`)) {\n        const filterval = this.filters[filtername];\n\n\n        const matchtype = node.getAttribute(`data-filter-${filtername}-matchtype`);\n        if (matchtype === \"partialtext\") {\n          const findinvalue = node.getAttribute(`data-filter-${filtername}`);\n          if (findinvalue.includes(filterval))\n            return true;\n\n          continue;\n        }\n\n\n        const setvalues = node.getAttribute(`data-filter-${filtername}`).split(' ');\n\n        if (Array.isArray(filterval)) {\n          if (!setvalues.some(val => filterval.includes(val)))\n            return false;\n        } else if (!setvalues.includes(filterval))\n          return false;\n      }\n    }\n    return true;\n  }\n\n  runFilterByDataTags() {\n    if (this.debug)\n      console.log(\"[ut-filters] runFilterByDataTags\", this.filters);\n\n    if (this.searchIndex) {\n      if (this.filters.query)\n        this.searchIndexMatch = this.searchIndex.search(this.filters.query);\n      else\n        this.searchIndexMatch = null;\n    }\n\n    this.items.forEach(item => item.node.hidden = !this.isMatch(item.node));\n\n    const totalfound = this.items.filter(item => !item.node.hidden).length;\n    this.setFeedback(totalfound, totalfound, this.items.length);\n  }\n\n  showResults() {\n    if (this.debug)\n      console.log(\"[ut-filters] showResults\", this.filters);\n\n    //let activefilters = Object.keys(this.filters).length;\n    let totalfound = 0;\n\n    for (let i = 0; i < this.items.length; ++i) {\n      const item = this.items[i].node; //this.items[i].details;\n      const itemdata = this.items[i].filterdata;\n\n      let doesnotmatch = false;\n\n      for (const key of Object.keys(this.filters)) {\n        // FIXME: ITC phd-projects specific hack, find another way to do this\n        if (key === \"status\") {\n          const selectedstatus = this.filters[key]; // 'ongoing', 'graduated'\n\n          if (selectedstatus.indexOf(\"ongoing\") > -1 && itemdata.graduationyear === 0)\n            continue; // OK\n\n          if (selectedstatus.indexOf(\"graduated\") > -1) {\n            if (this.form.graduationyear.value === 0) { // PhD project from any year\n              if (itemdata.graduationyear > 0)\n                continue; // graduated, so OK\n            } else if (this.form.graduationyear.value === itemdata.graduationyear)\n              continue; // OK\n          }\n\n          doesnotmatch = true;\n          continue;\n        } else if (key === \"graduationyear\") // skip this one, we handle it together with the 'status' field\n          continue; // FIXME: ITC phd-projects specific hack, find another way to do this\n        else if (key === \"words\") { // handled by RPC\n          if (this.debug) // if matching cannot be found here which are expected, try rebuilding the Consilio searchcatalog to make sure id's are in sync with the WRD schema\n            console.log(\"[ut-filters] Is\", item.dataset.id, \"IN\", this.rpccache.ids);\n\n          if (this.rpccache && this.rpccache.ids.indexOf(item.dataset.id) === -1)\n            doesnotmatch = true;\n\n          continue;\n        } else if (key === \"query\") { // handled by JS\n          if (!(\"searchtext\" in itemdata)) {\n            console.error(\"searchtext field missing in item's filterdata.\");\n            continue;\n          }\n\n          // FIXME: seperate words\n          if (this.debug)\n            console.log(\"[ut-filters] Got\", itemdata.searchtext, \"\\n\", \"Looking for\", this.filters.query.toLowerCase());\n\n          const parts = this.filters.query.toLowerCase().split(\" \");\n\n          let qmatches = true;\n          for (const findtext of parts) {\n            if (itemdata.searchtext.indexOf(findtext) === -1) {\n              qmatches = false;\n              break;\n            }\n          }\n\n          if (!qmatches)\n            doesnotmatch = true;\n\n          continue;\n        }\n\n        if (!(key in itemdata)) {\n          if (this.debug)\n            console.log(\"Cannot find search key '\" + key + \"'\");\n          continue;\n        }\n\n\n\n        const itemvalue = itemdata[key];\n        const searchvalue = this.filters[key];\n\n        if (this.debug)\n          console.log(\"[ut-filters] Looking for\", searchvalue, \"in\", itemvalue);\n\n\n        if (Array.isArray(searchvalue) && Array.isArray(itemvalue)) { // Find multiple values in multiple values\n          for (let i2 = 0; i2 < searchvalue.length; ++i2) {\n            let found = false;\n            if (itemvalue.indexOf(this.filters[key][i2]) > -1) {\n              found = true;\n              break;\n            }\n\n            if (!found)\n              doesnotmatch = true;\n          }\n        } else if (Array.isArray(itemvalue)) {\n          // lookup single value (pulldown or text) in array\n          if (itemvalue.indexOf(this.filters[key]) === -1)\n            doesnotmatch = true;\n        } else {\n          // lookup single value (pulldown or text) in a non-array (number of string)\n          const matchvalue = (typeof itemvalue === \"number\" ? parseInt(this.filters[key]) : this.filters[key]);\n\n          if (itemvalue !== matchvalue)\n            doesnotmatch = true;\n        }\n      }\n\n      const ismatch = !doesnotmatch;\n\n      item.classList[ismatch ? \"remove\" : \"add\"](\"hidden\");\n\n      if (ismatch) {\n        ++totalfound;\n        /*\n                item.style.opacity = 0;\n                //this.itemscontainer.appendChild( item );\n\n                item.clientHeight;//force css refresh\n                item.style.opacity = 1;\n        */\n      }\n    }\n\n    this.setFeedback(totalfound, totalfound, this.items.length);\n  }\n}\n","/**\n * Copyright (c) 2016 Denis Taran\n * \n * Homepage: https://smartscheduling.com/en/documentation/autocomplete\n * Source: https://github.com/denis-taran/autocomplete\n * \n * MIT License\n */\n\nexport const enum EventTrigger {\n    Keyboard = 0,\n    Focus = 1,\n    Mouse = 2,\n    /**\n     * Fetch is triggered manually by calling `fetch` function returned in `AutocompleteResult`\n     */\n    Manual = 3\n}\n\n/**\n * Enum for controlling form submission when `ENTER` key is pressed in the autocomplete input field.\n */\nexport const enum PreventSubmit {\n    Never = 0,\n    Always = 1,\n    /**\n     * Form submission is prevented only when an item is selected from the autocomplete list.\n     */\n    OnSelect = 2\n}\n\nexport interface AutocompleteItem {\n    label?: string;\n    group?: string;\n}\n\nexport interface AutocompleteEvent<T extends Event> {\n    /**\n     * Native event object passed by browser to the event handler\n     */\n    event: T;\n\n    /**\n     * Fetch data and display autocomplete\n     */\n    fetch: () => void;\n}\n\nexport interface AutocompleteSettings<T extends AutocompleteItem> {\n    /**\n     * Autocomplete will be attached to this element.\n     */\n    input: HTMLInputElement | HTMLTextAreaElement;\n\n    /**\n     * Provide your own container for the widget.\n     * If not specified, a new DIV element will be created.\n     */\n    container?: HTMLDivElement;\n\n    /**\n     * This method allows you to override the default rendering function for items.\n     * It must return a DIV element or undefined to skip rendering.\n     */\n    render?: (item: T, currentValue: string, index: number) => HTMLDivElement | undefined;\n\n    /**\n     * This method allows you to override the default rendering function for item groups.\n     * It must return a DIV element or undefined to skip rendering.\n     */\n    renderGroup?: (name: string, currentValue: string) => HTMLDivElement | undefined;\n\n    /**\n     * If specified, the autocomplete DOM element will have this class assigned to it.\n     */\n    className?: string;\n\n    /**\n     * Specify the minimum text length required to show autocomplete.\n     */\n    minLength?: number;\n\n    /**\n     * The message that will be showed when there are no suggestions that match the entered value.\n     */\n    emptyMsg?: string;\n\n    /**\n     * This method will be called when user choose an item in autocomplete. The selected item will be passed as the first parameter.\n     */\n    onSelect: (item: T, input: HTMLInputElement | HTMLTextAreaElement) => void;\n\n    /**\n     * Show autocomplete on focus event. Focus event will ignore the `minLength` property and will always call `fetch`.\n     */\n    showOnFocus?: boolean;\n\n    /**\n     * This method will be called to prepare suggestions and then pass them to autocomplete.\n     * @param {string} text - text in the input field\n     * @param {(items: T[] | false) => void} update - a callback function that must be called after suggestions are prepared\n     * @param {EventTrigger} trigger - type of the event that triggered the fetch\n     * @param {number} cursorPos - position of the cursor in the input field\n     */\n    fetch: (text: string, update: (items: T[] | false) => void, trigger: EventTrigger, cursorPos: number) => void;\n\n    /**\n     * Enforces that the fetch function will only be called once within the specified time frame (in milliseconds) and\n     * delays execution. This prevents flooding your server with AJAX requests.\n     */\n    debounceWaitMs?: number;\n\n    /**\n     * Callback for additional autocomplete customization\n     * @param {HTMLInputElement | HTMLTextAreaElement} input - input box associated with autocomplete\n     * @param {ClientRect | DOMRect} inputRect - size of the input box and its position relative to the viewport\n     * @param {HTMLDivElement} container - container with suggestions\n     * @param {number} maxHeight - max height that can be used by autocomplete\n     */\n    customize?: (input: HTMLInputElement | HTMLTextAreaElement, inputRect: ClientRect | DOMRect, container: HTMLDivElement, maxHeight: number) => void;\n\n    /**\n     * Controls form submission when the ENTER key is pressed in a input field.\n     */\n    preventSubmit?: PreventSubmit;\n\n    /**\n     * Prevents the first item in the list from being selected automatically. This option allows you\n     * to submit a custom text by pressing ENTER even when autocomplete is displayed.\n     */\n    disableAutoSelect?: boolean;\n\n    /**\n     * Provide your keyup event handler to display autocomplete when a key is pressed that doesn't modify the content. You can also perform some additional actions.\n     */\n    keyup?: (e: AutocompleteEvent<KeyboardEvent>) => void;\n\n    /**\n     * Allows to display autocomplete on mouse clicks or perform some additional actions.\n     */\n    click?: (e: AutocompleteEvent<MouseEvent>) => void;\n}\n\nexport interface AutocompleteResult {\n    /**\n     * Remove event handlers, DOM elements and ARIA/accessibility attributes created by the widget.\n     */\n    destroy: () => void;\n\n    /**\n     * This function allows to manually start data fetching and display autocomplete. Note that\n     * it does not automatically place focus on the input field, so you may need to do so manually\n     * in certain situations.\n     */\n    fetch: () => void;\n}\n\nexport default function autocomplete<T extends AutocompleteItem>(settings: AutocompleteSettings<T>): AutocompleteResult {\n\n    // just an alias to minimize JS file size\n    const doc = document;\n\n    const container: HTMLDivElement = settings.container || doc.createElement('div');\n    const preventSubmit: PreventSubmit = settings.preventSubmit || PreventSubmit.Never;\n\n    container.id = container.id || 'autocomplete-' + uid();\n    const containerStyle = container.style;\n    const debounceWaitMs = settings.debounceWaitMs || 0;\n    const disableAutoSelect = settings.disableAutoSelect || false;\n    const customContainerParent = container.parentElement;\n\n    let items: T[] = [];\n    let inputValue = '';\n    let minLen = 2;\n    const showOnFocus = settings.showOnFocus;\n    let selected: T | undefined;\n    let fetchCounter = 0;\n    let debounceTimer: number | undefined;\n    let destroyed = false;\n\n    // Fixes #104: autocomplete selection is broken on Firefox for Android\n    let suppressAutocomplete = false;\n\n    if (settings.minLength !== undefined) {\n        minLen = settings.minLength;\n    }\n\n    if (!settings.input) {\n        throw new Error('input undefined');\n    }\n\n    const input: HTMLInputElement | HTMLTextAreaElement = settings.input;\n\n    container.className = [container.className, 'autocomplete', settings.className || ''].join(' ').trim();\n    container.setAttribute('role', 'listbox');\n\n    input.setAttribute('role', 'combobox');\n    input.setAttribute('aria-expanded', 'false');\n    input.setAttribute('aria-autocomplete', 'list');\n    input.setAttribute('aria-controls', container.id);\n    input.setAttribute('aria-owns', container.id);\n    input.setAttribute('aria-activedescendant', '');\n    input.setAttribute('aria-haspopup', 'listbox');\n\n    // IOS implementation for fixed positioning has many bugs, so we will use absolute positioning\n    containerStyle.position = 'absolute';\n\n    /**\n     * Generate a very complex textual ID that greatly reduces the chance of a collision with another ID or text.\n     */\n    function uid(): string {\n        return Date.now().toString(36) + Math.random().toString(36).substring(2);\n    }\n\n    /**\n     * Detach the container from DOM\n     */\n    function detach() {\n        const parent = container.parentNode;\n        if (parent) {\n            parent.removeChild(container);\n        }\n    }\n\n    /**\n     * Clear debouncing timer if assigned\n     */\n    function clearDebounceTimer() {\n        if (debounceTimer) {\n            window.clearTimeout(debounceTimer);\n        }\n    }\n\n    /**\n     * Attach the container to DOM\n     */\n    function attach() {\n        if (!container.parentNode) {\n            (customContainerParent || doc.body).appendChild(container);\n        }\n    }\n\n    /**\n     * Check if container for autocomplete is displayed\n     */\n    function containerDisplayed(): boolean {\n        return !!container.parentNode;\n    }\n\n    /**\n     * Clear autocomplete state and hide container\n     */\n    function clear() {\n        // prevent the update call if there are pending AJAX requests\n        fetchCounter++;\n\n        items = [];\n        inputValue = '';\n        selected = undefined;\n        input.setAttribute('aria-activedescendant', '');\n        input.setAttribute('aria-expanded', 'false');\n        detach();\n    }\n\n    /**\n     * Update autocomplete position\n     */\n    function updatePosition() {\n        if (!containerDisplayed()) {\n            return;\n        }\n\n        input.setAttribute('aria-expanded', 'true');\n\n        containerStyle.height = 'auto';\n        containerStyle.width = input.offsetWidth + 'px';\n\n        let maxHeight = 0;\n        let inputRect: DOMRect | undefined;\n\n        function calc() {\n            const docEl = doc.documentElement as HTMLElement;\n            const clientTop = docEl.clientTop || doc.body.clientTop || 0;\n            const clientLeft = docEl.clientLeft || doc.body.clientLeft || 0;\n            const scrollTop = window.pageYOffset || docEl.scrollTop;\n            const scrollLeft = window.pageXOffset || docEl.scrollLeft;\n\n            inputRect = input.getBoundingClientRect();\n\n            const top = inputRect.top + input.offsetHeight + scrollTop - clientTop;\n            const left = inputRect.left + scrollLeft - clientLeft;\n\n            containerStyle.top = top + 'px';\n            containerStyle.left = left + 'px';\n\n            maxHeight = window.innerHeight - (inputRect.top + input.offsetHeight);\n\n            if (maxHeight < 0) {\n                maxHeight = 0;\n            }\n\n            containerStyle.top = top + 'px';\n            containerStyle.bottom = '';\n            containerStyle.left = left + 'px';\n            containerStyle.maxHeight = maxHeight + 'px';\n        }\n\n        // the calc method must be called twice, otherwise the calculation may be wrong on resize event (chrome browser)\n        calc();\n        calc();\n\n        if (settings.customize && inputRect) {\n            settings.customize(input, inputRect, container, maxHeight);\n        }\n    }\n\n    /**\n     * Redraw the autocomplete div element with suggestions\n     */\n    function update() {\n\n        container.textContent = '';\n        input.setAttribute('aria-activedescendant', '');\n\n        // function for rendering autocomplete suggestions\n        let render = function (item: T, _: string, __: number): HTMLDivElement | undefined {\n            const itemElement = doc.createElement('div');\n            itemElement.textContent = item.label || '';\n            return itemElement;\n        };\n        if (settings.render) {\n            render = settings.render;\n        }\n\n        // function to render autocomplete groups\n        let renderGroup = function (groupName: string, _: string): HTMLDivElement | undefined {\n            const groupDiv = doc.createElement('div');\n            groupDiv.textContent = groupName;\n            return groupDiv;\n        };\n        if (settings.renderGroup) {\n            renderGroup = settings.renderGroup;\n        }\n\n        const fragment = doc.createDocumentFragment();\n        let prevGroup = uid();\n\n        items.forEach(function (item: T, index: number): void {\n            if (item.group && item.group !== prevGroup) {\n                prevGroup = item.group;\n                const groupDiv = renderGroup(item.group, inputValue);\n                if (groupDiv) {\n                    groupDiv.className += ' group';\n                    fragment.appendChild(groupDiv);\n                }\n            }\n            const div = render(item, inputValue, index);\n            if (div) {\n                div.id = `${container.id}_${index}`;\n                div.setAttribute('role', 'option');\n                div.addEventListener('click', function (ev: MouseEvent): void {\n                    suppressAutocomplete = true;\n                    try {\n                        settings.onSelect(item, input);\n                    } finally {\n                        suppressAutocomplete = false;\n                    }\n                    clear();\n                    ev.preventDefault();\n                    ev.stopPropagation();\n                });\n                if (item === selected) {\n                    div.className += ' selected';\n                    div.setAttribute('aria-selected', 'true');\n                    input.setAttribute('aria-activedescendant', div.id);\n                }\n                fragment.appendChild(div);\n            }\n        });\n        container.appendChild(fragment);\n        if (items.length < 1) {\n            if (settings.emptyMsg) {\n                const empty = doc.createElement('div');\n                empty.id = `${container.id}_${uid()}`;\n                empty.className = 'empty';\n                empty.textContent = settings.emptyMsg;\n                container.appendChild(empty);\n                input.setAttribute('aria-activedescendant', empty.id);\n            } else {\n                clear();\n                return;\n            }\n        }\n\n        attach();\n        updatePosition();\n\n        updateScroll();\n    }\n\n    function updateIfDisplayed() {\n        if (containerDisplayed()) {\n            update();\n        }\n    }\n\n    function resizeEventHandler() {\n        updateIfDisplayed();\n    }\n\n    function scrollEventHandler(e: Event) {\n        if (e.target !== container) {\n            updateIfDisplayed();\n        } else {\n            e.preventDefault();\n        }\n    }\n\n    function inputEventHandler() {\n        if (!suppressAutocomplete) {\n            fetch(EventTrigger.Keyboard);\n        }\n    }\n\n    /**\n     * Automatically move scroll bar if selected item is not visible\n     */\n    function updateScroll() {\n        const elements = container.getElementsByClassName('selected');\n        if (elements.length > 0) {\n            let element = elements[0] as HTMLDivElement;\n\n            // make group visible\n            const previous = element.previousElementSibling as HTMLDivElement;\n            if (previous && previous.className.indexOf('group') !== -1 && !previous.previousElementSibling) {\n                element = previous;\n            }\n\n            if (element.offsetTop < container.scrollTop) {\n                container.scrollTop = element.offsetTop;\n            } else {\n                const selectBottom = element.offsetTop + element.offsetHeight;\n                const containerBottom = container.scrollTop + container.offsetHeight;\n                if (selectBottom > containerBottom) {\n                    container.scrollTop += selectBottom - containerBottom;\n                }\n            }\n        }\n    }\n\n    function selectPreviousSuggestion() {\n        const index = items.indexOf(selected!);\n\n        selected = index === -1\n            ? undefined\n            : items[(index + items.length - 1) % items.length];\n\n        updateSelectedSuggestion(index);\n    }\n\n    function selectNextSuggestion() {\n        const index = items.indexOf(selected!);\n\n        selected = items.length < 1\n            ? undefined\n            : index === -1\n                ? items[0]\n                : items[(index + 1) % items.length];\n\n        updateSelectedSuggestion(index);\n    }\n\n    function updateSelectedSuggestion(index: number) {\n        if (items.length > 0) {\n            unselectSuggestion(index);\n            selectSuggestion(items.indexOf(selected!));\n            updateScroll();\n        }\n    }\n\n    function selectSuggestion(index: number) {\n        var element = doc.getElementById(container.id + \"_\" + index);\n        if (element) {\n            element.classList.add('selected');\n            element.setAttribute('aria-selected', 'true');\n            input.setAttribute('aria-activedescendant', element.id);\n        }\n    }\n\n    function unselectSuggestion(index: number) {\n        var element = doc.getElementById(container.id + \"_\" + index);\n        if (element) {\n            element.classList.remove('selected');\n            element.removeAttribute('aria-selected');\n            input.removeAttribute('aria-activedescendant');\n        }\n    }\n\n    function handleArrowAndEscapeKeys(ev: KeyboardEvent, key: 'ArrowUp' | 'ArrowDown' | 'Escape') {\n        const containerIsDisplayed = containerDisplayed();\n\n        if (key === 'Escape') {\n            clear();\n        } else {\n            if (!containerIsDisplayed || items.length < 1) {\n                return;\n            }\n            key === 'ArrowUp'\n                ? selectPreviousSuggestion()\n                : selectNextSuggestion();\n        }\n\n        ev.preventDefault();\n\n        if (containerIsDisplayed) {\n            ev.stopPropagation();\n        }\n    }\n\n    function handleEnterKey(ev: KeyboardEvent) {\n        if (selected) {\n            if (preventSubmit === PreventSubmit.OnSelect) {\n                ev.preventDefault();\n            }\n            suppressAutocomplete = true;\n            try {\n                settings.onSelect(selected, input);\n            } finally {\n                suppressAutocomplete = false;\n            }\n            clear();\n        }\n\n        if (preventSubmit === PreventSubmit.Always) {\n            ev.preventDefault();\n        }\n    }\n\n    function keydownEventHandler(ev: KeyboardEvent) {\n        const key = ev.key;\n\n        switch (key) {\n            case 'ArrowUp':\n            case 'ArrowDown':\n            case 'Escape':\n                handleArrowAndEscapeKeys(ev, key);\n                break;\n            case 'Enter':\n                handleEnterKey(ev);\n                break;\n            default:\n                break;\n        }\n    }\n\n    function focusEventHandler() {\n        if (showOnFocus) {\n            fetch(EventTrigger.Focus);\n        }\n    }\n\n    function fetch(trigger: EventTrigger) {\n        if (input.value.length >= minLen || trigger === EventTrigger.Focus) {\n            clearDebounceTimer();\n            debounceTimer = window.setTimeout(\n                () => startFetch(input.value, trigger, input.selectionStart || 0),\n                trigger === EventTrigger.Keyboard || trigger === EventTrigger.Mouse ? debounceWaitMs : 0);\n        } else {\n            clear();\n        }\n    }\n\n    function startFetch(inputText: string, trigger: EventTrigger, cursorPos: number) {\n        if (destroyed) return;\n        const savedFetchCounter = ++fetchCounter;\n        settings.fetch(inputText, function (elements: T[] | false): void {\n            if (fetchCounter === savedFetchCounter && elements) {\n                items = elements;\n                inputValue = inputText;\n                selected = (items.length < 1 || disableAutoSelect) ? undefined : items[0];\n                update();\n            }\n        }, trigger, cursorPos);\n    }\n\n    function keyupEventHandler(e: KeyboardEvent) {\n        if (settings.keyup) {\n            settings.keyup({\n                event: e,\n                fetch: () => fetch(EventTrigger.Keyboard)\n            });\n            return;\n        }\n\n        if (!containerDisplayed() && e.key === 'ArrowDown') {\n            fetch(EventTrigger.Keyboard);\n        }\n    }\n\n    function clickEventHandler(e: MouseEvent) {\n        settings.click && settings.click({\n            event: e,\n            fetch: () => fetch(EventTrigger.Mouse)\n        });\n    }\n\n    function blurEventHandler() {\n        // when an item is selected by mouse click, the blur event will be initiated before the click event and remove DOM elements,\n        // so that the click event will never be triggered. In order to avoid this issue, DOM removal should be delayed.\n        setTimeout(() => {\n            if (doc.activeElement !== input) {\n                clear();\n            }\n        }, 200);\n    }\n\n    function manualFetch() {\n        startFetch(input.value, EventTrigger.Manual, input.selectionStart || 0);\n    }\n\n    /**\n     * Fixes #26: on long clicks focus will be lost and onSelect method will not be called\n     */\n    container.addEventListener('mousedown', function (evt: Event) {\n        evt.stopPropagation();\n        evt.preventDefault();\n    });\n\n    /**\n     * Fixes #30: autocomplete closes when scrollbar is clicked in IE\n     * See: https://stackoverflow.com/a/9210267/13172349\n     */\n    container.addEventListener('focus', () => input.focus());\n\n    // If the custom autocomplete container is already appended to the DOM during widget initialization, detach it.\n    detach();\n\n    /**\n     * This function will remove DOM elements and clear event handlers\n     */\n    function destroy() {\n        input.removeEventListener('focus', focusEventHandler);\n        input.removeEventListener('keyup', keyupEventHandler as EventListenerOrEventListenerObject)\n        input.removeEventListener('click', clickEventHandler as EventListenerOrEventListenerObject)\n        input.removeEventListener('keydown', keydownEventHandler as EventListenerOrEventListenerObject);\n        input.removeEventListener('input', inputEventHandler as EventListenerOrEventListenerObject);\n        input.removeEventListener('blur', blurEventHandler);\n        window.removeEventListener('resize', resizeEventHandler);\n        doc.removeEventListener('scroll', scrollEventHandler, true);\n        input.removeAttribute('role');\n        input.removeAttribute('aria-expanded');\n        input.removeAttribute('aria-autocomplete');\n        input.removeAttribute('aria-controls');\n        input.removeAttribute('aria-activedescendant');\n        input.removeAttribute('aria-owns');\n        input.removeAttribute('aria-haspopup');\n        clearDebounceTimer();\n        clear();\n        destroyed = true;\n    }\n\n    // setup event handlers\n    input.addEventListener('keyup', keyupEventHandler as EventListenerOrEventListenerObject);\n    input.addEventListener('click', clickEventHandler as EventListenerOrEventListenerObject);\n    input.addEventListener('keydown', keydownEventHandler as EventListenerOrEventListenerObject);\n    input.addEventListener('input', inputEventHandler as EventListenerOrEventListenerObject);\n    input.addEventListener('blur', blurEventHandler);\n    input.addEventListener('focus', focusEventHandler);\n    window.addEventListener('resize', resizeEventHandler);\n    doc.addEventListener('scroll', scrollEventHandler, true);\n\n    return {\n        destroy,\n        fetch: manualFetch\n    };\n}\n","import \"./autocomplete.scss\";\nimport autocomplete, { AutocompleteItem, AutocompleteSettings, AutocompleteResult } from \"autocompleter\";\n\n// Wrapper for npm autocompleter so we can use it for other utwente modules with utwente_base dependency\nexport default function UTAutoComplete<T extends AutocompleteItem>(settings: AutocompleteSettings<T>): AutocompleteResult {\n  return autocomplete(settings);\n}\n","import { levenshteinDistance } from \"@webhare/std\";\n\nconst wordRegex = new RegExp(\"\\\\w+\", \"g\");\nconst lastWordRegex = new RegExp(\"(.*[^\\\\w])?(\\\\w+)$\");\n\ntype FieldsMap = Map<string, number>;\ntype Fields = { fields: FieldsMap };\ntype ItemPositions = { positions: number[] };\ntype Entries<ItemType> = Map<ItemType, ItemPositions>;\n\nexport class SearchIndex<ItemType extends object> {\n  // Create a new index mapping\n  index = new Map<string, Entries<ItemType>>;\n  // Global item metadata (e.g. total wordcount per field)\n  items = new Map<ItemType, Fields>;\n\n  // Initialize the search and suggest fields, fill automatically\n  _searchFields: string[] = [];\n  _autoSearchFields = true;\n  _suggestFields: string[] = [];\n  _autoSuggestFields = true;\n  _completeSuggestFields: string[] = [];\n\n  /// The fields that are used for searching, defaults to all of the indexed fields\n  get searchFields() {\n    // Return the search fields\n    return this._searchFields;\n  }\n\n  set searchFields(fields) {\n    // The search fields are set manually\n    this._searchFields = fields;\n    this._autoSearchFields = false;\n  }\n\n  /// The fields that are used for suggestions, defaults to the searchFields\n  get suggestFields() {\n    // If not set manually, return the search fields\n    return this._autoSuggestFields ? this._searchFields : this._suggestFields;\n  }\n\n  set suggestFields(fields) {\n    // The suggest fields are set manually\n    this._suggestFields = fields;\n    this._autoSuggestFields = false;\n  }\n\n  /// If words from this field are suggested, the complete field is returned as a suggestion\n  get completeSuggestFields() {\n    return this._completeSuggestFields;\n  }\n\n  set completeSuggestFields(fields) {\n    this._completeSuggestFields = fields;\n  }\n\n  /** Index an item\n      This function indexes an item. All of the 'string' properties of the item are tokenized and indexed.\n  */\n  indexItem(item: ItemType): void {\n    const fields: FieldsMap = new Map;\n\n    // Index all indexable properties of the incoming item\n    for (const [key, invalue] of Object.entries(item as Record<string, string | unknown>)) {\n      // For now, we'll only index string values\n      if (typeof invalue !== \"string\")\n        continue;\n\n      // If not set manually, search through all indexed fields\n      if (this._autoSearchFields && !this._searchFields.includes(key))\n        this._searchFields.push(key);\n\n      // Normalize the value\n      const value = invalue.toLowerCase();\n\n      // Tokenize into words\n      let match;\n      let count = 0;\n      while ((match = wordRegex.exec(value)) !== null) {\n        const term = key + \":\" + match[0];\n        const pos = match.index;\n\n        // See if this term is already indexed\n        let entry = this.index.get(term);\n        if (!entry) {\n          // Create a new entry for this term\n          entry = new Map();\n          this.index.set(term, entry);\n        }\n\n        // See if this item is already indexed for this term\n        let props = entry.get(item);\n        if (!props) {\n          // Add the item to this term\n          props = { positions: [] } satisfies ItemPositions;\n          entry.set(item, props);\n        }\n\n        // Add the term's position\n        props.positions.push(pos);\n        ++count;\n      }\n      fields.set(key, count);\n\n    }\n    // Store the item's field counts\n    this.items.set(item, { fields });\n  }\n\n  /** Get suggestions for a query\n      @returns A list of suggested queries\n  */\n  suggest(query: string): string[] {\n    const results = new Map<string, number[]>;\n\n    // Split the incoming query into the array [ \"original query\", \"query up until last word\", \"last word of query\" ]\n    const parsedQuery = lastWordRegex.exec(query);\n    if (parsedQuery) {\n      const baseQuery = parsedQuery[1] || \"\";\n      const suggestQuery = parsedQuery[2];\n\n      let baseResults;\n      if (baseQuery)\n        baseResults = this.#searchInternal(baseQuery).results;\n\n      // Iterate over all the terms in the index\n      for (const [term, entry] of this.index) {\n        // Split the term into field and text\n        const termField = term.split(\":\")[0];\n        if (!this.suggestFields.includes(termField))\n          continue; // This is not a suggested field\n\n        const termText = term.substr(termField.length + 1);\n\n        // Check if the text matches the last query word\n        const score = this.#matchesText(suggestQuery, termText, { startsWithScore: .9 });\n        if (score) {\n          // Return the query, completed with the matching term text\n          let suggestion = baseQuery + termText;\n          if (!results.has(suggestion))\n            results.set(suggestion, [score]);\n\n          // If this field should be returned whole, return this field from each of the entry's items\n          if (this.completeSuggestFields.includes(termField)) {\n            for (const item of entry.keys()) {\n              if (baseResults && !baseResults.has(item))\n                continue;\n              const scores = [score];\n              if (baseResults)\n                scores.push(...baseResults.get(item)!); //due to the two 'if's before here, baseResults.get(item) is not null\n\n              suggestion = (item as Record<string, string>)[termField];\n              const result = results.get(suggestion);\n              if (result)\n                result.push(...scores);\n              else\n                results.set(suggestion, scores);\n            }\n          }\n        }\n      }\n    }\n    if (!results)\n      return [];\n\n    // Calcu§late single scores\n    const flatscores = this.#calculateScores(results);\n\n    // Sort by score and return the suggestions as an array\n    return this.#getSortedItems(flatscores);\n  }\n\n  /** Search for items\n      @param query - The query to search for (only words are searched, interpunction is ignored)\n      @returns The matching items, in scoring order\n  */\n  search(query: string): {\n    items: ItemType[];\n    terms: string[];\n  } {\n    const searchResult = this.#searchInternal(query);\n    // Sort by score and return the items as an array\n    const items = this.#getSortedItems(searchResult.results);\n    return { items, terms: searchResult.terms };\n  }\n\n  #searchInternal(query: string) {\n    const results = new Map<ItemType, number[]>();\n    const terms: string[] = [];\n\n    query = query.toLowerCase();\n\n    // Only search through searched fields\n    for (const field of this.searchFields) {\n      let fieldResults;\n      // Iterate over each of the words in the query\n      const matches = query.match(wordRegex);\n      if (matches) {\n        for (const word of matches) {\n          // Search for the word in this field\n          const queryResult = this.#executeQuery(field, word);\n          // If one the words doesn't match anything, return nothing (AND serach)\n          if (!queryResult.results.size)\n            continue;\n\n          for (const term of queryResult.terms)\n            if (!terms.includes(term))\n              terms.push(term);\n\n          // If there are no results yet, add these results\n          if (!fieldResults) {\n            fieldResults = new Map();\n            for (const [item, match] of queryResult.results)\n              fieldResults.set(item, match.scores);\n          } else {\n            // Keep all items that are already there (AND search)\n            for (const [item, match] of queryResult.results) {\n              if (fieldResults.has(item))\n                fieldResults.get(item).push(...match.scores);\n            }\n            // Remove all items that aren't found again (AND search)\n            for (const item of fieldResults.keys())\n              if (!queryResult.results.has(item))\n                fieldResults.delete(item);\n          }\n        }\n      }\n\n      if (fieldResults) {\n        for (const [item, scores] of fieldResults) {\n          const result = results.get(item);\n          if (result)\n            result.push(...scores);\n          else\n            results.set(item, scores);\n        }\n      }\n    }\n\n    // Calculate single scores\n    const flatscores = this.#calculateScores(results);\n    return { results: flatscores, terms };\n  }\n\n  // returns a Map from item to { scores, term, positions }\n  #executeQuery(field: string, text: string) {\n    let results;\n    const terms: string[] = [];\n    // Try a direct match\n    const entry = this.index.get(field + \":\" + text);\n    if (entry) {\n      // The entry's keys are the indexed items\n      results = new Map(Array.from(entry).map(item_positions => {\n        return [item_positions[0], { scores: [1], term: text, positions: item_positions[1].positions }];\n      }));\n      terms.push(text);\n    } else {\n      // Iterate over all the terms in the index\n      results = new Map();\n      for (const [term, indexEntry] of this.index) {\n        // Split the term into field and text\n        const termField = term.split(\":\")[0];\n        if (termField !== field && field !== \"*\")\n          continue; // This is not the field we're looking for\n\n        const termText = term.substr(termField.length + 1);\n\n        // Check if the text matches the query word\n        const score = this.#matchesText(text, termText);\n        if (score) {\n          for (const item_positions of Array.from(indexEntry)) {\n            if (!results.has(item_positions[0]))\n              results.set(item_positions[0], { scores: [score], term: termText, positions: item_positions[1].positions });\n            else\n              results.get(item_positions[0]).scores.push(score);\n          }\n          terms.push(termText);\n        }\n      }\n\n      // Calculate single scores\n      for (const [item, match] of results)\n        results.get(item).scores = [match.scores.reduce((avg: number, cur: number, idx: number) => ((avg * idx) + cur) / (idx + 1))];\n    }\n    return { results, terms };\n  }\n\n  #matchesText(queryWord: string, termWord: string, { limitDistance = 2, startsWithScore = .25 } = {}) {\n    if (queryWord === termWord)\n      return 1;\n    let score = 0;\n    // Require both terms to have a length of at least twice the distance\n    if (Math.min(queryWord.length, termWord.length) >= 2 * limitDistance) {\n      const dist = levenshteinDistance(queryWord, termWord);\n      if (dist <= limitDistance)\n        score = Math.max(score, (limitDistance - dist + 1) / limitDistance);\n    }\n    if (termWord.startsWith(queryWord))\n      score = Math.max(score, startsWithScore);\n    return score;\n  }\n\n  #calculateScores<KeyType>(results: Map<KeyType, number[]>) {\n    const flatscores = new Map<KeyType, number[]>;\n    for (const [key, scores] of results)\n      flatscores.set(key, [scores.reduce((avg, cur, idx) => ((avg * idx) + cur) / (idx + 1))]);\n    return flatscores;\n  }\n\n  #getSortedItems<KeyType>(results: Map<KeyType, number[]>): KeyType[] {\n    return Array.from(results).sort((a, b) => b[1][0] - a[1][0]).map(_ => _[0]);\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n/*\nThis variation on dompack-masonry has:\n- a breakclass which make the current widget appear on a new line\n- ability to have different gaps/margin for headers en normal items\n- setItems()\n- need to manually call refresh()\n\nTech\n- columnitems - list of which items each column\n- ability to influence rendering by reading/editting masonry.items after initialization, before the first refresh()\n*/\n\nimport * as dompack from \"dompack\";\n\n\nexport default class DompackMasonry {\n  constructor(node, options) {\n    const domoptions = dompack.getJSONAttribute(node, \"data-masonry-options\");\n    this.initialized = false;\n\n    // NOTE: we don't use Object.assign() here because we have some\n    //       smart rules (convert gutter to gutter_x and gutter_y for example)\n    this.options =\n    {\n      columns: 3,\n      columnwidth: 0,     // if not set the width will be set so the amount of columns will fill up the horizontal space\n\n      // gutter size\n      // gutter:            10 // shorthand for gutter_x and gutter_y\n      gutter_x: 10,\n      gutter_y: 10,\n      //            , gutter_y_header:    23\n\n      margin_header_top: 23,\n      margin_header_bottom: 23,\n\n      debug: false,\n\n      // CSS query (for example '.masonry-item' or array of nodes\n      // Pass an array of nodes if you want control over the order visual order of the items (without reordering the dom)\n      items: null,\n\n      // specify a class to ignore in layouting\n      // (can be used for items which you transition to hide/fade)\n      ignoreclass: \"hide\",\n      breakclass: \"\",\n\n      righttoleft: false // FIXME: keep or remove this option?\n    };//, domoptions, options;\n\n    this.items = [];   // render data\n\n    if (typeof (node) === \"string\")\n      this.container = document.getElementById(node);\n    else\n      this.container = node;\n\n    if (domoptions)\n      this.setOptions(domoptions);\n\n    if (options)\n      this.setOptions(options);\n\n    this.__height = 0;\n    this.__columnwidth = 0;    // (also used to detect whether widget width style has to be set)\n    this.__visiblewidgetscount = 0;\n    this.__singlerow = true;\n    this.__columncontainers = [];\n    this.__padding = 0;\n\n    this.__items_dirty = true;\n\n    // PRIVATE VARS!!\n    this.__leftoffset = 0;\n    this.__containerwidth = 0;\n    this.ignore_resize_events = false;\n\n    this.initialized = true;\n\n    //this.refresh();\n  }\n\n  setItems(items) {\n    //console.log(\"setItems\", items);\n\n    this.__items_dirty = true; // need to recheck all widgets, there might be new ones\n\n    // For now only store the existance and some info on the widgets\n    // DON'T do DOM manipulation here!\n    const widgetrecs = [];\n    for (const wnode of items) {\n      let widgetcols = wnode.getAttribute(\"data-cols\");\n      widgetcols = widgetcols ? parseInt(widgetcols) : 1;\n\n      const item =\n      {\n        node: wnode,\n        width: null,\n        height: null,\n        col: null, // explicit column number\n\n        colwanted: null,\n        colswanted: widgetcols,\n        breakbefore: this.options.breakclass != \"\" && wnode.classList.contains(this.options.breakclass)\n      };\n      // console.log(item);\n      widgetrecs.push(item);\n    }\n\n    console.log(\"Storing \" + widgetrecs.length + \" items\");\n    this.items = widgetrecs;\n  }\n\n  setOptions(options) {\n    if (\"gutter\" in options) {\n      options.gutter_x = options.gutter;\n      options.gutter_y = options.gutter;\n      delete options.gutter;\n    }\n\n    let setitems = false;\n    let widgets;\n    if (\"items\" in options) {\n      setitems = true;\n      if (typeof (options.items) === \"string\") {\n        console.info(\"Finding widgets by query:\", options.items, \"in\", this.container);\n        widgets = this.container.querySelectorAll(options.items);\n      } else\n        widgets = options.items;\n\n      delete options.items;\n    }\n\n    Object.assign(this.options, options);\n\n    if (setitems) // setitems uses this.options so we need it to be set before we call this.setItems\n      this.setItems(widgets);\n  }\n\n  /** @short full relayout\n      @long find all items, detect width, read data-cols attributes on items and relayout\n  */\n  refresh(elem) {\n    if (!this.initialized) {\n      console.info(\"Refresh called before initialization in ready!!\");\n      return;\n    }\n\n    if (this.options.debug) {\n      console.log(\"$wh.Masonry.refresh()\");\n      //console.trace();\n    }\n\n    const clientwidth = this.container.clientWidth;\n    if (clientwidth == 0) {\n      console.warn(\"Cannot determine size of mansonry container (got 0).\", this.container);\n      return;\n    }\n\n    this.ignore_resize_events = true;\n\n    // FIXME: assuming padding in px\n    // FIXME: assuming correct box-sizing\n    // FIXME: assumption that this container (with the padding) is also the positioning container\n    const cstyle = window.getComputedStyle(this.container);\n    const padtop = parseInt(cstyle.paddingTop, 10);\n    const padbottom = parseInt(cstyle.paddingBottom, 10);\n    const padleft = parseInt(cstyle.paddingLeft, 10);\n    const padright = parseInt(cstyle.paddingRight, 10);\n    this.__padding = {\n      top: padtop,\n      bottom: padbottom,\n      left: padleft,\n      right: padright\n    };\n    //console.log(this.container, this.__padding);\n\n    this.__leftoffset = padleft;\n    this.__containerwidth = clientwidth - padleft - padright;\n\n    this.pvt_relayout();\n\n    this.ignore_resize_events = false;\n  }\n\n  /** @short only update heights and position\n             New items and changed widths aren't detected\n  */\n  refreshHeights(elem) {\n    this.pvt_relayout(null, true);\n  }\n\n  getLastRenderInfo() {\n    return {\n      container: this.container,\n      visiblewidgetscount: this.__visiblewidgetscount,\n      width: this.__containerwidth,\n      height: this.__height,\n      items: this.items,\n      singlerow: this.__singlerow\n    };\n  }\n\n\n  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n  //\n  //  Private functions\n  //\n\n  pvt_relayout(widgets) {\n    if (this.options.debug)\n      console.group(\"$wh.Masonry.pvt_relayout()\");\n\n    let visiblewidgetscount = 0;\n\n    let columnwidth = this.options.columnwidth;\n    if (!columnwidth)\n      columnwidth = (this.__containerwidth - (this.options.columns - 1) * this.options.gutter_x) / this.options.columns;\n\n    if (this.options.debug)\n      console.info(\"Colwidth OLD:\", this.__columnwidth, \", NEW:\", columnwidth);\n\n    if (columnwidth == 0) {\n      console.error(\"Cannot render, columnwidth is 0\");\n      return;\n    }\n\n    if (isNaN(this.options.columns)) {\n      console.error(\"options.columns MUST be a number!\");\n      return;\n    }\n\n\n    const columncount = this.options.columns;\n    let singlerow = true; // until we have to place a new widget below another one all widgets are still on a single row\n\n    const columns = []; // the last Y position in use per column\n    for (var xcol = 0; xcol < columncount; xcol++)\n      columns.push(0);\n\n\n    // for each column the items in that column\n    const columnitems = [];\n    for (var xcol = 0; xcol < columncount; xcol++)\n      columnitems.push([]);\n\n\n\n    /*\n    console.log({ columns:     this.options.columns\n                , columnwidth: columnwidth\n                });\n    */\n\n    let widgetrecs;\n    if (!widgets) // If we didn't get a list of items to render we must rerender ALL items\n      widgetrecs = this.items;\n\n\n    if (this.options.debug)\n      console.info(\"$wh.Masonry relayouting \" + widgetrecs.length + \" items\");\n\n\n    // Only change widget width's when needed\n    if (this.__items_dirty || this.__columnwidth != columnwidth) // new items or width for widgets need to change?\n    {\n      // First apply the new width to all widgets, so we can later determine the correct height\n      //console.info(\"Measuring items\");\n\n      for (const widget of widgetrecs) {\n        const widgetcols = widget.colswanted > this.options.columns ? this.options.columns : widget.colswanted;\n        const width = columnwidth * widgetcols + (widgetcols - 1) * this.options.gutter_x;\n\n        widget.node.style.position = \"absolute\";\n        widget.node.style.width = Math.floor(width) + \"px\"; // round using pixelratio ??\n        widget.node.style.height = \"\"; // clear any inline specified height (we only allow a fixed height if specified in CSS)\n\n        widget.width = width;\n        widget.cols = widgetcols;\n      }\n\n\n      /*\n      Let our children relayout to match our new width\n      (after which layout of masonry item contents should be done, meaning the height is known and we can start to build up the masonry)\n\n      if (this.options.debug)\n        console.log(\"Firing layout change event\");\n\n      // Notify any of our components within the Masonry container that layout has changed.\n      // After they have updated their layout we know the final height of each widget and can start to layout our Masonry.\n      //$wh.fireLayoutChangeEvent(this.container, \"down\"); // FIXME\n      */\n    }\n\n\n    // measure all widgets in one go to prevent extreneous reflows by mixing writes and reads\n    for (const widget of widgetrecs)\n      widget.height = widget.node.clientHeight;\n\n\n\n    if (this.options.debug)\n      console.log(\"relayout mainloop\");\n\n\n    for (let idx = 0; idx < widgetrecs.length; idx++) {\n      const widgetrec = widgetrecs[idx];\n      const wnode = widgetrec.node;\n\n      const widgetheight = widgetrec.height;\n\n      if (this.options.debug)\n        console.log(\"#\" + idx, widgetheight + \"px\", wnode.className);\n\n      if (widgetheight == 0 || (this.options.ignoreclass != \"\" && wnode.classList.contains(this.options.ignoreclass)))\n        continue;\n\n      visiblewidgetscount++;\n\n\n\n      /*\n            if (widgetrec.breakbefore)\n            {\n              ypos = Math.max.apply(null, columns);\n              for (var col = 0; col < columncount; ++col)\n                columns[col] = ypos;\n            }\n      */\n\n\n\n      // Force all columns to continue rendering items below the top position\n      // of all current items\n      if (widgetrec.breakbefore) {\n        // find the widget which starts the lowest\n        let min_ypos = 0;\n        for (var col = 0; col < columncount; ++col) {\n          const itemcount = columnitems[col].length;\n          if (itemcount == 0)\n            continue;\n\n          const lastitemincol = columnitems[col][itemcount - 1];\n          if (lastitemincol.top > ypos)\n            min_ypos = lastitemincol.top;\n        }\n\n        //console.log(\"!! BREAK, lowest widget top\", min_ypos);\n\n        if (min_ypos > 0) {\n          min_ypos += 160;\n\n          // make all column continue at least 60 pixels lower...\n          for (var col = 0; col < columncount; ++col) {\n            if (columns[col] < min_ypos)\n              columns[col] = min_ypos;\n          }\n        }\n      }\n\n\n\n      // set increase the last used ypos within the columns the current widget will occupy\n      // find the first ypos where the whole block would fit\n      if (this.options.debug)\n        console.info(columns);\n\n\n\n      var bestcol = -1, ypos = 0;\n\n\n      // Forced to be in a specific column?\n      if (widgetrec.colwanted !== null && widgetrec.colwanted < columncount) {\n        bestcol = widgetrec.colwanted;\n        ypos = columns[widgetrec.colwanted];\n      } else {\n        // console.log(\"Find column\");\n        for (var xcol = 0; xcol <= columncount - widgetrec.cols; ++xcol) {\n          const col = this.options.righttoleft ? columncount - widgetrec.cols - xcol : xcol;\n          const maxypos = Math.max.apply(null, columns.slice(col, col + widgetrec.cols));\n          //console.log(col, \"has enough room for \", widgetrec.cols, \" columns starting at Y pos\", maxypos);\n\n          if (bestcol == -1 || maxypos < ypos) // no column yet or we can place the item higher at this location than the previous found position\n          {\n            bestcol = col;\n            ypos = maxypos;\n          }\n        }\n      }\n\n\n      if (ypos > 0) {\n        singlerow = false;\n\n\n        // A big hack for some special timeline related layouting\n        if (wnode.classList.contains(\"timeline__header\")) {\n          if (columnitems[bestcol].length > 0 && columnitems[bestcol][columnitems[bestcol].length - 1].breakbefore) {\n            // .header + .header\n            ypos += this.options.margin_header_top; // hack\n            // wnode.style.outline = \"1px solid #F00\";\n          } else {\n            // .normalitem + .header\n            ypos += this.options.gutter_y;\n            // wnode.style.outline = \"1px solid #0F0\";\n          }\n        } else // hack\n        {\n          // Normal item with an header above it?\n          if (columnitems[bestcol].length > 0 && columnitems[bestcol][columnitems[bestcol].length - 1].breakbefore) {\n            ypos += this.options.margin_header_bottom;\n            // wnode.style.outline = \"1px solid #F0F\";\n          } else // Normal item + normal item\n          {\n            ypos += this.options.gutter_y;\n            // wnode.style.outline = \"1px solid #0FF\";\n          }\n        }\n      }\n\n\n      const widgetbottom = ypos + widgetheight;\n      for (var col = 0; col < widgetrec.cols; ++col) {\n        columns[bestcol + col] = widgetbottom;\n        columnitems[bestcol + col].push(widgetrec);\n      }\n\n\n      widgetrec.col = bestcol;\n      widgetrec.left = this.__leftoffset + (bestcol * columnwidth + (bestcol) * this.options.gutter_x);\n      widgetrec.top = ypos;\n\n      const styles = {\n        position: \"absolute\",\n        left: widgetrec.left, // 300 width, 10 px leftmargin, 20 inter\n        top: widgetrec.top + this.__padding.top\n        //, width:    columnwidth * widgetrec.cols + (widgetrec.cols-1) * this.options.gutter_x\n      };\n\n      if (this.options.debug)\n        console.log(\"Will be placed into col\", bestcol);\n\n      wnode.style.position = styles.position;\n      wnode.style.left = styles.left + \"px\";\n      wnode.style.top = styles.top + \"px\";\n    }\n\n    const maxheight = Math.max.apply(null, columns) + this.__padding.top + this.__padding.bottom;\n\n    //reorderWidgets(keepcolumnpos);\n    if (this.options.columnwidth)\n      this.container.style.width = (this.options.columnwidth * this.options.columns + (this.options.columns - 1) * this.options.gutter_x) + \"px\";\n\n    this.container.style.height = maxheight + \"px\";\n\n    /*\n    // Now we want our parents to know we have changed in size\n    // FIXME: add a check whether we actually changed in size\n    if (this.options.debug)\n      console.log(\"Firing layout change event\");\n\n    $wh.fireLayoutChangeEvent(this.container, \"up\"); // FIXME\n    */\n\n    if (this.options.debug) {\n      console.log(this.container, \"has\", visiblewidgetscount, \"visible widgets\");\n      console.groupEnd();\n    }\n\n    /*\n    store render information (can be used to add extra behaviour outside this class for example:\n    - to equalize heights of widgets by external code or hide a widgets grid\n    - to hide a widgets container in case it has no visible widgets\n    */\n    this.__itemdata = widgetrecs;\n    this.__columnwidth = columnwidth;\n    this.__height = maxheight;\n    this.__visiblewidgetscount = visiblewidgetscount;\n    this.__singlerow = singlerow;\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\nimport { qS, qSA } from 'dompack';\nimport './timetable.scss';\nimport './whtimetable.scss';\nimport WHTimeTable from './whtimetable';\n\nimport * as modaldialog from \"../../../shared/dialog\";\n\n\n\nclass TimeTableWidget {\n  constructor(widget) {\n    console.log(\"Initializing TimeTableWidget node\", widget);\n\n    this.widgetcontainer = widget;\n    this.tabstrip = null;\n    this.tabselect = null; // <select> used as fallback in case the tabstrip doesn't fit\n    this.currenttab = null;\n    this.orig_before_node = widget.nextSibling;\n    this.orig_parent_node = widget.parentNode;\n\n    this.initTimeTables();\n    this.initTabStrip();\n\n    this.onViewportResize();\n\n    window.addEventListener(\"resize\", this.onViewportResize.bind(this));\n    window.addEventListener(\"hashchange\", this.doCheckHash.bind(this));\n\n    this.widgetcontainer.querySelector(\".ttw-enter-fullscreen\").addEventListener(\"click\", this.enterFullscreen.bind(this));\n    this.widgetcontainer.querySelector(\".ttw-exit-fullscreen\").addEventListener(\"click\", this.exitFullscreen.bind(this));\n\n    this.doCheckHash();\n  }\n\n  doCheckHash() {\n    if (!this.tabstrip) // no need to switch, we only have one timetable\n      return;\n\n    console.log(location.hash);\n\n    const hash = location.hash.substr(1);\n\n    // we generated placeholder's in the HTML for the browser to scroll to.\n    // These are placed right above the viewport of the timetable(s).\n    // Now we only have to switch to the correct timetable.\n    // FIXME: check if the browse afterwards correctly scrolls due to changed\n    //        page size due to switching timetables and loading of content such as custom fonts/images etc.\n    //console.log(\"Looking up tab with hash\", '.ttw-tab[data-urlhash=\"'+hash+'\"');\n    const tab = this.tabstrip.querySelector('.ttw-tab[data-urlhash=\"' + hash + '\"');\n    if (tab)\n      this.__selectTab(tab);\n  }\n\n  /*\n  There are three types of fullscreen we could use:\n  - browser fullscreen mode ->\n  - fixed pos -> triggers lots of iOS/Android bugs, issues with zooming and smooth scrolling\n  - hide content and make our content \"the page\" -> smooth (** this is the way we do it!)\n  */\n  enterFullscreen() {\n    this.origscrolly = document.body.scrollTop;\n    document.body.scrollTop = 0; // iOS workaround\n\n    document.documentElement.classList.add(\"html--onlyfullscreenelement\");\n    this.widgetcontainer.classList.add(\"ttw-fullscreen\");\n\n    document.body.appendChild(this.widgetcontainer);\n  }\n\n  exitFullscreen() {\n    this.orig_parent_node.insertBefore(this.widgetcontainer, this.orig_before_node);\n\n    document.documentElement.classList.remove(\"html--onlyfullscreenelement\");\n    this.widgetcontainer.classList.remove(\"ttw-fullscreen\");\n    document.body.scrollTop = this.origscrolly;\n  }\n\n  /** @short Initializate the timetables which are grouped in this widget\n  */\n  initTimeTables() {\n    const timetablenodes = this.widgetcontainer.querySelectorAll(\".wh-timetable\");\n    for (const ttnode of timetablenodes) {\n      const timetable = new WHTimeTable(ttnode\n        , {\n          timestep_mins: 60,\n          starttime_max: \"08:00\",\n          endtime_min: \"21:30\",\n\n          rows: JSON.parse(ttnode.dataset.timetableinfo),\n          onSelect: this.openEventPopup.bind(this),\n          debug: false,\n\n          // use at least 30 * slots as height\n          slots: [\n            { height: 46, gutter: 0 }, // 1 slot\n            { height: 74, gutter: 1 }, // 2 slots\n            { height: 104, gutter: 1 }, // 3 slots\n            { height: 134, gutter: 1 }, // 4 slots\n            { height: 164, gutter: 1 }, // 5 slots\n            { height: 180, gutter: 1 }, // 6 slots\n            { height: 210, gutter: 1 }, // 7 slots\n            { height: 240, gutter: 1 }, // 8 slots\n            { height: 270, gutter: 1 }, // 9 slots\n            { height: 300, gutter: 1 } // 10 slots\n          ]\n        });\n    }\n  }\n\n  initTabStrip() {\n    this.tabstrip = this.widgetcontainer.querySelector(\".ttw-tabstrip\");\n    if (!this.tabstrip) // single timetable so no tabstrip added\n      return;\n\n    this.tabstrip.addEventListener(\"click\", this.onTabStripClick.bind(this));\n\n    this.tabselect = this.widgetcontainer.querySelector(\"select.ttw-tabselect\");\n    this.tabselect.addEventListener(\"change\", this.onTabPulldownSelection.bind(this));\n\n    const firsttabbutton = this.tabstrip.querySelector(\".ttw-tab\");\n    if (firsttabbutton)\n      this.__selectTab(firsttabbutton);\n  }\n\n  onTabPulldownSelection(evt) {\n    const tabnode = this.tabstrip.querySelector('[data-tabcontentid=\"' + this.tabselect.value + '\"]');\n    this.__selectTab(tabnode);\n  }\n\n  onTabStripClick(evt) {\n    let tabnode = evt.target;\n    while (tabnode && !evt.target.classList.contains(\"ttw-tab\"))\n      tabnode = tabnode.parentNode;\n\n    const urlhash = tabnode.getAttribute(\"data-urlhash\");\n    if (urlhash) {\n      if (window.history && window.history.replaceState)\n        history.replaceState(undefined, undefined, \"#\" + urlhash);\n      /*\n      else // IE9\n      {\n        var scrollx = window.getScrollLeft();\n        var scrolly = window.getScrollTop();\n        console.log(scrolly);\n        location.replace(\"#\"+urlhash);\n        window.scrollTo(scrollx, scrolly);\n        setTimeout(function() { window.scrollTo(scrollx, scrolly); console.log(window.getScrollTop()); }, 0);\n      }\n      */\n    }\n\n    if (!tabnode)\n      return; // the click wasn't within one of the tabbuttons\n\n    evt.preventDefault();\n    this.__selectTab(tabnode);\n  }\n\n  __selectTab(tabnode) {\n    const tabcontentid = tabnode.dataset.tabcontentid;\n    const contentnode = qS('#' + tabcontentid);\n\n    // update value of the <select>\n    if (this.currenttab != tabcontentid && this.tabselect.value != tabcontentid) {\n      /*\n      var whpulldown = this.tabselect.retrieve(\"wh-pulldown\");\n      if (whpulldown)\n        whpulldown.setValue(tabcontentid);\n      else\n        */\n      this.tabselect.value = tabcontentid;\n    }\n\n    this.currenttab = tabcontentid;\n\n    const tabnodes = this.tabstrip.querySelectorAll(\".ttw-tab\");\n    for (const tnode of tabnodes)\n      tnode.classList[tnode == tabnode ? 'add' : 'remove'](\"selected\");\n\n    const contentnodes = this.widgetcontainer.querySelectorAll(\".ttw-tabpanel\");\n    for (const cnode of contentnodes)\n      cnode.classList[cnode == contentnode ? 'add' : 'remove'](\"selected\");\n  }\n\n\n  openEventPopup(ttevent) {\n    const popupnode = qS('#' + ttevent.data.data.popupid);\n    if (!popupnode) {\n      console.error(\"Missing TimeTable widget popupid\", ttevent.data.popupid);\n      return;\n    }\n\n    console.info(\"POPUP\", popupnode);\n\n    /*\n    NOTE: we don't use an advanced popup system anymore.\n          We don't have popup_viewport's or position relative to the event clicked.\n\n    $wh.PopupManager.setOptions({ keepscrollevents: false });\n\n    var popup = $wh.Popup.createFromElement( popupnode\n                               , { cssclass:         \"timetablewidget-popup \" + ttevent.data.cssclass // use colorschema\n                                 , theme:            \"blub\"\n                                 , position:         \"relative\"\n                                 , positionanchor_x: $(\"contentbody\")\n                                 , positionanchor_y: ttevent.target\n                                 //, scroll:           \"popup_viewport\"\n                                 , modal:            true\n                                 , maxwidth:         $(\"contentbody\").clientWidth\n                                 , maxheight:        \"none\" // important in combination with using option position: \"relative\" or \"absolute\"\n                                 , width: \"stretch\"\n                                 //, keepscrollevents: false\n                                 }); //, { maxwidth: 890 - 20 });\n     */\n\n    modaldialog.showModalDialog(\"\"\n      , popupnode.cloneNode(true)\n      , { theme: \"timetablewidget-popup \" + ttevent.data.cssclass }\n    );\n  }\n\n  onViewportResize() {\n    // if the tabs won't fit in the available horizontal space,\n    // show the pulldown instead as method to select a timetable tab.\n    if (this.tabstrip) {\n      var overflow = this.tabstrip.offsetWidth > this.widgetcontainer.clientWidth;\n\n      const tabs = this.tabstrip.querySelectorAll(\".ttw-tab\");\n      const lastxwithin = tabs[tabs.length - 1].getBoundingClientRect().right - this.tabstrip.getBoundingClientRect().left;\n      var overflow = lastxwithin > this.widgetcontainer.clientWidth;\n\n      this.widgetcontainer.classList[overflow ? 'add' : 'remove'](\"hide_tabstrip\");\n    }\n  }\n\n  refresh() {\n    //$wh.fireLayoutChangeEvent( $(\"contentwidgets\") );\n  }\n}\n\n// make sure we initialize after load because otherwise Firefox and Safari won't have\n// the stylesheets the timetable component required to initialize/measure correctly.\n// (Chrome seems to have stylesheets ready during the document's 'interactive'-state when components initializing)\nif (document.readyState == \"complete\")\n  dompack.register('.timetablewidget', node => new TimeTableWidget(node));\nelse {\n  window.addEventListener(\"load\",\n    function () {\n      dompack.register('.timetablewidget', node => new TimeTableWidget(node));\n    });\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n/*\n\n- this is an adapted version of the popupout code used in dottwente\n  for for studylist, relatedprogrammes and researchprogrammes.\n  (and ws2013 for CuriousU timetable popouts)\n\n- the code auto-initialized on DOMContentReady\n\n- use. Add attribute data-popout=\"[id-of-panel]\" to any element which should trigger a popout\n\n\nADDME:\n\n- rewrite and make it into a generic library\n\n- implement the popup zones I intended to implement years ago :P\n\nADDME: detect scrollpos and keep inside of screen\nADDME: detect zoomed onto part of screen and keep inside that part\n\nADDME: detect transition end like designfiles's wh.ui.popup\n\nADDME: a wh-popout-action-close class?\n\n*/\n\n//(function($) {\n\nif (!window.$wh) window.$wh = {};\n\nlet currenthovertarget;\n\nfunction activatePopupPanels() {\n  const body = document.body;\n  body.addEventListener('touchstart', dorelay.bind(this, \"[data-popout]\", togglePopup, onTouchEnd));\n  body.addEventListener('mouseover', dorelay.bind(this, \"[data-popout]\", onEnterPopupTrigger, onLeavePopupTrigger));\n  //body.addEventListener('mouseenter', dorelay.bind(this, \".-wh-popoutpanel\", onEnterPopupPanel));\n  //body.addEventListener('mouseleave', dorelay.bind(this, \".-wh-popoutpanel\", onLeavePopupPanel));\n\n  /*\n    $wh.PopoutManager.definePopupType( \"calitem_description\"\n                                , { within_node: $(\"newsgrid\")\n                                  , panelhoverkeepsopen: true\n                                  , closedelay: 0\n                                  , closetransitiondelay: 200\n                                  });\n  \n      body.addEventListener('mouseenter:relay(*[data-popout])', onEnterPopupTrigger.bind(this));\n      body.addEventListener('mouseleave:relay(*[data-popout])', onLeavePopupTrigger.bind(this));\n  \n      body.addEventListener('mouseenter:relay(.-wh-popoutpanel)', onEnterPopupPanel.bind(this));\n      body.addEventListener('mouseleave:relay(.-wh-popoutpanel)', onLeavePopupPanel.bind(this));\n    }\n  */\n}\n\nfunction dorelay(cssselector, callback_enter, callback_leave, evt) {\n  //var elem = evt.target.closest(cssselector);\n  const elem = evt.target.closest(cssselector);\n\n  //console.log(evt.target, elem ? elem : \"no match for \"+cssselector);\n\n  if (currenthovertarget == elem)\n    return; // we already knew we are hovering this item (we probably switched subnodes)\n\n  if (currenthovertarget) {\n    console.info(\"mouseleave\", currenthovertarget);\n    callback_leave(evt, currenthovertarget);\n  }\n\n  currenthovertarget = elem;\n\n  //  console.log(\"RELAY\", evt.type, cssselector, callback, this, elem);\n\n  if (elem) {\n    console.info(\"mouseenter\", elem);\n    callback_enter(evt, elem);\n  }\n}\n\n\nfunction onTouchEnd(evt) {\n  if ($utPopupActive)\n    _hidePopup($utPopupActive);\n}\n\nfunction onEnterPopupPanel(evt, node) {\n  const popuptype = getPopupType(node);\n  if (!popuptype.panelhoverkeepsopen)\n    return; // no need to keep the popup open on mouseover\n\n  // did we move into the active popup panel (should be, unless another popuppanel somehow is set to be visible)\n  if (node == $utPopupActive)\n    cancelPopupClose();\n}\n\nfunction onLeavePopupPanel(event, node) {\n  event.stop();\n  schedulePopupClose();\n  // FIXME: check targetnode if the user didn't quickly returned to the trigger node\n}\n\n\n\n\nfunction onPopoutPanelClick(event, node) {\n  // let's not mess up the useability of an anchor\n  const targetnode = event.target;\n  if (targetnode.tagName == \"A\" || targetnode.getParent(\"A\"))\n    return;\n\n  event.stop();\n  schedulePopupClose();\n}\n\n\n\nfunction togglePopup(event, node) {\n  // let's not mess up the useability of an anchor\n  const targetnode = event.target;\n  if (targetnode.tagName == \"A\" || targetnode.getParent(\"A\"))\n    return;\n\n  event.stop();\n\n  const popupid = node.getAttribute(\"data-popout\");\n\n  const popupnode = $(popupid);\n  if (!popupnode)\n    return;\n\n  // make sure only one popup is visible at a time\n  if ($utPopupActive !== null && $utPopupActive !== popupnode)\n    _hidePopup($utPopupActive);\n\n  if (popupnode.hasClass(\"active\"))\n    onLeavePopupTrigger(event, node, true);\n  else\n    onEnterPopupTrigger(event, node);\n}\n\nfunction onEnterPopupTrigger(event, node) {\n  event.preventDefault();\n  event.stopPropagation();\n\n  const popupid = node.getAttribute(\"data-popout\");\n\n  const popuptype = getPopupType(node);\n  //console.log(popuptype);\n  window.$wh.PopoutManager.currenttype = popuptype;\n\n  const popupnode = document.getElementById(popupid);\n  if (!popupnode)\n    return;\n\n  // We MUST be positioned in the body\n  // (to be on top so whe're always visible and so positioning works correctly)\n  if (popupnode.parentNode !== document.body)\n    $(document.body).adopt(popupnode);\n\n  // is another popup active? close it first.\n  if ($utPopupActive !== null) {\n    if ($utPopupActive !== popupnode)\n      _hidePopup($utPopupActive);\n    else\n      cancelPopupClose();\n  }\n\n  $utPopupActive = popupnode;\n\n\n  //requestAnimationFrame(function() { popupnode.classList.add(\"animate\"); })\n\n  let posinfo = popupnode.getAttribute(\"data-popout-position\");\n  //console.log(posinfo);\n  if (posinfo == null)\n    posinfo = [\"middle\", \"middle\"];\n  else\n    posinfo = posinfo.split(\" \");\n\n\n  posinfo = [\"middle\", \"above\"];\n\n\n  let popupx = 0;\n  let popupy = 0;\n\n  popupnode.style.position = \"absolute\";\n  popupnode.style.left = \"0\";\n  popupnode.style.top = \"0\";\n  popupnode.style.visibility = \"hidden\";\n  popupnode.style.display = \"block\";\n\n  const body_pos = document.body.getBoundingClientRect();\n  const anode_pos = node.getBoundingClientRect();\n  //console.log(\"trigger\", anode_pos);\n  //console.log(\"body\", body_pos);\n  const anchor_pos = {\n    x: anode_pos.left - body_pos.left,\n    y: anode_pos.top - body_pos.top\n  };\n\n  const anchor_size = {\n    x: node.offsetWidth,\n    y: node.offsetHeight\n  };\n\n  const popup_size = {\n    x: popupnode.offsetWidth,\n    y: popupnode.offsetHeight\n  };\n\n  /*\n  console.log(anchor_pos);\n  console.log(anchor_size);\n  console.log(popup_size);\n  console.log(\"***\");\n  */\n  const marginsize = 2;\n\n  /*\n  console.group(\"Positioning popoutpanel\");\n  console.log(posinfo);\n  console.log(\"Anchor pos\", anchor_pos);\n  console.log(\"Anchor size\", anchor_size);\n  console.log(\"Popup size\", popup_size);\n  console.groupEnd();\n  */\n\n  switch (posinfo[0]) {\n    case \"left\":\n      popupx = anchor_pos.x - popup_size.x - marginsize;\n      break;\n\n    case \"middle\":\n      popupx = anchor_pos.x + anchor_size.x / 2 - popup_size.x / 2;\n      break;\n\n    case \"right\":\n      popupx = anchor_pos.x + anchor_size.x + marginsize;\n      break;\n  }\n\n  switch (posinfo[1]) {\n    case \"above\":\n      popupy = anchor_pos.y - popup_size.y - marginsize;\n      break;\n\n    case \"top\":\n      popupy = anchor_pos.y;\n      break;\n\n    case \"middle\":\n      popupy = anchor_pos.y + anchor_size.y / 2 - popup_size.y / 2;\n      break;\n\n    case \"bottom\":\n      popupy = anchor_pos.y + anchor_size.y - popup_size.y;\n      break;\n\n    case \"below\":\n      popupy = anchor_pos.y + anchor_size.y + marginsize;\n      break;\n  }\n\n  if (popupx < 0)\n    popupx = 0;\n\n  if (popupy < 0)\n    popupy = 0;\n\n  popupnode.style.visibility = \"none\";\n  popupnode.style.display = \"block\";\n  popupnode.style.zIndex = \"99999\";\n\n  const popupwidth = popupnode.offsetWidth;\n\n  const pagewidth = document.body.clientWidth;\n  /*\n  console.log({ popupwidth: popupwidth\n              , pagewidth: pagewidth\n              , popupx: popupx\n              , popup_right: popupx+popupwidth\n              });\n  */\n\n  const maxleft = pagewidth - popupwidth - marginsize;\n  if (popupx > maxleft)\n    popupx = maxleft;\n\n  popupnode.style.visibility = \"visible\";\n  popupnode.style.left = popupx + \"px\";\n  popupnode.style.top = popupy + \"px\";\n\n  document.clientWidth; // flush CSS queue, so next CSS change will trigger a transition\n  popupnode.classList.add(\"active\");\n}\n\nfunction onLeavePopupTrigger(event, node, nodelay) // FIXME: remove?\n{\n  const popupid = node.getAttribute(\"data-popout\");\n  const popupnode = document.getElementById(popupid);\n  if (!popupnode)\n    return;\n\n  const popuptype = getPopupType(popupnode);\n\n  schedulePopupClose();\n}\n\nfunction getPopupType(node) {\n  for (var typeindex = 0; typeindex < $wh.PopoutManager.types.length; typeindex++) {\n    var type = $wh.PopoutManager.types[typeindex];\n    if (node.hasClass(type.cssclass))\n      return type;\n  }\n\n  for (var typeindex = 0; typeindex < $wh.PopoutManager.types.length; typeindex++) {\n    var type = $wh.PopoutManager.types[typeindex];\n    if (type.within_node.contains(node)) // needs SF 5.2.2+ ??\n      return type;\n  }\n\n  return {\n    panelhoverkeepsopen: true,\n    closedelay: 500\n  };\n}\n\nfunction _hidePopup(popupnode) {\n  console.log(\"_hidePopup \", popupnode);\n  if (!popupnode) {\n    console.error(\"_hidepopup didn't get a node\");\n    return;\n  }\n\n  $utPopupActive = null;\n\n  //if (popupnode === $utPopupActive)\n  //  return; //$utPopupActive = null;\n\n  const popuptype = window.$wh.PopoutManager.currenttype;\n\n  popupnode.classList.remove(\"active\");\n\n  setTimeout(function () { popupnode.classList.remove(\"visible\"); }, popuptype.closetransitiondelay);\n\n  popupnode.style.display = \"\"; // have display:none; in the default popup style\n}\n\nfunction schedulePopupClose() {\n  console.log(\"schedulePopupClose\");\n  const popuptype = window.$wh.PopoutManager.currenttype;\n\n  if (!popuptype)\n    return; // ??\n\n  //  if (popuptype.closedelay == 0) // && !nodelay) // a delay is wanted and isn't disabled (delay is disabled when switching between panels)\n  _hidePopup($utPopupActive);\n  /*\n    else\n    {\n      window.$wh.PopoutManager.hidedelaytimer = setTimeout(function(popup) { console.log(popup); _hidePopup(popup); }.bind(this, $utPopupActive), popuptype.closedelay);\n      $utPopupActive = null;\n    }\n  */\n}\n\nfunction cancelPopupClose() {\n  clearTimeout(window.$wh.PopoutManager.hidedelaytimer);\n}\n\nvar $utPopupActive = null;\nwindow.$wh.PopoutManager = {};\nwindow.$wh.PopoutManager.hidedelaytimer = null;\nwindow.$wh.PopoutManager.currenttype = null;\nwindow.$wh.PopoutManager.types = [];\nwindow.$wh.PopoutManager.definePopupType = function (cssclass, settings) {\n  settings.cssclass = cssclass;\n  window.$wh.PopoutManager.types.push(settings);\n};\nwindow.activatePopupPanels = activatePopupPanels;\n\nif ([\"interactive\", \"complete\"].indexOf(document.readyState) > -1)\n  activatePopupPanels();\nelse\n  window.addEventListener(\"DOMContentLoaded\", function () { activatePopupPanels(); });\n\n//})(document.id);\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport makeTextFit from \"../../../shared/wh.layout.autofit\";\n// import * as measuretools from \"./components/wh.layout.measure\";\nimport \"./components/popuppanel\";\n\n\n/*\nImplementation: Mark\narnold: Moved to UT timetable.es until we find more users for this code\n\nImplemented:\n- a setup for a library-agnostic (no dependencies) Time Table class\n- detection of which timerange needs to be displayed\n- generation of DOM (once)\n- overlapping events\n- colorschemes\n- text ellipsis\n- vertical align row labels\n\n\nFIXME:\n- object.assign not supported by IE or SF < 9\n\n\nADDME:\n- refresh/regeneration/updating the DOM\n- tags\n- overlapping events\n\nNICE TO HAVE:\n- a line indicating the current time (only relevant when we know the timeline is for the current day??)\n- if two events connect together in time, give them a border inbetween to be able to distinguish them from each other\n- button 'Show favorited' to only show favorite events, compacted\n\n\nRequired DOM:\n\n    <div id=\"mytimetable\" class=\"wh-timetable\">\n\n      <div class=\"wh-timetable-header\">\n        Locatie\n      </div>\n      <div class=\"wh-timetable-header-placeholder\">\n      </div>\n\n      <div class=\"wh-timetable-viewport\"><!-- container for positioning (mostly for the non-scrollable content) -->\n\n        <div class=\"wh-timetable-scrollport\">\n          <div class=\"wh-timetable-content\"><!-- actual content, can get big -->\n\n            <!-- wh-timetable-row's will be generated here -->\n\n          </div><!-- avail space container, for example width:200%; is twice as width as the view-/scroll-port -->\n        </div><!-- /scrollport -->\n\n        <!-- Locations which will keep floating over the timeline -->\n        <div class=\"wh-timetable-rowlabels\">\n          <!--\n          <div class=\"wh-timetable-row\">\n            <div class=\"wh-timetable-label\">Hofnar</div>\n          </div>\n          -->\n        </div>\n\n      </div><!-- /viewport -->\n    </div>\n\n\n*/\n\n\nexport default class TimeTable {\n  constructor(container, options) {\n    this.nodes = {};\n    this.rows = [];\n    this.firstminute = null;\n    this.lastminute = null;\n    this.__fixedpos = null;\n\n    this.options =\n    {\n      starttime_max: null, // null means auto-detect\n      endtime_min: null, // null means auto-detect\n      timestep_mins: 30,\n\n      slots: [\n        { height: 60, gutter: 0 }, // 1 slot\n        { height: 80, gutter: 1 }, // 2 slots\n        { height: 100, gutter: 1 }, // 3 slots\n        { height: 120, gutter: 1 }, // 4 slots\n        { height: 140, gutter: 1 } // 5 slots\n      ],\n\n      row_gutter: 1,\n\n      events_max_overlap_px: 5, // how many pixels events are allowed to overlap before being moved to a seperate slot\n      //, events_max_overlap_mins:\n      //, events_overlap_behaviour: // overlap (last event overlaps the previous one), middle (have both events use half of the overlapping space)\n\n      onSelect: null, // FIXME: proper custom event\n      onOpen: null, // FIXME: proper custom event\n\n      debug: false,\n      debug_stickyheader: false,\n      debug_overflow: false\n    };\n    if (options.debug) {\n      console.log(\"Prototype options\", this.options);\n      console.log(\"Specified options\", options);\n    }\n    this.setOptions(options);\n    if (options.debug)\n      console.log(\"Merged options\", this.options);\n\n    if (!container) {\n      console.error(\"No container specified.\");\n      return;\n    }\n\n    this.nodes.container = container;\n    this.nodes.header = container.querySelector(\".wh-timetable-header\");\n    this.nodes.header_placeholder = container.querySelector(\".wh-timetable-header-placeholder\");\n    this.nodes.rowlabels = container.querySelector(\".wh-timetable-rowlabels\");\n\n    this.nodes.viewport = container.querySelector(\".wh-timetable-viewport\");\n    this.nodes.scrollport = container.querySelector(\".wh-timetable-scrollport\");\n    this.nodes.content = container.querySelector(\".wh-timetable-content\");\n\n    this.nodes.btn_prev = container.querySelector(\".wh-timetable-prev\");\n    this.nodes.btn_next = container.querySelector(\".wh-timetable-next\");\n\n    this.__addEvents();\n\n    this.refresh();\n\n    this.onScrollView();\n  }\n\n  __addEvents() {\n    document.addEventListener(\"scroll\", this.doUpdateStickyHeader.bind(this));\n\n    // detect clicks on events (.wh-timetable-time)\n    document.addEventListener(\"click\", this.onClick.bind(this));\n\n    this.nodes.scrollport.addEventListener(\"scroll\", this.onScrollView.bind(this));\n\n    this.nodes.btn_prev.addEventListener(\"mousedown\", this.startScrollLeft.bind(this));\n    this.nodes.btn_next.addEventListener(\"mousedown\", this.startScrollRight.bind(this));\n    this.nodes.btn_prev.addEventListener(\"mouseup\", this.stopScrollAnim.bind(this));\n    this.nodes.btn_next.addEventListener(\"mouseup\", this.stopScrollAnim.bind(this));\n\n    this.nodes.btn_prev.addEventListener(\"touchstart\", this.startScrollLeft.bind(this), { passive: true });\n    this.nodes.btn_next.addEventListener(\"touchstart\", this.startScrollRight.bind(this), { passive: true });\n    this.nodes.btn_prev.addEventListener(\"touchend\", this.stopScrollAnim.bind(this));\n    this.nodes.btn_next.addEventListener(\"touchend\", this.stopScrollAnim.bind(this));\n  }\n\n  __removeEvents() {\n    //document.removeEventListener(\"scroll\", this.doUpdateStickyHeader.bind(this));\n    this.nodes.container.removeEventListener(\"scroll\", this.doUpdateStickyHeader.bind(this));\n    document.removeEventListener(\"click\", this.onClick.bind(this));\n    this.nodes.scrollport.removeEventListener(\"scroll\", this.onScrollView.bind(this));\n\n    this.nodes.btn_prev.removeEventListener(\"mousedown\", this.startScrollLeft.bind(this));\n    this.nodes.btn_next.removeEventListener(\"mousedown\", this.startScrollRight.bind(this));\n    this.nodes.btn_prev.removeEventListener(\"mouseup\", this.stopScrollAnim.bind(this));\n    this.nodes.btn_next.removeEventListener(\"mouseup\", this.stopScrollAnim.bind(this));\n  }\n\n  startScrollLeft(evt) {\n    evt.preventDefault();\n\n    this.__scroll_direction = -1; // pixels per ms\n    this.__scroll_lastframetime = new Date().getTime();\n\n    if (this.__animframe)\n      this.stopScrollAnim();\n\n    this.__animframe = requestAnimationFrame(this.doScrollAnimFrame.bind(this));\n  }\n\n  startScrollRight(evt) {\n    evt.preventDefault();\n\n    this.__scroll_direction = 1;\n    this.__scroll_lastframetime = new Date().getTime();\n\n    if (this.__animframe)\n      this.stopScrollAnim();\n\n    this.__animframe = requestAnimationFrame(this.doScrollAnimFrame.bind(this));\n  }\n\n  doScrollAnimFrame() {\n    const currenttime = new Date().getTime();\n    const time_passed = currenttime - this.__scroll_lastframetime;\n    //console.log(time_passed);\n\n    this.__scroll_lastframetime = currenttime;\n    //console.log(new Date().getTime();\n\n    let newx = this.nodes.scrollport.scrollLeft + (time_passed * this.__scroll_direction);\n    if (newx < 0) {\n      newx = 0;\n      this.stopScrollAnim();\n    }\n\n    //console.log(newx, this.nodes.scrollport.scrollWidth - this.nodes.scrollport.clientWidth);\n\n    const maxx = this.nodes.scrollport.scrollWidth - this.nodes.scrollport.clientWidth;\n    if (newx > maxx) {\n      newx = maxx;\n      this.stopScrollAnim();\n    }\n\n    //this.nodes.btn_prev.toggleClass(\"enabled\", newx > 0);\n    //this.nodes.btn_next.toggleClass(\"enabled\", newx < maxx);\n\n    this.nodes.scrollport.scrollLeft = newx;\n\n    this.__animframe = requestAnimationFrame(this.doScrollAnimFrame.bind(this));\n  }\n\n  stopScrollAnim() {\n    cancelAnimationFrame(this.__animframe);\n    this.__animframe = null;\n  }\n\n  onScrollView() {\n    const scrollx = this.nodes.scrollport.scrollLeft;\n    const maxx = this.nodes.scrollport.scrollWidth - this.nodes.scrollport.clientWidth;\n    this.nodes.btn_prev.classList[scrollx > 0 ? \"add\" : \"remove\"](\"enabled\");\n    this.nodes.btn_next.classList[scrollx < maxx ? \"add\" : \"remove\"](\"enabled\");\n\n    if (this.__fixedpos) {\n      // not part of the scrollport anymore, so we have to sync scrolling\n      this.nodes.header.scrollLeft = this.nodes.scrollport.scrollLeft;\n    }\n  }\n\n  destroy() {\n    this.__removeEvents();\n  }\n\n  onClick(evt) {\n    const eventnode = evt.target.closest(\".wh-timetable-time\");\n    if (!eventnode)\n      return;\n\n    evt.preventDefault();\n\n    const event = eventnode.__wh_timeline_event;\n    /*\n    event.data = the original definition\n    event.data.data = the extra data in the definition (usefull for callbacks);\n    */\n\n    if (this.options.debug)\n      console.info(\"Selected $wh.TimeTable item:\", event.data);\n\n    if (this.options.onSelect)\n      this.options.onSelect({\n        target: eventnode,\n        data: event.data\n      });\n  }\n\n  _parseRows(rows) {\n    const prows = [];\n    let firstminute = 24 * 60;\n    let lastminute = 0;\n\n    for (const row of rows) {\n      let events = [];\n      if (row.events.length > 0) {\n        events = this._parseEvents(row.events);\n\n        if (events.firstminute < firstminute)\n          firstminute = events.firstminute;\n\n        if (events.lastminute > lastminute)\n          lastminute = events.lastminute;\n      } else {\n        events = {\n          events: [],\n          firstminute: -1,\n          lastminute: -1\n        };\n      }\n\n      prows.push({\n        title: row.title,\n        events: events.events,\n        firstminute: events.firstminute,\n        lastminute: events.lastminute\n      });\n    }\n\n    return {\n      rows: prows,\n      firstminute: firstminute,\n      lastminute: lastminute\n    };\n  }\n\n  _parseTime(timestr) {\n    const parts = timestr.split(\":\");\n    const minutes = parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10);\n    return minutes;\n  }\n\n  _parseEvents(events) {\n    //console.info(\"raw\", events);\n\n    const pevents = [];\n    let firstminute = 24 * 60;\n    let lastminute = 0;\n\n    for (const event of events) {\n      if (!event.start || !event.end) {\n        console.warn(\"Skipping event, start en end are both required!\", event);\n        continue;\n      }\n\n      const startparts = event.start.split(\":\");\n\n      const minutes_start = parseInt(startparts[0], 10) * 60 + parseInt(startparts[1], 10);\n\n      var minutes_end;\n      if (event.duration)\n        minutes_end = minutes_start + event.duration;\n      else {\n        const endparts = event.end.split(\":\");\n        minutes_end = parseInt(endparts[0], 10) * 60 + parseInt(endparts[1], 10);\n      }\n\n      if (minutes_start < firstminute)\n        firstminute = minutes_start;\n\n      if (minutes_end > lastminute)\n        lastminute = minutes_end;\n\n      pevents.push(\n        {\n          node: null,\n          minutes_start: minutes_start,\n          minutes_end: minutes_end,\n          data: { ...event } // store a clone of the original definition of the event\n        });\n    }\n\n    // make sure events are sorted by starttime in minutes ascending, so we can easily detect overlap\n    pevents.sort(function (ev1, ev2) { return ev1.minutes_start > ev2.minutes_start ? 1 : -1; });\n\n    //console.info(\"parsed\", pevents);\n\n    return {\n      events: pevents,\n      firstminute: firstminute,\n      lastminute: lastminute\n    };\n  }\n\n\n  setOptions(options) {\n    if (\"timestep_mins\" in options && [5, 10, 15, 30, 60].indexOf(options.timestep_mins) == -1) {\n      console.error(\"The timestep must be one of 5, 10, 15, 30, 60\");\n      return;\n    }\n\n    const mergedoptions = { ...options }; // make a clone, so we don't edit the original options object\n    this.options = Object.assign(mergedoptions, this.options);\n    this.options.onSelect = options.onSelect;\n    this.options.starttime_max = options.starttime_max;\n    this.options.endtime_min = options.endtime_min;\n\n    if (\"slots\" in options)\n      this.options.slots = options.slots;\n\n    if (\"rows\" in options) {\n      const parsedrows = this._parseRows(options.rows);\n      //console.info(\"parsedrows\", parsedrows);\n\n      this.firstminute = parsedrows.firstminute;\n      this.lastminute = parsedrows.lastminute;\n      this.rows = parsedrows.rows;\n    }\n  }\n\n  refresh() {\n    // ADDME: replace (or update) all previous content\n    // reposition time indicator guidelines\n\n    let timestart_startmins = this.firstminute;\n    if (this.options.starttime_max) {\n      const stmins = this._parseTime(this.options.starttime_max);\n      if (timestart_startmins > stmins)\n        timestart_startmins = stmins;\n    }\n\n    let timeend_minutes = this.lastminute;\n    if (this.options.endtime_min) {\n      const etmins = this._parseTime(this.options.endtime_min);\n      if (timeend_minutes < etmins)\n        timeend_minutes = etmins;\n    }\n\n    const timerange_in_minutes = timeend_minutes - timestart_startmins;\n\n\n    const timestep_mins = this.options.timestep_mins; // per half hour\n\n\n    /*\n    Decide on the width\n    ADDME: Factor into the width:\n      - wide enough to be able to display the time markers (for example: \"12:00\") - ADDME: measure needed width\n    */\n    const minwidth_to_fit_timeindicators = (timerange_in_minutes / this.options.timestep_mins) * 65;\n    const scrollviewport_width = this.nodes.scrollport.clientWidth;\n\n    let contentwidth = scrollviewport_width;\n    if (minwidth_to_fit_timeindicators > scrollviewport_width)\n      contentwidth = minwidth_to_fit_timeindicators;\n\n    this.nodes.content.style.width = contentwidth + \"px\";\n\n\n\n    const rowlabelnodes = [];\n    for (var idx = 0; idx < this.rows.length; idx++) {\n      var row = this.rows[idx];\n\n      /*\n      <div class=\"wh-timetable-row\">\n        <div class=\"wh-timetable-label\">Hofnar</div>\n      </div>\n      */\n\n      var rownode = document.createElement(\"div\");\n      rownode.className = \"wh-timetable-row\";\n\n      // Safari & Firefox  might not have loaded/processed the stylesheet at this point (when using webpack)\n      // Chrome always seems to have the stylesheets loaded when we run here\n      //rownode.style.position = \"absolute\";\n\n      const rowlabelnode = document.createElement(\"div\");\n      rowlabelnode.className = \"wh-timetable-label\";\n      rowlabelnode.appendChild(document.createTextNode(row.title));\n\n      rownode.appendChild(rowlabelnode);\n      this.nodes.rowlabels.appendChild(rownode);\n\n      rowlabelnodes.push(rowlabelnode); // for measuring\n\n      row.labelcontainernode = rownode;\n      row.labelnode = rowlabelnode;\n    }\n\n    const rowlabels_width = this.nodes.rowlabels.offsetWidth;\n    console.log(\"Rowlabels width \" + rowlabels_width);\n\n    /*\n    for (let node of rowlabelnodes)\n    {\n      // add padding...\n      let labelsize = measuretools.getElementTextualContentBounds(node);\n      let labellines = measuretools.countLinesInElement(node);\n      console.log( \"Label textrects size\"\n                 , node.innerText\n                 , labelsize.width.toFixed(0)\n                 , labelsize.height.toFixed(0)\n                 , labellines + \"lines\"\n                 );\n    }\n    */\n\n    //var required_guidelines = Math.round((endhour - starthour) * 60 / timestep_mins);\n    const required_guidelines = Math.ceil(timerange_in_minutes / timestep_mins);\n\n    // size of the timetable (minus the space reserved for location labels to not overlap events on the starthour)\n    const timetable_width = this.nodes.content.clientWidth - rowlabels_width;\n\n    // FIXME: which one shall we use?\n    const guidelines_interspace = timetable_width / required_guidelines;\n    const guidelines_interperc = 100 / required_guidelines;\n    /*\n        if (this.options.debug)\n        {\n          console.log(timetable_width);\n          console.log(\"Guidelines inbetween space:\", guidelines_interspace, \"or\", guidelines_interperc+\"%\");\n        }\n    */\n    let timemins = timestart_startmins;\n\n    for (var idx = 0; idx < required_guidelines; idx++) {\n      const guideline = document.createElement(\"div\");\n      guideline.className = \"wh-timetable-timeindicator\";\n      const csstext = \"position: absolute; left: \" + (rowlabels_width + guidelines_interspace * idx) + \"px; top: 0; bottom: 0;\";\n      guideline.style.cssText = csstext;\n\n      const str_hours = Math.floor(timemins / 60);\n      const str_minutes = timemins % 60;\n\n      const timestr = str_hours + \":\" + (str_minutes < 10 ? \"0\" + str_minutes : str_minutes);\n\n      //console.log(timemins, str_hours, str_minutes, timestr);\n\n      const header_guideline = guideline.cloneNode(true);\n      header_guideline.appendChild(document.createTextNode(timestr));\n      this.nodes.header.appendChild(header_guideline);\n\n      this.nodes.content.appendChild(guideline);\n\n      timemins += timestep_mins;\n    }\n\n\n    const eventnodes = [];\n    const labelnodes = [];\n\n    for (var idx = 0; idx < this.rows.length; idx++) {\n      /*\n                  <div class=\"wh-timetable-row\">\n                    <div class=\"wh-timetable-time schema1\"\n                         style=\"margin-left: 350px; width: 400px;\">\n                      Test\n                    </div>\n                  </div>\n      */\n      var row = this.rows[idx];\n\n      // FIXME: 10 slots ought be enough for anyone\n      const slots_endx = [-1, -1, -1, -1, -1]; // to keep track of after which time a slot will be free\n      let highestslotidx = 0;\n\n      var rownode = document.createElement(\"div\");\n      rownode.className = \"wh-timetable-row\";\n\n\n\n      // Layout preparation phase ------------------------------------------------------------------------\n\n      // We have to do both the pixel position AND overlap calculations, because:\n      // - so we know the amount of required slots when we render (and do things such as divide the vertical space for the amount of slots)\n      // - we check overlap by pixels instead of minutes. This way if we have a very dense timeline,\n      //   events (maybe only overlapping with a few minutes) which won't visually overlap won't take up new slots\n      for (var event_idx = 0; event_idx < row.events.length; event_idx++) {\n        var event = row.events[event_idx];\n\n        const xstart = Math.round(timetable_width / timerange_in_minutes * (event.minutes_start - timestart_startmins));\n        const xend = Math.round(timetable_width / timerange_in_minutes * (event.minutes_end - timestart_startmins));\n        /*\n                if (this.options.debug)\n                {\n                  //console.log(event.data.title, \"starting at \" + event.minutes_start + \"mins ending at \" + event.minutes_end + \"mins\");\n                  console.log(event.data.title, \"starting at \" + xstart + \"px ending at \" + xend + \"px\");\n                }\n        */\n        // find the first available slot (within our row) we can place the event in\n        // (the first slot in which the event wouldn't cause too much overlap)\n        // ADDME: maybe find the slot in which we have the least overlap?\n        let slot_idx = 0;\n        for (slot_idx = 0; slot_idx < 5; slot_idx++) {\n          if (this.options.debug)\n            console.log(\"Slot #\" + slot_idx + \" ends at \" + slots_endx[slot_idx] + \"px\");\n\n          if (xstart > slots_endx[slot_idx] - this.options.events_max_overlap_px)\n            break;\n        }\n\n        if (slot_idx > highestslotidx)\n          highestslotidx = slot_idx;\n\n        slots_endx[slot_idx] = xend;\n\n        event.left = xstart;\n        event.right = xend;\n        event.width = xend - xstart;\n        event.overlapping = xstart <= slots_endx[slot_idx];\n        event.slot = slot_idx;\n      }\n\n      row.highestslotidx = highestslotidx;\n\n\n\n      // Rendering phase ---------------------------------------------------------------------------------\n\n      const slotsettings = this.options.slots[row.highestslotidx];\n      if (!slotsettings)\n        console.error(\"options.slots[#\" + row.highestslotidx + \"] has not been defined\");\n\n      const slots_needed = highestslotidx + 1;\n\n      var slotheight = (slotsettings.height - (highestslotidx * slotsettings.gutter)) / slots_needed;\n\n      rownode.style.height = slotsettings.height + \"px\";\n      row.labelcontainernode.style.height = slotsettings.height + \"px\";\n\n\n      for (var event_idx = 0; event_idx < row.events.length; event_idx++) {\n        var event = row.events[event_idx];\n\n        const eventnode = document.createElement(\"div\");\n        eventnodes.push(eventnode);\n\n        let classes = \"wh-timetable-time\";\n\n        if (event.overlapping)\n          classes += \" whtt-time-overlapping\";\n\n        if (event.data.cssclass)\n          classes += \" \" + event.data.cssclass;\n\n        eventnode.className = classes;\n\n        eventnode.style.left = (rowlabels_width + event.left) + \"px\";\n        eventnode.style.top = (slotheight * event.slot + slotsettings.gutter * event.slot) + \"px\";\n        eventnode.style.width = event.width + \"px\";\n        eventnode.style.height = slotheight + \"px\";\n        //eventnode.appendChild(document.createTextNode(event.data.title));\n\n        /*******************************************************/\n        // little info box popping out of the event when hovering\n\n        const infonode = document.createElement(\"div\");\n        infonode.className = \"icon UT-icon-UT_icon_58_info-round-16px\"; // FIXME: ut-specific\n        eventnode.appendChild(infonode);\n\n        const popoutnode = document.createElement(\"div\");\n        popoutnode.id = \"popout-\" + event.data.id;\n        popoutnode.className = \"popout\";\n\n        const contentnode = document.createElement(\"div\");\n        contentnode.appendChild(document.createTextNode(event.data.title));\n\n        //popoutnode.appendChild(flapnode);\n        popoutnode.appendChild(contentnode);\n        document.body.appendChild(popoutnode);\n\n        /*******************************************************/\n\n        const labelnode = document.createElement(\"span\"); // *MUST BE INLINE*\n        labelnode.appendChild(document.createTextNode(event.data.title));\n        labelnodes.push(labelnode);\n\n        eventnode.appendChild(labelnode);\n\n        // store node so we can quickly find the associated event(data)\n        // upon a click on/within a eventnode\n        eventnode.__wh_timeline_event = event;\n\n        rownode.appendChild(eventnode);\n      }\n\n      this.nodes.content.appendChild(rownode);\n    }\n\n\n    // make a list of eventnodes which have labels which don't fit\n    // FIXME: prevent reflows by batching read operations and also batch label resize attempts\n    const must_use_ellipsis_nodes = [];\n    const cannot_show_label_nodes = [];\n    for (var idx = 0; idx < eventnodes.length; idx++) {\n      /*\n      NOTE: Even though ellipsis has been applies, the browser (or at least Webkit)\n            reports the full width.\n            Therefore we cannot detect whether ellipsis was correctly applied or\n            whether Webkit decided ... didn't fit and show the full text anyway\n\n      var range = document.createRange();\n      range.selectNode( eventnodes[idx].childNodes[1] );\n      console.log(range.getBoundingClientRect());\n      */\n\n      let label_width = labelnodes[idx].offsetWidth;\n      const label_height = 0; // not relevant yet, because the first attempt is to get everything on a single line without wrapping\n\n      const compstyle = getComputedStyle(eventnodes[idx]);\n      const avail_width = eventnodes[idx].clientWidth - parseFloat(compstyle.paddingLeft) - parseFloat(compstyle.paddingRight);\n      const avail_height = eventnodes[idx].clientHeight - parseFloat(compstyle.paddingTop) - parseFloat(compstyle.paddingBottom);\n\n      if (this.options.debug_overflow)\n        console.log(eventnodes[idx].childNodes[1].innerHTML, label_width, avail_width, labelnodes[idx]);\n\n      /*\n      What can happen?\n      - Horizontally scale if we almost fit on a single line\n      - Resize font resize to the largest font-size which still fits (down to a minumum font-size)\n        If it still doesn't fit, a part of the text will be clipped.\n      - < 65, no interesting label will fit anyway, so replace it with an 'info' button\n\n      /* strategies\n        - almost fits on one line -> scale horizontally\n        - autofit text\n        - still doesn't fit -> info button\n      */\n\n      // if it almost fits on a single line, scale the line horizontally\n      if (label_width > avail_width) {\n        if (label_width * 0.75 <= avail_width) {\n          const scalefactor = avail_width / label_width;\n          const scaletext = \"scale(\" + scalefactor.toFixed(3) + \", 1)\";\n\n          labelnodes[idx].style.msTransform = scaletext;\n          labelnodes[idx].style.msTransformOrigin = \"0 0\";\n\n          labelnodes[idx].style.webkitTransform = scaletext;\n          labelnodes[idx].style.webkitTransformOrigin = \"0 0\";\n\n          labelnodes[idx].style.transform = scaletext;\n          labelnodes[idx].style.transformOrigin = \"0 0\";\n\n          //console.log(\"xx scale(\" + scalefactor.toFixed(3) + \", 1)\", labelnodes[idx]);\n        } else if (avail_width < 65) // FIXME: detect when the browser fails to apply ellipsis\n        {\n          cannot_show_label_nodes.push(eventnodes[idx]);\n        } else {\n          // ADDME: try to minimize the amount of line by using horizontal scaling when we it's a small percentage which doesn't fit\n          eventnodes[idx].classList.add(\"whtt-allowmultiline\");\n          makeTextFit(labelnodes[idx]\n            , {\n              node_applystyle: eventnodes[idx],\n              node_measurewidth: labelnodes[idx],\n              node_measureheight: labelnodes[idx],\n\n              minfontsize: 10.5,\n              maxfontsize: 14,\n              lineheight: \"110%\",\n\n              maxwidth: avail_width,\n              maxheight: slotheight, //44\n\n              debug: false\n            }\n          );\n\n          // if scaling the font-size didn't help flag this item\n          // as 'cannot show label' so an info button can be shown instead\n          label_width = labelnodes[idx].offsetWidth;\n          //label_height = labelnodes[idx].offsetHeight;\n          /*\n          console.log({ labelwidth: label_width\n                      , availwidth: avail_width\n                      });\n          */\n          //console.log(\"Avail \"+avail_width+\"x\"+avail_height+\", final label size \"+label_width+\"x\"+label_height);\n\n          if (label_width > avail_width)\n            must_use_ellipsis_nodes.push(eventnodes[idx]);\n          //cannot_show_label_nodes.push(eventnodes[idx]);\n        }\n      }\n    }\n\n    if (this.options.debug_overflow) {\n      //console.log(\"OVERFLOWING\", overflow_nodes);\n      console.log(\"Ellipsis:\", must_use_ellipsis_nodes);\n      console.log(\"Hide:\", cannot_show_label_nodes);\n    }\n\n    // now it's time to set all overflow classes in a single sweep\n    for (const eventnode of eventnodes) //var idx = 0; idx < eventnodes.length; idx++)\n    {\n      const use_ellipsis = must_use_ellipsis_nodes.indexOf(eventnode) > -1;\n      const use_icon = cannot_show_label_nodes.indexOf(eventnode) > -1;\n      eventnode.classList[use_ellipsis ? \"add\" : \"remove\"](\"label_ellipsis\");\n      eventnode.classList[use_icon ? \"add\" : \"remove\"](\"label_hide\");\n\n      if (use_ellipsis || use_icon)\n        eventnode.setAttribute(\"data-popout\", \"popout-\" + eventnode.__wh_timeline_event.data.id); // event.data.id);\n      else\n        eventnode.removeAttribute(\"data-popout\");\n    }\n\n    this.doUpdateStickyHeader();\n  }\n\n  doUpdateStickyHeader() {\n    //var scroll = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;\n\n    const header_bcr = this.nodes.header.getBoundingClientRect();\n    const viewport_bcr = this.nodes.viewport.getBoundingClientRect();\n\n    // to stabilize the values (when fixed we still track the top as it would be in relative position)\n    const headerheight = (header_bcr.bottom - header_bcr.top);\n    const header_would_be_top = viewport_bcr.top;\n\n    const page_viewport_height = document.body.clientHeight; // FIXME: might in some cases need to use documentElement.clientHeight??\n\n    if (this.options.debug_stickyheader) {\n      console.log(header_bcr);\n      console.log(viewport_bcr);\n    }\n\n    let fixedpos = false;\n    this.__fixedpos = true;\n    //console.info(headerheight);\n\n    if (viewport_bcr.bottom - headerheight < 0 || viewport_bcr.top > page_viewport_height) // out of view\n    {\n      // RELATIVE\n    } else if (header_would_be_top < 0) {\n      // FIXED\n      fixedpos = true;\n    }\n    /*\n    else\n    {\n      // RELATIVE\n    }\n    */\n\n    if (fixedpos) {\n      this.nodes.header.style.position = \"fixed\";\n      this.nodes.header.style.top = \"0\";\n      this.nodes.header.style.zIndex = 10;\n\n      this.nodes.header_placeholder.style.display = \"block\";\n      this.nodes.header_placeholder.style.height = headerheight + \"px\";\n\n      //console.info(this.nodes.header_placeholder.offsetWidth );\n      this.nodes.header.style.width = this.nodes.scrollport.offsetWidth + \"px\"; // sync with the width the placeholder gets\n\n      this.nodes.viewport.insertBefore(this.nodes.header, this.nodes.viewport.firstChild);\n    } else {\n      this.nodes.content.insertBefore(this.nodes.header, this.nodes.content.firstChild);\n\n      this.nodes.header.style.position = \"relative\";\n      this.nodes.header.style.width = \"\";\n\n      this.nodes.header_placeholder.style.display = \"none\";\n      this.nodes.header_placeholder.style.width = \"\";\n    }\n\n    //console.log(\"zichtbaar\");\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport * as crm from \"../../../shared/crm\";\nimport * as managedctas from \"../../../shared/crm/managedctas\";\nimport { getTid } from \"@webhare/gettid\";\nimport * as tagmanager from '@mod-publisher/js/analytics/gtm';\nimport scrollListener from \"../../../components/scrolllistener\";\nimport { pushToDataLayer } from \"@webhare/frontend\";\n\nconst managedCTASlot = Symbol();\nlet userCountry = \"\", userBeacons = null, ctas = [];\n\n\nfunction setupManagedCTA(node) {\n  userCountry = userCountry || crm.getUserCountry();\n  if (!userBeacons) {\n    userBeacons = crm.getUserBeacons();\n    if (dompack.debugflags.umc)\n      console.log(`[umc] User beacons`, userBeacons);\n  }\n\n  const ctadata = {\n    displayed: false,\n    ctas: [],\n    curcta: \"\" // tag of currently visible CTA\n  };\n\n  for (const subnode of node.querySelectorAll(\".cta--managed\")) {\n    ctadata.ctas.push({\n      node: subnode,\n      config: managedctas.parseManagedCTAConfig(subnode.dataset.ctaconfig)\n    });\n  }\n\n  if (dompack.debugflags.umc) {\n    const ctatags = ctadata.ctas.map(cta => cta.config.tag).join(', ');\n    console.log(`[umc] Found a managed CTA ${node.dataset.ctatag} with ${ctadata.ctas.length} CTAs: ${ctatags}`);\n  }\n\n  node[managedCTASlot] = ctadata;\n  updateManagedCTA(node);\n  ctas.push(node);\n\n  if (!userCountry) {\n    if (dompack.debugflags.umc)\n      console.log(`[umc] Requesting user country`);\n    crm.requestGeoIP().then(country => {\n      userCountry = country;\n      updateManagedCTA(node);\n    });\n  }\n\n  // Send a \"cta-display\" event when the CTA is in view\n  scrollListener.addNodes([node]);\n  node.addEventListener(\"wh:visibilitychange\", onManagedCTADisplay);\n\n  // Send a \"cta-display\" event on page load\n  node.addEventListener(\"click\", onManagedCTAClick);\n\n  // Listen for beacon updates\n  window.addEventListener(\"ut-beaconchange\", updateAllManagedCTAs);\n}\n\nfunction updateAllManagedCTAs() {\n  ctas.forEach(updateManagedCTA);\n}\nfunction updateManagedCTA(node) {\n  // If this CTA has already been into view, we cannot change it\n  if (!node[managedCTASlot] || node[managedCTASlot].displayed) {\n    if (dompack.debugflags.umc)\n      console.log(`[umc] Not updating managed CTA ${node.dataset.ctatag}, it's already been displayed`);\n    return;\n  }\n\n  if (document.documentElement.classList.contains(\"ut--ctapreview\")) //preview mode\n  {\n    showManagedCTAPreview(node);\n    return;\n  }\n\n  let haveCTA = false;\n\n  const params = new URL(location.href).searchParams;\n  const forced = (params.get(\"showcta\") || '').split(\":\"); //to show a specific cta use eg ?showcta=open_dagen_algemeen_bachelor_nl:speciaal\n\n  node[managedCTASlot].curcta = null;\n  let displaycta = null;\n  for (const cta of node[managedCTASlot].ctas) {\n    if (forced[0] == node.dataset.ctatag) {\n      if (forced.length == 1 || forced[1] == cta.config.tag) {\n        if (dompack.debugflags.umc)\n          console.info(`[umc] Showing forced CTA ${cta.config.tag}`);\n        cta.node.classList.add(\"cta--show\");\n        displaycta = cta;\n      } else {\n        if (dompack.debugflags.umc)\n          console.warn(`[umc] Not showing CTA ${cta.config.tag}: Not matched by URL variable: '${cta.config.tag}' != '${forced[1]}'`);\n        cta.node.classList.remove(\"cta--show\");\n      }\n    } else if (!haveCTA) {\n      try {\n        managedctas.tryMatchCTAConfig(cta.config, { country: userCountry, beacons: userBeacons, url: location.href });\n\n        if (dompack.debugflags.umc)\n          console.info(`[umc] Showing CTA ${cta.config.tag}`);\n        cta.node.classList.add(\"cta--show\");\n        node[managedCTASlot].curcta = cta.config.tag;\n        displaycta = cta;\n        haveCTA = true;\n      } catch (e) {\n        if (e instanceof managedctas.CTAMatchError) {\n          if (dompack.debugflags.umc)\n            console.warn(`[umc] Not showing CTA ${cta.config.tag}: ${e.message}`);\n          cta.node.classList.remove(\"cta--show\");\n        } else\n          throw e;\n      }\n    } else {\n      cta.node.classList.remove(\"cta--show\");\n    }\n    cta.node._wsTmpDisplay = getComputedStyle(cta.node).display;\n  }\n  if (displaycta) {\n    node.style.display = \"block\";\n    node._wsTmpDisplay = getComputedStyle(node).display;\n    setTimeout(() => {\n      dompack.dispatchCustomEvent(node, \"ws:managed-cta\",\n        {\n          bubbles: true,\n          cancelable: false,\n          detail: { cta: displaycta }\n        });\n    }, 1);\n  }\n}\n\nfunction showManagedCTAPreview(node) {\n  const params = new URL(location.href).searchParams;\n  let testprops = JSON.parse(params.get(\"testprops\"));\n  if (testprops)\n    testprops = { ...testprops, url: testprops.url || location.href };\n\n  node.style.display = \"block\";\n  node[managedCTASlot].curcta = null;\n  const any_shown = node[managedCTASlot].ctas.some(cta => {\n    let matcherror;\n    if (testprops) {\n      try {\n        managedctas.tryMatchCTAConfig(cta.config, testprops);\n\n        if (dompack.debugflags.umc)\n          console.info(`[umc] Showing CTA ${cta.config.tag}`);\n        cta.node.classList.add(\"cta--show\");\n        node[managedCTASlot].curcta = cta.config.tag;\n        return true; // Break out of the 'some' loop\n      } catch (e) {\n        if (e instanceof managedctas.CTAMatchError) {\n          if (dompack.debugflags.umc)\n            console.warn(`[umc] Not showing CTA ${cta.config.tag}: ${e.message}`);\n\n          if (!testprops || !testprops.showskipped) {\n            cta.node.classList.remove(\"cta--show\");\n            return; // Go to next CTA\n          }\n          matcherror = e;\n        } else\n          throw e;\n      }\n    }\n\n    cta.node.classList.add(\"cta--show\");\n\n    if (cta.node.querySelector(\".ut--cta__explain\"))\n      return; // Already explained\n\n    const explanations = [];\n    if (cta.config.publish_from) {\n      if (matcherror && matcherror.prop == \"publish_from\")\n        explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.publish_from-skipped\", new Date(matcherror.values.expected).toLocaleString(), new Date(matcherror.values.got).toLocaleString()));\n      else if (!matcherror)\n        explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.publish_from\", new Date(cta.config.publish_from).toLocaleString()));\n    }\n    if (cta.config.publish_until) {\n      if (matcherror && matcherror.prop == \"publish_until\")\n        explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.publish_until-skipped\", new Date(matcherror.values.expected).toLocaleString(), new Date(matcherror.values.got).toLocaleString()));\n      else if (!matcherror)\n        explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.publish_until\", new Date(cta.config.publish_until).toLocaleString()));\n    }\n    if (cta.config.countries && cta.config.countries.length) {\n      if (matcherror && matcherror.prop == \"countries\")\n        explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.countries-skipped\", matcherror.values.expected.join(\", \"), matcherror.values.got));\n      else if (!matcherror)\n        explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.countries\", cta.config.countries.join(\", \")));\n    }\n    if (cta.config.beacons) {\n      if (matcherror && matcherror.prop == \"beacons\") {\n        if (!matcherror.values.expected && !matcherror.values.got)\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.beacons-skipped-none\"));\n        else if (!matcherror.values.got)\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.beacons-skipped\", matcherror.values.expected));\n        else\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.beacons-skipped-time\", matcherror.values.tag, new Date(matcherror.values.expected).toLocaleString(), new Date(matcherror.values.got).toLocaleString()));\n      } else if (!matcherror)\n        explanations.push(...cta.config.beacons.map(beacon => {\n          if (beacon.maxdays)\n            return getTid(\"utwente_base:frontend.ws2016.js.managedcta.beacon-maxdays\", beacon.tag, beacon.maxdays);\n          return getTid(\"utwente_base:frontend.ws2016.js.managedcta.beacon\", beacon.tag);\n        }));\n    }\n    if (cta.config.regexes && cta.config.regexes.length) {\n      if (matcherror && matcherror.prop == \"regexes\") {\n        if (matcherror.values.error)\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.regex-skipped-error\", matcherror.values.expected, matcherror.values.error));\n        else if (matcherror.values.expected)\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.regex-skipped\", `/${matcherror.values.expected}/`, matcherror.values.got));\n        else\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.regex-skipped-none\", matcherror.values.got));\n      } else if (!matcherror) {\n        const positives = cta.config.regexes.filter(_ => !_.exclude).map(_ => _.regex.source);\n        if (positives.length)\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.regex\", `[ /${positives.join(\"/, /\")}/ ]`));\n        const negatives = cta.config.regexes.filter(_ => _.exclude).map(_ => _.regex.source);\n        if (negatives.length)\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.regex-exclude\", `[ /${negatives.join(\"/, /\")}/ ]`));\n      }\n    }\n    if (cta.config.queries && cta.config.queries.length) {\n      if (matcherror && matcherror.prop == \"queries\") {\n        if (matcherror.values.error)\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.query-skipped-error\", matcherror.values.expected, matcherror.values.error));\n        else\n          explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.query-skipped\", matcherror.values.got));\n      } else if (!matcherror) {\n        explanations.push(getTid(\"utwente_base:frontend.ws2016.js.managedcta.query\", `[ '${cta.config.queries.map(_ => _._term).join(\"', '\")}' ]`));\n      }\n    }\n\n    if (explanations.length)\n      cta.node.after(\n        <div class=\"ut--cta__explain\">\n          {testprops && testprops.showskipped ? getTid(\"utwente_base:frontend.ws2016.js.managedcta.explanation-skipped\") : getTid(\"utwente_base:frontend.ws2016.js.managedcta.explanation\")}:\n          <ul class=\"unordered\">\n            {explanations.map(text => <li>{text}</li>)}\n          </ul>\n        </div>);\n    else\n      cta.node.after(<div class=\"ut--cta__explain ut--cta__explain--empty\"></div>);\n  });\n  if (testprops && testprops.showskipped && !any_shown) {\n    node.append(<div class=\"ut--cta__explain ut--cta__explain--nocta\">{getTid(\"utwente_base:frontend.ws2016.js.managedcta.noctatoshow\")}</div>);\n  }\n}\n\nfunction onManagedCTADisplay(event) {\n  // If the CTA is now visible, but hasn't been visible yet, push a \"cta-display\" event\n  const node = event.target;\n  if (event.detail.visible && !node[managedCTASlot].displayed) {\n    if (dompack.debugflags.umc)\n      console.info(`[umc] Managed CTA ${node.dataset.ctatag} is displayed`, node);\n\n    node[managedCTASlot].displayed = true;\n    if (window.dataLayer && node[managedCTASlot].curcta) {\n      const eventValues = {\n        event: \"cta-display\",\n        \"cta-tag-main\": node.dataset.ctatag\n      };\n      if (node[managedCTASlot].curcta)\n        eventValues[\"cta-tag-variant\"] = node[managedCTASlot].curcta;\n      window.dataLayer.push(eventValues);\n    }\n  }\n}\n\nfunction onManagedCTAClick(event) {\n  let target = event.target;\n  if (!target.href)\n    target = target.closest(\"[href]\");\n  if (target) {\n    const node = target.closest(\".managedcta\");\n    if (node && node[managedCTASlot]) {\n      if (dompack.debugflags.umc)\n        console.info(`[umc] Received link click in managed CTA ${node.dataset.ctatag}`);\n\n      // Prevent navigation when clicking the link\n      event.stopPropagation();\n      event.preventDefault();\n\n      // Push a \"cta-click\" event and handle the navigation afterwards\n      pushToDataLayer({\n        event: 'cta-click',\n        \"cta-tag-main\": node.dataset.ctatag,\n        \"cta-tag-variant\": node[managedCTASlot].curcta || undefined,\n        eventCallback: () => location.href = target.href\n      });\n    }\n  }\n}\n\ndompack.register(\".managedcta\", setupManagedCTA);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from 'dompack';\n\n/** @short Parse the CTA configuration from a data-ctaconfig attribute */\nexport function parseManagedCTAConfig(ctaconfig) {\n  const config = JSON.parse(ctaconfig);\n  // Parse datetimes\n  config.publish_from = Date.parse(config.publish_from) || null;\n  config.publish_until = Date.parse(config.publish_until) || null;\n  // Convert regexes\n  if (config.regexes)\n    config.regexes.forEach(_ => _.regex = new RegExp(_.regex, \"i\"));\n  // Convert search queries\n  if (config.queries)\n    config.queries = config.queries.map((regex, idx) => {\n      const r = new RegExp(regex, \"i\");\n      r._term = config._queryterms[idx];\n      return r;\n    });\n  return config;\n}\n\n/** @short Thrown by tryMatchCTAConfig if the given properties don't match the CTA's configuration\n*/\nexport class CTAMatchError extends Error {\n  constructor(prop, values, ...params) {\n    super(...params);\n    this.name = \"CTAMatchError\";\n    this._prop = prop;\n    this._values = values;\n  }\n\n  /** @short The configuration property that failed\n      @long One of `publish_from`, `publish_until`, `countries`, `beacons`, `regexes` or `queries`\n  */\n  get prop() {\n    return this._prop;\n  }\n\n  /** @short The values that failed\n      @long This object holds the expected and received values, which may be different based on the property and context:\n\n          | prop | values |\n          | :--- | :----- |\n          | `publish_from` | `expected`: the date after which the CTA is shown<br>`got`: the 'now' date that was used for this check |\n          | `publish_until` | `expected`: the date before which the CTA is shown<br>`got`: the 'now' date that was used for this check |\n          | `countries` | `expected`: the list of country codes for which the CTA is shown<br>`got`: the country code that was used for this check |\n          | `beacons` | if neither `expected` nor `got` are present, there were no beacons triggered<br><br>`expected`: if only `expected` is present, the tag of the beacon that was not triggered<br><br>`expected`: if both `expected` and `got` are present, the date before which the beacon had to be triggered to show the CTA<br>`got`: the 'now' date that was used for this check<br>`tag`: the tag of the failing beacon |\n          | `regexes` | `expected`: if present, the regex that matched the url (causing the CTA _not_ to be shown) or that caused an error, if not present, no regex matched the url<br>`got`: if present, the url that was used for this check<br>`error`: if present, the this error was thrown while matching the regex |\n          | `queries` | `expected`: if not present, no query regex matched the query, if present, the query regex that caused an error<br>`got`: if present, the query that was used for this check<br>`error`: if present, the this error was thrown while matching the query regex |\n  */\n  get values() {\n    return this._values;\n  }\n}\n\n/*\n  @short Check if the given props match the given config\n  @long This function throws a CTAMatchError if the props don't match the config\n  @cell config.publish_from\n  @cell config.publish_until\n  @cell config.countries\n  @cell config.beacons\n  @cell config.regexes\n  @cell config.queries\n  @cell props.country\n  @cell props.beacons\n  @cell props.url\n  @cell props.query\n*/\nexport function tryMatchCTAConfig(config, props) {\n  const now = props.date || Date.now();\n  if (dompack.debugflags.umc)\n    console.info(`[umc] tryMatchCTAConfig`, config, props, now);\n\n  if (config.publish_from && now < config.publish_from)\n    throw new CTAMatchError(\"publish_from\", { expected: config.publish_from, got: now }, `Not yet published: ${now} < ${config.publish_from}`);\n  if (config.publish_until && now >= config.publish_until)\n    throw new CTAMatchError(\"publish_until\", { expected: config.publish_until, got: now }, `No longer published: ${now} >= ${config.publish_until}`);\n  if (config.countries && config.countries.length && (!props.country || !config.countries.includes(props.country)))\n    throw new CTAMatchError(\"countries\", { expected: config.countries, got: props.country }, `'${props.country}' not in [ '${config.countries.join(\"', '\")}' ]`);\n  if (config.beacons && config.beacons.length) {\n    if (!props.beacons)\n      throw new CTAMatchError(\"beacons\", {}, `No beacons triggered`);\n\n    let hitanybeacon;\n\n    for (const beacon of config.beacons) {\n      if (!props.beacons[beacon.tag]) {\n        if (config.anybeacon)\n          continue;\n        throw new CTAMatchError(\"beacons\", { expected: beacon.tag }, `Beacon ${beacon.tag} not triggered`);\n      }\n\n      const maxtime = beacon.maxdays * 24 * 60 * 60 * 1000;\n      const beacondate = parseInt(props.beacons[beacon.tag]);\n      if (maxtime > 0 && now > beacondate + maxtime) {\n        if (config.anybeacon)\n          continue;\n\n        throw new CTAMatchError(\"beacons\", { expected: beacondate + maxtime, got: now, tag: beacon.tag }, `Beacon ${beacon.tag} too old: ${now} > ${beacondate} + ${maxtime}`);\n      }\n\n      hitanybeacon = true;\n    }\n\n    if (!hitanybeacon)\n      throw new CTAMatchError(\"beacons\", { expected: config.beacons }, `No allowed beacon triggered`);\n  }\n  if (config.regexes && config.regexes.length) {\n    let matching_regex = null;\n    let only_excludes = true;\n    for (const cta_regex of config.regexes) {\n      only_excludes = only_excludes && cta_regex.exclude;\n      try {\n        if (cta_regex.regex.test(props.url)) {\n          matching_regex = cta_regex;\n          break;\n        }\n      } catch (e) {\n        throw new CTAMatchError(\"regexes\", { expected: cta_regex.regex.source, error: e }, `Error while trying to match regular expression '${cta_regex.regex.source}': ${e}`);\n      }\n    }\n    if (matching_regex) {\n      if (matching_regex.exclude)\n        throw new CTAMatchError(\"regexes\", { expected: matching_regex.regex.source, got: props.url }, `URL ${props.url} matches exclusion regular expression '${matching_regex.regex.source}'`);\n      if (dompack.debugflags.umc)\n        console.info(`[umc] URL ${props.url} matches inclusion regular expression '${matching_regex.regex.source}'`);\n    } else if (only_excludes) {\n      // If there are only 'exclude' regexes, and the url didn't match any, we can show the cta\n      if (dompack.debugflags.umc)\n        console.info(`[umc] URL ${props.url} not matching any regular expression`);\n    } else {\n      // The url matched none of the 'include' regexes, so don't show this\n      throw new CTAMatchError(\"regexes\", { got: props.url }, `URL ${props.url} not matching any regular expression`);\n    }\n  }\n  if (config.queries && config.queries.length) {\n    for (const regex of config.queries) {\n      try {\n        if (regex.test(props.query)) {\n          if (dompack.debugflags.umc)\n            console.info(`[umc] Query '${props.query}' matches search term '${regex.source}'`);\n          return;\n        }\n      } catch (e) {\n        throw new CTAMatchError(\"queries\", { expected: regex.source, error: e }, `Error while trying to match search term '${regex.source}': ${e}`);\n      }\n    }\n    throw new CTAMatchError(\"queries\", { got: props.query || \"\" }, `Query '${props.query || \"\"}' not matching any search term`);\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./publicationslist.scss\";\nimport * as dompack from 'dompack';\n\nasync function getPublicationLinks(container, url) {\n  let resultinghtml;\n  try {\n    const response = await fetch(url, { cache: 'reload' });\n    if (response.status === 200)\n      resultinghtml = await response.text();\n  } catch (err) {\n    console.error(\"Publications download failed\", err);\n    return;\n  }\n\n  if (!resultinghtml) {\n    container.replaceChildren();\n    return;\n  }\n\n  const doc = (new DOMParser).parseFromString(resultinghtml, 'text/html');\n  return doc;\n}\n\nasync function setupArticlesAsPlainLinks(node) {\n  const container = node.closest(\".publicationslist\");\n  const doc = await getPublicationLinks(container, node.dataset.link || container.dataset.publicationsSource); //<div class=\"publicationslist__articles\" data-link=\"[link]\"> is the old location\n  node.replaceChildren();\n  for (const item of doc.querySelectorAll(\"body > div\"))\n    node.appendChild(item);\n}\n\nasync function setupArticlesAsDownloadsAndLinks(container) {\n  const doc = await getPublicationLinks(container, container.dataset.publicationsSource);\n  const items = Array.from(doc.querySelectorAll(\".ep_results > div\")).map(item => {\n    const researchlink = item.querySelector(`a[href^=\"https://research.utwente.nl/en/publications/\"]`)\n      || tem.querySelector(`a[href]`); //then take the first hyperlink\n    if (!researchlink)\n      return null;\n\n    return <li>\n      <a class=\"widget-downloads__item\" href={researchlink.href}>\n        <span class=\"widget-downloads__item__description\">{item.textContent}</span>\n        <i class=\"widget-downloads__item__icon UT-icon-UT_icon_52_arrow-right-round-16px\"></i>\n      </a>\n    </li>;\n  });\n\n  container.querySelector('ul').replaceChildren(...items);\n}\n\ndompack.register(\".publicationslist__articles\", node => setupArticlesAsPlainLinks(node));\ndompack.register(\".widget__publicationslist\", node => setupArticlesAsDownloadsAndLinks(node));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./banner.scss\";\nimport * as dompack from \"dompack\";\n//import CarrouselSlideshow from \"@webhare/dompack-carrousel-slideshow\";\nimport CarrouselSlideshow from \"../slideshow/dompack-carrousel-slideshow\";\n\nwindow.__slideshows_banner = [];\n\n\nclass BannerSlideshowWidget {\n  constructor(widgetnode) {\n    this.widgetnode = widgetnode;\n\n    this.slides = widgetnode.querySelectorAll(\".carrousel__cell\");\n    if (this.slides.length < 2)\n      return;\n\n    window.__slideshows_banner.push(this);\n\n    this.slideshow =\n      new CarrouselSlideshow(widgetnode, {\n        jumpbuttons: \".banner__slidedot\",\n        jumpbutton_selectedclass: \"banner--activedot\",\n        autoplay: true,\n        eventPassthrough: true,\n        autoplay_freezeslideduration: 5000,\n        transitionDuration: 500,\n        updateviewportheight: true\n      });\n    //this.slideshow.carrousel.options.updateviewportheight = true;\n    //this.slideshow.carrousel.options.debugdimensions = true;\n\n    this.refresh();\n\n    //widgetnode.addEventListener(\"wh:activeslidechange\", this.onSlideChange.bind(this));\n  }\n\n  /*\n  onSlideChange(evt)\n  {\n    this.slides[evt.detail.previousactiveidx].classList.remove(\"active\");\n    this.slides[evt.detail.nextactiveidx].classList.add(\"active\");\n  }\n  */\n\n  refresh() {\n    for (const slide of this.slides)\n      slide.style.minHeight = \"\";\n\n    let largestheight = 0;\n    for (const slide of this.slides) {\n      const slideheight = slide.offsetHeight;\n      if (slideheight > largestheight)\n        largestheight = slideheight;\n    }\n\n    //console.log(\"Largest height\", largestheight);\n\n    for (const slide of this.slides)\n      slide.style.minHeight = largestheight + \"px\";\n\n    this.widgetnode.querySelector(\".banner__viewport\").style.height = largestheight + \"px\";\n  }\n}\n\nfunction refreshBannerSlideshowWidgets() {\n  for (const widget of window.__slideshows_banner)\n    widget.refresh();\n}\n\n\ndompack.register(\".embeddedobject--banner\",\n  widgetnode => new BannerSlideshowWidget(widgetnode)\n);\n\nwindow.addEventListener(\"resize\", refreshBannerSlideshowWidgets);\n\n// the browser (Especially Firefox) may not have loaded the CSS stylesheet yet,\n// so we need to refresh after load to make sure we use the correct height specified in CSS for the viewport width.\nwindow.addEventListener(\"load\", refreshBannerSlideshowWidgets);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./linkspercategory_tabs.scss\";\nimport * as dompack from \"dompack\";\nimport SmoothScroll from \"../../../components/smoothscroll\";\n\n\nwindow.widgets_lpct = [];\n\n\n/// scroll a little further up so we keep the tabs in view (for context)\nconst offsety = -60;\n\n\nclass LinksPerCategoryWidget {\n  constructor(widget) {\n    widgets_lpct.push(this);\n\n    this.container = widget;\n    this.pointer = widget.querySelector(\".lpct__pointer\");\n    this.categorylist = this.container.querySelector(\".lpct__categorylist\"); // tabs\n    this.contentpanel = this.container.querySelector(\".lpct__categoriespanel\");\n\n    this.container.addEventListener(\"click\", evt => this.doCheckForTabClick(evt));\n\n    this.scroller = new SmoothScroll([], {\n      sethash: false,\n      offsety: offsety\n    });\n\n    this.refresh();\n    this.pointer.querySelector(\"path\").style.display = \"\"; // remove the \"display: none;\" in the template\n  }\n\n  doCheckForTabClick(evt) {\n    const tab = evt.target.classList.contains(\"lpct__categorylist__item\") ? evt.target : evt.target.closest(\".lpct__categorylist__item\");\n    if (!tab)\n      return;\n\n    const tabs = this.container.querySelectorAll(\".lpct__categorylist__item\");\n    const contentpanels = this.container.querySelectorAll(\".lpct__category\");\n\n    for (const tabnode of tabs) {\n      tabnode.classList.remove(\"lpct__categorylist__item--active\");\n      tabnode.classList.remove(\"lpct__categorylist__item--activeinitial\");\n    }\n\n    for (const cnode of contentpanels) {\n      cnode.classList.remove(\"lpct__category--active\");\n      cnode.classList.remove(\"lpct__category--activeinitial\");\n    }\n\n    // Mark the selected tab as active\n    tab.classList.add(\"lpct__categorylist__item--active\");\n\n    // Mark the associated content panel as active\n    const idx = Array.from(tabs).indexOf(tab);\n    contentpanels[idx].classList.add(\"lpct__category--active\");\n\n    const contentpanelbounds = contentpanels[idx].getBoundingClientRect();\n\n    const tabsbounds = this.categorylist.getBoundingClientRect();\n    //let bodybounds = document.scrollingElement.getBoundingClientRect(); // Not supported by IE\n    const bodybounds = document.documentElement.getBoundingClientRect();\n\n    if (tabsbounds.top < 0\n      || contentpanelbounds.top > bodybounds.height * 0.75\n    ) {\n      const isSmoothScrollSupported = 'scrollBehavior' in document.documentElement.style;\n\n      if (isSmoothScrollSupported) {\n        const scrolltoy = tabsbounds.top - bodybounds.top + offsety;\n        window.scrollTo({ top: scrolltoy, behavior: 'smooth' });\n      } else\n        this.scroller.scrollTo(this.categorylist, evt);\n      //this.scroller.scrollTo(contentpanels[idx], evt);\n    }\n\n    pointCurveFromTo(this.pointer, tab, this.contentpanel);\n  }\n\n  refresh() {\n    let activetab = this.container.querySelector(\".lpct__categorylist__item--active\");\n    if (!activetab)\n      activetab = this.container.querySelector(\".lpct__categorylist__item--activeinitial\");\n    if (activetab)\n      pointCurveFromTo(this.pointer, activetab, this.contentpanel);\n  }\n}\n\n\nfunction pointCurveFromTo(curve, startnode, endnode) {\n  const pointerrect = curve.getBoundingClientRect();\n  const startnoderect = startnode.getBoundingClientRect();\n  const endnoderect = endnode.getBoundingClientRect();\n\n  const topy = startnoderect.top - pointerrect.top + startnoderect.height / 2;\n  const bottomy = endnoderect.top - pointerrect.top + endnoderect.height / 2;\n\n  const pathwidth = pointerrect.width;\n  const pathheight = bottomy - topy;\n  const abspathheight = pathheight < 0 ? -pathheight : pathheight;\n\n\n  let curveradiusx = 15;\n  const curveradiusy = 15;\n\n  if (curveradiusx * 2 > pathwidth)\n    curveradiusx = curveradiusx / 2;\n\n  // console.info(\"Curveradius\", curveradiusx, curveradiusy);\n  // console.log(`Pathsize ${pathwidth} x ${pathheight}`);\n\n  // if the item we point to is almost aligned with the category we need\n  // to squeze the radius to fit within the vertical space we have\n  if (curveradiusy * 2 > abspathheight) {\n    /*\n    Option 1: - shrink the curve to fit\n    curveradiusy = curveradiusy / 2;\n    */\n\n    // Draw a simple horizontal line\n    curve.querySelector(\"path\").setAttribute(\"d\", `M0,${topy} ${pathwidth},${topy}`);\n    return;\n  }\n\n  const x0 = 0;\n  const x1 = pathwidth / 2 - curveradiusx;\n  const x2 = pathwidth / 2; // middle\n  const x3 = pathwidth / 2 + curveradiusx;\n  const x4 = pathwidth;\n\n  const y0 = topy;\n  const y1 = topy + (pathheight < 0 ? -curveradiusy : curveradiusy);\n  const y2 = bottomy - (pathheight < 0 ? -curveradiusy : curveradiusy);\n  const y3 = bottomy;\n\n  /*\n  let path = `M${x0} ${y0} L${x1} ${y0}\n              L${x2} ${y1}\n              L${x2} ${y2}\n              L${x3} ${y3}\n              L${x4} ${y3}\n             `;\n  */\n\n  const path = `M${x0} ${y0}\n              L${x1} ${y0}\n              C${x2},${y0} ${x2},${y1} ${x2},${y1}\n              L${x2} ${y2}\n              C${x2},${y3} ${x3},${y3} ${x3},${y3}\n              L${x4} ${y3}\n             `;\n  curve.querySelector(\"path\").setAttribute(\"d\", path);\n}\n\n\nfunction refreshWidgets(evt) {\n  for (const widget of window.widgets_lpct)\n    widget.refresh();\n}\nwindow.refreshit = refreshWidgets;\n\n\n\ndompack.register(\".embeddedobject--linkspercategory_tabs\", node => {\n  new LinksPerCategoryWidget(node);\n});\n\n\nwindow.addEventListener(\"load\", evt => refreshWidgets(evt));\n// window.addEventListener(\"ws:responsivemode\",  evt => refreshWidgets(evt));\nwindow.addEventListener(\"ws:resize\", evt => refreshWidgets(evt));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./newsevents.scss\";\nimport \"./newseventsrecent.scss\";\n// import Tabstrip from \"../../../shared/dompack-tabstrip\";\nimport * as dompack from \"dompack\";\n\ndompack.register(\".embeddedobject--newseventsrecent\", node => {\n  new Tabstrip(node);\n  node.addEventListener(\"wh:tabchange\", evt => onSwitchTab(evt, node));\n});\n\n\nfunction onSwitchTab(evt, widgetnode) {\n  // Sync the readmore link with the selected tab\n  const links = widgetnode.querySelectorAll(\".newseventsrecent__sidebar .newseventsrecent__readmore\");\n  for (let idx = 0; idx < links.length; idx++)\n    links[idx].style.display = idx === evt.detail.idx ? \"block\" : \"none\";\n}\n\ndompack.register(\".widget-newsevents__list\", node => {\n  node.addEventListener(\"click\", ev => {\n    if (ev.target.closest(\".widget-newsevents__item__tags\") && ev.target.dataset.link) {\n      dompack.stop(ev);\n      location.href = ev.target.dataset.link;\n    }\n  });\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\nimport \"./figures-widgets.css\";\nimport \"./figures-widgets.scss\";\n\n\nfunction initProgressCircles(node) {\n  let animationsdone = false;//check of animation is done\n  if (document.documentElement.classList.contains(\"wh-widgetpreview\")) {\n    animationsdone = true;\n\n    const percentage = Math.round(1 * (node.getAttribute('data-percentage')));\n    const contoursize = 2 * Math.PI * 68; //radius 68\n    const circlenode = node.querySelector('.progresscircle__fill');\n    const percentagenode = node.querySelector('.percentage');\n\n    circlenode.style.strokeDashoffset = Math.round(contoursize - (contoursize * 0.01 * percentage) + 6);\n    percentagenode.innerHTML = Math.round(percentage);\n  }\n\n  node.addEventListener(\"wh:visibilitychange\", function (ev) {\n    if (animationsdone || !ev.detail.visible)\n      return;\n\n    const percentage = Math.round(1 * (node.getAttribute('data-percentage')));\n\n    const contoursize = 2 * Math.PI * 68; //radius 68\n    const circlenode = node.querySelector('.progresscircle__fill');\n\n    const duration = 1500;\n\n    const timestep = Math.round(duration / (2 * percentage));\n    let step = 0;\n    const percentagenode = node.querySelector('.percentage');\n    const t = setTimeout(updateDigits, timestep);\n\n    function updateDigits() {\n      step += 0.5;\n\n      circlenode.style.strokeDashoffset = Math.round(contoursize - (contoursize * 0.01 * step) + 6);\n      percentagenode.innerHTML = Math.round(step);\n      if (step < percentage)\n        setTimeout(updateDigits, timestep);\n    }\n\n    animationsdone = true;\n  });\n}\n\nfunction initProgressBars(node) {\n  let animationsdone = false;\n  if (document.documentElement.classList.contains(\"wh-widgetpreview\")) {\n    animationsdone = true;\n\n    const percentage = Math.round(1 * (node.getAttribute('data-percentage')));\n    node.querySelector('.progressbar__progress').style.width = percentage + '%';\n    const percentagenode = node.querySelector('.percentage');\n    percentagenode.innerHTML = percentage;\n  }\n\n  node.addEventListener(\"wh:visibilitychange\", function (ev) {\n    if (animationsdone || !ev.detail.visible)\n      return;\n\n    //animate progressbar percentage from 0 to actual percentage\n    const percentage = Math.round(1 * (node.getAttribute('data-percentage')));\n    node.querySelector('.progressbar__progress').style.width = percentage + '%';\n\n    const duration = 2000;\n\n    const timestep = Math.round(duration / percentage); //steps over 2000 secs\n    let step = 0;\n    const percentagenode = node.querySelector('.percentage');\n    const t = setTimeout(updateDigits, timestep);\n    function updateDigits() {\n      step++;\n      percentagenode.innerHTML = step;\n      if (step < percentage)\n        setTimeout(updateDigits, timestep);\n    }\n\n    animationsdone = true;\n  });\n}\n\nfunction initSegmentedCircle(basenode) {\n  //NOTE: IE does not support css transition animation on svg elements.\n  //      IE bug: classList is undefined on svg elements.\n  for (const node of basenode.querySelectorAll(\".path, .label\")) {\n    node.addEventListener(\"mouseover\", function () {\n      if (node.getAttribute(\"class\").indexOf(\"hover\") != -1)\n        return;\n\n      const sel_idx = 1 * (node.getAttribute(\"data-index\"));\n\n      for (const subnode of basenode.querySelectorAll(\".path, .label\")) {\n        const idx = 1 * (subnode.getAttribute(\"data-index\"));\n        if (idx == sel_idx)\n          subnode.setAttribute(\"class\", subnode.nodeName == \"path\" ? \"path hover\" : \"label hover\");\n        else\n          subnode.setAttribute(\"class\", subnode.nodeName == \"path\" ? \"path\" : \"label\");\n      }\n    });\n\n    node.addEventListener(\"mouseout\", function () {\n      if (node.getAttribute(\"class\").indexOf(\"hover\") == -1)\n        return;\n      const sel_idx = node.getAttribute(\"data-index\");\n      for (const selnode of basenode.querySelectorAll(\".path[data-index='\" + sel_idx + \"'], .label[data-index='\" + sel_idx + \"']\"))\n        selnode.setAttribute(\"class\", selnode.nodeName == \"path\" ? \"path\" : \"label\");\n    });\n  }\n\n  let animationsdone = false;\n  basenode.addEventListener(\"wh:visibilitychange\", function (ev) {\n    if (animationsdone || !ev.detail.visible)\n      return;\n\n    animationsdone = true;\n\n    //animate segments\n    const timeout = 500;\n    const labelnodes = basenode.querySelectorAll(\".label\");\n    for (const node of labelnodes) {\n      const idx = 1 * (node.getAttribute(\"data-index\"));\n\n      setTimeout(function () {\n\n        if (idx > 0) {\n          basenode.querySelector(\".path[data-index='\" + (idx - 1) + \"']\").setAttribute(\"class\", \"path\");\n          basenode.querySelector(\".label[data-index='\" + (idx - 1) + \"']\").classList.remove('hover');\n        }\n\n        node.classList.add('hover');\n        basenode.querySelector(\".path[data-index='\" + idx + \"']\").setAttribute(\"class\", \"path hover\");\n\n        basenode.clientWidth;//force css update\n\n        if (idx == labelnodes.length - 1) {\n          setTimeout(function () {\n            basenode.querySelector(\".path[data-index='\" + idx + \"']\").setAttribute(\"class\", \"path\");\n            basenode.querySelector(\".label[data-index='\" + idx + \"']\").classList.remove('hover');\n          }, timeout);\n        }\n\n      }, timeout * (idx + 1) - timeout * 0.5);\n\n    }\n\n\n  });\n}\n\nfunction initChart(node, chartnr) {\n  const chartdata = JSON.parse(node.getAttribute(\"data-chart\"));\n  if (!chartdata)\n    return;\n\n  const ispreview = document.documentElement.classList.contains(\"wh-widgetpreview\");\n\n  const rgbcolor = ColorStringToRGB(chartdata.color);//darkcolor\n\n  const labels = chartdata.values[0].col;\n  const nrvalues = labels.length - 1;\n  const nrgroups = chartdata.values.length - 1;\n  if (nrgroups <= 0)\n    return;\n\n  const chartnode = node.querySelector(\".chart__area\");\n  const legendanode = node.querySelector(\".chart__legend\");\n  const chartsize = { \"x\": 545, \"y\": 200 };//preview has problems getting correct width/height\n  // let chartsize = { \"x\" : chartnode.clientWidth, \"y\" : chartnode.clientHeight };\n\n  const hintervalwidth = chartsize.x / nrvalues;\n\n  for (let i = 0; i < labels.length; i++) {\n    const labelnode = document.createElement(\"span\");\n    labelnode.innerHTML = labels[i];\n\n    if (i > 0) { //horizontal axis values\n      labelnode.className = \"vlabel\";\n      labelnode.setAttribute(\"style\", \"left:\" + ((i - 1) * hintervalwidth) + \"px;width:\" + hintervalwidth + \"px;\");\n    } else if (labels[i] != \"\") { //horizontal axis label on bottom right\n      labelnode.className = \"htitle\";\n    }\n    chartnode.appendChild(labelnode);\n  }\n\n  //get max value for scale calculations\n  let valuesmax = 0;\n  let valuesmin = 0;\n  for (let c = 1; c < chartdata.values.length; c++) {\n    for (let i = 1; i < chartdata.values[c].col.length; i++) {\n      if (valuesmax < 1 * chartdata.values[c].col[i])\n        valuesmax = 1 * chartdata.values[c].col[i];\n\n      if (valuesmin > 1 * chartdata.values[c].col[i])\n        valuesmin = 1 * chartdata.values[c].col[i];\n    }\n  }\n\n  if (valuesmin < 0)\n    node.classList.add('chart--negativevalues');\n\n  const hlinescount = 5;//nr of horizontal gridlines to display\n\n  //calculate nice factor for dividing values over vertical axis\n  let hspacesteps = (valuesmax - valuesmin) / hlinescount;\n  const precisionfactor = Math.floor(Math.log(hspacesteps) / Math.log(10));\n  hspacesteps = Math.pow(10, precisionfactor);\n\n  valuesmax = hspacesteps * Math.ceil(valuesmax / hspacesteps);\n  valuesmin = hspacesteps * Math.floor(valuesmin / hspacesteps);\n\n  const hvaluestep = (valuesmax - valuesmin) / hlinescount;\n  let labelwidth = 0;\n  let haszeroline;\n  for (let v = 0; v <= hlinescount; v++) { //draw horizontal lines and labels\n    let yvalue = (valuesmax - hvaluestep * v);\n    haszeroline = !haszeroline && yvalue == 0;\n\n    const hnode = document.createElement(\"div\");\n    hnode.className = \"hline\" + (yvalue == 0 ? \" hline--zero\" : \"\");\n    hnode.setAttribute(\"style\", \"top:\" + ((100 / hlinescount) * v) + \"%;\");\n\n    yvalue = parseFloat(yvalue.toFixed(precisionfactor + 1));\n    let vlabelnode;\n    if (yvalue != 0) {\n      vlabelnode = document.createElement(\"span\");\n      vlabelnode.className = \"label\";\n      vlabelnode.innerHTML = yvalue;\n      hnode.appendChild(vlabelnode);\n    }\n\n    chartnode.appendChild(hnode);\n\n    if (vlabelnode && v == 0)\n      labelwidth = vlabelnode.clientWidth + 5;//used for aligning axis title. Add 5px margin\n  }\n\n  if (!haszeroline) {\n    const hnode = document.createElement(\"div\");\n    hnode.className = \"hline hline--zero\";\n    hnode.setAttribute(\"style\", \"top:\" + (valuesmax * 100 / (valuesmax - valuesmin)) + \"%;\");\n    chartnode.appendChild(hnode);\n  }\n\n  if (chartdata.vtitle) { //title vertical axis\n    const vtitlenode = document.createElement(\"span\");\n    vtitlenode.className = \"vtitle\";\n    vtitlenode.innerHTML = chartdata.vtitle;\n    vtitlenode.setAttribute(\"style\", \"margin-left:-\" + labelwidth + \"px;\");\n    chartnode.appendChild(vtitlenode);\n  }\n\n  if (node.classList.contains(\"chart--linechart\")) { //draw svg linechart\n    const svgnode = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n    svgnode.setAttribute(\"width\", \"100%\");\n    svgnode.setAttribute(\"height\", \"100%\");\n\n    const scaley = chartsize.y / (valuesmax - valuesmin);\n    for (let c = 1; c < chartdata.values.length; c++) {\n      const opacity = c * (1 / nrgroups);\n      let svgpath = \"\";\n      const linenode = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n      for (let i = 0; i < chartdata.values[c].col.length; i++) {\n        const colval = chartdata.values[c].col[i];\n        if (i > 0) {\n          const x = (hintervalwidth * (i - 1)) + (hintervalwidth / 2);\n          const y = chartsize.y - scaley * (1 * colval - valuesmin);\n\n          svgpath += (i == 1 ? \"M\" : \" L\") + RoundValue(x, 2) + \" \" + RoundValue(y, 2);\n          if (i == chartdata.values[c].col.length - 1) {\n            linenode.setAttribute(\"d\", svgpath);\n            linenode.setAttribute(\"stroke\", RGBaToColorString(rgbcolor.r, rgbcolor.g, rgbcolor.b, opacity));\n            linenode.setAttribute(\"stroke-width\", 2);\n            linenode.setAttribute(\"fill\", \"none\");\n            linenode.setAttribute(\"data-id\", \"chart\" + chartnr + \"_\" + c);\n            svgnode.appendChild(linenode);\n\n            if (!ispreview) {\n              linenode.addEventListener(\"mouseover\", function () {\n                const hoverid = this.getAttribute(\"data-id\");\n                if (hoverid == node.getAttribute(\"data-hover\"))\n                  return;\n                this.setAttribute(\"stroke-width\", 3);\n                node.setAttribute(\"data-hover\", hoverid);\n\n                const legendalabel = node.querySelector(\".chart__legend > div:nth-child(\" + c + \")\");\n                if (legendalabel)\n                  legendalabel.classList.add(\"label--hover\");\n              });\n              linenode.addEventListener(\"mouseout\", function () {\n                this.setAttribute(\"stroke-width\", 2);\n                const legendalabel = node.querySelector(\".chart__legend > div:nth-child(\" + c + \")\");\n                if (legendalabel)\n                  legendalabel.classList.remove(\"label--hover\");\n\n                const hoverid = this.getAttribute(\"data-id\");\n                if (hoverid == node.getAttribute(\"data-hover\"))\n                  node.setAttribute(\"data-hover\", \"\");\n              });\n            }\n          }\n\n          const pointnode = document.createElement(\"div\");\n          pointnode.className = \"point\";\n          pointnode.setAttribute(\"style\", \"left:\" + x + \"px;top:\" + y + \"px;border-color:\" + RGBaToColorString(rgbcolor.r, rgbcolor.g, rgbcolor.b, opacity) + \";\");\n          chartnode.appendChild(pointnode);\n\n          if (!ispreview) {\n            const valuenode = document.createElement(\"span\");\n            valuenode.className = \"value\";\n            valuenode.innerHTML = RoundValue(1 * colval, chartdata.decimals);\n            pointnode.appendChild(valuenode);\n            valuenode.setAttribute(\"style\", \"margin-left:\" + (-0.5 * valuenode.clientWidth) + \"px;background-color:\" + chartdata.color + \";border-color:\" + chartdata.color + \";\"); //center valuenode (on top of point)\n\n            pointnode.addEventListener(\"mouseover\", function () {\n              const hoverid = linenode.getAttribute(\"data-id\");\n              if (hoverid == node.getAttribute(\"data-hover\"))\n                return;\n              linenode.setAttribute(\"stroke-width\", 3);\n              node.setAttribute(\"data-hover\", hoverid);\n\n              const legendalabel = node.querySelector(\".chart__legend > div:nth-child(\" + c + \")\");\n              if (legendalabel)\n                legendalabel.classList.add(\"label--hover\");\n            });\n\n            pointnode.addEventListener(\"mouseout\", function () {\n              linenode.setAttribute(\"stroke-width\", 2);\n              const legendalabel = node.querySelector(\".chart__legend > div:nth-child(\" + c + \")\");\n              if (legendalabel)\n                legendalabel.classList.remove(\"label--hover\");\n\n              const hoverid = linenode.getAttribute(\"data-id\");\n              if (hoverid == node.getAttribute(\"data-hover\"))\n                node.setAttribute(\"data-hover\", \"\");\n            });\n          }\n        } else {\n          const infonode = document.createElement(\"div\");\n          infonode.setAttribute(\"data-id\", \"chart\" + chartnr + \"_\" + c);\n          infonode.className = \"label\";\n          infonode.innerHTML = colval;\n\n          const bulletnode = document.createElement(\"span\");\n          bulletnode.className = \"bullet\";\n          bulletnode.setAttribute(\"style\", \"background-color:\" + RGBaToColorString(rgbcolor.r, rgbcolor.g, rgbcolor.b, opacity) + \";\");\n\n          infonode.appendChild(bulletnode);\n          legendanode.appendChild(infonode);\n\n          if (!ispreview) {\n            infonode.addEventListener(\"mouseover\", function () {\n              const hoverid = this.getAttribute(\"data-id\");\n              if (hoverid == node.getAttribute(\"data-hover\"))\n                return;\n              this.classList.add(\"label--hover\");\n              node.setAttribute(\"data-hover\", hoverid);\n\n              const line = node.querySelector(\"svg > path:nth-child(\" + c + \")\");\n              if (line)\n                line.setAttribute(\"stroke-width\", 3);\n\n            });\n\n            infonode.addEventListener(\"mouseout\", function () {\n              this.classList.remove(\"label--hover\");\n\n              const line = node.querySelector(\"svg > path:nth-child(\" + c + \")\");\n              if (line)\n                line.setAttribute(\"stroke-width\", 2);\n\n              const hoverid = this.getAttribute(\"data-id\");\n              if (hoverid == node.getAttribute(\"data-hover\"))\n                node.setAttribute(\"data-hover\", \"\");\n            });\n          }\n\n        }\n      }\n    }\n\n    chartnode.appendChild(svgnode);\n  } else { //barchart, just plain html\n\n    const groupoffset = -0.5 * (12 * nrgroups + 5 * (nrgroups - 1));//width of bars is 12px, 5px margin between grouped bars\n\n    const barnodes = [];\n    for (let c = 1; c < chartdata.values.length; c++) {\n      const opacity = c * (1 / nrgroups);\n\n      for (let i = 0; i < chartdata.values[c].col.length; i++) {\n        const colval = chartdata.values[c].col[i];\n        if (i > 0) {\n          const percentage = Math.abs(100 * colval / (valuesmax - valuesmin));\n          const left = (i - 1) * hintervalwidth + (hintervalwidth / 2);\n\n          const barheight = ispreview ? percentage : 0;\n          let stylstr = \"left:\" + left + \"px;height:\" + barheight + \"%;\"; //height will be animated later\n          stylstr += \"margin-left:\" + (groupoffset + (c - 1) * 17) + \"px;\"; //17 = 12 + 5 (bar-width + margin)\n          stylstr += \"background-color:\" + RGBaToColorString(rgbcolor.r, rgbcolor.g, rgbcolor.b, opacity) + \";\";\n\n          const barnode = document.createElement(\"div\");\n          barnode.setAttribute(\"data-id\", \"chart\" + chartnr + \"_\" + c);\n          barnode.className = \"bar\";\n          barnode.setAttribute(\"style\", stylstr);\n\n          if (valuesmin < 0) {\n            if (colval < 0) {\n              barnode.style.bottom = 'auto';\n              barnode.style.top = 100 * valuesmax / (valuesmax - valuesmin) + '%';\n            } else\n              barnode.style.bottom = -100 * valuesmin / (valuesmax - valuesmin) + '%';\n          }\n\n          chartnode.appendChild(barnode);\n          barnodes.push({ \"node\": barnode, \"percentage\": percentage, \"value\": colval });\n\n\n          if (!ispreview) {\n            const valuenode = document.createElement(\"span\");\n            valuenode.className = \"value\";\n            valuenode.innerHTML = RoundValue(1 * colval, chartdata.decimals);\n            valuenode.setAttribute(\"style\", \"background-color:\" + chartdata.color + \";border-color:\" + chartdata.color + \";\");\n            barnode.appendChild(valuenode);\n\n            //center valuenode (on top of bar)\n            valuenode.style.marginLeft = (-0.5 * valuenode.clientWidth) + \"px\";\n\n            barnode.addEventListener(\"mouseover\", function () {\n              const hoverid = this.getAttribute(\"data-id\");\n              if (hoverid == node.getAttribute(\"data-hover\"))\n                return;\n              this.setAttribute(\"stroke-width\", 3);\n              node.setAttribute(\"data-hover\", hoverid);\n\n              const legendalabel = node.querySelector(\".chart__legend > div:nth-child(\" + c + \")\");\n              if (legendalabel)\n                legendalabel.classList.add(\"label--hover\");\n            });\n            barnode.addEventListener(\"mouseout\", function () {\n              this.setAttribute(\"stroke-width\", 2);\n              const legendalabel = node.querySelector(\".chart__legend > div:nth-child(\" + c + \")\");\n              if (legendalabel)\n                legendalabel.classList.remove(\"label--hover\");\n\n              const hoverid = this.getAttribute(\"data-id\");\n              if (hoverid == node.getAttribute(\"data-hover\"))\n                node.setAttribute(\"data-hover\", \"\");\n            });\n          }\n\n        } else {\n          const infonode = document.createElement(\"div\");\n          infonode.setAttribute(\"data-id\", \"chart\" + chartnr + \"_\" + c);\n          infonode.className = \"label\";\n          infonode.innerHTML = colval;\n\n          const bulletnode = document.createElement(\"span\");\n          bulletnode.className = \"bullet\";\n          bulletnode.setAttribute(\"style\", \"background-color:\" + RGBaToColorString(rgbcolor.r, rgbcolor.g, rgbcolor.b, opacity) + \";\");\n\n          infonode.appendChild(bulletnode);\n          legendanode.appendChild(infonode);\n        }\n      }\n    }\n\n    let animationsdone = false;\n    node.addEventListener(\"wh:visibilitychange\", function (ev) {\n      if (animationsdone || !ev.detail.visible)\n        return;\n\n      //barchart animation\n      for (let i = 0; i < barnodes.length; i++)\n        barnodes[i].node.style.height = barnodes[i].percentage + \"%\";\n\n      animationsdone = true;\n    });\n  }\n}\n\n\n\n\n\n/* Helper functions */\n\nfunction RoundValue(number, decimalplaces) {//round value with given decimals\n  if (decimalplaces > 0) {\n    const multiply1 = Math.pow(10, (decimalplaces + 4));\n    const divide1 = Math.pow(10, decimalplaces);\n    return Math.round(Math.round(number * multiply1) / 10000) / divide1;\n  }\n  if (decimalplaces < 0) {\n    const divide2 = Math.pow(10, Math.abs(decimalplaces));\n    const multiply2 = Math.pow(10, Math.abs(decimalplaces));\n    return Math.round(Math.round(number / divide2) * multiply2);\n  }\n  return Math.round(number);\n}\n\n\nfunction ColorStringToRGB(colorstr) { //convert color hex string to RGB values\n  colorstr = colorstr.toUpperCase().replace(/[^0-9A-F]/g, \"\");\n  const color = {\n    r: parseInt(colorstr.substr(0, 2), 16),\n    g: parseInt(colorstr.substr(2, 2), 16),\n    b: parseInt(colorstr.substr(4, 2), 16)\n  };\n  return color;\n}\n\nfunction RGBaToColorString(r, g, b, a) { //convert rgba to rgb string based on white background\n  // basic calculation: RGB.red = Math.round((RGBA.alpha * (RGBA.red / 255) + (alpha * (bg.red / 255))) * 255);\n  const alpha = 1 - a;\n  r = Math.round((a * (r / 255) + alpha) * 255);\n  g = Math.round((a * (g / 255) + alpha) * 255);\n  b = Math.round((a * (b / 255) + alpha) * 255);\n\n  return \"#\" + (r < 16 ? \"0\" : \"\") + r.toString(16) + (g < 16 ? \"0\" : \"\") + g.toString(16) + (b < 16 ? \"0\" : \"\") + b.toString(16);\n}\n\n\n\n//dompack.register('.embeddedobject__sharelink', initEmbeddedObjectShare);\ndompack.register('.segmentedcircle', initSegmentedCircle);\ndompack.register('.progressbar', initProgressBars);\ndompack.register('.progresscircle', initProgressCircles);\n\n//ADDME: Get rid of load event necessity\nwindow.addEventListener(\"load\", () => {\n  dompack.register('.chart', initChart, { waitEmbedded: true });\n\n  //Force scroll update incase scroll event was triggered before element is initialized\n  dompack.dispatchCustomEvent(window, \"scroll\", { bubbles: true, cancelable: false });\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n/** @short Get the value of a CSS variable\n    @long If the DOM is not fully loaded and the CSS is not fully applied, CSS variables may not have been fully computed.\n        This function returns a promise that resolves with the value of the requested CSS variable once it's available. It\n        rejects after a timeout, if set through the options. This function checks if the value is set (getPropertyValue\n        returns an empty string for unknown variables), so it can only be used for variables that eventually will be set to a\n        non-empty value.\n    @param property The CSS variable (custom property) to read\n    @param options.element The element to query, defaults to document.documentElement\n    @param options.timeout The timeout in ms, defaults to 10000, set to 0 to disable timeout and return only after the\n        variable has received a non-empty (and keep running in the background!)\n*/\nexport function getCSSVariable(property, options?) {\n  options =\n  {\n    element: document.documentElement,\n    timeout: 10000,\n    ...options\n  };\n\n  return new Promise((resolve, reject) => {\n    // Local state\n    const data =\n    {\n      timeout: -1, // Signal to timeout has been set\n      property,\n      element: options.element,\n      resolve\n    };\n\n    // Set a timeout if requested\n    if (options.timeout > 0)\n      data.timeout = setTimeout(() => {\n        // Clear the timeout value, to signal a timeout to the checkCSSVariable function\n        data.timeout = 0;\n        reject(new Error(`Timeout after ${options.timeouts}ms reading CSS variable '${property}'`));\n      }, options.timeout);\n    // Check if the CSS variable is set\n    checkCSSVariable(data);\n  });\n}\n\nfunction checkCSSVariable(data) {\n  // If the request has timed out (i.e. the variable didn't receive a value within the given time), we're done\n  if (data.timeout === 0)\n    return;\n  // Get the CSS variable value\n  const value = getComputedStyle(data.element).getPropertyValue(data.property);\n  if (value) {\n    // Clear the timeout\n    clearTimeout(data.timeout);\n    // Return the value\n    data.resolve(value);\n    return;\n  }\n  // Check again in the next animation frame\n  requestAnimationFrame(() => checkCSSVariable(data));\n}\n\nexport function setCSSVariable(property, value, options) {\n  options =\n  {\n    element: document.documentElement,\n    ...options\n  };\n\n  options.element.style.setProperty(property, value);\n}\n\n/*\n  Function to apply ellipsis on multiple lines with overflow=hidden container\n  Only works properly with childnode for text wrapper (display block or inline-block) to measure text height\n*/\nlet ellipsislines = [];\nlet ellipsislinesInitdone = false;\nexport function setEllipsisLines(forcerefresh, options) {\n  const textsuffix = \"...\";\n  if (!ellipsislinesInitdone || forcerefresh) {\n    let basenode = document;\n    if (options && options.basenode && typeof options.basenode === \"object\")\n      basenode = options.basenode;\n\n    ellipsislines = [];\n    const nodes = basenode.querySelectorAll(\"[data-ellipsislines]\");\n\n    for (const node of nodes) {\n      if (node.clientHeight == 0)\n        continue;//probably not a block element\n\n      const innernode = node.firstElementChild;\n      if (!innernode || innernode.clientHeight == 0)\n        continue;//missing wrapper node or not a block element\n\n      ellipsislines.push({\n        \"text\": innernode.textContent,\n        \"dimensions\": \"\",\n        \"node\": node,\n        \"innernode\": innernode\n      });\n    }\n    ellipsislinesInitdone = true;\n  }\n\n  for (const item of ellipsislines) {\n    const dimensions = item.node.clientWidth + 'x' + item.node.clientHeight;\n    if (dimensions == item.dimensions)\n      continue;//no need to change\n    item.dimensions = dimensions;\n\n    item.innernode.textContent = item.text;//put back orginal text\n    let nodeheight = item.innernode.clientHeight;\n    const maxheight = item.node.clientHeight;\n    if (maxheight >= nodeheight)\n      continue;//no need to fit text\n\n    let hasfitt = false;\n    let testlength = item.text.length;\n    let prevlength = testlength;\n    while (!hasfitt) {\n      testlength = Math.round(testlength / 2);//first a rough fit\n      item.innernode.textContent = item.text.substr(0, testlength) + textsuffix;\n      nodeheight = item.innernode.clientHeight;\n      hasfitt = maxheight >= nodeheight;\n      if (maxheight >= nodeheight) { //now add characters until fit\n        for (let i = testlength + 1; i < prevlength; ++i) {\n          item.innernode.textContent = item.text.substr(0, i) + textsuffix;\n          nodeheight = item.innernode.clientHeight;\n          if (maxheight < nodeheight) { //one step back\n            item.innernode.textContent = item.text.substr(0, i - 1) + textsuffix;\n            break;\n          }\n        }\n      }\n      prevlength = testlength;\n    }\n  }\n}\n\n\n/*\n  Function to scale down font-size / line-height until text fits in container\n  Only works properly with block or inline-block elements\n*/\n\nlet fitfontlist = [];\nlet fitfontlistInitDone = false;\nexport function fitFonts(forcerefresh) {\n  if (!fitfontlistInitDone || forcerefresh) {\n    fitfontlist = [];\n    for (const node of document.querySelectorAll(\"[data-fontfit-height],[data-fontfit-width]\")) {\n      let h_attr = node.getAttribute(\"data-fontfit-height\");\n      let maxheight = h_attr ? 1 * h_attr.replace(/[^0-9.]/g, \"\") : 0;\n      if (maxheight <= 0) {\n        maxheight = 100;\n        h_attr = \"100%\";\n      }\n\n      let w_attr = node.getAttribute(\"data-fontfit-width\");\n      let maxwidth = w_attr ? 1 * w_attr.replace(/[^0-9.]/g, \"\") : 0;\n      if (maxwidth <= 0) {\n        maxwidth = 100;\n        w_attr = \"100%\";\n      }\n\n      let wrappernode = null;\n      const wrapperattr = node.getAttribute(\"data-fontfit-wrapper\");\n      if (wrapperattr)\n        wrappernode = node.closest(wrapperattr);\n      if (!wrappernode)//if no wrappernode, then use parentnode\n        wrappernode = node.parentNode;\n\n      fitfontlist.push({\n        node: node,\n        dimensions: \"\",\n        wrappernode: wrappernode,\n        maxheight: maxheight,\n        maxwidth: maxwidth,\n        width_isperc: w_attr.indexOf(\"%\") != -1,\n        height_isperc: h_attr.indexOf(\"%\") != -1,\n        debug: node.getAttribute(\"data-fontfit-debug\") == \"true\"\n      });\n    }\n    fitfontlistInitDone = true;\n  }\n\n  for (const item of fitfontlist) {\n    if (item.debug)\n      console.groupCollapsed(\"fitFonts\", item);\n\n    const wrappersize = item.wrappernode.getBoundingClientRect();\n    const wrapperheight = wrappersize.height;\n    const wrapperwidth = wrappersize.width;\n\n    const dimensions = wrapperwidth + 'x' + wrapperheight;\n    if (dimensions == item.dimensions) {\n      if (item.debug) {\n        console.warn(\"No need to fit\", { wrapper: dimensions, item: item.dimensions });\n        console.groupEnd();\n      }\n      continue;\n    }\n    item.dimensions = dimensions;\n\n    //reset inline style to get actual css font size\n    item.node.style.fontSize = null;\n    item.node.style.lineHeight = null;\n\n    //get actual css fontsize\n    const fontsize = window.getComputedStyle(item.node, null).getPropertyValue('font-size');\n    const fontunit = fontsize.replace(/[0-9.]/g, \"\");\n    let fontnum = 1 * fontsize.replace(/[^0-9.]/g, \"\");\n    if (fontnum <= 0) {\n      if (item.debug) {\n        console.warn(\"Unable to get fontsize\", { fontsize, fontunit, fontnum });\n        console.groupEnd();\n      }\n      continue;\n    }\n\n    const lineheight = window.getComputedStyle(item.node, null).getPropertyValue('line-height');\n    const lineunit = lineheight.replace(/[0-9.]/g, \"\");\n    let linenum = 1 * lineheight.replace(/[^0-9.]/g, \"\");\n\n    //create temporary inline node for correct measurement of width\n    const contents = item.node.innerHTML;\n    item.node.innerHTML = '<span class=\"wh-measure\" style=\"display:inline;\">' + contents + '</span>';\n    const measurenode = item.node.querySelector(\".wh-measure\");\n\n    let maxheight = item.height_isperc ? item.maxheight * wrapperheight * 0.01 : item.maxheight;\n    if (maxheight > wrapperheight)\n      maxheight = wrapperheight;\n\n    let maxwidth = item.width_isperc ? item.maxwidth * wrapperwidth * 0.01 : item.maxwidth;\n    if (maxwidth > maxwidth)\n      maxwidth = wrapperwidth;\n\n    let measurement = measurenode.getBoundingClientRect();\n    if (measurement.height == 0 || (measurement.height <= maxheight && measurement.width <= maxwidth)) { //fits or not visible\n      item.node.removeChild(measurenode);\n      item.node.innerHTML = contents;\n      if (item.debug) {\n        console.warn(\"Contents fits or isn't visible\", { measurement, maxheight, maxwidth });\n        console.groupEnd();\n      }\n      continue;\n    }\n\n    let hasfitt = false;\n    while (!hasfitt) {\n      item.node.style.fontSize = fontnum + fontunit;\n      item.node.style.lineHeight = linenum + lineunit;\n\n      measurement = measurenode.getBoundingClientRect();\n      hasfitt = (maxheight >= measurement.height && maxwidth >= measurement.width) || fontnum < 3; //makes no sense to go smaller\n\n      --fontnum;\n      --linenum;\n    }\n    item.node.removeChild(measurenode);\n    item.node.innerHTML = contents;//put back original content\n\n    if (item.debug) {\n      console.log(\"done!\", { fontunit, fontnum, lineunit, linenum });\n      console.groupEnd();\n    }\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n/*\n\nSmart layout\n- This adds contextual information to elements on their (original) previous and next element\n- This makes it possible to\n  - add vertical space between texts and large widgets (even if these end up in different deeplink containers for the mobile accordion)\n  - allow specific widgets to stick to eachother if needed (magnetic)\n\n\nNOTES:\n- This originally was made for the tophomepage (dec 2018) but broke at some point.\n  (at the latest when we moved to ws2021)\n  Now it's repurposed for the Facts & Figures sites.\n\n- activateSmartLayout() must be called BEFORE the mobile deeplinks reorganize the DOM\n\n- nested content (for example due to accordeons) aren't supported\n\n- elements without .embeddedobject or .embeddedobject--\n  get a .smartlayout--rtdtext class.\n\n- elements get a data-contentbelow and data-contentafter attribute.\n  These contain all classnames starting with \"embeddedobject--\"\n  for the corrosponding element before and after the current element.\n  (before the DOM is reorganized for mobile accordion)\n\n\nWhy clientside?\n- Due to changing visibility/order of content based on the visitor,\n  the order might differ.\n- So it's done after the combining paragraph to support floats\n- Less complex than serverside rewriting of the DOM.\n\n\nFUTURE:\n- use a before/after to communicatie whether the element is\n  considered \"block\" in it's current layout mode.\n  (and whether a border can be removed)\n*/\n\n\nexport function activateSmartLayout() {\n  // Only activate on Facts & Figures pages\n  // if (!document.documentElement.classList.contains(\"page-toplevelhome\") // we don't do the toplevelhome anymore\n  if (!document.documentElement.classList.contains(\"ut--factsfigures\")) {\n    console.info(\"Not applying layout info to DOM.\");\n    return;\n  }\n\n  enrichLayoutInfoFor(document);\n}\n\n// FIXME: we don't support deep nesting yet\nfunction enrichLayoutInfoFor(mainnode) {\n  const maincontainers = mainnode.querySelectorAll(\".contentpart__main, .widgetsblock\");\n  if (maincontainers.length === 0)\n    return;\n\n  let mainchildren = [];\n\n  /*\n    // Was the content divided into an accordeon (which appears in mobile mode) ?\n    // ... in desktop we should treat all their content as being next to each other,\n    // in mobile mode (when the accordeon becomes visible) they should be treated as seperate parts\n    if (mainchildren[0].classList.contains(\".foldabledeeplink\"))\n    {\n      ... depending on mobile or desktop mode\n         mobile -> recursive\n                     for (let container of maincontainers)\n                       enrichLayoutInfoFor(container);\n\n         desktop -> gather all children of these foldabledeeplinks\n                    these will be the new maincontainers array\n    }\n  */\n\n  //console.group(\"Main nodes\");\n  for (const container of maincontainers) {\n    if (container.classList.contains(\"contentpart__main\")) {\n      const children = Array.from(container.children);\n      //console.log(container, children);\n      //mainchildren.concat(children);\n      mainchildren = [...mainchildren, ...children];\n    } else if (container.classList.contains(\"widgetsblock\"))\n      mainchildren.push(container);\n  }\n  //console.groupEnd();\n\n  console.info(mainchildren);\n\n  /*\n  console.group(\"All main content\");\n  for (let node of mainchildren)\n    console.log(node);\n  console.groupEnd();\n  */\n\n  if (mainchildren.length === 0)\n    return;\n\n\n  const elemdescr = [];\n\n  // First sweep, make a list of all content\n  // (possible recursing for some elements/widgets) which display\n  // their content as if it's on the page flow)\n  for (let idx = 0; idx < mainchildren.length; idx++) {\n    const description = [];\n    const node = mainchildren[idx];\n\n    if (node.classList.contains(\"widgetsblock\")) { // FIXME: is this still the correct classname?\n      description.push(\"widgetsblock\");\n    } else if (node.classList.contains(\"embeddedobject\")) {\n      /*\n      // ADDME: handle accordeon's by recursing?\n      if (node.classList.contains(\"foldablecontent\"))\n      {\n        description.push(\"foldablecontent\");\n        enrichLayoutInfoFor(node);\n      }\n      else\n      */\n\n      // For embeddedobjects try to find the className that describes which embeddedobject it is\n      for (const classname of node.classList) {\n        // store the type of embedded object and all modifiers\n        // for example \"embeddedobject--rte\" and \"embeddedobject--rte--themecolor\"\n        if (classname.substring(0, 16) === \"embeddedobject--\")\n          description.push(classname);\n      }\n    }\n\n    // if this wasn't an embeddedobject use the tagName as description\n    // <p>, <ol>, <ul> , ... as elem-p\n    if (description === \"\") {\n      // When it's not an embeddedobject or we cannot determine it's time we assume it's textual/inflow\n      node.classList.add(\"smartlayout--rtdtext\");\n      description.push(\"elem-\" + node.tagName.toLowerCase());\n    }\n\n    elemdescr.push(description);\n  }\n\n  // Second sweep, add contextual information on each element node\n  // on what elements/widgets they originally had (and on desktop visually still have).\n  for (let idx = 0; idx < mainchildren.length; idx++) {\n    const node = mainchildren[idx];\n\n    if (idx > 0 && elemdescr[idx - 1] !== \"\")\n      node.setAttribute(\"data-contentabove\", elemdescr[idx - 1].join(\" \"));\n    else\n      node.removeAttribute(\"data-contentabove\");\n\n    if (idx < mainchildren.length - 1 && elemdescr[idx + 1] !== \"\")\n      node.setAttribute(\"data-contentbelow\", elemdescr[idx + 1].join(\" \"));\n    else {\n      node.removeAttribute(\"data-contentbelow\");\n      if (idx > 0) {\n        const footer = document.querySelector(\".footer\");\n        if (footer)\n          footer.setAttribute(\"data-contentabove\", elemdescr[idx - 1].join(\" \"));\n      }\n    }\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport SlideShow from \"../shared/slideshow\";\nimport setupShowAllLinks from \"../shared/showalllinks\";\nimport \"../shared/newwindow\";\n// import \"../shared/resizelistener\";\nimport \"./footer.scss\";\n\nlet windowMode;\n\nfunction checkWindowSize(event) {\n  if (event.detail.level <= 3) // medium\n  {\n    if (windowMode != \"wide\") {\n      // Close all mobile footer link sections when switching from mobile to desktop\n      for (const section of document.querySelectorAll(\".footer__linksection\")) {\n        const titlenode = section.querySelector(\".footer__sectiontitle\");\n        if (titlenode)\n          titlenode.classList.remove(\"footer__sectiontitle--open\");\n\n        const linkscontainer = section.querySelector(\".footer__sectionlinks\");\n        if (linkscontainer) {\n          linkscontainer.classList.remove(\"footer__sectionlinks--open\");\n          linkscontainer.style.height = \"\";\n        }\n      }\n      windowMode = \"wide\";\n    }\n  } else {\n    if (windowMode != \"small\") {\n      // Close all 'all links' sections when switching from desktop to mobile (the mobile footer sections are closed)\n      for (const section of document.querySelectorAll(\".footer__sectionlinks\")) {\n        section.style.height = \"\";\n      }\n      windowMode = \"small\";\n    }\n  }\n}\n\n\ndompack.register(\".footer__linksection\", section => {\n  // Open/close link sections when in accordion mode\n  const titleNode = section.querySelector(\".footer__sectiontitle\");\n  if (titleNode) {\n    titleNode.addEventListener(\"click\", event => {\n      // Check if the footer is actually in accordion mode\n      const target = event.target.closest(\".footer__sectiontitle\");\n      if (getComputedStyle(target).display != \"block\") // The sectiontitle is hidden, no accordion\n        return;\n\n      // Save section height so it can be animated using transition (which only animates explicitly set height)\n      const links = section.querySelector(\".footer__sectionlinks\");\n      if (links.classList.contains(\"footer__sectionlinks--init\")) {\n        links.setAttribute(\"data-height\", links.clientHeight + \"px\");\n        links.classList.remove(\"footer__sectionlinks--init\");\n\n        // Force a style recompute after the links 'init' class is removed, so the transition will work properly\n        links._wsTmpHeight = getComputedStyle(links).height;\n      }\n\n      // Toggle section open/close, update height to trigger height transition\n      requestAnimationFrame(() => {\n        if (target.classList.contains(\"footer__sectiontitle--open\")) {\n          target.classList.remove(\"footer__sectiontitle--open\");\n          links.classList.remove(\"footer__sectionlinks--open\");\n          links.style.height = \"\";\n        } else {\n          target.classList.add(\"footer__sectiontitle--open\");\n          links.classList.add(\"footer__sectionlinks--open\");\n          links.style.height = links.getAttribute(\"data-height\");\n        }\n      });\n    });\n  }\n\n  // Initialize the footer logo slideshow\n  if (section.classList.contains(\"footer__linksection--logos\")) {\n    const logosNode = section.querySelector(\".footer__logos\");\n    new SlideShow(logosNode.querySelectorAll(\".footer__logoslide\"),\n      {\n        dotNodes: logosNode.querySelectorAll(\".footer__logosliderdot\"),\n        pauseNode: logosNode\n      });\n  }\n});\n\ndompack.register(\".footer__sectionlinks\", section => setupShowAllLinks(section, \"footer__sectionlinksall\", \"footer__sectionlink\"));\n\nwindow.addEventListener(\"ws:responsivemode\", checkWindowSize);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nexport default function setupShowAllLinks(node, containerClass, linkClass) {\n  const target = node.querySelector(\".\" + linkClass + \"--showall\");\n  if (target) {\n    // Open/close 'all links' sections\n    target.addEventListener(\"click\", event => {\n      if (target.parentNode) {\n        // Subtract the 'showall' link height from the links section height and remove the 'showall' link\n        const style = getComputedStyle(target);\n        node.setAttribute(\"data-height\", parseInt(node.getAttribute(\"data-height\")) - parseInt(style.height) - parseInt(style.marginTop));\n        target.parentNode.removeChild(target);\n\n        // Force a style recompute after the 'showall' link is removed, so the transition will work properly\n        node._wsTmpHeight = getComputedStyle(node).height;\n      }\n\n      // Save section height so it can be animated using transition (which only animates explicitly set height)\n      const links = node.querySelector(\".\" + containerClass);\n      if (links.classList.contains(containerClass + \"--init\")) {\n        links.setAttribute(\"data-height\", links.clientHeight + \"px\");\n        links.classList.remove(containerClass + \"--init\");\n\n        // Force a style recompute after the links 'init' class is removed, so the transition will work properly\n        links._wsTmpHeight = getComputedStyle(links).height;\n      }\n\n      // Toggle section open/close, update height to trigger height transition (update parent link section height as well)\n      requestAnimationFrame(() => {\n        if (target.classList.contains(linkClass + \"--open\")) {\n          target.classList.remove(linkClass + \"--open\");\n          links.classList.remove(containerClass + \"--open\");\n          links.style.height = \"\";\n\n          node.setAttribute(\"data-height\", (parseInt(node.getAttribute(\"data-height\")) - parseInt(links.getAttribute(\"data-height\"))) + \"px\");\n          node.style.height = node.getAttribute(\"data-height\");\n        } else {\n          target.classList.add(linkClass + \"--open\");\n          links.classList.add(containerClass + \"--open\");\n          links.style.height = links.getAttribute(\"data-height\");\n\n          node.setAttribute(\"data-height\", (parseInt(node.getAttribute(\"data-height\")) + parseInt(links.getAttribute(\"data-height\"))) + \"px\");\n          node.style.height = node.getAttribute(\"data-height\");\n        }\n      });\n    });\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport domtemplate from \"@mod-utwente_base/webdesigns/ws2016/src/shared/domtemplate\";\nimport { observeNodeResize } from \"@mod-utwente_base/webdesigns/ws2016/src/components/resizeobserver\";\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\nimport promiseXMLHttpRequest from \"../components/promisexmlhttprequest\";\nimport SlideShow from \"../shared/slideshow\";\nimport * as fsslideshow from \"./embeddedobjects/photoalbum/fullscreen-slideshow\";\n\nimport \"./widgetsholder/widgetsholder\";\nimport * as widgets from \"./embeddedobjects\";\nimport * as layout from '@mod-utwente_base/webfeatures/utwidgets/layout';\nexport { relayoutWidgets } from '@mod-utwente_base/webfeatures/utwidgets/layout'; //Needed by external deps!\n\nimport \"./consentcheck\";\n\nimport \"./widgets.scss\";\nimport \"./widgets-general.scss\";\nimport \"./homepage\";\nimport \"./edunumbers/edunumbers.scss\";\nimport \"./ff-innumbers\";\n\nimport '@mod-utwente_base/webfeatures/utwidgets/countdown';\nimport '@mod-utwente_base/webfeatures/utwidgets/ctawithimage/ctawithimage';\nimport '@mod-utwente_base/webfeatures/utwidgets/downloads';\nimport '@mod-utwente_base/webfeatures/utwidgets/events';\nimport '@mod-utwente_base/webfeatures/utwidgets/faq';\nimport '@mod-utwente_base/webfeatures/utwidgets/featuredpages';\nimport '@mod-utwente_base/webfeatures/utwidgets/imagewithcaption';\nimport '@mod-utwente_base/webfeatures/utwidgets/imagevideowithtext';\nimport '@mod-utwente_base/webfeatures/utwidgets/insetblock';\nimport '@mod-utwente_base/webfeatures/utwidgets/news';\nimport '@mod-utwente_base/webfeatures/utwidgets/phonedirectory';\nimport '@mod-utwente_base/webfeatures/utwidgets/programmelist';\nimport '@mod-utwente_base/webfeatures/utwidgets/quote';\nimport '@mod-utwente_base/webfeatures/utwidgets/soundcloud';\nimport '@mod-utwente_base/webfeatures/utwidgets/tablewithtabs';\nimport '@mod-utwente_base/webfeatures/utwidgets/video';\n\nconst dir = document.documentElement.dir === 'rtl' ? 1 : -1;\nconst frontproperty = document.documentElement.dir === 'rtl' ? 'right' : 'left';\n\nclass Tabs {\n  constructor(container) {\n    this.tabIndicator = container.querySelector(\".widget__tabs-currenttitle\");\n    this.tabs = [];\n    this.pageholder = container.querySelector(\".widget__tabs-contents\");\n    this.pulldown = null;\n    if (container.classList.contains(\"widget__tabs--pulldown\")) {\n      this.pulldown = container.querySelector(\".widget__tabs-pulldown\");\n      this.pulldown.addEventListener(\"change\", event => this.switchTab(this.pulldown.value));\n    }\n\n    const titles = !this.pulldown ? container.querySelectorAll(\".widget__tabs-titletext\") : [];\n    dompack.qSA(container, \".widget__tabs-page\").forEach((page, idx) => {\n      const tab = {\n        title: titles[idx],\n        page: page\n      };\n      this.tabs.push(tab);\n      if (tab.title)\n        tab.title.addEventListener(\"click\", this.switchTab.bind(this, idx));\n      else {\n        // Position each subsequent tab over the first tab (we cannot use position: absolute, because we want our container\n        // to have the height of the highest tab)\n        tab.page.style.marginLeft = idx ? (100 * dir) + \"%\" : \"0\";\n      }\n      tab.page.classList.remove(\"widget__tabs-page--init\");\n    });\n\n    this.curIdx = 0;\n    observeNodeResize(container, () => this.resizeTimeout = this.resizeTimeout || requestAnimationFrame(() => this.updateTabIndicator()));\n    this.resizeTimeout = requestAnimationFrame(() => this.updateTabIndicator());\n  }\n\n  switchTab(newIdx) {\n    this.curIdx = newIdx;\n\n    if (!this.pulldown) {\n      const pos = dir * 100 * this.curIdx;\n      this.pageholder.style.transform = `translateX(${pos}%)`;\n    }\n\n    this.updateTabIndicator();\n  }\n\n  updateTabIndicator() {\n    this.resizeTimeout = null;\n    let firstLeft = 0;\n    this.tabs.forEach((tab, idx) => {\n      if (this.pulldown) {\n        if (idx === this.curIdx) {\n          // Position the next tab on top of the current tab (the new tab is transparent and fades in)\n          tab.page.style.zIndex = 2;\n          tab.page.classList.add(\"widget__tabs-page--current\");\n        } else {\n          // Position the current tab beneath the new tab (the new tab is transparent and fades in)\n          tab.page.style.zIndex = 1;\n          tab.page.classList.remove(\"widget__tabs-page--current\");\n        }\n        return;\n      }\n      const titleRect = tab.title.getBoundingClientRect(); //title is .widget__tabs-titletext\n      if (!idx)\n        firstLeft = titleRect[frontproperty];\n\n      if (idx === this.curIdx) {\n        tab.title.classList.add(\"widget__tabs-titletext--current\");\n        this.tabIndicator.style[frontproperty] = (-dir) * (titleRect[frontproperty] - firstLeft) + \"px\";\n        this.tabIndicator.style.width = tab.title.getBoundingClientRect().width + \"px\";\n      } else {\n        tab.title.classList.remove(\"widget__tabs-titletext--current\");\n      }\n    });\n  }\n}\n\n\n\nexport class ListTemplate {\n  constructor(node, template, type) {\n    this.node = node;\n    this.template = template;\n    this.templatetype = type;\n    this.instanceid = this.node.getAttribute(\"data-instance\");\n    if (this.templatetype === \"photo\") {\n      this.sliderdots = template.parentNode.querySelector(\".widget__photosliderdots\");\n    }\n  }\n\n  getItems(url) {\n    return Promise.resolve([]);\n  }\n\n  parseTemplateItem(item) {\n    return item;\n  }\n\n  async retrieveItems(url) {\n    try {\n      const items = await this.getItems(url);\n      if (this.templatetype === \"list\" || this.templatetype === \"embed\") {\n        for (const item of items) {\n          const data = this.parseTemplateItem(item);\n          domtemplate.expandTemplate(this.template, data);\n        }\n\n        // If widget-newsevents component with 2 or less events, fallback to 8col grid!\n        if (this.node.classList.contains(\"widget-newsevents--event\") && items.length < 3)\n          this.node.classList.remove(\"main__contents--12col\");\n      } else if (this.templatetype === \"photo\") {\n        const photosNode = this.template.parentNode;\n        if (items.length && items[0].photolink) {\n          const data = this.parseTemplateItem(items[0]);\n\n          // The fragment contains a <style> containing a JS template string, a <div class=\"widget__photoslide\">\n          // and a <span class=\"widget__photosliderdot\">\n          const fragment = domtemplate.instantiate(this.template, data);\n\n          // Format the style template string with the data object\n          let styleNode = fragment.querySelector(\"style\");\n          const cssText = this.applyTemplate(styleNode.textContent, data);\n          // Create a new style node and insert it into the DOM\n          styleNode = document.createElement(\"style\");\n          photosNode.insertBefore(styleNode, this.template);\n          // Add the CSS to the new style node\n          this.addCssRules(styleNode, cssText);\n\n          // Insert the photo slide node\n          photosNode.insertBefore(fragment.querySelector(\".widget__photoslide\"), this.template);\n          // We'll discard the slider dots as we're only showing 1 photo\n\n          // Create a (single slide) slide show\n          // (Only select .widget__photoslide nodes with a data-photoslide attribute, otherwise IE11 will also select slide\n          // nodes within the template)\n          new SlideShow(photosNode.querySelectorAll(\".widget__photoslide[data-photoslide]\"));\n        } else {\n          // Remove the photos node, there are no photos to show\n          photosNode.parentNode.removeChild(photosNode);\n        }\n      }\n      this.node.classList.toggle(\"noresults\", items.length === 0);\n      this.node.dataset.itemcount = String(items.length);\n      this.node.dataset.rendering = \"finished\";\n      layout.relayoutWidgets(this.node);\n    } catch (e) {\n      console.error(e);\n    }\n\n  }\n\n  // Use an ordinary \"string\" as a `string template`\n  applyTemplate(templateString, data) {\n    function replaceMatch(match, key) {\n      const levelKey = key.split(\".\")[0];\n      key = key.substr(levelKey.length + 1);\n      return Object.prototype.hasOwnProperty.call(data, levelKey) ? (key.length ? replaceMatch(match, key) : data[levelKey]) : \"\";\n    }\n\n    return templateString.replace(/\\$\\{([a-zA-Z0-9._]+)\\}/g, replaceMatch);\n  }\n\n  // The style node should already be inserted into the DOM, otherwise its sheet property is null\n  addCssRules(styleNode, cssText) {\n    // Simple CSS text into CSS rules splitter\n    const cssRules = [];\n    // Find the start of the first block\n    let startIdx = cssText.indexOf(\"{\");\n    let depth = 0; // Nested block level (for media queries)\n    while (startIdx >= 0) {\n      // See if the current block is closed or a new nested block is opened\n      const endIdx = cssText.indexOf(\"}\", startIdx + 1);\n      startIdx = cssText.indexOf(\"{\", startIdx + 1);\n      if (startIdx < 0) {\n        // There are now new blocks, the current CSS text is the last rule\n        cssRules.push(cssText.trim());\n      } else if (endIdx < startIdx) {\n        // The current block is closed\n        if (depth) {\n          // The current block was nested, decrease the level to go into the parent block\n          --depth;\n        } else {\n          // The current block is closed, add the CSS text up until and including the closing bracket\n          cssRules.push(cssText.substr(0, endIdx + 1).trim());\n          // Discard this block, continue with the rest of the text (startIdx will already contain the next opening bracket)\n          cssText = cssText.substr(endIdx + 1);\n        }\n      } else {\n        // Stepping into a nested block\n        ++depth;\n      }\n    }\n    // Add the CSS rules\n    for (const rule of cssRules)\n      styleNode.sheet.insertRule(rule, styleNode.sheet.cssRules.length);\n  }\n}\n\n\n\nconst cachedNewsEvents = {};\n\nclass NewsEventsTemplate extends ListTemplate {\n  constructor(node, template, type) {\n    super(node, template, type);\n\n    const options = JSON.parse(this.node.getAttribute(\"data-options\"));\n    this.type = options.type;\n    this.publoc = options.publoc;\n    this.retrieveItems(options.publocfile + \"&type=json\");\n  }\n\n  // Returns a promise that is resolved with the requested items\n  getItems(url) {\n    // Check if we already known this url\n    if (url in cachedNewsEvents) {\n      const cached = cachedNewsEvents[url];\n      // Check if we already retrieved this url\n      if (cached.items)\n        return Promise.resolve(cached.items);\n      else {\n        // Wait for the url to be retrieved\n        return new Promise((resolve, reject) => {\n          const deferred = dompack.createDeferred();\n          cached.deferred.push(deferred);\n          deferred.promise.then(items => {\n            resolve(this.filterItems(items));\n          });\n        });\n      }\n    }\n\n    // Retrieve the url\n    const cached = {\n      deferred: [],\n      items: null\n    };\n    cachedNewsEvents[url] = cached;\n    return new Promise((resolve, reject) => {\n      promiseXMLHttpRequest(url + \"&\" + Date.now(), {\n        timeout: 5000,\n        responseType: \"json\",\n        reuseRequest: false\n      }).then(items => {\n        // IE11 fix\n        if (typeof items === \"string\")\n          items = JSON.parse(items);\n\n        // Cache the result\n        cached.items = items;\n\n        // Resolve waiting promises\n        for (const deferred of cached.deferred)\n          deferred.resolve(items);\n\n        resolve(this.filterItems(items));\n      }).catch(e => reject(e));\n    });\n  }\n\n  filterItems(items) {\n    if (items && Object.prototype.hasOwnProperty.call(items, \"p\" + this.publoc))\n      return items[\"p\" + this.publoc].items.map((item, idx) => { item.seqnr = idx; return item; });\n    return [];\n  }\n\n  parseTemplateItem(item) {\n    if (this.templatetype === \"list\") {\n      return {\n        text: item.title,\n        link: item.url,\n        linkarrow: true,\n        subtext: this.type === \"event\" || this.type === \"edu\" ? item.widgetdate : \"\"\n      };\n    } else if (this.templatetype === \"embed\") {\n      return {\n        title: item.title,\n        link: item.url,\n        date: this.type === \"event\" ? item.widgetdate : \"\",\n        icon: item.icon ? item.icon : \"\",\n        category: item.category ? item.category : \"\",\n        event_start: this.type === \"event\" && item.eventdate ? item.eventdate.startdate : \"\",\n        event_end: this.type === \"event\" && item.eventdate ? item.eventdate.enddate : \"\",\n        location: this.type === \"event\" && item.location ? item.location : \"\",\n        description: item.articleintro ? item.articleintro : \"\",\n        photo_small: item.embedphotolink,\n        photos_small: item.embedphotolink ? item.embedphotolink + \" 1x, \" + item.embedphotolink_2x + \" 2x\" : \"\",\n        photo_large: item.infocusphotolink,\n        photos_large: item.infocusphotolink ? item.infocusphotolink + \" 1x, \" + item.infocusphotolink_2x + \" 2x\" : \"\",\n        photoalt: item.photoalt ? item.photoalt : \"\",\n        instanceid_seqnr: this.instanceid + \"-\" + item.seqnr,\n        tags: item.tags ? item.tags : []\n      };\n    } else if (this.templatetype === \"photo\") {\n      return {\n        photo: item.photolink,\n        photo_2x: item.photolink_2x,\n        photoalt: item.photoalt ? item.photoalt : \"\",\n        link: item.url,\n        instanceid_seqnr: this.instanceid + \"-1\"\n      };\n    }\n  }\n}\n\nlet callbackFormRPC;\n\nfunction initializeCallbackForm(node) {\n  callbackFormRPC = new JSONRPC({ url: \"/wh_services/utwente_base/rpc/\" });\n  const formNode = node.querySelector(\"form\");\n  if (formNode) {\n    const inputNode = formNode.querySelector(\"input[name='phone']\");\n    inputNode.value = \"\";\n    formNode.addEventListener(\"submit\", event => {\n      event.preventDefault();\n      event.stopPropagation();\n      if (callbackFormRPC.isRequestPending())\n        return false;\n\n      const phonenr = inputNode.value;\n      if (Number(phonenr.replace(/[^0-9]/g, \"\")) > 999) // Submit at least 4 digits\n      {\n        const formdata = {\n          phone: phonenr,\n          pageid: formNode.getAttribute(\"data-pageid\"),\n          widgetid: formNode.getAttribute(\"data-widgetid\")\n        };\n        node.classList.add(\"widget__callbackform--loading\");\n        callbackFormRPC.request(\"MailContactPerson\",\n          [formdata],\n          result => {\n            if (result.success) {\n              node.classList.remove(\"widget__callbackform--loading\");\n              node.classList.add(\"widget__callbackform--success\");\n              layout.relayoutWidgets(node);\n            }\n          });\n      }\n    });\n  }\n}\n\n\n\nfunction initializePhotoslide(widgetphotos) {\n  const slides = widgetphotos.querySelectorAll(\".widget__photoslide\");\n\n  if (widgetphotos.classList.contains(\"widget__photos--infos\")) {\n    widgetphotos.closest(\".widget\").addEventListener(\"ws:relayoutwidgetcontent\", relayoutPhotoslideByEvent);\n    relayoutPhotoslide(widgetphotos);\n  }\n\n  widgetphotos.whSlideshow =\n    new SlideShow(slides,\n      {\n        dotNodes: widgetphotos.querySelectorAll(\".widget__photosliderdot\"),\n        pauseNode: widgetphotos\n      });\n}\n\nfunction relayoutPhotoslideByEvent(evt) {\n  relayoutPhotoslide(evt.target.querySelector(\".widget__photos\"));\n}\n\nfunction relayoutPhotoslide(widgetphotos) {\n  const slides = widgetphotos.querySelectorAll(\".widget__photoslide\");\n\n  let infoheight = 0;\n  for (const node of slides) {\n    const info = node.querySelector(\".widget__photoinfo\");\n    const height = info.getBoundingClientRect().height;\n    if (height > infoheight)\n      infoheight = height;\n\n    if (node.classList.contains(\"widget__photoslide--infoinit\"))\n      node.classList.remove(\"widget__photoslide--infoinit\");\n  }\n  if (infoheight > 0) {\n    widgetphotos.style.marginBottom = `${infoheight}px`;\n  }\n}\nwindow.relayoutPhotoslide = relayoutPhotoslide;\n\n\n// Initialize widget photo slideshows\ndompack.register(\".widget__photos\", widgetphotos => initializePhotoslide(widgetphotos));\n\n\n// Initialize widget info slideshows\ndompack.register(\".widget__infos--slideshow\",\n  widgetinfos => {\n    widgetinfos._wsSlideShow = new SlideShow(widgetinfos.querySelectorAll(\".widget__infoslide\"),\n      {\n        dotNodes: widgetinfos.querySelectorAll(\".widget__infosliderdot\"),\n        pauseNode: widgetinfos\n      });\n  }\n);\n\n\n\n\n// Initialize widget tabs\ndompack.register(\".widget__tabs\", widgettabs => new Tabs(widgettabs));\n\n// Initialize widget flips\ndompack.register(\".widget__flip\", widgetflip => {\n  widgetflip.addEventListener(\"click\", event => {\n    const widget = event.target.closest(\".widget\");\n    if (widget) {\n      const widgetinfos = widget.querySelector(\".widget__infos--slideshow\");\n\n      if (widget.classList.contains(\"widget--rotated\")) {\n        widget.classList.remove(\"widget--rotated\");\n        if (widgetinfos)\n          widgetinfos._wsSlideShow.resume();\n      } else {\n        widget.classList.add(\"widget--rotated\");\n        if (widgetinfos)\n          widgetinfos._wsSlideShow.stop();\n      }\n    }\n  });\n});\n\n// Initialize callbackforms (contactperson widgets)\ndompack.register(\".widget__callbackform\", callbackform => initializeCallbackForm(callbackform));\n\n// Initialize news/events and vacancy lists\ndompack.register(\".template__newsevents-list\", newseventstemplate => {\n  const node = newseventstemplate.closest(\".widget\");\n  new NewsEventsTemplate(node, newseventstemplate.querySelector(\"template\"), \"list\");\n});\ndompack.register(\".template__newsevents-photo\", newseventstemplate => {\n  const node = newseventstemplate.closest(\".widget\");\n  new NewsEventsTemplate(node, newseventstemplate.querySelector(\"template\"), \"photo\");\n});\ndompack.register(\".template__newsevents-embed\", newseventstemplate => {\n  const node = newseventstemplate.closest(\".embeddedobject\");\n  new NewsEventsTemplate(node, newseventstemplate.querySelector(\"template\"), \"embed\");\n});\ndompack.register(\".template__newsstories-embed\", newseventstemplate => {\n  const node = newseventstemplate.closest(\".embeddedobject\");\n  new NewsEventsTemplate(node, newseventstemplate.querySelector(\"template\"), \"embed\");\n});\n\ndompack.register(\".widget__image\", imagewidget => {\n  const instanceid = imagewidget.getAttribute(\"data-instanceid\");\n  imagewidget.addEventListener(\"click\", event => {\n    const headeranim = document.querySelector(\".header__universe\");\n    if (headeranim)\n      headeranim.style.display = \"none\";\n\n    fsslideshow.doActivateSlideshow(instanceid, 0);\n  });\n});\n\n\n\n\n//Reflow widgets if the form is changed\nwindow.addEventListener('wh:form-validitychange', event => {\n  const widget = event.target.closest('.widget');\n  if (widget)\n    layout.relayoutWidgets(widget);\n});\n\n// Use onLoad where we need actual element sizes after rendering (like custom fonts)\n// Also this fixes initial layout issues in Firefox (0px height widgets)\nwindow.addEventListener(\"load\", function () {\n  //ADDME: Get rid of load event necessity for foldable content (use event delegation?)\n  widgets.initFoldableContent();\n\n  // Force redoing layouts\n  layout.forceRelayoutWidgets();\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n// A wrapper around ResizeObserver with a polyfill for browsers that don't support it\n\nlet observer, resizeListener;\nif (ResizeObserver)\n  observer = new ResizeObserver(entries => onResize(entries));\nelse\n  window.addEventListener(\"resize\", () => resizeListener = resizeListener || requestAnimationFrame(event => onWindowResize(event)));\nconst nodes = new Map();\n\nfunction onResize(entries) {\n  for (const entry of entries) {\n    const callback = nodes.get(entry.target);\n    if (callback)\n      callback(entry);\n  }\n}\n\nfunction onWindowResize() {\n  for (const [node, entry] of nodes.entries()) {\n    const rect = node.getBoundingClientRect();\n    if (rect.height != entry.rect.height || rect.width != entry.rect.width) {\n      entry.rect = rect;\n      entry.callback({ target: node, boundingClientRect: rect });\n    }\n  }\n  resizeListener = null;\n}\n\n/** @short Call the callback if the node is resized\n    @long This registers a callback which is called if the given node is resized. If called multiple times for the same node,\n        only the last callback is called.\n    @param The node to observe\n    @callback The callback that is called if the node is resized, receiving a ResizeObserverEntry object if the browser\n        supports ResizeObserver, or an object containing `target` (the node that was resized) and `boundingClientRect`\n        (the new size of the node) properties\n*/\nexport function observeNodeResize(node, callback) {\n  if (observer)\n    observer.observe(node);\n\n  if (observer)\n    nodes.set(node, callback);\n  else\n    nodes.set(node, { callback, rect: node.getBoundingClientRect() });\n}\n\n/** @short Stop observing this node for resizing\n    @long This unregisters a previously registered callback for the given node. It is not an error to call this function for\n        a node without a registered callback.\n    @param The node that was being observed\n*/\nexport function unobserveNodeResize(node) {\n  if (nodes.has(node)) {\n    nodes.delete(node);\n    if (observer)\n      observer.unobserve(node);\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n// http://masonry.desandro.com/\nimport DesandroMasonry from \"masonry-layout\";\n\n//import DompackMasonry  from \"dompack-masonry\";\nimport DompackMasonry from \"./dompack-masonry\";\n\nimport { getCSSVariable } from \"../../shared/layout-tools\";\n\nimport \"./widgetsholder.scss\";\nimport \"./widgetsholder-eqheight.scss\";\n\n\nconst widgetContainers = []; // all .widgetblock elements\nwindow.widgetContainers = widgetContainers;\n\nlet relayout_throttle; // timer to wait for 250ms without any relayout calls before relayouting\n\nlet windowMode;\n\n\n/*\n\nEvents\n\n\"ws:widgetholders-beforerelayout\n- Fired once on window just before ALL masonries are relayouted\n\n\"ws:relayoutwidgetcontent\"\n- request from dompack-masonry for widgets to relayout content AFTER correct width is set\n- request before running Desonry masonry (width is assumed to be correct due to using a fixed width)\n\n\"ws:relayoutwidgets\"\n- This event SHOULD BE FIRED USING layout.es relayoutWidgets()\n- request to have the widgetsholder relayout all widgets\n  (after widgets have changes size)\n- Example:\n  import * as layout from \"@mod-utwente_base/webfeatures/utwidgets/layout\";\n  layout.relayoutWidgets(this.node);\n\n\n\nWidgetblocks:\n\nDesonry\n  used by:\n    - Footer\n  behaviour:\n    - fullwidth\n    - widgets have a fixed width of 300px (unless mobile mode)\n    - Desonry masonry\n\nDompack-masonry\n  used by:\n    - Pagecontent \"widgetblock\"\n  behaviour:\n    - width is 8 column page layout\n    - normal contentpage: 2 column layout within\n    - toplevel homepage:  2 or 3 columns within depending on the available width\n    - widgets stretch to fill up their column\n\nCSS equal-height\n  used by:\n    - People Page (gridview)\n  behaviour:\n    - CSS uses flex to generate a grid with 2 or 3 columns\n\n*/\n\n\nfunction registerWidgetsContainer(widgetContainer) {\n  widgetContainers.push(widgetContainer);\n\n  /*\n  - Default: white background and widgets have a border\n  - Grey bg: (layout using Desanro)\n  */\n\n  // Determine which layout to use (\"none\" (CSS, for equal-height items), \"desanro\" or \"dompack-carrousel\")\n  if (widgetContainer.classList.contains(\"widgetsblock__contents--equalheight\")\n    || widgetContainer.classList.contains(\"widgetsblock__contents--singlewidget\")\n  )\n    widgetContainer._whMasonryType = \"none\";\n  else\n    widgetContainer._whMasonryType = \"dompack-masonry\";\n}\n\n\n// used on window resize\nfunction throttledRelayoutWidgets() {\n  clearTimeout(relayout_throttle);\n  relayout_throttle = setTimeout(evt => relayoutWidgetsDueToResize(evt), 250);\n}\n\nfunction relayoutWidgetsDueToResize() {\n  sendBeforeRelayoutEvent();\n\n  // In case of a window resize, a widget might have changed in width\n  for (const widgetContainer of widgetContainers)\n    refreshWidgetBlock(widgetContainer);\n}\n\n// a relayout event will trigger a direct relayout of widgets\nfunction onRelayoutWidgets(event) {\n  sendBeforeRelayoutEvent();\n\n  for (const widgetContainer of widgetContainers) {\n    // in case a specific container was passed\n    // we only relayout that container.\n    if (!event.detail.container || widgetContainer == event.detail.container)\n      refreshWidgetBlock(widgetContainer, Boolean(event.detail.force));\n  }\n}\n\nfunction sendBeforeRelayoutEvent() {\n  dompack.dispatchCustomEvent(window, \"ws:widgetholders-beforerelayout\",\n    {\n      bubbles: false,\n      cancelable: false\n    });\n}\n\n\n// The widgets are full width on xsmall and xxsmall devices, but the masonry\n// doesn't play well with switching between fixed column width and full width,\n// it should be activated and deactivated. Because it doesn't support that,\n// we'll just initialize and destroy it when necessary.\nfunction checkWindowSize(mode) {\n  for (const widgetContainer of widgetContainers) {\n    if (widgetContainer._whMasonryType == \"dompack-masonry\")\n      refreshDompackWidgetBlock(widgetContainer);\n    else if (widgetContainer._whMasonryType == \"desandro\")\n      refreshDesandroWidgetBlock(mode, widgetContainer);\n  }\n}\n\nfunction refreshDesandroWidgetBlock(mode, widgetContainer) {\n  if (mode != windowMode) {\n    windowMode = mode;\n    if (windowMode == \"small\") {\n      // When switching to small mode, destroy the widget masonry (if it's still active)\n      if (widgetContainer._wsMasonry) {\n        widgetContainer._wsMasonry.destroy();\n        widgetContainer._wsMasonry = null;\n      }\n\n      const widget = widgetContainer.closest(\".widgetsblock\");\n      widget.classList.remove(\"widgetsblock--defaultlayout\");\n    } else {\n      // When switching to wide mode, initialize the widget masonry (if it isn't already active)\n      const widget = widgetContainer.closest(\".widgetsblock\");\n      widget.classList.add(\"widgetsblock--defaultlayout\");\n\n      if (!widgetContainer._wsMasonry) {\n        // console.log(\"Init Desandro\", widgetContainer);\n        widgetContainer._wsMasonry = new DesandroMasonry(widgetContainer\n          , {\n            itemSelector: \".widget\",\n            columnWidth: \".widgetsblock__contents-sizer\",\n            fitWidth: true,\n            gutter: 15\n          });\n      }\n    }\n  }\n}\n\n\nfunction refreshDompackWidgetBlock(widgetContainer, force) {\n  let options = {};\n\n  widgetContainer.classList.add(\"widgetsblock--dompackmasonry\");\n\n  // Retrieve current settings from CSS /////////////////////////////////////////////////\n  const comp = window.getComputedStyle(widgetContainer, '::before');\n  let layout = comp.content;\n\n  // remove the \" some browsers add (Safari doesn't add quotes)\n  if (layout != \"\" && layout.startsWith('\"'))\n    layout = layout.substring(1, layout.length - 1); // remove the \"'s around the string\n\n  // console.log(\"Masonry CSS hints\", layout, \"for\", widgetContainer);\n\n  if (layout != \"none\") {\n    const parts = layout.split(\":\");\n\n    options = {\n      columns: parseInt(parts[0]),\n      gutter: parseInt(parts[1])\n    };\n  } else // CSS not loaded/parsed yet?\n  {\n    // fallback values\n    options = {\n      columns: 2,\n      gutter: 30\n    };\n  }\n  ////////////////////////////////////////////////////////////////////////////////////////\n\n  //console.info(\"Masonry\", options);\n\n  if (!widgetContainer._wsMasonry) {\n    widgetContainer._wsMasonry = new DompackMasonry(widgetContainer\n      , {\n        ...options,\n        items: \".widget\",\n        breakclass: \".widget__break__title\"\n      });\n  } else {\n    widgetContainer._wsMasonry.setOptions(options);\n    widgetContainer._wsMasonry.refresh(force);\n  }\n}\n\n\nfunction refreshWidgetBlock(widgetContainer, force) {\n  if (widgetContainer._whMasonryType == \"desandro\") {\n    // Give all widgets the ability to do their resize handlers before doing the relayout of the widgetholders.\n    // Because the Desanro masonry layout uses a fixed width we can get away with this.\n    // (ideally we want the refresh trigger events to be send after the masonry determined the width of the widgets)\n    const widgets = widgetContainer.querySelectorAll(\".widget\");\n    for (const widget of widgets) {\n      dompack.dispatchCustomEvent(widget, \"ws:relayoutwidgetcontent\",\n        {\n          bubbles: true,\n          cancelable: false,\n          detail: { force: force } // let our child content also know we want to force relayouting\n        });\n    }\n\n    if (widgetContainer._wsMasonry)\n      widgetContainer._wsMasonry.layout();\n  } else if (widgetContainer._whMasonryType == \"dompack-masonry\")\n    refreshDompackWidgetBlock(widgetContainer, force);\n}\n\n\n\n// Add new widget blocks to the list of containers to relayout\ndompack.register(\".widgetsblock__contents\", widgetblock => registerWidgetsContainer(widgetblock));\nwindow.addEventListener(\"ws:relayoutwidgets\", onRelayoutWidgets); // listen for trigger to refresh the widgetsholder\nwindow.addEventListener(\"ws:responsivemode\", event => checkWindowSize(event.detail.level <= 1 ? \"small\" : \"wide\")); // ws2016\nwindow.addEventListener(\"resize\", throttledRelayoutWidgets);\n\ngetCSSVariable(\"--breakpoint-phone\").then(breakpoint_phone => {\n  // Read the breakpoint CSS variable and get a MediaQueryList\n  const initMasonryMedia = matchMedia(`(max-width: ${breakpoint_phone})`);\n  // Setup an onchange listener to activate/deactivate the deeplinks\n  initMasonryMedia.addEventListener(\"change\", event => checkWindowSize(event.matches ? \"small\" : \"wide\"));\n  // Directly check the query\n  checkWindowSize(initMasonryMedia.matches ? \"small\" : \"wide\");\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n/*\nThis is an updated DompackMasonry.\n- Equalheight has been removed\n- force parameter added to refresh()\n- event is fired to all widgets when they need to relayout due to\n  - changed columnwidth\n  - force parameter used (in case of load event or custom fonts or CSS files loaded)\n*/\n\n\nexport default class DompackMasonry {\n  constructor(node, options) {\n    const domoptions = dompack.getJSONAttribute(node, \"data-masonry-options\");\n\n    // NOTE: we don't use Object.assign() here because we have some\n    //       smart rules (convert gutter to gutter_x and gutter_y for example)\n    this.options =\n    {\n      columns: 3,\n      columnwidth: 0,     // if not set the width will be set so the amount of columns will fill up the horizontal space\n\n      // gutter size\n      // gutter:            10 // shorthand for gutter_x and gutter_y\n      gutter_x: 10,\n      gutter_y: 10,\n\n      debug: false,\n\n      // CSS query (for example '.masonry-item' or array of nodes\n      // Pass an array of nodes if you want control over the order visual order of the items (without reordering the dom)\n      items: null,\n\n      // specify a class to ignore in layouting\n      // (can be used for items which you transition to hide/fade)\n      ignoreclass: \"hide\",\n\n      righttoleft: false // FIXME: keep or remove this option?\n    };//, domoptions, options;\n\n    if (domoptions)\n      this.setOptions(domoptions);\n\n    if (options)\n      this.setOptions(options);\n\n    if (typeof (node) === \"string\")\n      this.container = document.getElementById(node);\n    else\n      this.container = node;\n\n    this.__height = 0;\n    this.__columnwidth = 0;    // (also used to detect whether widget width style has to be set)\n    this.__itemdata = [];   // render data\n    this.__visiblewidgetscount = 0;\n    this.__singlerow = true;\n    this.__columncontainers = [];\n\n    this.__items_dirty = true;\n\n    // PRIVATE VARS!!\n    this.__leftoffset = 0;\n    this.__containerwidth = 0;\n    this.__widgetrecs = [];\n    this.ignore_resize_events = false;\n\n    this.refresh();\n  }\n\n  setOptions(options) {\n    if (\"gutter\" in options) {\n      options.gutter_x = options.gutter;\n      options.gutter_y = options.gutter;\n      delete options.gutter;\n    }\n\n    if (\"items\" in options)\n      this.__items_dirty = true; // need to recheck all widgets, there might be new ones\n\n    Object.assign(this.options, options);\n  }\n\n  /** @short full relayout\n      @long find all items, detect width, read data-cols attributes on items and relayout\n  */\n  refresh(force) {\n    if (this.options.debug) {\n      console.log(\"$wh.Masonry.refresh()\");\n      console.trace();\n    }\n\n    const clientwidth = this.container.clientWidth;\n    if (clientwidth == 0) {\n      console.warn(\"Cannot determine size of mansonry container (got 0).\", this.container);\n      return;\n    }\n\n    this.ignore_resize_events = true;\n\n    // FIXME: assuming padding in px\n    // FIXME: assuming correct box-sizing\n    // FIXME: assumption that this container (with the padding) is also the positioning container\n    const cstyle = window.getComputedStyle(this.container);\n    const padtop = parseInt(cstyle.paddingTop, 10);\n    const padbottom = parseInt(cstyle.paddingBottom, 10);\n    const padleft = parseInt(cstyle.paddingLeft, 10);\n    const padright = parseInt(cstyle.paddingRight, 10);\n    this.__padding = {\n      top: padtop,\n      bottom: padbottom,\n      left: padleft,\n      right: padright\n    };\n    //console.log(this.container, this.__padding);\n\n    this.__leftoffset = padleft;\n    this.__containerwidth = clientwidth - padleft - padright;\n\n    let widgets;\n    if (!this.options.items)\n      widgets = this.container.querySelectorAll(\".wh-masonry-item\");\n    else if (typeof (this.options.items) === \"string\")\n      widgets = this.container.querySelectorAll(this.options.items);\n    else\n      widgets = this.options.items;\n\n    this.pvt_relayout(widgets, force);\n\n    this.ignore_resize_events = false;\n  }\n\n  /** @short only update heights and position\n             New items and changed widths aren't detected\n  */\n  refreshHeights() {\n    this.pvt_relayout(null, true);\n  }\n\n  getLastRenderInfo() {\n    return {\n      container: this.container,\n      visiblewidgetscount: this.__visiblewidgetscount,\n      width: this.__containerwidth,\n      height: this.__height,\n      items: this.__itemdata,\n      singlerow: this.__singlerow\n    };\n  }\n\n\n  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n  //\n  //  Private functions\n  //\n\n  //, __padding: 0\n\n  // update through on of our components using $wh.fireLayoutChangeEvent\n  onLayoutChange(elem) {\n    //console.log(\"event for\", elem);\n\n    // regardless of the direction we will also receive the event on the element it's fired on\n    if (elem == this.container) {\n      //  console.log(\"ignore\");\n      return;\n    }\n\n    this.refreshHeights();\n  }\n\n  pvt_relayout(widgets, force) {\n    if (this.options.debug)\n      console.group(\"$wh.Masonry.refresh()\", force ? \"FORCE\" : \"\");\n\n    let visiblewidgetscount = 0;\n\n    let columnwidth = this.options.columnwidth;\n    if (!columnwidth)\n      columnwidth = (this.__containerwidth - (this.options.columns - 1) * this.options.gutter_x) / this.options.columns;\n\n    const columncount = this.options.columns;\n    let singlerow = true; // until we have to place a new widget below another one all widgets are still on a single row\n\n    const columns = []; // the last Y position in use per column\n    for (var xcol = 0; xcol < columncount; xcol++)\n      columns.push(0);\n\n    /*\n    console.log({ columns:     this.options.columns\n                , columnwidth: columnwidth\n                });\n    */\n\n    let widgetrecs;\n\n\n\n    // Only change widget width's when needed\n    const dirty = this.__items_dirty || this.__columnwidth != columnwidth;\n    if (dirty) // new items or width for widgets need to change?\n    {\n      widgetrecs = [];\n      // First apply the new width to all widgets, so we can later determine the correct height\n      for (var idx = 0; idx < widgets.length; idx++) {\n        var widget = widgets[idx];\n\n        let widgetcols = widget.getAttribute(\"data-cols\");\n        widgetcols = widgetcols ? parseInt(widgetcols) : 1;\n\n        if (widgetcols > this.options.columns)\n          widgetcols = this.options.columns;\n\n        const width = columnwidth * widgetcols + (widgetcols - 1) * this.options.gutter_x;\n\n        widget.style.position = \"absolute\";\n        widget.style.width = width + \"px\";\n        widget.style.height = \"\"; // clear any inline specified height (we only allow a fixed height if specified in CSS)\n\n        widgetrecs.push(\n          {\n            node: widget,\n            width: width,\n            height: null,\n            cols: widgetcols\n          });\n      }\n    } else {\n      widgetrecs = this.__itemdata;\n    }\n\n    // We force widgets to relayout if we are dirty or force is used\n    // (force is usefull in case a load, custom font load or CSS load event was detected)\n    if (dirty || force) {\n      /*\n      Let our children relayout to match our new width\n      (after which layout of masonry item contents should be done, meaning the height is known and we can start to build up the masonry)\n      */\n      if (this.options.debug)\n        console.log(\"Firing ws:relayoutwidgetcontent event\");\n\n      // Notify any of our components within the Masonry container that layout has changed.\n      // After they have updated their layout we know the final height of each widget and can start to layout our Masonry.\n\n      for (var idx = 0; idx < widgets.length; idx++) {\n        var widget = widgets[idx];\n        // Inform widgets without our masonry grid to relayout\n        // (due to a change in the width)\n        dompack.dispatchCustomEvent(widget, \"ws:relayoutwidgetcontent\",\n          {\n            bubbles: true,\n            cancelable: false,\n            detail: { force: force } // let our child content also know we want to force relayouting\n          });\n      }\n\n      if (this.options.debug)\n        console.log(\"Continue dompack-masonry layouting.\");\n    }\n\n\n\n    // measure all widgets in one go to prevent extreneous reflows by mixing writes and reads\n    for (var idx = 0; idx < widgetrecs.length; idx++)\n      widgetrecs[idx].height = widgetrecs[idx].node.clientHeight;\n\n\n\n    for (var idx = 0; idx < widgetrecs.length; idx++) {\n      const widgetrec = widgetrecs[idx];\n      var widget = widgetrec.node;\n\n      const widgetheight = widgetrec.height;\n\n      if (this.options.debug)\n        console.log(\"#\" + idx, widgetheight + \"px\", widget.className);\n\n      if (widgetheight == 0 || (this.options.ignoreclass != \"\" && widget.classList.contains(this.options.ignoreclass)))\n        continue;\n\n      visiblewidgetscount++;\n\n      let bestcol = -1, ypos = 0;\n\n      // set increase the last used ypos within the columns the current widget will occupy\n      // find the first ypos where the whole block would fit\n      if (this.options.debug)\n        console.info(columns);\n\n      for (var xcol = 0; xcol <= columncount - widgetrec.cols; ++xcol) {\n        var col = this.options.righttoleft ? columncount - widgetrec.cols - xcol : xcol;\n\n        const maxypos = Math.max.apply(null, columns.slice(col, col + widgetrec.cols));\n        //console.log(col, \"has enough room for \", widgetrec.cols, \" columns starting at Y pos\", maxypos);\n\n        // if we cannot find any column in which we can place the block,\n        // move to below where all previous block are\n        if (bestcol == -1 || maxypos < ypos) {\n          //          console.log(widgetrec, maxypos, ypos);\n          bestcol = col;\n          ypos = maxypos;\n        }\n      }\n\n      //console.log(\"We select column\", bestcol);\n\n      if (columns[bestcol] > 0) {\n        if (ypos > 0)\n          singlerow = false;\n\n        ypos += this.options.gutter_y;\n      }\n\n      for (var col = 0; col < widgetrec.cols; ++col) {\n        const nextypos = ypos + widgetheight;\n        columns[bestcol + col] = nextypos;\n      }\n\n      widgetrec.col = bestcol;\n      widgetrec.left = this.__leftoffset + (bestcol * columnwidth + (bestcol) * this.options.gutter_x);\n      widgetrec.top = ypos;\n\n      const styles = {\n        position: \"absolute\",\n        left: widgetrec.left, // 300 width, 10 px leftmargin, 20 inter\n        top: widgetrec.top + this.__padding.top\n        //, width:    columnwidth * widgetrec.cols + (widgetrec.cols-1) * this.options.gutter_x\n      };\n\n      if (this.options.debug)\n        console.log(\"Will be placed into col\", bestcol);\n\n      widget.style.position = styles.position;\n      widget.style.left = styles.left + \"px\";\n      widget.style.top = styles.top + \"px\";\n    }\n\n    const maxheight = Math.max.apply(null, columns) + this.__padding.top + this.__padding.bottom;\n\n    //reorderWidgets(keepcolumnpos);\n    if (this.options.columnwidth)\n      this.container.style.width = (this.options.columnwidth * this.options.columns + (this.options.columns - 1) * this.options.gutter_x) + \"px\";\n\n    this.container.style.height = maxheight + \"px\";\n\n    /*\n        // Now we want our parents to know we have changed in size\n        // FIXME: add a check whether we actually changed in size\n        if (this.options.debug)\n          console.log(\"Firing layout change event\");\n    \n        $wh.fireLayoutChangeEvent(this.container, \"up\"); // FIXME\n    */\n\n    if (this.options.debug) {\n      console.log(this.container, \"has\", visiblewidgetscount, \"visible widgets\");\n      console.groupEnd();\n    }\n\n    /*\n    store render information (can be used to add extra behaviour outside this class for example:\n    - to equalize heights of widgets by external code or hide a widgets grid\n    - to hide a widgets container in case it has no visible widgets\n    */\n    this.__itemdata = widgetrecs;\n    this.__columnwidth = columnwidth;\n    this.__height = maxheight;\n    this.__visiblewidgetscount = visiblewidgetscount;\n    this.__singlerow = singlerow;\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n// Relayout the widget masonry if a widget was resized\nexport function relayoutWidgets(widgetnode) {\n  dompack.dispatchCustomEvent(window, \"ws:relayoutwidgets\",\n    {\n      bubbles: true,\n      cancelable: false,\n      detail: { container: widgetnode ? widgetnode.closest(\".widgetsblock__contents\") : null }\n    });\n}\nwindow.__relayoutWidgets = relayoutWidgets;\n\nexport function forceRelayoutWidgets(widgetnode) {\n  dompack.dispatchCustomEvent(window, \"ws:relayoutwidgets\",\n    {\n      bubbles: true,\n      cancelable: false,\n      detail: {\n        container: widgetnode ? widgetnode.closest(\".widgetsblock__contents\") : null,\n        force: true\n      }\n    });\n}\n","import utwenteCookies from \"@mod-utwente_design/js/cookiebar\";\nimport { getTid } from \"@webhare/gettid\";\nimport * as dompack from '@webhare/dompack';\nimport './consentcheck.scss';\n\nfunction setConsentLayers() {\n  for (const node of dompack.qSA(\"*[data-needsconsent],.wh-video.wh-requireconsent\")) {\n    // console.info(\"setConsentLayer\", node.dataset.needsconsent, \"for node\", node);\n\n    let shieldnode = node.querySelector(\".consentblocker\");\n    if (shieldnode)//already added\n      continue;\n\n    if (node.dataset.needsconsent === \"video\" || node.matches('.wh-video')) {\n      let directlink = \"\";\n      let network = \"\";\n\n      const infocode = node.dataset.needsconsent === \"video\" ? dompack.qS(node, \"[data-video]\")?.dataset.video : node.dataset.whVideo;\n\n      if (infocode) {\n        const info = JSON.parse(infocode);\n        network = info.network;\n\n        if (network === \"youtube\") {\n          network = \"YouTube\";\n          directlink = \"https://youtu.be/\" + info.id;\n        } else if (network === \"vimeo\") {\n          network = \"Vimeo\";\n          directlink = \"https://vimeo.com/\" + info.id;\n        } else if (network === \"yuja\") {\n          // Yuja only uses functional cookies (no tracking), so we don't need to block\n          continue;\n        }\n      }\n\n      shieldnode = <div class=\"consentblocker\">\n        <div class=\"consentblocker__title\">{getTid(\"utwente_base:frontend.ws2016.js.consentblock-video-title\")}</div>\n        <div class=\"consentblocker__description\">\n          {getTid(\"utwente_base:frontend.ws2016.js.consentblock-video-line1\", network) + \" \"}\n          <a href=\"#accept\">{getTid(\"utwente_base:frontend.ws2016.js.consentblock-accept3thpartycookies\")}</a>\n          {' ' + getTid(\"utwente_base:frontend.ws2016.js.consentblock-video-accept3thpartycookies-suffix\")}\n          {directlink\n            ? <span>\n              {\" \" + getTid(\"utwente_base:frontend.ws2016.js.consentblock-video-directlink-prefix\") + \" \"}\n              <a target=\"_blank\" rel=\"noopener noreferrer\" href={directlink}>{getTid(\"utwente_base:frontend.ws2016.js.consentblock-video-directlink\", network)}</a>\n            </span>\n            : null\n          }\n        </div>\n      </div>;\n    } else if (node.dataset.needsconsent === \"soundcloud\") {\n      let playername = \"SoundCloud\";\n      if (node.dataset.provider && node.dataset.provider === \"transistor\")\n        playername = \"Transistor\";\n\n      shieldnode = <div class=\"consentblocker\">\n        <div class=\"consentblocker__title\">{getTid(\"utwente_base:frontend.ws2016.js.consentblock-soundcloud-title\")}</div>\n        <div class=\"consentblocker__description\">\n          {getTid(\"utwente_base:frontend.ws2016.js.consentblock-soundcloud-line1\", playername) + ' '}\n          <a href=\"#accept\">{getTid(\"utwente_base:frontend.ws2016.js.consentblock-accept3thpartycookies\")}</a>\n          {' ' + getTid(\"utwente_base:frontend.ws2016.js.consentblock-soundcloud-accept3thpartycookies-suffix\")}\n          {node.dataset.directlink\n            ? <span>\n              {\" \" + getTid(\"utwente_base:frontend.ws2016.js.consentblock-soundcloud-directlink-prefix\") + \" \"}\n              <a target=\"_blank\" rel=\"noopener noreferrer\" href={node.dataset.directlink}>{getTid(\"utwente_base:frontend.ws2016.js.consentblock-soundcloud-directlink\")}</a>\n            </span>\n            : null\n          }\n        </div>\n      </div>;\n    } else if (node.dataset.needsconsent === \"facebook\") {\n      node.replaceChildren(); //empty it\n      shieldnode = <div class=\"consentblocker\">\n        <div class=\"consentblocker__title\">{getTid(\"utwente_base:frontend.ws2016.js.consentblock-facebook-title\")}</div>\n        <div class=\"consentblocker__description\">\n          {getTid(\"utwente_base:frontend.ws2016.js.consentblock-facebook-line1\") + ' '}\n          <a href=\"#accept\">{getTid(\"utwente_base:frontend.ws2016.js.consentblock-accept3thpartycookies\")}</a>\n          {' ' + getTid(\"utwente_base:frontend.ws2016.js.consentblock-facebook-accept3thpartycookies-suffix\")}\n        </div>\n      </div>;\n    } else if (node.dataset.needsconsent === \"twitter-embed\") {\n      shieldnode = getTwitterConsentlayer();\n    }\n\n\n    if (shieldnode) {\n      // console.info(\"Inserting shieldnode\", shieldnode);\n      shieldnode.addEventListener(\"click\", ev => onShieldNodeClick(ev));\n      node.appendChild(shieldnode);\n    }\n  }\n}\n\n\nfunction onShieldNodeClick(ev: Event) {\n  ev.stopPropagation();\n  const link = dompack.isHTMLElement(ev.target) && ev.target.closest(\".consentblocker a\");\n  if (link) {\n    if (link.getAttribute(\"href\") === \"#accept\") {\n      ev.preventDefault();\n      utwenteCookies.acceptMarketingCookies();\n    }\n    return;\n  }\n  ev.preventDefault();\n}\n\n\nfunction getTwitterConsentlayer() {\n  const node =\n    <div class=\"consentblocker\">\n      <div class=\"consentblocker__description\">\n        {getTid(\"utwente_base:frontend.ws2016.js.consentblock-twitterembed-line1\") + ' '}\n        <a href=\"#accept\">{getTid(\"utwente_base:frontend.ws2016.js.consentblock-accept3thpartycookies\")}</a>\n        {' ' + getTid(\"utwente_base:frontend.ws2016.js.consentblock-twitterembed-accept3thpartycookies-suffix\")}\n      </div>\n    </div>;\n\n  return node;\n}\n\n\n\n\n/*\n\nhttps://www.facebook.com/v7.0/plugins/page.php?adapt_container_width=true&app_id=113869198637480&channel=https%3A%2F%2Fstaticxx.facebook.com%2Fx%2Fconnect%2Fxd_arbiter%2F%3Fversion%3D46%23cb%3Df2005fcb13555e8%26domain%3Ddevelopers.facebook.com%26origin%3Dhttps%253A%252F%252Fdevelopers.facebook.com%252Ff1487e3ace22ef8%26relation%3Dparent.parent&container_width=735&hide_cover=false&href=https%3A%2F%2Fwww.facebook.com%2Ffantasyfair%2F&locale=en_US&sdk=joey&show_facepile=true&small_header=false&tabs=timeline%2C%20events%2C%20messages\n*/\nfunction removeConsentLayers() {\n  for (const node of dompack.qSA(\"*[data-needsconsent], .wh-video.wh-requireconsent\")) {\n    //remove overlay with warning text\n    node.querySelector(\".consentblocker\")?.remove();\n  }\n}\n\ndompack.onDomReady(() => {\n  if (!utwenteCookies.getConsent())\n    setConsentLayers();\n  else\n    removeConsentLayers();\n\n  document.addEventListener(\"wh:consent-change\", ev => {\n    if (!utwenteCookies.getConsent())\n      setConsentLayers();\n    else\n      removeConsentLayers();\n  });\n});\n","import { setupCookieWidget } from \"@mod-utwente_design/js/cookiebar\";\nimport \"./widgets-homepage.css\";\nimport \"@mod-utwente_design/js/crm/consenthandler\";\nimport { register } from \"@webhare/dompack\";\n\nregister<HTMLFormElement>(\".ut-cookiewidget\", setupCookieWidget);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\nimport * as dompack from \"dompack\";\nimport \"./countdown.css\";\n\ntype onExpiredCallbackFunction = () => void;\n\nexport class CountDownComponent {\n  node: HTMLElement;\n  node_day: HTMLElement;\n  node_daydigits: HTMLElement[];\n  node_hours: HTMLElement;\n  node_hourdigits: HTMLElement[];\n  node_minutes: HTMLElement;\n  node_minutedigits: HTMLElement[];\n  node_seconds: HTMLElement;\n  node_seconddigits: HTMLElement[];\n  node_digits: HTMLElement[]; // HTMLCollection;// NodeList;\n  animframetimer: null | number = null;\n  options: {\n    countdownto: \"\";\n    countdownfrom: \"\";\n    onexpired: onExpiredCallbackFunction | null; //Function;\n  };\n\n  countdownvalue: {\n    days: number;\n    hours: number;\n    minutes: number;\n    seconds: number;\n    expired: boolean;\n  } | null = null;\n  countdownto: string = \"\";\n  countdownfrom: string = \"\";\n  countdownto_timestamp: number = 0; // Timestamp\n  countdownfrom_timestamp: number = 0; // Timestamp\n\n  previousroundedtime: number = 0;\n  /*\n  this.countdownvalue =\n  { days:    0\n  , hours:   0\n  , minutes: 0\n  , seconds: 0\n  , expired: true\n  };\n  */\n\n  debug: boolean;\n  initialized: boolean = false;\n\n\n  constructor(node: HTMLElement, options: { countdownto?: string; onexpired?: onExpiredCallbackFunction | null }) {\n    this.node = node;\n\n    this.debug = node.hasAttribute(\"data-debugcountdown\");\n\n    const mergedOptions = {\n      countdownto: \"\",\n      countdownfrom: \"\",\n      onexpired: null,\n      ...options\n    };\n    this.options = mergedOptions;\n\n    if (this.debug)\n      console.log(\"[CountDownComponent] initializing\", options);\n\n    this.node_day = node.querySelector(\".countdown__section--days\") as HTMLElement;\n    this.node_daydigits = Array.from(this.node_day.querySelectorAll(\".countdown__digit\"));\n    this.node_hours = node.querySelector(\".countdown__section--hours\") as HTMLElement;\n    this.node_hourdigits = Array.from(this.node_hours.querySelectorAll(\".countdown__digit\"));\n    this.node_minutes = node.querySelector(\".countdown__section--minutes\") as HTMLElement;\n    this.node_minutedigits = Array.from(this.node_minutes.querySelectorAll(\".countdown__digit\"));\n    this.node_seconds = node.querySelector(\".countdown__section--seconds\") as HTMLElement;\n    this.node_seconddigits = Array.from(this.node_seconds.querySelectorAll(\".countdown__digit\"));\n\n    this.node_digits = Array.from(node.querySelectorAll(\".countdown__digit\"));\n\n    if (this.debug)\n      console.info(\"[CountDownComponent] Counting down to %s\", node.dataset.countdownto, this.countdownto_timestamp);\n\n    this.enhanceDOM();\n\n    if (options.countdownfrom)\n      this.setCountdownFrom(options.countdownfrom);\n    else if (node.dataset.countdownfrom)\n      this.setCountdownFrom(node.dataset.countdownfrom);\n\n    if (options.countdownto)\n      this.setCountdownTo(options.countdownto);\n    else if (node.dataset.countdownto)\n      this.setCountdownTo(node.dataset.countdownto);\n    else\n      console.error(\"[CountDownComponent] initialized without setting options.countdownto or a data-countdownto attribute on .component-countdown\");\n\n    this.refreshAndScheduleNextFrame();\n\n    // FIXME: how to handle this with multiple events !!?\n    if (this.countdownvalue && this.countdownvalue.days === 0)\n      this.node_day.classList.add(\"countdown__section--initiallyleadingzero\");\n\n    node.classList.add(\"component-countdown--allowanimation\");\n\n    this.node.addEventListener(\"transitionend\", evt => this.onTransitionEnd(evt));\n    document.addEventListener(\"visibilitychange\", evt => this.onPageVisibilityChange(evt));\n\n    this.initialized = true;\n  }\n\n  setCountdownFrom(countdownfrom) {\n    this.countdownfrom = parseCountdownToString(countdownfrom);\n    this.countdownfrom_timestamp = this.countdownfrom.getTime();\n\n    if (this.countdownfrom_timestamp && new Date() < this.countdownfrom_timestamp) {\n      if (this.debug)\n        console.info(\"[CountDownComponent] The countdown has not started yet!\");\n\n      this.node.classList.add(\"component-countdown--before\");\n\n      // Solution for browsers which don't support :has\n      // If all browsers support this we could use .widget-countdown:has(.component-countdown--exired)\n      const specialcontainer = this.node.closest(\"[data-markifbefore]\");\n      if (specialcontainer)\n        specialcontainer.classList.add(\"has-before-countdown\");\n    }\n  }\n\n  setCountdownTo(countdownto) {\n    this.countdownto = parseCountdownToString(countdownto);\n    this.countdownto_timestamp = this.countdownto.getTime();\n    this.countdownvalue = null; // the next refresh() (called in onAnimFrame) will set this.countdownvalue again\n    this.previousroundedtime = 0; // timestamp used last time for drawing the countdown\n\n    this.node.classList.remove(\"component-countdown--expired\");\n\n    // refreshing is meant for when external code calls setCountdownTo().\n    // When we call setCountdownTo() during initialization we aren't ready yet for this.\n    if (this.initialized)\n      this.refreshAndScheduleNextFrame();\n  }\n\n  stopCountdown() {\n    if (!this.animframetimer)\n      return;\n\n    cancelAnimationFrame(this.animframetimer);\n    this.animframetimer = null;\n  }\n\n  onPageVisibilityChange(evt) {\n    if (document.visibilityState === \"hidden\") {\n      this.node.classList.remove(\"component-countdown--allowanimation\");\n      return;\n    }\n\n    // When returning to a previous invisible page CSS will be computed again and transitions will\n    // we triggered which were meant to have been finished earlyer.\n    // To prevent this whe'll disable transitions for a moment.\n    if (document.visibilityState === \"visible\") {\n      // Fix any zero's which we haven't moved\n      // (because we useually do this in the transitionend, but transitions aren't done\n      // while the document isn't visible (tab hidden or browser window minimized)\n      for (const digitnode of this.node_digits) {\n        if (digitnode.firstElementChild!.__countdown_value! === 0) {\n          const wrapidx = this.__getWrapDigitIDX(digitnode);\n          this.setTrackPosition(digitnode, wrapidx);\n        }\n      }\n\n      requestAnimationFrame(this.reenableTransitions.bind(this));\n    }\n  }\n\n  reenableTransitions() {\n    // first frame after we became visible.\n    // This animation frame will trigger a transition if we directly enable transitions,\n    // so whe'll delay until the next one.\n    requestAnimationFrame(this.reenableTransitions2.bind(this));\n  }\n\n  reenableTransitions2() {\n    this.node.classList.add(\"component-countdown--allowanimation\");\n  }\n\n\n\n  onAnimFrame(evt) {\n    this.animframetimer = null;\n    this.refreshAndScheduleNextFrame();\n  }\n\n  refreshAndScheduleNextFrame() {\n    this.refresh();\n\n    if (!this.animframetimer\n      && (!this.countdownvalue // first frame for the current countdown value (so no value available yet)\n        || !this.countdownvalue.expired)) {\n      this.animframetimer = requestAnimationFrame(this.onAnimFrame.bind(this));\n    }\n  }\n\n  refresh() {\n    const now = new Date();\n    let now_timestamp = now.getTime();\n\n    if (now_timestamp % 1000 > 950)\n      now_timestamp += 1000 - now_timestamp % 1000;\n    else\n      now_timestamp = now_timestamp - now_timestamp % 1000;\n\n    if (now_timestamp === this.previousroundedtime)\n      return;\n\n    this.previousroundedtime = now_timestamp;\n    this.refreshFor(now_timestamp);\n  }\n\n  refreshFor(now) {\n    // console.info(\"refreshFor\", now);\n    if (this.node.classList.contains(\"component-countdown--before\")) {\n      if (this.countdownfrom_timestamp && now >= this.countdownfrom_timestamp) {\n        if (this.debug)\n          console.info(\"[CountDownComponent] The countdown starts now!\");\n\n        this.node.classList.remove(\"component-countdown--before\");\n\n        // Solution for browsers which don't support :has\n        // If all browsers support this we could use .widget-countdown:has(.component-countdown--exired)\n        const specialcontainer = this.node.closest(\"[data-markifbefore]\");\n        if (specialcontainer)\n          specialcontainer.classList.remove(\"has-before-countdown\");\n      } else {\n        // Still before the countdown start date\n        return;\n      }\n\n    }\n\n    if (now > this.countdownto_timestamp) {\n      if (this.debug)\n        console.info(\"[CountDownComponent] The countdown has expired!\");\n\n      this.node.classList.add(\"component-countdown--expired\");\n\n      // Solution for browsers which don't support :has\n      // If all browsers support this we could use .widget-countdown:has(.component-countdown--exired)\n      const specialcontainer = this.node.closest(\"[data-markifexpired]\");\n      if (specialcontainer)\n        specialcontainer.classList.add(\"has-expired-countdown\");\n\n      this.countdownvalue =\n      {\n        days: 0,\n        hours: 0,\n        minutes: 0,\n        seconds: 0,\n        expired: true\n      };\n\n      if (this.options.onexpired)\n        this.options.onexpired();\n\n      return;\n    }\n\n    const distance = this.countdownto_timestamp - now;\n\n    // Time calculations for days, hours, minutes and seconds\n    const days = Math.floor(distance / (1000 * 60 * 60 * 24));\n    const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));\n    const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));\n    const seconds = Math.floor((distance % (1000 * 60)) / 1000);\n\n    this.node_day.classList.toggle(\"leadingzeros\", days === 0);\n    this.node_hours.classList.toggle(\"leadingzeros\", days === 0 && hours === 0);\n    this.node_minutes.classList.toggle(\"leadingzeros\", days === 0 && hours === 0 && minutes === 0);\n    this.node_seconds.classList.toggle(\"leadingzeros\", days === 0 && hours === 0 && minutes === 0 && seconds === 0);\n\n    const digits =\n      [\n        Math.floor(days / 100),      // day X..\n        Math.floor(days / 10) % 10,  // day .X.\n        days % 10,                   // day ..X\n\n        Math.floor(hours / 10),\n        hours % 10,\n\n        Math.floor(minutes / 10),\n        minutes % 10,\n\n        Math.floor(seconds / 10),\n        seconds % 10\n      ];\n\n    let idx = 0;\n    let leadingzero = true;\n    let initially_visible_digits = 0;\n\n    for (const digitnr of digits) {\n      void digitnr; // FIXME: just to stop eslint from complaining - but may we should use for with a counter instead?\n      const value = digits[idx];\n      if (value > 0)\n        leadingzero = false;\n\n      if (!leadingzero)\n        initially_visible_digits++;\n\n      const digitnode = this.node_digits[idx];\n\n      // Especially for days we may want to hide the digits which will start at 0\n      if (!this.initialized && leadingzero)\n        this.node_digits[idx].classList.toggle(\"countdown__digit--initiallyleadingzero\", leadingzero);\n\n      // Prevent basing the DOM with unnessecary updates\n      // AND prevent scrolling back from the 2nd zero to the first zero.\n      if (digitnode.firstElementChild!.__countdown_value !== value) {\n        this.setDigit(digitnode, value);\n        this.node_digits[idx].classList.toggle(\"countdown__digit--leadingzero\", leadingzero);\n      }\n\n      idx++;\n    }\n\n    this.node.setAttribute(\"data-initiallyvisibledigits\", initially_visible_digits.toString());\n\n    this.countdownvalue =\n    {\n      days: days,\n      hours: hours,\n      minutes: minutes,\n      seconds: seconds,\n      expired: false\n    };\n\n    if (this.debug)\n      console.info(\"[CountDownComponent]\", this.countdownvalue);\n  }\n\n  setDigit(node: HTMLElement, number: number) {\n    node.firstElementChild.__countdown_value = number;\n    node.setAttribute(\"data-countvalue\", number);\n    this.__shiftTrack(node, number);\n  }\n\n  __shiftTrack(node, amount) {\n    /*\n    We need to go to the wrapping digit if:\n    - we start at 0 (during initialization)\n    - the document/browser-tab isn't visible (because whe're hidden there'll be no transition or transitionend event)\n    */\n    if (amount === 0 && (!this.initialized || document.visibilityState === \"hidden\"))\n      amount = this.__getWrapDigitIDX(node);\n\n    this.setTrackPosition(node, amount);\n  }\n\n  __getWrapDigitIDX(node: HTMLElement) {\n    // console.log(\"Because document isn't visible whe'll directly move to the 2nd zero\");\n    //this.__shiftTrack(digitcontainer, 10); // shift to the 2nd occurence of 0 so we can scroll back up to 9 again\n    const digitdesc = node.getAttribute(\"data-digit\");\n    if (digitdesc === \"minutes-ten\" || digitdesc === \"seconds-ten\")\n      return 6;\n    else if (digitdesc === \"hours-ten\")\n      return 3;\n    else\n      return 10;\n  }\n\n  setTrackPositionToWrapDigit(node: HTMLElement) {\n    const position = this.__getWrapDigitIDX(node);\n    this.setTrackPosition(node, position);\n  }\n\n  setTrackPosition(node: HTMLElement, amount: number) {\n    const value = `translateY(calc(-${100 * amount}% - ${amount}px))`;\n    node.firstElementChild.style.transform = value;\n    node.firstElementChild.__countdown_digitidx = amount;\n  }\n\n  onTransitionEnd(evt) {\n    /*\n    let digit_idx = Array.from(this.node_digits).indexOf(evt.target.parentNode);\n    console.info(\"transitionend for\", evt.target, digit_idx, evt.target.__countdown_value);\n    */\n\n    // When our transition landed on a 0\n    if (evt.target.__countdown_value === 0) {\n      /* Shift any digit which stopped their transition landing on a zero\n         to the second occurence of zero at the bottom of the track.\n         This ensures we can continue scroll up as if our scroller wraps. */\n      const tracknode = evt.target;\n      const digitcontainer = tracknode.parentNode;\n\n      if (document.hidden) {\n        // shift to the 2nd occurence of 0 so we can scroll back up to 9 again\n        this.setTrackPositionToWrapDigit(digitcontainer);\n      } else {\n        tracknode.style.transition = \"none\";\n\n        // shift to the 2nd occurence of 0 so we can scroll back up to 9 again\n        this.setTrackPositionToWrapDigit(digitcontainer);\n\n        setTimeout(() => { tracknode.style.transition = \"\"; });\n      }\n    }\n  }\n\n  enhanceDOM() {\n    const digits = this.node.querySelectorAll(\".countdown__digit\");\n\n    const frag_alldigits = this.getDigitsFragment([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);\n    const frag_lessdigits = this.getDigitsFragment([0, 1, 2, 3, 4, 5, 0]); // seconds and minutes only go up to 59\n    const frag_digits_hourstens = this.getDigitsFragment([0, 1, 2, 0]); // hours only goes up to 23\n\n    for (const digit of digits) {\n      const digitdesc = digit.getAttribute(\"data-digit\");\n\n      let frag;\n      if (digitdesc === \"minutes-ten\" || digitdesc === \"seconds-ten\")\n        frag = frag_lessdigits;\n      else if (digitdesc === \"hours-ten\")\n        frag = frag_digits_hourstens;\n      else\n        frag = frag_alldigits;\n\n      digit.replaceChild(frag.cloneNode(true), digit.firstChild);\n    }\n  }\n\n  getDigitsFragment(nrs: number[]) {\n    /*\n    Create digits DOM which we can clone/copy into each digit container.\n    These are the numbers we can scroll.\n    By adding an extra 0 we can animate from the last number (9 or 5) to the 0\n    and after the transition finished jump back to the 0 at the top\n    so it seems the counter wraps endlessly.\n    */\n    const frag = document.createDocumentFragment();\n    const paper = document.createElement(\"div\"); // container which we move through the .countdown__digit viewport/track\n    paper.className = \"countdown__digit__track\";\n    frag.appendChild(paper);\n\n\n    // 0 to 9\n    for (const current_nr of nrs) {\n      const digitnode = document.createElement(\"div\");\n      digitnode.className = \"countdown__digit__number\";\n      digitnode.innerText = current_nr.toString();\n      paper.appendChild(digitnode);\n    }\n\n    return frag;\n  }\n}\n\n\nexport function parseCountdownToString(str: string) {\n  // console.info(\"parseCountdownToString\", str);\n  const parts = str.split(\" \");\n  const dayparts = parts[0].split(\"-\");\n  const timeparts = parts[1].split(\":\");\n  const date = new Date(dayparts[0], dayparts[1] - 1, dayparts[2], timeparts[0], timeparts[1]);\n  // console.log(date);\n  return date;\n}\n\n\n\n\ndompack.register(\".component-countdown[data-countdownto]\", initCountdownComponent);\n\n\nfunction initCountdownComponent(node: HTMLElement) {\n  new CountDownComponent(node, {});\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n/*\nFIXME: do we need to use the servertime to ensure the correct countdown (even if the datetime on the computer is messed up) ?\n\nNOTES:\n- countdown components will auto-initialize if they have a data-countdownto attribute\n\n\n[data-markifexpired]\n*/\nimport \"./countdown-widget.css\";\nimport \"./countdown-eventslist.css\";\nimport * as countdown from \"@mod-utwente_base/webfeatures/utcomponents/countdown\";\nimport * as dompack from \"dompack\";\n\n\n\n\n\n\n/*\nGlobal working of the \"Countdown (with events)\" widget\n- The widget will gather the event information attached as JSON to each event (.component-ctalinks__item)\n- We don't specify data-countdownto on .component-countdown so it won't autoinitialize\n  (leaving our CountDownEventsWidget to handle which event we start with)\n- The widget will update all .widget-countdown-expireditem classes\n  (upon initialization and each time after the CountDownComponent used the onexpired callback)\n- The widget will control to which event to count (which is next in time)\n- Only when the enddate of the last event has expired, the expired panel will be shown\n- The \".addeventatc\" class is the triger for AddEvent\n\nWorkin of \"Add to calendar\" functionality\n- The \"Add to calendar\" button will only add the event which we currently count down to\n- Each event in the list contains a <div class=\"addevent-data\" style=\"display:none\">\n  which contains the information for AddEvent.\n  When a countdown is started for an event, the innerHTML of this element will be copied\n  to \".widget-countdown__addtocalendar .addevent-data\"\n*/\nclass CountDownEventsWidget {\n  constructor(node) {\n    console.info(\"[CountDownEventsWidget] Welcome\");\n\n    this.node = node;\n\n    this.events = [];\n    this.currentevent = null;\n\n    this.counter = null;\n    this.countdownnode = node.querySelector(\".component-countdown\");\n\n    const now = new Date();\n\n    this.eventnodes = this.node.querySelectorAll(\".component-ctalinks__item\");\n    for (const eventnode of this.eventnodes) {\n      const eventdata = JSON.parse(eventnode.dataset.event);\n\n      this.events.push(\n        {\n          node: eventnode,\n          ...eventdata,\n          countdownto_start_dt: countdown.parseCountdownToString(eventdata.countdownto_start),\n          countdownto_end_dt: countdown.parseCountdownToString(eventdata.countdownto_end),\n          expired: now > eventdata.countdownto_end_dt\n        });\n    }\n\n    this.refresh();\n  }\n\n  refresh() {\n    const now = new Date();\n\n    let firstupcomingevent = null;\n\n    // The events are sorted by date so we can assume the first event with\n    // the startdate in the future is the \"first upcoming event\"\n    for (const eventdata of this.events) {\n      if (eventdata.expired)\n        continue;\n\n      if (now > eventdata.countdownto_end_dt)\n        eventdata.node.classList.add(\"widget-countdown-expireditem\");\n      else if (!firstupcomingevent)\n        firstupcomingevent = eventdata;\n    }\n\n    // Start countdown for the first upcoming event\n    if (firstupcomingevent) {\n      firstupcomingevent.node.classList.add(\"widget-countdown-countingdownto\");\n\n      this.currentevent = firstupcomingevent; // set before initializing, in case expiry is triggered directly when initializing\n\n\n      // Update the \"Add to calendar\" button\n      // With the DOM addevent.com needs.\n      const addevent_data_container = this.node.querySelector(\".widget-countdown__addtocalendar .addevent-data\");\n      if (addevent_data_container)\n        addevent_data_container.innerHTML = firstupcomingevent.node.querySelector(\".addevent-data\").innerHTML;\n\n\n      if (!this.counter) {\n        console.info(\"Setting event (initializing countdown)\", firstupcomingevent);\n        this.counter = new countdown.CountDownComponent(this.countdownnode, {\n          countdownto: firstupcomingevent.countdownto_start,\n          onexpired: this.onCurrentCountdownExpired.bind(this)\n        });\n      } else {\n        console.info(\"Setting event (update countdown to new countdown target)\", firstupcomingevent);\n        this.counter.setCountdownTo(firstupcomingevent.countdownto_start);\n      }\n    } else {\n      this.node.classList.add(\"has-expired-countdown\");\n    }\n  }\n\n  onCurrentCountdownExpired() {\n    // console.info(\"Current countdown expired\");\n    this.currentevent.expired = true;\n    this.currentevent.node.classList.remove(\"widget-countdown-countingdownto\");\n    this.currentevent.node.classList.add(\"widget-countdown-expireditem\");\n    this.refresh();\n  }\n}\n\n// \"Countdown (with events)\" widget needs to handle multiple events\n// and control which event is count down to.\ndompack.register(\".widget-countdown--withevents\", initCountDownWidget);\n\nfunction initCountDownWidget(node) {\n  new CountDownEventsWidget(node);\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./events.scss\";\nimport * as dompack from \"dompack\";\nimport { relayoutWidgets } from \"../layout\";\n\nfunction renderEvents(node, items) {\n  if (items.length === 0) {\n    dompack.remove(node); //Just remove widget if no events\n    return;\n  }\n\n  const listnode = dompack.qS(node, \".widget__list\");\n  items.forEach(item => {\n    const link = node.dataset.baseurl ? node.dataset.baseurl + item.suburl : item.url;\n    listnode.appendChild(<a href={link} class=\"widget__listitem widget__listitem--link\">\n      <span class=\"widget__listitem-icon widget__listitem-icon--small UT-icon-UT_icon_52_arrow-right-round-16px\" />\n      <span class=\"widget__listitem-text\">{item.title}</span>\n      <span class=\"widget__listitem-subtext\">{item.widgetdate}</span>\n    </a>);\n  });\n\n  //Trigger ut masonry update\n  relayoutWidgets(node);\n}\n\nasync function getEventItems(node) {\n  const response = await fetch(node.dataset.publocfile);\n  if (response && response.status === 200) {\n    const items = await response.json();\n    if (items && items[\"p\" + node.dataset.publoc])\n      renderEvents(node, items[\"p\" + node.dataset.publoc].items);\n    else\n      dompack.remove(node); //Just remove widget if no events\n  }\n}\n\ndompack.register(\".widget-ws2016events\", node => getEventItems(node));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./faq.scss\";\n// import * as dompack from 'dompack';\n// import { foldableContent } from '@mod-utwente_design/js/foldablecontent';\nimport { RPCFormBase, registerHandler } from '@mod-publisher/js/forms';\n\nclass FeedbackForm extends RPCFormBase {\n  constructor(node) {\n    super(node);\n\n    this.container = this.node.closest(\".feedback\");\n\n    for (const inpnode of this.container.querySelectorAll(\"input[name='useful']\")) {\n      inpnode.addEventListener(\"change\", ev => {\n        this.ispositive = ev.target.value === \"yes\";\n        this.container.classList.add(this.ispositive ? \"feedback--ispositive\" : \"feedback--isnegative\");\n\n        if (!this.faqquestion) {\n          const faqnode = this.node.closest(\".wh-details\");\n          if (!faqnode)\n            return;\n          this.faqquestion = faqnode.querySelector(\".wh-details__summary\");\n        }\n\n        if (window.dataLayer)\n          window.dataLayer.push({ event: \"faq-\" + (this.ispositive ? \"ja\" : \"nee\"), \"faqcontent\": this.faqquestion.textContent });\n      });\n    }\n  }\n\n  getFormExtraSubmitData() {\n    return {\n      token: this.node.dataset.token,\n      faqquestion: this.faqquestion ? this.faqquestion.textContent : \"\"\n    };\n  }\n\n  onSubmitSuccess(res) {\n    if (res.success) {\n      this.reset();//empty form\n      this.container.classList.add(\"feedback--send\");\n    }\n  }\n}\n\nregisterHandler(\"utwente_base:faqfeedbackform\", node => new FeedbackForm(node));\n\n//dompack.register(\".embeddedobject-faq__list__item .wh-details\", node => new foldableContent(node, { gtmevent: node.dataset.gtmevent }));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n/*\n\nCarrouselContent V1.3 dev\nby Mark\n\nV1.1\n- can also act as a slideshow\n\nV1.2\n- improvements backported from utwente_base version\n  (createbullets and small tweaks)\n- options.onchangeslide\n\nV1.3 dev\n- Use of resizeObserver\n- detect scroll position not being in sync (fix debugging purposes)\n\n\nIssues which we havn't been able to reproduce and how\nwe intent to fix or find them:\n\n- Missing a resize (could happen if our container resizes due to changes made in code)\n  This should not happen anymore now we are using resizeObserver.\n\n- Missing a scroll event. This should only happen when our tab is invisible... and even then a browser\n  may fire a new scroll event when we return(??).\n  We've added an interval which checks for this and warns + fixes it - hopefully we can remove this workaround later\n  - Browser thinks tab/document isn't visible and doesn't trigger scroll events?\n  - Something canceling a scroll event?\n- rounding issue in measuring\n  This shouldn't happen...\n- rounding issue in scrollTo\n  We removed the Math.floor we did on the position of each page, so we can scroll to the exact subpixel.\n  This shouldn't have been an issue because the scrollsnap should snap to the exact position of the closest element.\n  Also the active page check checked for this rounded down number. If it went wrong we could expect it to detect a too high page number instead of too low(??).\n\n\n\nFIXME: Chrome 81 and newer resnap while resizing the window... However Firefox doesn't do this yet.\n       Let us force snapping to the current page upon resize?\n\nNOTE: For making an element work as <button> in an accessible way see: https://www.deque.com/blog/accessible-aria-buttons/\n\nUse the smoothscroll-polyfill (for Safari and IE) with this:\n- npm i smoothscroll-polyfill\n- import smoothscroll from 'smoothscroll-polyfill'; // For Safari, IE and Edge (works natively in Chrome, Firefox and iOS)\n- smoothscroll.polyfill();\n\n\n\nADDME: reschedule auto-slide after manual slide (to prevent direct autoslide after manually sliding)\n\nADDME: mutationobserver so we pick up new content (even though viewport_inner wasn't set or size didn't change)\n\n*/\nwindow.__carrouselcontent_instances = [];\n\n\n// Get the first carrousel which is in debug mode\nwindow.getCC = function () {\n  for (const block of window.__carrouselcontent_instances) {\n    if (block.instance.options.debug)\n      return block.instance;\n  }\n};\n\n\n\nclass CarrouselContent {\n  constructor(widgetnode, options) {\n    options =\n    {\n      viewport: \"\", // __itemswrapper - Viewport\n      viewport_inner: \"\", // __items - The container with the items, usually aligned to the content\n      itemsselector: \"\", // __item - Selector to find items to determine how to distribute them into pages\n      item_activeclass: \"\",\n      itemmeasureselector: \"\", // In case the element used in itemsselector has display:contents; or is inline (for example <a>) you might want to target a node within the item to measure\n\n      // Navigation UI\n      bulletscontainer: \"\", // __bullets - To find the container to create bullets into\n      bulletclass: \"\", // __bullet - The class for each bullet / jumpbutton\n      bulletselectedclass: \"\", // __bullet-selected - The class to add to a bullet which indicated a selected page\n      createbullet: null, // function which return a node for the bullet\n      previousbutton: null,\n      nextbutton: null,\n      allowwrap: false, // next on last page will go to the first, previous on the first page will go to the last\n\n      // Autoplay\n      autoplay: false,\n      autoplay_initialdelay: 0,       // delay the first start of autoplay to prevent having a lot of slideshows run in sync\n      autoplay_freezeslideduration: 6000, // how long to keep the slide still (FIXME: should be after the transition) before going to the next\n      transitionDuration: 1500,\n\n      debug: false,\n      debug_determineactivepage: false,\n\n      onchangeslide: null,\n      ...options\n    };\n\n    if (window.location.href.indexOf(\"debugcc\") > -1) {\n      options.debug = true;\n      options.debug_determineactivepage = true;\n    }\n\n    this.options = options;\n\n    if (this.options.debug)\n      console.log(\"[CarrouselContent] Options\", options);\n\n\n    this.prevactivepage = null;\n    this.activepage = 0;\n    this.pagesinfo = [];\n    this.scrollLeft = 0; // for debugging whether we get all scroll events\n\n\n\n    this.initAutoplayVars();\n\n\n    //console.log(\"CarrouselContent options\", options);\n\n    this.widgetnode = widgetnode;\n    //console.log(typeof(this.viewport), typeof(this.viewport) == \"string\");\n    if (typeof (options.viewport) === \"string\") {\n      this.viewport = widgetnode.querySelector(options.viewport);\n      if (!this.viewport)\n        console.error(options.viewport, \"not found in\", widgetnode);\n    }\n\n    if (typeof (options.viewport_inner) === \"string\") {\n      this.viewport_inner = widgetnode.querySelector(options.viewport_inner);\n      if (!this.viewport_inner)\n        console.error(options.viewport_inner, \"not found in\", widgetnode);\n    }\n\n    //this.items = widgetnode.querySelectorAll(options.itemsselector);\n    this.items = [];\n    for (const itemnode of widgetnode.querySelectorAll(options.itemsselector)) {\n      if (this.options.itemmeasureselector) {\n        const measurenode = itemnode.querySelector(this.options.itemmeasureselector);\n        if (!measurenode)\n          console.error(\"Missing measurenode\");\n\n        this.items.push({ node: itemnode, measurenode: measurenode });\n      } else\n        this.items.push({ node: itemnode });\n    }\n\n    if (this.options.debug)\n      console.log(\"[CarrouselContent] Items\", this.items);\n\n    if (!this.viewport) {\n      console.error(\"[CarrouselContent] Missing viewport for\", widgetnode);\n      return;\n    }\n\n    //console.log(this.options.__test + \" - \" + this.options.viewport_inner)\n\n    if (!this.viewport_inner) {\n      console.error(\"[CarrouselContent] Missing viewport_inner for\", widgetnode);\n      return;\n    }\n\n    if (options.bulletscontainer != \"\") {\n      this.bulletscontainer = widgetnode.querySelector(options.bulletscontainer);\n      if (!this.bulletscontainer) {\n        console.error(\"[CarrouselContent] Missing bulletscontainer for\", widgetnode);\n        return;\n      }\n    }\n\n    this.bullets = [];\n\n    this.viewport.addEventListener(\"scroll\", evt => this.onScroll(evt));\n\n    if (this.bulletscontainer) {\n      //this.bulletscontainer.addEventListener(\"click\", evt => this.onBulletClick(evt));\n      this.bulletscontainer.addEventListener(\"mousedown\", evt => this.onBulletClick(evt));\n      this.bulletscontainer.addEventListener(\"touchstart\", evt => this.onBulletClick(evt), { passive: true });\n    }\n\n    if (this.options.previousbutton) {\n      this.options.previousbutton.addEventListener(\"click\", evt => this.previousPage(evt));\n      this.options.previousbutton.addEventListener(\"keypress\", evt => this.maybePreviousPage(evt)); // in case the button isn't made using an <button> element we need to handle keyboard events ourselves\n    }\n\n    if (this.options.nextbutton) {\n      this.options.nextbutton.addEventListener(\"click\", evt => this.nextPage(evt));\n      this.options.nextbutton.addEventListener(\"keypress\", evt => this.maybeNextPage(evt)); // in case the button isn't made using an <button> element we need to handle keyboard events ourselves\n    }\n\n    // this.viewport.scrollTo(0,0); // work around Firefox restoring the scrollposition\n    this.refresh();\n    this.gotoPage(0);\n    this.updateNavigationBar();\n\n    if (this.options.debug) {\n      console.info(\"[CarrouselContent]\"\n        , {\n          widgetnode: this.widgetnode,\n          viewport: this.viewport,\n          viewport_inner: this.viewport_inner,\n          items: this.items,\n          bulletscontainer: this.bulletscontainer,\n          pages: this.pages\n        }\n      );\n    }\n\n    if (this.playing)\n      this.__applyCurrentAutoplay(this.options.autoplay_initialdelay);\n\n\n    if (window.resizeObserver) {\n      // Listen for changes in the viewport size (where we see the animation happen)\n      resizeObserver.observe(this.viewport);\n\n      // Listen for changes in content\n      // (this only works in viewport_inner was explicitly set)\n      if (this.viewport != this.viewport_inner)\n        resizeObserver.observe(this.viewport_inner);\n    }\n\n\n    window.__carrouselcontent_instances.push(\n      {\n        node: widgetnode,\n        instance: this\n      });\n\n    /*\n    This for now is to:\n    - fix the case in which we didn't pick up a scroll due to our tab not being visible\n    - detect/workaround a reported bug which we cannot reproduce\n    */\n    setInterval(this.verifyScrollPosition.bind(this), 1000);\n  }\n\n  verifyScrollPosition() {\n    const scrollLeft = this.viewport.scrollLeft; // for debugging\n\n    if (this.debug)\n      console.log(\"INTERVAL\", document.visibilityState, scrollLeft, this.scrollLeft);\n\n    if (scrollLeft != this.scrollLeft) {\n      console.error(\"scrollLeft checked in interval doesn't match the value from the last received scroll event.\");\n      this.onScroll(null);\n    }\n  }\n\n  maybePreviousPage(evt) {\n    if (evt.keyCode == 13 || evt.keyCode == 32) {\n      this.previousPage();\n      evt.preventDefault(); // we emulate a <button>, so \"space\" must trigger our click action, DON'T let the browser think the user wants to scroll the page\n    }\n  }\n\n  maybeNextPage(evt) {\n    if (evt.keyCode == 13 || evt.keyCode == 32) {\n      this.nextPage();\n      evt.preventDefault();\n    }\n  }\n\n  previousPage() {\n    if (this.options.debug)\n      console.log(\"previousPage\");\n\n    if (this.activepage > 0)\n      this.gotoPage(this.activepage - 1, true);\n    else if (this.options.allowwrap)\n      this.gotoPage(this.pages.length - 1);\n  }\n\n  nextPage() {\n    if (this.options.debug) {\n      console.log(\"nextPage\"\n        , {\n          activepage: this.activepage,\n          pagescount: this.pages.length,\n          nextactivepage: this.activepage + 1\n        });\n    }\n\n    if (this.activepage < this.pages.length - 1)\n      this.gotoPage(this.activepage + 1, true);\n    else if (this.options.allowwrap)\n      this.gotoPage(0);\n  }\n\n  gotoPage(idx, animate) {\n    if (this.options.debug)\n      console.log(\"[CarrouselContent] gotoPage\", idx, this.pages[idx], animate);\n\n    if (this.viewport.scrollTo) // asumming SmoothScroll polyfill has loaded (FIXME: check for scrollBehaviour or polyfill existance)\n      this.viewport.scrollTo({ left: this.pages[idx], behavior: \"smooth\" });\n    else\n      this.viewport.scrollLeft = this.pages[idx]; // SmoothScroll polyfill not loaded yet, IE might not have a scrollTo() function\n\n    //    if (animate && ('scrollBehavior' in document.documentElement.style))\n    //      this.viewport.scrollTo({ left: this.pages[idx], behavior: \"smooth\" });\n    //    else // IE\n    // this.viewport.scrollTo(this.pages[idx], 0);\n    //      this.viewport.scrollLeft = this.pages[idx];\n  }\n\n\n\n  onBulletClick(evt) {\n    if (evt.type == \"click\")\n      evt.preventDefault();\n\n    const bullet = evt.target.closest(\".\" + this.options.bulletclass);\n    const idx = this.bullets.indexOf(bullet);\n    if (!bullet)\n      return;\n\n    if (this.options.debug)\n      console.log(\"[CarrouselContent] onButtonClick\", bullet, idx);\n\n    this.gotoPage(idx, true);\n  }\n\n  onScroll(evt) {\n    this.scrollLeft = this.viewport.scrollLeft; // for debugging\n\n    const activepage = this.determineActivePage();\n    this.activepage = activepage;\n\n    if (this.activepage != this.prevactivepage) {\n      if (this.options.debug)\n        console.log(\"CarrouselContent::onScroll] active page changed to \", this.activepage);\n\n      this.updateNavigationBar();\n      this.prevactivepage = this.activepage;\n\n      if (this.options.onchangeslide) {\n        if (this.options.debug)\n          console.info(\"CarrouselContent::onScroll] using slidechange callback\");\n\n        this.options.onchangeslide({\n          slideidx: this.activepage,\n          slideidx_prev: this.prevactivepage,\n          slidedata: this.pagesinfo[this.activepage]\n        });\n      }\n    }\n  }\n\n  updateNavigationBar() {\n    if (this.options.previousbutton) {\n      if (!this.options.allowwrap && this.activepage == 0)\n        this.options.previousbutton.setAttribute(\"disabled\", \"\");\n      else\n        this.options.previousbutton.removeAttribute(\"disabled\");\n    }\n\n\n    if (this.options.nextbutton) {\n      if (!this.options.allowwrap && this.activepage == this.pages.length - 1)\n        this.options.nextbutton.setAttribute(\"disabled\", \"\");\n      else\n        this.options.nextbutton.removeAttribute(\"disabled\");\n    }\n\n    if (this.bullets.length > 0) {\n      for (let idx = 0; idx < this.pages.length; idx++)\n        this.bullets[idx].classList[idx == this.activepage ? \"add\" : \"remove\"](this.options.bulletselectedclass);\n    }\n\n    // Mark the first item of the page as active\n    if (this.options.item_activeclass != \"\") {\n      if (this.options.debug)\n        console.log(\"Active page\", this.activepage, this.pagesinfo[this.activepage]);\n\n      for (const item of this.items) {\n        //console.log(\"Updating active class for\", itemnode);\n        const in_view = this.pagesinfo[this.activepage].itemnodes.indexOf(item.node) > -1;\n\n        if (this.options.debug)\n          console.log(item, in_view);\n\n        item.node.classList.toggle(this.options.item_activeclass, in_view);\n      }\n    }\n  }\n\n  determineActivePage() {\n    const scrollLeft = this.viewport.scrollLeft;\n    const scrollWidth = this.viewport.scrollWidth;\n\n    const containerbounds = this.viewport_inner.getBoundingClientRect();\n\n    if (this.options.debug_determineactivepage)\n      console.group(\"[CarrouselContent] determineActivePage\");\n\n    let activepage = -1;\n\n    if (this.options.debug_determineactivepage) {\n      console.log(\"Pages\", this.pages);\n      console.info(\"ScrollLeft\", scrollLeft);\n    }\n\n\n    if (scrollLeft + this.viewport.offsetWidth == scrollWidth) {\n      if (this.options.debug) {\n        console.log(\"Reached last scrollLeft position, so last page.\");\n        console.groupEnd();\n      }\n\n      // we reached the end, so it'll always be the last bullet we need to highlight\n      activepage = this.pages.length - 1;\n      return activepage;\n    }\n\n\n    // Find the page we are in\n    for (let idx = 0; idx < this.pages.length - 1; idx++) {\n      const pagex = this.pages[idx];\n\n      if (this.options.debug_determineactivepage) {\n        console.info(\"Page\", idx, \"at\", pagex, \"till\", pagex + containerbounds.width);\n      }\n\n      if (idx == this.pages.length\n        || this.pages[idx + 1] > scrollLeft) //pagex + containerbounds.width > scrollLeft)// + 15 + 1) // FIXME: magic padding number\n      {\n        // Found active page\n        activepage = idx;\n        break;\n      }\n    }\n\n    // If we somehow passed without finding the page, it must be the last page\n    if (activepage == -1)\n      activepage = this.pages.length - 1;\n\n    if (this.options.debug_determineactivepage)\n      console.groupEnd();\n\n    return activepage;\n  }\n\n\n  refresh() {\n    this.recalculatePages();\n    this.createJumpButtons();\n    this.updateNavigationBar();\n  }\n\n  recalculatePages() {\n    if (!this.viewport)\n      return;\n\n    if (this.options.debug) {\n      console.group(\"[CarrouselContent] recalculatePages\", this.options.__test);\n      console.log(\"Items\", this.items);\n    }\n\n    this.pages = [];\n    // this.pageselem = [];\n    this.pagesinfo = [];\n    const viewportbounds_inner = this.viewport_inner.getBoundingClientRect();\n\n    const viewportbounds = this.viewport.getBoundingClientRect();\n    const scrollLeft = this.viewport.scrollLeft;\n\n    let nextpage_xpos = 0; //viewportbounds.width;\n\n\n    //let scrollSnapSupport = true;\n\n    let pagenr = 0;\n    let items_this_page = [];\n    let itemnodes_this_page = [];\n\n    for (const item of this.items) {\n      const measurenode = item.measurenode ?? item.node;\n      //console.log(\"Measurenode\", measurenode);\n      const itembounds = measurenode.getBoundingClientRect();\n      //console.log(itembounds);\n      if (itembounds.width == 0) // skip hidden items\n        continue;\n\n\n      let itemx, itemxend;\n      //if (scrollSnapSupport)\n      //{\n      // itemx = Math.floor(itembounds.left - viewportbounds.left) + scrollLeft;\n      // itemxend = Math.floor(itembounds.right - viewportbounds.left) + scrollLeft;\n      itemx = itembounds.left - viewportbounds.left + scrollLeft;\n      itemxend = itembounds.right - viewportbounds.left + scrollLeft;\n\n      // Get amount to keep from the edge... This is the amount we have to scroll less to get there\n      const comp = window.getComputedStyle(measurenode); //this.pageselem[idx]);\n      let left;\n      if (comp.scrollMarginLeft) {\n        left = parseInt(comp.scrollMarginLeft);\n\n        //if (this.options.debug)\n        //  console.log(\"scrollMarginLeft\", left);\n      } else if (comp.scrollSnapMarginLeft) // older Safari (11 up till 14)\n      {\n        left = parseInt(comp.scrollSnapMarginLeft);\n\n        //if (this.options.debug)\n        //  console.log(\"scrollSnapMarginLeft\", left);\n      } else {\n        // FIXMNE: or use item[0].getBoundingClientRect().left - viewport.getBoundingClientRect().left als scrollMarginLeft ??\n        left = viewportbounds_inner.left - viewportbounds.left; // Don't stoll the first item skipping the whitespace (padding in viewport, margin-left of viewport_iunner)\n\n        if (this.options.debug)\n          console.log(\"Keeping whitespace at start\", left);\n      }\n\n      // Reduce with the amount we have to scroll less\n      // (because the is meant to be whitespace at the left)\n      itemx -= left;\n      itemxend -= left;\n      /*\n      Support for older browsers (such as Internet Explorer)\n\n      }\n      else\n      {\n        // use inner because it's useually within the scroll snap bounds\n        itemx = Math.floor(itembounds.left) - Math.floor(viewportbounds_inner.left);\n        itemxend = Math.floor(itembounds.right) - Math.floor(viewportbounds_inner.left);\n\n        // If the container of the items\n        if (this.viewport == this.viewport_inner)\n        {\n          let scrollLeft = this.viewport.scrollLeft;\n          itemx += scrollLeft;\n          itemxend += scrollLeft;\n        }\n      }\n      */\n\n\n      if (this.options.debug) {\n        console.log({\n          node: item,\n          //  , innerviewport_left: viewportbounds_inner.left\n          item_left: itembounds.left,\n          item_width: itembounds.width,\n\n          xstart: itemx,\n          xend: itemxend\n        });\n      }\n\n      items_this_page.push(item);\n      itemnodes_this_page.push(item.node);\n\n\n      //if (itemx >= nextpage_xpos)\n      if (itemxend > nextpage_xpos) {\n        // console.log(\"Page will start at\", nextpage_xpos);\n        if (this.options.debug)\n          console.log(\"Page #\" + pagenr + \" starts at\", nextpage_xpos, \"and end before\", nextpage_xpos + this.viewport.clientWidth);\n\n        this.pages.push(Math.floor(itemx));\n        // this.pageselem.push(item);\n        this.pagesinfo.push(\n          {\n            x: Math.floor(itemx),\n            items: items_this_page,\n            itemnodes: itemnodes_this_page\n          });\n\n        items_this_page = [];\n        itemnodes_this_page = [];\n        pagenr++;\n\n        nextpage_xpos = itemx + this.viewport.clientWidth; // Math.floor(viewportbounds.width);\n\n        //if (this.options.debug)\n        //  console.log(\"Next page might be at\", nextpage_xpos);\n      }\n\n    }\n\n    if (this.options.debug)\n      console.log(\"pages:\", this.pagesinfo);\n\n    console.groupEnd();\n  }\n\n  createJumpButtons() {\n    if (!this.viewport || !this.bulletscontainer)\n      return;\n\n    const activepage = this.determineActivePage();\n\n    this.bulletscontainer.innerHTML = \"\";\n    this.bullets = [];\n\n    for (let idx = 0; idx < this.pages.length; idx++) {\n      let bullet = null;\n\n      if (this.options.createbullet) {\n        bullet = this.options.createbullet();\n      } else {\n        bullet = document.createElement(\"div\");\n        bullet.className = this.options.bulletclass;\n        bullet.classList[idx == activepage ? \"add\" : \"remove\"](this.options.bulletselectedclass);\n      }\n\n      //console.log(\"New bullet node\", bullet);\n\n      this.bulletscontainer.appendChild(bullet);\n      this.bullets.push(bullet);\n    }\n\n    const multiplepages = this.pages.length > 1;\n    this.bulletscontainer.style.display = multiplepages ? \"\" : \"none\";\n\n    this.widgetnode.classList[multiplepages ? \"add\" : \"remove\"](\"carrouselcontent--multiplepages\");\n  }\n\n  onResize() {\n    this.refresh();\n  }\n\n\n\n  //////////////////////////////////////////////\n  //\n  //  Autoplay support\n  //\n\n  initAutoplayVars() {\n    // autoplay support variables\n    this.autoplaytimer = null;\n    this.lastautoslidetime = null;\n    this.playing = this.options.autoplay;\n  }\n\n  // autoplay support\n  destroy() {\n    clearTimeout(this.autoplaytimer);\n    this.autoplaytimer = null;\n    this.playing = false;\n  }\n\n  // autoplay support\n  pause() {\n    this.playing = false;\n    this.__applyCurrentAutoplay();\n  }\n\n  // autoplay support\n  play() {\n    this.playing = true;\n    this.__applyCurrentAutoplay();\n  }\n\n\n\n  __applyCurrentAutoplay(delay) {\n    if (this.options.debug)\n      console.log(\"[CarrouselContent] __applyCurrentAutoplay\");\n\n    if (!delay)\n      delay = 0;\n\n    //console.log(this.__nextSlideByTimer);\n    if (this.playing)// && !document.hidden && this.inviewport)\n    {\n      if (!this.autoplaytimer) {\n        if (this.options.debug)\n          console.log(\"[CarrouselContent] Setting new timer for auto slide\");\n\n        this.autoplaytimer = setTimeout(this.__nextSlideByTimer.bind(this), this.options.autoplay_freezeslideduration + delay);\n      } else if (this.options.debug)\n        console.log(\"[CarrouselContent] Timer already running...\");\n    } else {\n      if (this.options.debug)\n        console.log(\"[CarrouselContent] No autoplay\");//, { play: this.playing, dochidden: document.hidden, inviewport: this.inviewport });\n\n      if (this.autoplaytimer) {\n        clearTimeout(this.autoplaytimer);\n        this.autoplaytimer = null;\n      }\n    }\n  }\n\n  __nextSlideByTimer() {\n    if (!this.options.autoplay) // did a timer event still get through?\n      return;\n\n    this.lastautoslidetime = new Date().getTime();\n\n    this.nextPage();\n\n    this.autoplaytimer = setTimeout(this.__nextSlideByTimer.bind(this), this.options.autoplay_freezeslideduration);\n  }\n}\n\n\n//module.exports = { CarrouselContent: CarrouselContent };\nexport { CarrouselContent };\n\n\n\n/*\nHaving a single resizeObserver is better for performance.\nSee: https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ?pli=1\n*/\nlet resizeObserver;\nif (window.ResizeObserver)\n  resizeObserver = new ResizeObserver(entries => onResize(entries));\nelse\n  window.addEventListener(\"resize\", resizeAllContentCarrousels); // handled using the resizeObserver\n\n\n\nfunction onResize(entries) {\n  console.log(\"onResize\", entries);\n\n  for (const entry of entries) {\n    for (const widgetdata of window.__carrouselcontent_instances) {\n      if (entry.target == widgetdata.instance.viewport) {\n        console.info(\"Widget has resized\");\n        widgetdata.instance.onResize();\n      }\n    }\n  }\n}\n\nfunction resizeAllContentCarrousels() {\n  for (const widgetdata of window.__carrouselcontent_instances)\n    widgetdata.instance.onResize();\n}\n\ndompack.onDomReady(resizeAllContentCarrousels);\nwindow.addEventListener(\"load\", resizeAllContentCarrousels);\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./imagewithcaption.scss\";\nimport * as CarrouselContent from \"@mod-utwente_base/webdesigns/ws2016/src/components/carrouselcontent\";\nimport * as dompack from \"dompack\";\n\n\n\nfunction initImagesWithCaptionWidget(widgetnode) {\n  const carrousel = new CarrouselContent.CarrouselContent(widgetnode\n    , {\n      viewport: \".imageswithcaption--multiple .imageswithcaption__images\",\n      viewport_inner: \".imageswithcaption__images\",\n      // , itemsselector:    \".imageswithcaption__item\"\n      itemsselector: \".imageswithcaption__item__image\",\n      bulletscontainer: \".imageswithcaption__jumpbuttons\",\n\n      bulletclass: \"imageswithcaption__jumpbutton\",\n      bulletselectedclass: \"slideshow--activedot\",\n      createbullet: doCreateBullet,\n\n      onchangeslide: onChangeSlide,\n\n      autoplay: true,\n      allowwrap: true,\n\n      // Debug settings\n      __test: \"ImagesWithCaption\"\n      // , debug:                     debug\n      // , debug_determineactivepage: debug\n    });\n\n  // Pause the carrousel while hovering over it\n  widgetnode.addEventListener(\"mouseenter\", () => {\n    widgetnode.classList.add(\"imageswithcaption--paused\");\n    carrousel.pause();\n  });\n  widgetnode.addEventListener(\"mouseleave\", () => {\n    widgetnode.classList.remove(\"imageswithcaption--paused\");\n    carrousel.play();\n  });\n}\n\nfunction onChangeSlide(details) {\n  const firstnodeinslide = details.slidedata.itemnodes[0];\n  const nodeid = firstnodeinslide.getAttribute(\"aria-describedby\");\n  const activemetanode = document.getElementById(nodeid);\n\n\n  const widget = firstnodeinslide.closest(\".embeddedobject--imageswithcaption\");\n  const metaslidescontainer = widget.querySelector(\".imageswithcaption__metaslides\");\n\n  // Update the active state of each information panel\n  let metanode = metaslidescontainer.firstElementChild;\n  while (metanode) {\n    metanode.classList.toggle(\"active\", activemetanode == metanode);\n    metanode = metanode.nextElementSibling;\n  }\n}\n\nfunction doCreateBullet() {\n  return <span class=\"imageswithcaption__jumpbutton UT-icon-UT_icon_77_sliderdot-16px\">\n    <span class=\"imageswithcaption__jumpbutton-active UT-icon-UT_icon_76_slider-dot-active-16px\"></span>\n  </span>;\n}\n\ndompack.register(\".imageswithcaption--multiple\", initImagesWithCaptionWidget);\n","import \"./imagevideowithtext.scss\";\nimport * as dompack from \"dompack\";\nimport * as modaldialog from \"@mod-utwente_base/webdesigns/ws2016/src/shared/dialog\";\n\ndompack.register(\".embeddedobject-imagevideowithtext__image__fullscreen\", node => {\n  node.addEventListener(\"click\", () => {\n    modaldialog.showModalDialog(\"\",\n      <img src={node.dataset.src} class=\"embeddedobject-imagevideowithtext-dialog__image\" alt=\"\" />, {\n        theme: \"embeddedobject-imagevideowithtext-dialog\"\n      }\n    );\n  });\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./news.scss\";\nimport * as dompack from \"dompack\";\nimport { relayoutWidgets } from \"../layout\";\n\nfunction renderNews(node, items) {\n  if (items.length === 0) {\n    dompack.remove(node); //Just remove widget if no news\n    return;\n  }\n\n  const photosnode = dompack.qS(node, \".widget-ws2016news__photo\");\n  const listnode = dompack.qS(node, \".widget__list\");\n  items.forEach((item, i) => {\n    const link = node.dataset.baseurl ? node.dataset.baseurl + item.suburl : item.url;\n\n    if (i === 0 && photosnode) {\n      if (item.photolink) {\n        photosnode.setAttribute(\"href\", link);\n        photosnode.style.backgroundImage = \"url(\" + item.photolink + \")\";\n        photosnode.setAttribute(\"role\", item.photoalt ? \"image\" : \"presentation\");\n        if (item.photoalt)\n          photosnode.setAttribute(\"aria-label\", item.photoalt);\n      } else\n        dompack.remove(photosnode);//If no picture, remove photo node\n    }\n\n    listnode.appendChild(<a href={link} class=\"widget__listitem widget__listitem--link\">\n      <span class=\"widget__listitem-icon widget__listitem-icon--small UT-icon-UT_icon_52_arrow-right-round-16px\" />\n      <span class=\"widget__listitem-text\">{item.title}</span>\n    </a>);\n  });\n\n  //Trigger ut masonry update\n  relayoutWidgets(node);\n}\n\nasync function getNewsItems(node) {\n  const response = await fetch(node.dataset.publocfile);\n  if (response && response.status === 200) {\n    const items = await response.json();\n    if (items && items[\"p\" + node.dataset.publoc])\n      renderNews(node, items[\"p\" + node.dataset.publoc].items);\n    else\n      dompack.remove(node); //Just remove widget if no news\n  }\n}\n\ndompack.register(\".widget-ws2016news\", node => {\n  void getNewsItems(node);\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./quote.scss\";\nimport * as dompack from \"dompack\";\nimport { renderPrettyPhoneNumber } from '@mod-utwente_design/js/ut-formatting';\nimport { relayoutWidgets } from \"../layout\";\n\nfunction showDetails(container, timer) {\n  container.style.maxHeight = \"0\";\n  container.classList.add(\"opendetails\");\n  container.style.maxHeight = container.children[0].clientHeight + \"px\";\n  return setTimeout(() => {\n    container.style.maxHeight = \"\";\n  }, 200); //Should be same as duration set in css\n}\n\nfunction hideDetails(container) {\n  container.style.maxHeight = container.children[0].clientHeight + \"px\";\n  void (container.clientHeight);//force css update\n  container.style.maxHeight = \"0\";\n  container.classList.remove(\"opendetails\");\n}\n\nlet __timer = null;\nfunction togglePersonalDetails(node) {\n  node.addEventListener(\"click\", ev => {\n    dompack.stop(ev);\n\n    const quoteswidget = node.closest(\".widget-quotes\");\n    if (quoteswidget) { //If inside multiple quotes widget, 3d - rotate for persondetails\n      ev.preventDefault();\n      quoteswidget.classList.toggle(\"showslidedetails\");\n\n      return;\n    }\n\n    //Inside embedded object, then use foldin/out\n    clearTimeout(__timer);\n    node.classList.toggle(\"opendetails\");\n    const widgetnode = node.closest(\".widget-quote\");\n    const foldcontainer = dompack.qS(widgetnode, \".widget-quote__persondetails\");\n    if (node.classList.contains(\"opendetails\"))\n      __timer = showDetails(foldcontainer, __timer);\n    else\n      hideDetails(foldcontainer);\n  });\n}\n\nclass EmbQuoteSlides {\n  constructor(wrapper) {\n    this.items = dompack.qSA(wrapper, \".widget-quote\");\n    this.idx = 0;\n\n    wrapper.parentNode.appendChild(<div class={\"embeddedobject-quotes__nav\" + (dompack.qS(wrapper, \".widget-quote--withphoto\") ? \" embeddedobject-quotes__nav--spaceleft\" : \"\")}>\n      {this.items.map((_, i) => <button onClick={() => this.gotoSlide(i)} type=\"button\" class=\"embeddedobject-quotes__nav__button\" />)}\n    </div>);\n    this.btns = dompack.qSA(wrapper.parentNode, \".embeddedobject-quotes__nav__button\");\n\n    this.items[this.idx].classList.add(\"active\");\n    this.btns[this.idx].classList.add(\"active\");\n\n    this.timer = setTimeout(() => this.nextSlide(), 7000);\n\n    wrapper.addEventListener(\"mouseover\", () => clearTimeout(this.timer));\n    wrapper.addEventListener(\"mouseout\", () => {\n      clearTimeout(this.timer);\n      this.timer = setTimeout(() => this.nextSlide(), 7000);\n    });\n  }\n\n  nextSlide() {\n    this.gotoSlide(this.idx + 1);\n    this.timer = setTimeout(() => this.nextSlide(), 7000);\n  }\n\n  gotoSlide(idx) {\n    if (idx < 0)\n      idx = this.items.length - 1;\n    else if (idx >= this.items.length)\n      idx = 0;\n\n    if (idx !== this.idx) {\n      clearTimeout(this.timer);\n\n      this.items[this.idx].classList.remove(\"active\");\n      this.btns[this.idx].classList.remove(\"active\");\n      this.idx = idx;\n      this.items[this.idx].classList.add(\"active\");\n      this.btns[this.idx].classList.add(\"active\");\n    }\n  }\n}\n\ndompack.register(\".embeddedobject-quotes__wrapper\", node => new EmbQuoteSlides(node));\n\nclass quotesSlideshow {\n  constructor(node) {\n    this.node = node;\n    this.node.addEventListener(\"click\", ev => this.onClick(ev));\n\n    this.items = dompack.qSA(node, \".widget-quotes__slide\");\n    window.addEventListener(\"load\", ev => this.setQuotesHeight());\n    document.fonts.ready.then(() => this.setQuotesHeight());\n    this.setQuotesHeight();\n\n    const itemcount = this.items.length;\n    if (itemcount <= 1)\n      return;\n\n    this.delay = 7000;//ms. delay between animations\n    this.duration = 1000;//ms. fade animation duration\n    this.idx = 0;\n\n    this.jmpbtns = [];\n    this.items.forEach((item, i) => {\n      item.style.transition = \"opacity \" + this.duration + \"ms\";\n\n      const frontnode = dompack.qS(item, \".widget-quote__front\");\n      const jmpbtns = <div class=\"widget-quotes__jumpbuttons\" />;\n      for (let c = 0; c < itemcount; ++c)\n        jmpbtns.appendChild(<span class={i === c ? \"active\" : \"\"} />);\n      frontnode.appendChild(jmpbtns);\n      this.jmpbtns.push(jmpbtns);\n    });\n\n    this.timer = setTimeout(() => this.nextSlide(), this.delay);\n\n    node.addEventListener(\"mouseover\", ev => {\n      clearTimeout(this.timer);\n    });\n    node.addEventListener(\"mouseout\", ev => {\n      clearTimeout(this.timer);\n      this.timer = setTimeout(() => this.nextSlide(), this.delay);\n    });\n  }\n\n  onClick(ev) {\n    const jmpbtn = ev.target.closest(\".widget-quotes__jumpbuttons > span\");\n    if (jmpbtn) {\n      for (let i = 0; i < this.jmpbtns[this.idx].children.length; ++i) {\n        if (this.jmpbtns[this.idx].children[i] === jmpbtn) {\n          this.gotoSlide(i);\n          break;\n        }\n      }\n    }\n  }\n\n  gotoSlide(idx) {\n    if (this.node.classList.contains(\"showslidedetails\"))\n      return;\n\n    const oldidx = this.idx;\n    this.idx = idx;\n    if (idx < 0)\n      this.idx = this.items.length - 1;\n    this.idx = this.idx % this.items.length;\n\n    if (this.idx === oldidx)\n      return;\n\n    clearTimeout(this.timer);\n\n    this.items.forEach(item => item.classList.remove(\"fadeout\"));//Make sure all other slides are in background\n\n    this.items[oldidx].classList.remove(\"active\");\n    this.items[oldidx].classList.add(\"fadeout\");\n    this.items[this.idx].classList.add(\"active\");\n\n    this.timer = setTimeout(() => this.nextSlide(), this.delay);\n  }\n\n  previousSlide() {\n    this.gotoSlide(this.idx - 1);\n  }\n\n  nextSlide() {\n    if (this.node.classList.contains(\"showslidedetails\")) {//just try next time\n      clearTimeout(this.timer);\n      this.timer = setTimeout(() => this.nextSlide(), this.delay);\n      return;\n    }\n\n    this.gotoSlide(this.idx + 1);\n  }\n\n  setQuotesHeight() { //set all quote widgets to height of largest widget\n    let minh = 0;\n\n    this.items.forEach(item => {\n      dompack.qSA(item, \".widget-quote__front, .widget-quote__persondetails__content\").forEach(panel => {//check front/backside\n        panel.style.minHeight = \"\";\n        const y = panel.clientHeight;\n        if (y > minh)\n          minh = y;\n      });\n    });\n\n    this.items.forEach(item => {\n      dompack.qSA(item, \".widget-quote__front, .widget-quote__persondetails__content\").forEach(panel => {//check front/backside\n        panel.style.minHeight = minh + \"px\";\n      });\n    });\n\n    this.node.style.height = minh + \"px\";\n\n    //Trigger ut masonry update\n    relayoutWidgets(this.node);\n  }\n}\n\ndompack.register(\".widget-quote a[href^='tel:'] > .value\", node => renderPrettyPhoneNumber(node));\ndompack.register(\".widget-quote__togglemore\", node => togglePersonalDetails(node));\ndompack.register(\".widget-quotes\", node => new quotesSlideshow(node));\n","import * as dompack from \"@webhare/dompack\";\n\nexport function renderPrettyPhoneNumber(node: HTMLElement) {\n  if (!node.textContent)\n    return;\n\n  const numbers = node.textContent.replace(/[^0-9]+/g, '');\n  const parts = numbers.split('53487');\n  if (parts.length === 2 && parts[1].length === 4) {\n    node.replaceChildren(<span class=\"prettyphonenumber\">+31 (0)53 487 <b>{parts[1]}</b></span>);\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport utwenteCookies from \"@mod-utwente_design/js/cookiebar\";\nimport * as dompack from \"dompack\";\n\nfunction setupPodcast(node) {\n  let params;\n  try {\n    params = JSON.parse(node.dataset.options);\n  } catch (e) { }\n\n  if (params && params.loadifconsent) {\n    if (utwenteCookies.getConsent()) {\n      startPodcast(node, params);\n    } else {\n      document.addEventListener(\"wh:consent-change\", ev => {\n        if (utwenteCookies.getConsent())\n          startPodcast(node, params);\n      });\n    }\n  }\n\n  node.addEventListener(\"click\", () => startPodcast(node, params));\n}\n\nfunction startPodcast(node, params) {\n  if (dompack.qS(node, \"iframe\"))\n    return;//already loaded\n\n  if (!params)\n    return;\n\n  const podcast_title = node.dataset.title ? node.dataset.title : \"\";\n  if (window.dataLayer)\n    window.dataLayer.push({\n      event: \"podcast_play\",\n      podcast_title\n    });\n\n  node.replaceChildren();\n\n  if (params.url && params.url.indexOf(\".transistor.fm/e/\") > -1)\n    startTransistor(node, params.url);\n  else\n    startSoundCloud(node, params);\n\n  node.parentNode.classList.add(\"widget-soundcloud--loaded\");\n}\n\nfunction startTransistor(node, url) {\n  node.appendChild(<iframe allow=\"autoplay\"\n    src={url}\n    width=\"100%\"\n    height=\"100%\"\n    frameborder=\"0\"\n    scrolling=\"no\"\n    seamless=\"true\"\n    allowtransparency=\"true\" />);\n}\n\nfunction startSoundCloud(node, params) {\n  const urlparts = [];\n  const paramnames = Object.keys(params);\n  for (const name of paramnames)\n    urlparts.push(name + \"=\" + escape(params[name]));\n\n  node.appendChild(<iframe allow=\"autoplay\"\n    src={\"https://w.soundcloud.com/player/?\" + urlparts.join(\"&amp;\")}\n    width=\"100%\"\n    height=\"100%\"\n    frameborder=\"0\"\n    scrolling=\"no\"\n    seamless=\"true\"\n    allowtransparency=\"true\" />);\n}\n\ndompack.register(\".widget-soundcloud__wrapper[data-options]\", node => setupPodcast(node));\n","import \"./tablewithtabs.scss\";\nimport * as dompack from \"@webhare/dompack\";\nimport { foldableContent } from '@mod-utwente_design/js/foldablecontent';\nimport { pushToDataLayer } from \"@webhare/frontend\";\n\n//NOTE we get attached to both the .wh-details[data-main-item] and .wh-details[data-sub-item]\nclass TimelineTableContent extends foldableContent {\n  override sendToggleEvent(params: { isopen: boolean }): void { //subclasses can override us\n    const table_with_timeline_title = this.node.closest<HTMLElement>('[data-widget-title]')?.dataset.widgetTitle ?? \"\";\n    const table_with_timeline_main_item = this.node.closest<HTMLElement>('[data-main-item]')?.dataset.mainItem ?? \"\";\n    const table_with_timeline_sub_item = this.node.dataset.subItem ?? \"\";\n\n    if (params.isopen)\n      pushToDataLayer({ event: \"table_with_timeline_click\", table_with_timeline_main_item, table_with_timeline_sub_item, table_with_timeline_title });\n  }\n}\n\ndompack.register(\".embeddedobject-tablewithtabs .wh-details\", node => {\n  new TimelineTableContent(node);\n});\n","import \"./foldablecontent.scss\";\nimport * as dompack from '@webhare/dompack';\nimport * as domevents from \"dompack/src/events\";\nimport { pushToDataLayer } from \"@webhare/frontend/src/gtm\";\n\n// Note: custom foldin/out animation not possible with details element\n//  if you want animated foldin/out, details/summary elements should be replace with div's\n\ninterface FoldableContentOptions {\n  duration: number;\n  gtmevent: string;\n}\n\nexport class foldableContent {\n  node;\n  containernode;\n  summarynode;\n  options: FoldableContentOptions;\n  _timer: NodeJS.Timeout | undefined;\n\n  constructor(node: HTMLElement, options?: Partial<FoldableContentOptions>) {\n    this.options = {\n      duration: 200, //Animation duration in ms\n      gtmevent: \"\",\n      ...options\n    };\n\n    this.node = node;\n\n    this.containernode = this.node.querySelector(\".wh-details__container\")! as HTMLElement;\n    this.containernode.style.transition = \"height \" + this.options.duration + \"ms\";\n\n    this.summarynode = this.node.querySelector(\".wh-details__summary\")! as HTMLElement;\n    this.summarynode.addEventListener(\"click\", ev => this.toggleAnimatedDetails(ev));\n  }\n\n  toggleAnimatedDetails(ev: MouseEvent) {\n    if (ev) //prevent double triggering open/close\n      dompack.stop(ev);\n\n    const open = !this.node.classList.contains(\"wh-details--open\");\n\n    clearTimeout(this._timer);\n    this.containernode.style.height = this.containernode.clientHeight + \"px\";\n    void (this.containernode.clientHeight);//force css update\n\n    this.containernode.style.height = (open ? this.containernode.children[0].clientHeight : 0) + \"px\";\n\n    this.node.classList.toggle(\"wh-details--open\", open);\n\n    this.sendToggleEvent({ isopen: open });\n\n    this._timer = setTimeout(() => {\n      this.containernode.style.height = \"\";\n    }, this.options.duration);\n  }\n\n  sendToggleEvent(params: { isopen: boolean }): void { //subclasses can override us\n    if (this.options?.gtmevent && params.isopen) {\n      if (this.options.gtmevent === \"accordion\")\n        pushToDataLayer({ event: \"accordion-klik\", \"accordioncontent\": this.summarynode.textContent || '' });\n      else\n        pushToDataLayer({ event: \"faq-klik\", \"faqcontent\": this.summarynode.textContent || '' });\n    }\n  }\n}\n\nfunction findDetailsHash() {\n  const hash = location.hash.substr(1);\n  if (hash)\n    openCollapsableContainerFor(hash);\n}\n\nfunction openCollapsableContainerFor(hash: string) {\n  // return;\n  const target = document.getElementById(hash);\n  if (target) {\n    let detailsnode = (target.parentNode as HTMLElement)?.closest?.(\"details,.wh-details\");\n    console.log(\"OPEN\", detailsnode);\n    while (detailsnode) { // check of if is subset inside tree. Also open parents\n      if (detailsnode.nodeName === \"DETAILS\")\n        detailsnode.setAttribute(\"open\", \"\");\n      detailsnode.classList.add(\"wh-details--open\");\n      detailsnode = (detailsnode.parentNode as HTMLElement)?.closest(\"details,.wh-details\");\n    }\n  }\n}\n\nexport function setDetailsEvents() {\n  if (location.hash.length > 1)\n    findDetailsHash();\n\n  if (dompack.qS(\"details\") || dompack.qS(\".wh-details\")) {\n    window.addEventListener(\"hashchange\", ev => findDetailsHash());\n\n    //Accessibility for foldablecontent\n    window.addEventListener(\"keydown\", ev => {\n      if (ev.keyCode === 13) {\n        const node = (ev.target as HTMLElement)?.closest(\".wh-details__summary\");\n\n        // If the toggle isn't a button handle the keyboard interaction ourselves\n        if (node && node.tagName !== \"BUTTON\")\n          domevents.fireHTMLEvent(node, 'click');\n      }\n    });\n  }\n}\n\n\ndompack.register(\"details[data-gtmevent]\", init);\n\n\nfunction init(node: HTMLDetailsElement) {\n  node.addEventListener(\"toggle\", (e: Event) => onToggleDetails(e as ToggleEvent));\n}\n\nfunction onToggleDetails(evt: ToggleEvent) {\n  const target = evt.target as HTMLDetailsElement;\n\n  const isOpen = target.open;\n  if (!isOpen)\n    return;\n\n  const gtmevent = target.getAttribute(\"data-gtmevent\");\n  const summaryNode = target.querySelector(\"summary\");\n  if (!summaryNode)\n    return;\n\n  const summaryText = summaryNode.textContent;\n\n  console.log(gtmevent, isOpen, summaryText);\n\n  if (gtmevent === \"accordion\")\n    pushToDataLayer({ event: \"accordion-klik\", \"accordioncontent\": summaryText || '' });\n  else\n    pushToDataLayer({ event: \"faq-klik\", \"faqcontent\": summaryText || '' });\n}\n\n\ndompack.onDomReady(setDetailsEvents);\n","import \"./video.scss\";\nimport * as dompack from \"dompack\";\n\n/*\nPlaybuttons\n\n- Publisher video widget\n  .wh-video .wh-video__playbutton\n\n- Slideshow widget\n  .carrousel__cell__playbutton\n*/\n\ndompack.register(\".wh-video .wh-video__playbutton, .carrousel__cell__playbutton\", node => fixVideoPlayButton(node));\n\nfunction fixVideoPlayButton(playbutton: HTMLElement) {\n  console.log(\"Playbutton\", playbutton);\n  playbutton.classList.add(\"UT-icon-UT_icon_82_play-16px\");\n}\n","/*\nNOTE: This code overrides the viewport settings, an improvement would be\n      to take the original value and only add or change the user-scalable value\n*/\n\n// optionally only activate for iOS (done because I havn't tested the effect under other OS/devices combinations such as Android)\nvar iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)\nif (iOS)\n  preventZoomOnFocus();\n\n\nfunction preventZoomOnFocus()\n{\n  document.documentElement.addEventListener(\"touchstart\", onTouchStart);\n  document.documentElement.addEventListener(\"focusin\", onFocusIn);\n}\n\n\nlet dont_disable_for = [\"checkbox\", \"radio\", \"file\", \"button\", \"image\", \"submit\", \"reset\", \"hidden\"];\n//let disable_for = [\"text\", \"search\", \"password\", \"email\", \"tel\", \"url\", \"number\", \"date\", \"datetime-local\", \"month\", \"year\", \"color\"];\n\n\nfunction onTouchStart(evt)\n{\n  let tn = evt.target.tagName;\n\n  // No need to do anything if the initial target isn't a known element\n  // which will cause a zoom upon receiving focus\n  if (    tn != \"SELECT\"\n      &&  tn != \"TEXTAREA\"\n      && (tn != \"INPUT\" || dont_disable_for.indexOf(evt.target.getAttribute(\"type\")) > -1)\n     )\n    return;\n\n  // disable zoom\n  setViewport(\"width=device-width, initial-scale=1.0, user-scalable=0\");\n}\n\nfunction onFocusIn(evt)\n{\n  // reenable zoom\n  setViewport(\"width=device-width, initial-scale=1.0, user-scalable=1\");\n}\n\n// add or update the <meta name=\"viewport\"> element\nfunction setViewport(newvalue)\n{\n  let vpnode = document.documentElement.querySelector('head meta[name=\"viewport\"]');\n  if (vpnode)\n    vpnode.setAttribute(\"content\",newvalue);\n  else\n  {\n    vpnode = document.createElement(\"meta\");\n    vpnode.setAttribute(\"name\", \"viewport\");\n    vpnode.setAttribute(\"content\", newvalue);\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport service from \"./pirservice.rpc.json?proxy\";\n\n// People Image Replacement\nexport default class cPIR {\n  constructor() {\n    this.images = [];\n\n    this.matchstr = \"/people-placeholder.png#replace=\";\n\n    this.parseFromImageElements();\n    this.parseFromInlineCss();\n\n    const imagekeys = [];\n    for (let i = 0; i < this.images.length; ++i) {\n      let key = this.images[i].url1.split(\"#replace=\")[1];\n      if (imagekeys.indexOf(key) == -1)\n        imagekeys.push(key);\n\n      if (this.images[i].url2) {\n        key = this.images[i].url2.split(\"#replace=\")[1];\n        if (imagekeys.indexOf(key) == -1)\n          imagekeys.push(key);\n      }\n    }\n\n    if (imagekeys.length)\n      this.getReplacements(imagekeys);\n  }\n\n  getLinkFromResults(oldurl) {\n    if (!this.results)\n      return;\n\n    const key = oldurl.split(\"#replace=\")[1];\n    for (let i = 0; i < this.results.images.length; ++i) {\n      if (key == this.results.images[i].key)\n        return this.results.images[i].url;\n    }\n    return \"\";\n  }\n\n  async getReplacements(imagekeys) {\n    this.results = await service.getPIR(imagekeys);\n\n    if (this.results && this.results.success)\n      this.setReplacements();\n  }\n\n  setReplacements() {\n    for (let i = 0; i < this.images.length; ++i) {\n      const url1 = this.getLinkFromResults(this.images[i].url1);\n      if (!url1)\n        continue;\n\n      if (this.images[i].node) {\n        let url2;\n        if (this.images[i].node.srcset)\n          url2 = this.getLinkFromResults(this.images[i].url2);\n\n        this.images[i].node.src = url1;\n        if (this.images[i].node.srcset)\n          this.images[i].node.srcset = url1 + \" 1x,\" + url2 + \" 2x\";\n      } else if (this.images[i].style) {\n        this.images[i].style.backgroundImage = \"url('\" + url1 + \"')\";\n        if (this.images[i].selector) { //remove class indicating use of placeholder (used in embeddedobject personinfo)\n          for (const node of document.querySelectorAll(\".haspeopleplaceholder \" + this.images[i].selector))\n            node.closest(\".haspeopleplaceholder\").classList.remove(\"haspeopleplaceholder\");\n        }\n      }\n    }\n  }\n\n  parseFromImageElements() {\n    for (const node of document.querySelectorAll(\"img[src*='\" + this.matchstr + \"']\")) {\n      let url1, url2;\n      if (node.srcset) {\n        const parts = node.srcset.split(\",\");\n        for (let i = 0; i < parts.length; ++i) {\n          const part = parts[i].trim();\n          if (part.indexOf(this.matchstr) > -1) {\n            if (part.indexOf(\" 2x\") > -1)\n              url2 = part.split(\" \")[0];\n            else\n              url1 = part.split(\" \")[0];\n          }\n        }\n      } else\n        url1 = node.src;\n\n      this.images.push({\n        \"node\": node,\n        \"url1\": url1,\n        \"url2\": url2,\n        \"style\": null\n      });\n    }\n  }\n\n  parseFromInlineCss() {\n    //check inline styleSheets\n    for (let i = 0; i < window.document.styleSheets.length; ++i) {\n      if (window.document.styleSheets[i].href)\n        continue;//Ignore external stylesheets\n\n      const rules = this.getAllCssRules(window.document.styleSheets[i]);\n      if (!rules)\n        continue;\n\n      const regexp = /(?:\\(['\"]?)(.*?)(?:['\"]?\\))/;\n\n      for (let c = 0; c < rules.length; ++c) {\n        if (rules[c].style.backgroundImage) {\n          const match = regexp.exec(rules[c].style.backgroundImage);\n          if (match && match[1].indexOf(this.matchstr) > -1) {\n            this.images.push({\n              \"node\": null,\n              \"url1\": match[1],\n              \"url2\": \"\",\n              \"style\": rules[c].style,\n              \"selector\": rules[c].selectorText\n            });\n          }\n        }\n      }\n    }\n  }\n\n  getAllCssRules(cssitem) {\n    let items = [];\n    const rules = cssitem.rules || cssitem.cssRules;\n    for (let c = rules.length - 1; rules && c >= 0; --c) {\n      if (rules[c].media) {\n        const mediarules = this.getAllCssRules(rules[c]);\n        if (mediarules)\n          items = items.concat(mediarules);\n      } else if (rules[c].style)\n        items.push(rules[c]);\n    }\n    return items;\n  }\n}\n\ndompack.onDomReady(() => {\n  new cPIR();\n});\n","const { createService } = require(\"@mod-system/js/wh/rpc.ts\"); export default createService(\"utwente_base:pirservice\");","/* eslint-disable @typescript-eslint/no-explicit-any -- we have no types for the PSA and its loader classes */\n\n/* Due to load ordering issues (https://gitlab.webhare.com/utwente/utwente_base/-/issues/2728#note_242336) and the fact that this code\n   rarely changes, we're integrating it directly into JS and taking a careful approach to executing the sync HTML steps it would originally take\n\n   This is the code that was used to load the PSA widget\n\nThis was the original widget code.\n<link href=\"/repository/utwente-data/psa/css/chat.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<div id=\"container\">\n  <!-- The PSA's GUI controls go here -->\n</div>\n\n<script src=\"/repository/utwente-data/psa/build/autocomplete.js\" type=\"text/javascript\"></script>\n<script src=\"/repository/utwente-data/psa/build/require.js\" type=\"text/javascript\"></script>\n<script>\nrequire.config({baseUrl:\"/repository/utwente-data/psa/build\",paths:{App:\"build/app\"}}),require([\"app\"],function(i){psa=new i.ApplicationAssistant,psa.init()}),requirejs([\"autocomplete\"],function(i){});\n</script>\n\n<div class=\"embeddedobject inlinecta \" id=\"inlinebutton\"><div class=\"inlinecta__content\"><div class=\"inlinecta__title \"></div><a class=\"inlinecta__button \" href=\"#\" onclick=\"psa.showChat(true); return false;\">Okay, let's start!</a><div class=\"inlinecta__description\"></div></div></div>\n*/\n\nimport { loadCSS, loadScript, onDomReady, register } from \"@webhare/dompack\";\n\nregister(\".js-psa-chatbot\", (node: HTMLElement) => {\n  //PSA Chatbot 'Sam' initializing. Load the CSS right away\n  const cssPromise = loadCSS(\"/repository/utwente-data/psa/css/chat.css\");\n  //But delay script loads until the DOM is ready and (by extension) all ws2016 code has parsed\n  const psaPromise: Promise<any> = (async () => {\n    await new Promise<void>(r => onDomReady(r));\n    await loadScript(\"/repository/utwente-data/psa/build/autocomplete.js\"); //we load them one-by-one, as they were originall edsigned to\n    await loadScript(\"/repository/utwente-data/psa/build/require.js\");\n    await cssPromise;\n\n    /* require.config({\n          baseUrl: \"/repository/utwente-data/psa/build\",\n          paths:{App:\"build/app\"}\n          });\n        require([\"app\"],function(i) {\n          psa=new i.ApplicationAssistant;\n          psa.init()\n        });\n      requirejs([\"autocomplete\"],function(i){});\n      */\n\n    //So first we 'require.config' the loader\n    //And then we launch both app and autocomplete, apparently they accept a callback, so we can just use promises for those\n\n    const req: any = globalThis.require;\n    req.config({\n      baseUrl: \"/repository/utwente-data/psa/build\",\n      paths: { App: \"build/app\" }\n    });\n\n    const loadApp = await new Promise<any>(resolve => req([\"app\"], (i: any) => resolve(i)));\n    await new Promise<any>(resolve => req([\"autocomplete\"], (i: any) => resolve(i)));\n    const psa = new loadApp.ApplicationAssistant;\n    psa.init();\n    return psa;\n  })();\n\n  node.addEventListener(\"click\", (e) => {\n    e.preventDefault();\n    void psaPromise.then(psa => psa.showChat(true));\n  });\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"@webhare/dompack\";\nimport { getCSSVariable } from \"@mod-utwente_base/webdesigns/ws2016/src/shared/layout-tools\";\nimport SlideShow from \"@mod-utwente_base/webdesigns/ws2016/src/shared/slideshow\";\nimport makeTextFit from \"@mod-utwente_base/webdesigns/ws2016/src/shared/wh.layout.autofit\";\nimport * as videotools from \"@mod-utwente_base/webdesigns/ws2016/src/components/video\";\nimport { UniverseAnimation } from \"../shared/universe\";\n\nconst videoSlideTimeout = 8000;\n\ndompack.register(\".contentpart__header > .contentpart__header-messagesarea\", node => {\n  node.parentNode.before(<div class=\"contentpart__header-messagesarea-wrapper\">{node}</div>);\n});\n\n// Catch click on header tags incase tag content is hidden (mobile)\ndompack.register(\".contentpart__header-tags\", node => {\n  node.addEventListener(\"click\", ev => {\n    const tag = ev.target.closest(\".contentpart__header-tag\");\n    if (!tag)\n      return;\n\n    if (ev.target.tagName !== \"A\")\n      tag.classList.add(\"contentpart__header-tag--expanded\");\n  });\n});\n\n// -----------------------------------------------------------------------------\n//\n// Header CTA title scaling\n//\n\nclass HeaderCTAScaler {\n  constructor(node) {\n    this.node = node;\n    this.headerNode = this.node.closest(\".contentpart__header-cta\");\n    this.containerNode = this.node.querySelector(\".cta__textholder\");\n    this.titleNode = this.node.querySelector(\".cta__title\");\n    if (!this.containerNode || !this.titleNode)\n      return;\n\n    // If this is a header with filters, the CTA is positioned above the title instead of over it, so its height doesn't\n    // have to be restrained\n    this.headerWithFilters = this.node.closest(\".contentpart__header--withfilters\");\n\n    // Scale text on window resize\n    this.scaling = null;\n    this.resizeHandler = () => this.scaling = this.scaling || requestAnimationFrame(() => this.scaleText());\n    window.addEventListener(\"resize\", this.resizeHandler);\n    window.addEventListener(\"load\", this.resizeHandler);\n\n    // Read the breakpoint CSS variable and get a MediaQueryList\n    getCSSVariable(\"--breakpoint-tablet\").then(breakpoint_tablet => {\n      const flatCTAMedia = matchMedia(`(max-width: ${breakpoint_tablet})`);\n      // Setup an onchange listener\n      flatCTAMedia.addEventListener(\"change\", event => this.flatCTA = event.matches);\n      // Directly check the query and rescale\n      this.flatCTA = flatCTAMedia.matches;\n      this.resizeHandler();\n    });\n  }\n\n  scaleText() {\n    this.scaling = null;\n\n    makeTextFit(this.titleNode,\n      {\n        maxwidth: this.containerNode.clientWidth,\n        maxheight: this.flatCTA ? this.headerNode.clientHeight * .3 : !this.headerWithFilters ? this.headerNode.clientHeight - 40 : this.containerNode.clientWidth * .6,\n\n        node_applystyle: this.titleNode,\n        node_measurewidth: this.titleNode,  // The final (possible overflowing) width of text (if we measure using header CTA, we don't detect overflow due to unbreakable lines/words)\n        node_measureheight: this.node, // The final height of text + CTA determines whether this is a fit\n\n        minfontsize: 20,\n        maxfontsize: 40,\n        fontsizethreshold: 1,\n        lineheight: \"100%\"\n\n        //, debug:              true\n      });\n  }\n}\n\ndompack.register(\".headercta\", node => new HeaderCTAScaler(node));\n\n\n// -----------------------------------------------------------------------------\n//\n// Header photo slideshow\n//\n\ndompack.register(\".contentpart__header--photos\", node => {\n  // Initialize the header photo slideshow\n  new SlideShow(node.querySelectorAll(\".contentpart__header-slide\"),\n    {\n      dotNodes: node.querySelectorAll(\".contentpart__header-sliderdot\"),\n      pauseNode: node\n    });\n});\n\n\n// -----------------------------------------------------------------------------\n//\n// Header homepage videos\n//\n\nclass VideoSlideShow {\n  constructor(node, videoClass) {\n    this.node = node;\n    this.videos = [];\n    this.curVideo = -1;\n    this.active = false;\n    this.fallbackTimeout = null;\n    this.autoplaySupported = null;\n    this.videoClass = videoClass;\n\n    const videoNodes = this.node.querySelectorAll(`.${this.videoClass}`);\n    if (videoNodes.length == 0)\n      return; // our header is empty\n\n    for (const videoNode of videoNodes)\n      if (videoNode.hasAttribute(\"data-video\"))\n        this.videos.push({ node: videoNode });\n\n    // Read the breakpoint CSS variable and get a MediaQueryList\n    getCSSVariable(\"--breakpoint-deeplinks\").then(breakpoint_deeplinks => {\n      const videoPauseMedia = matchMedia(`(max-width: ${breakpoint_deeplinks})`);\n      // Setup an onchange listener\n      videoPauseMedia.addEventListener(\"change\", event => this.checkVideo(event.matches));\n      // Directly check the query and maybe start video\n      this.checkVideo(videoPauseMedia.matches);\n    });\n  }\n\n  checkVideo(pauseVideo) {\n    if (pauseVideo)\n      this.pauseVideo();\n    else\n      this.startVideo();\n  }\n\n  startVideo() {\n    this.active = true;\n    // There is no video loaded yet, load the first video, otherwise play the\n    // current video\n    if (this.curVideo < 0)\n      this.nextVideo();\n    else if (this.autoplaySupported === false)\n      this.fallbackTimeout = setTimeout(() => this.nextVideoSlide(), videoSlideTimeout);\n    else\n      this.videos[this.curVideo].player.play();\n  }\n\n  pauseVideo() {\n    this.active = false;\n    // If there is a video loaded, pause it\n    if (this.autoplaySupported === false)\n      this.fallbackTimeout = clearTimeout(this.fallbackTimeout);\n    else if (this.curVideo >= 0)\n      this.videos[this.curVideo].player.pause();\n  }\n\n  async nextVideo() {\n    if (!this.active)\n      return;\n\n    if (++this.curVideo >= this.videos.length)\n      this.curVideo = 0;\n\n    const video = this.videos[this.curVideo];\n    if (!videotools.isVideoNodeInitialized(video.node)) {\n      // Initialize and load the video\n      video.player = await videotools.initializeVideoNode(video.node);\n\n      // If the video started playing, hide the poster image\n      video.node.addEventListener(\"video:play\", () => this.videoStarted());\n\n      // If the video has finished playing, show the next video\n      video.node.addEventListener(\"video:finish\", () => this.nextVideo());\n\n      // Start the video when it's ready\n      video.node.addEventListener(\"video:ready\", () => this.playVideo());\n    } else if (video.player) {\n      // Resume/replay the video\n      this.playVideo();\n    }\n  }\n\n  playVideo() {\n    const video = this.videos[this.curVideo];\n\n    // Show the current video's poster image\n    video.node.classList.add(`${this.videoClass}--current`);\n\n    // Hide the previous video\n    let prevVideo = this.curVideo - 1;\n    if (prevVideo < 0)\n      prevVideo = this.videos.length - 1;\n    this.videos[prevVideo].node.classList.remove(`${this.videoClass}--current`, `${this.videoClass}--playing`);\n\n    // Start the video\n    video.player.play();\n\n    // Set a timeout to check if the video is actually playing\n    if (!this.fallbackTimeout)\n      this.fallbackTimeout = setTimeout(() => this.videoFallback(), videoSlideTimeout);\n  }\n\n  videoStarted() {\n    // Remove the poster image\n    this.videos[this.curVideo].node.classList.add(`${this.videoClass}--playing`);\n    // Clear the fallback timeout, fallback isn't needed\n    this.fallbackTimeout = clearTimeout(this.fallbackTimeout);\n    // If this function is called, we know autoplay is supported\n    this.autoplaySupported = true;\n  }\n\n  videoFallback() {\n    // If this function is called, the video never actually started playing\n    console.warn(\"Video fallback mode activated\");\n    this.autoplaySupported = false;\n    this.node.querySelector(\".contentpart__header-videos\").classList.add(\"contentpart__header-videos--fallback\");\n    // Force CSS recalculation\n    this.videos[this.curVideo].node._wsTmpTransition = getComputedStyle(this.videos[this.curVideo].node).transition;\n\n    // Show next video poster slide\n    this.nextVideoSlide();\n  }\n\n  nextVideoSlide() {\n    if (!this.active)\n      return;\n\n    if (++this.curVideo >= this.videos.length)\n      this.curVideo = 0;\n\n    // Show the new video poster slide\n    this.videos[this.curVideo].node.classList.add(`${this.videoClass}--current`);\n\n    // Hide the previous video poster slide\n    let prevVideo = this.curVideo - 1;\n    if (prevVideo < 0)\n      prevVideo = this.videos.length - 1;\n    this.videos[prevVideo].node.classList.remove(`${this.videoClass}--current`);\n\n    // Show next video poster slide after timeout\n    this.fallbackTimeout = setTimeout(() => this.nextVideoSlide(), videoSlideTimeout);\n  }\n}\n\ndompack.register(\".contentpart__header--homevideo\", node => new VideoSlideShow(node, \"contentpart__header-video\"));\n\n\n// -----------------------------------------------------------------------------\n//\n// Header universe animation\n//\n\ndompack.register(\"html:not(.ws2016--iframed) .contentpart__header-universe\", node => new UniverseAnimation(node));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\"; //needed for jsx-like element creation\nimport * as whintegration from \"@mod-system/js/wh/integration\";\nimport \"./universe.scss\";\n\n/*\nelement with class \"universe\" get a universe svg element injected.\ndefault this universe elements gets standard site color animation\nIf the element contains data-color=\"[hexcolor/colorname]\" then animation is discared and the given (fill) color will be set\n*/\n\nexport class UniverseAnimation {\n  constructor(node) {\n    if (!whintegration.config.site.universeelements || dompack.debugflags.unh)\n      return;\n\n    const prevelement = localStorage[\"ucs-element\"] || \"\";\n\n    this.node = node;\n    this.element = null;\n    if (node.dataset.element || window.__pageuniverse) {\n      // Get preselected element and keep same universe element within same page\n      const elementname = window.__pageuniverse ? window.__pageuniverse.toUpperCase() : node.dataset.element.toUpperCase();\n      if (elementname == \"-NONE-\")\n        this.element = elementname;\n      else\n        this.element = whintegration.config.site.universeelements.filter(_ => _.filename.toUpperCase() == elementname).shift();\n    }\n    if (!this.element) {\n      // Get random element but skip previous used element\n      const elements = whintegration.config.site.universeelements.filter(_ => _.filename != prevelement);\n      this.element = elements[~~(Math.random() * elements.length)];\n    }\n\n    if (!this.element || this.element == \"-NONE-\")\n      return;\n\n    // Keep same universe element within same page\n    window.__pageuniverse = this.element.filename;\n    localStorage[\"ucs-element\"] = this.element.filename;\n\n    this.fetchSVG();\n  }\n\n  async fetchSVG() {\n    const url = \"https://utwente.becdn.net/.publisher/sd/utwente_base/ws2016/elements/\" + this.element.filename;\n\n    let response;\n    try {\n      response = await fetch(url, { cache: \"reload\" });\n    } catch (e) { }\n\n    if (!response || response.status != 200) {\n      console.error(\"Error loading universe element from: \" + url);\n      return;\n    }\n\n    const content = await response.text();\n    const parser = new DOMParser();\n    let svg = parser.parseFromString(content, \"image/svg+xml\");\n    svg = svg.documentElement;\n\n    svg.style.width = this.element.width + \"px\";\n    svg.style.marginTop = this.element.top + \"px\";\n\n    this.animcontainer = <div class=\"universe__container\" />;\n    this.animcontainer.appendChild(svg);\n    if (!dompack.debugflags.unr) {\n      this.animcontainer.classList.add(\"universe__container--animate\");\n      if (svg.classList.contains(\"universe__container--reverse\"))\n        this.animcontainer.classList.add(\"universe__container--reverse\");\n    }\n\n    this.node.appendChild(this.animcontainer);\n    this.node.clientWidth;//force css update\n\n    this.animcontainer.style.width = svg.clientWidth + \"px\";\n    this.animcontainer.style.height = svg.clientHeight + \"px\";\n\n    svg.style.marginLeft = this.element.left - ~~(svg.clientWidth / 2) + \"px\";\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport * as browser from 'dompack/extra/browser';\nimport { observeNodeResize, unobserveNodeResize } from \"@mod-utwente_base/webdesigns/ws2016/src/components/resizeobserver\";\nimport * as searchSheet from \"@mod-utwente_base/webdesigns/ws2016/src/shared/searchsheet\";\nimport { getCSSVariable, setCSSVariable } from \"@mod-utwente_base/webdesigns/ws2016/src/shared/layout-tools\";\nimport SiteMenu from \"./sitemenu\";\n// webdesign node modules aren't accessible from webfeatures, load them directly\nimport PerfectScrollbar from \"@mod-utwente_design/vendor/perfect-scrollbar-wh\";\nimport { setupLanguageSwitch } from \"./langswitch\";\n\n// -----------------------------------------------------------------------------\n//\n// Menu hidden media query\n//\n\n// Read the breakpoint CSS variable and get a MediaQueryList, returns the MediaQueryList if already available, or a Promise\n// that resolves with the MediaQueryList\nlet _hiddenMenuMedia, _hiddenMenuMediaPromise;\nfunction getHiddenMenuMedia() {\n  if (!_hiddenMenuMedia) {\n    if (!_hiddenMenuMediaPromise)\n      _hiddenMenuMediaPromise = new Promise(resolve => {\n        getCSSVariable(\"--breakpoint-menuhidden\").then(breakpoint_menuhidden => {\n          _hiddenMenuMedia = matchMedia(`(max-width: ${breakpoint_menuhidden})`);\n          resolve(_hiddenMenuMedia);\n        });\n      });\n    return _hiddenMenuMediaPromise;\n  }\n  return _hiddenMenuMedia;\n}\n\n\n// -----------------------------------------------------------------------------\n//\n// Showing/hiding menu\n//\n\nexport function toggleMenu(state) {\n  // Toggle the menu\n  document.documentElement.classList.toggle(\"utwente--menuopen\", state);\n  dompack.dispatchCustomEvent(window, \"ws:menu-open\", { bubbles: true, cancelable: false, detail: { open: document.documentElement.classList.contains(\"utwente--menuopen\") } });\n  // Close any open navigation menus\n  for (const node of document.querySelectorAll(\".contentpart__topmenuitem--hasmenu\"))\n    node.classList.remove(\"contentpart__topmenuitem--menuopen\");\n}\n\n// Activate the menu transition only if the menu is hidden, to prevent the menu sliding out when the screen gets smaller\nfunction toggleMenuTransition(node, active) {\n  if (active)\n    requestAnimationFrame(() => {\n      document.documentElement.classList.add(\"utwente--menuhidden\");\n      getComputedStyle(node).transition;\n    });\n  else {\n    document.documentElement.classList.remove(\"utwente--menuhidden\");\n    getComputedStyle(node).transition;\n    toggleMenu(false);\n  }\n}\n\ndompack.register(\".contentpart__hamburger\", node => {\n  node.addEventListener(\"click\", event => {\n    event.preventDefault();\n    event.stopPropagation();\n\n    toggleMenu();\n  });\n});\n\ndompack.register(\".menupart__modalbg\", node => {\n  node.addEventListener(\"wheel\", event => {\n    event.preventDefault();\n    event.stopPropagation();\n  }, { passive: false }); // explicitly mention we will cancel scrolling so Chrome doesn't give \"Violation\" warnings in the console\n  node.addEventListener(\"touchstart\", event => {\n    if (!event.target.closest(\".contentpart__hamburger\")) {\n      event.preventDefault();\n      event.stopPropagation();\n    }\n  }, { passive: false }); // explicitly mention we will cancel scrolling so Chrome doesn't give \"Violation\" warnings in the console\n});\n\ndompack.register(\".menupart\", async node => {\n  // Setup an onchange listener\n  const media = await getHiddenMenuMedia();\n  media.addEventListener(\"change\", event => toggleMenuTransition(node, event.matches));\n  // Directly check the query\n  toggleMenuTransition(node, media.matches);\n  // Activate the background transition (if it's activated by default, it causes a white flash for a grey background)\n  requestAnimationFrame(() => node.classList.add(\"menupart--activetransition\"));\n});\n\n\n// -----------------------------------------------------------------------------\n//\n// Navigating menu\n//\n\n\ndompack.register(\".menupart__menu\", node => new SiteMenu(node));\n\n\n// -----------------------------------------------------------------------------\n//\n// Activating search\n//\n\ndompack.register(\".contentpart__topmenuitem--search\", node => {\n  node.addEventListener(\"click\", event => {\n    event.preventDefault();\n    event.stopPropagation();\n\n    searchSheet.toggle();\n    toggleMenu(false);\n  });\n});\n\n\n// -----------------------------------------------------------------------------\n//\n// Breadcrumbs\n//\n\nclass BreadcrumbList {\n  constructor(node) {\n    this.node = node;\n\n    // The padding is needed to quickly calculate the total height of the element using contentRect if borderBoxSize is\n    // not available on older browsers\n    const style = getComputedStyle(this.node);\n    this.padding = parseInt(style.paddingLeft) + parseInt(style.paddingRight);\n\n    // Get a list of all breadcrumbs\n    this.itemNodes = [...this.node.childNodes];\n    this.itemWidths = [];\n    this.listWidth = 0;\n    // Add the ellipsis (which can be clicked to show all breadcrumbs)\n    const ellipsisNode = <span class=\"contentpart__breadcrumbitem contentpart__breadcrumbitem--ellipsis\">&hellip;</span>;\n    this.node.append(ellipsisNode);\n    ellipsisNode.addEventListener(\"click\", event => this.unshortenBreadcrumbList(event));\n    // Initial check\n    this.checkShortenBreadcrumbList({ boundingClientRect: this.node.getBoundingClientRect() });\n  }\n\n  checkShortenBreadcrumbList(entry) {\n    if (!this.observing) {\n      this.observing = true;\n      // Check upon resize\n      observeNodeResize(this.node, entry => this.checkShortenBreadcrumbList(entry));\n    }\n\n    let width;\n    if (entry.borderBoxSize) // spec\n      width = entry.borderBoxSize[0].inlineSize;\n    else if (entry.contentRect) // fallback for older browsers that don't have borderBoxSize\n      width = entry.contentRect.width + this.padding;\n    else // polyfilled for even older browsers that don't have ResizeObserver\n      width = entry.boundingClientRect.width;\n    if (!width)\n      return; // Not visible\n\n    // Calculate item sizes\n    if (!this.listWidth) {\n      this.node.classList.add(\"contentpart__breadcrumblist--measure\");\n      if (this.node.clientWidth) // Force CSS update, check if visible\n      {\n        // Iterate over all child nodes, including the ellipsis node\n        for (const childNode of this.node.childNodes) {\n          const width = Math.ceil(childNode.getBoundingClientRect().width);\n          this.itemWidths.push(width);\n          // For the width to check, only consider the breadcrumbs\n          if (!childNode.classList.contains(\"contentpart__breadcrumbitem--ellipsis\"))\n            this.listWidth += width;\n        }\n      }\n      this.node.classList.remove(\"contentpart__breadcrumblist--measure\");\n    }\n\n    // Calculate the list's content width\n    const styles = getComputedStyle(this.node);\n    width = Math.floor(width - parseFloat(styles.paddingLeft) - parseFloat(styles.paddingRight));\n    // We must shorten if there's not enough room for all breadcrumbs\n    const shorten = width < this.listWidth;\n    this.node.classList.toggle(\"contentpart__breadcrumblist--shorten\", shorten);\n    if (shorten) {\n      // From right to left, hide the breadcrumb if there's not enough room for it\n      let itemsWidth = this.itemWidths[this.itemNodes.length]; // ellipsis width\n      for (let item = this.itemNodes.length - 1; item >= 0; --item) {\n        itemsWidth += this.itemWidths[item];\n        this.itemNodes[item].classList.toggle(\"contentpart__breadcrumbitem--hide\", itemsWidth > width);\n      }\n    }\n  }\n\n  unshortenBreadcrumbList() {\n    // Once unshortened, the breadcrumb list won't be shortened again, so we no longer have to observe node resizes\n    unobserveNodeResize(this.node);\n    this.node.classList.remove(\"contentpart__breadcrumblist--shorten\");\n  }\n}\n\ndompack.register(\".contentpart__breadcrumblist\", node => new BreadcrumbList(node));\n\n\n// -----------------------------------------------------------------------------\n//\n// Showing/hiding navbar menu\n//\n\n/*\n  This class takes care of not immediately closing the menu if the mouse cursor leaves the menu node briefly when moving down\n  diagonally from the menu button to the menu itself. The downside of this approach is that the menu only closes after a\n  timeout, even when not moving toward the menu.\n*/\n\nconst NAVIGATIONMENU_CLOSE_TIMEOUT = 200;\n\nclass NavigationMenu {\n  constructor(node) {\n    this.node = node;\n    this.isPartnerMenu = node.classList.contains(\"contentpart__topmenuitem--partners\");\n\n    if (this.isPartnerMenu) {\n      node.addEventListener(\"mousedown\", event => this.onMouseDown(event));\n      node.addEventListener(\"touchstart\", event => this.onTouchStart(event), { passive: false }); // explicly signal we might cancel the scroll (so Chrome won't give a violation for not specifying passive)\n      node.addEventListener(\"touchend\", event => this.onTouchEnd(event));\n    } else {\n      node.addEventListener(\"mouseenter\", event => this.onMouseEnter(event));\n      node.addEventListener(\"mouseleave\", event => this.onMouseLeave(event));\n      node.addEventListener(\"touchstart\", event => this.onTouchStart(event), { passive: false }); // explicly signal we might cancel the scroll (so Chrome won't give a violation for not specifying passive)\n      node.addEventListener(\"touchend\", event => this.onTouchEnd(event));\n    }\n  }\n\n  toggleMenu(force) {\n    if (this.isPartnerMenu && !this.node.classList.contains(\"contentpart__topmenuitem--menuopen\")) {\n      // The partner popup menu has a fixed width, but we want the 'Hide partners' text to overlap the 'Partners' button, so\n      // we'll adjust the partner popup navbar padding to align the close text\n\n      // Distance between left of 'Partners' and right side of screen\n      const navbarWidth = window.innerWidth - this.node.getBoundingClientRect().left;\n      // Popup menu width\n      const menuWidth = this.node.querySelector(\".contentpart__topsubmenu\").getBoundingClientRect().width;\n      // Width of 'Hide Partners' and X close button\n      const closeWidth = [...this.node.querySelectorAll(\".partnermenu__close\")].map(_ => _.getBoundingClientRect().width).reduce((acc, cur) => acc + cur);\n      // Set the padding to the space between the left of the menu and the left of 'Partners', but make sure the padding plus\n      // the width of 'Hide Partners' and the X close button doesn't exceed the menu width\n      const padding = Math.floor(Math.min(Math.max(menuWidth - navbarWidth, 0), menuWidth - closeWidth));\n      this.node.querySelector(\".partnermenu__navbar\").style.paddingLeft = `${padding}px`;\n    }\n    this.node.classList.toggle(\"contentpart__topmenuitem--menuopen\", force);\n  }\n\n  onMouseEnter() {\n    // Clear the closing menu timeout\n    if (this.mouseTimeout) {\n      clearTimeout(this.mouseTimeout);\n      this.mouseTimeout = 0;\n    }\n    this.toggleMenu(true);\n  }\n\n  onMouseLeave() {\n    if (dompack.debugflags[\"ut-nomenuclose\"])\n      return;\n\n    // Close the menu after a timeout\n    if (this.mouseTimeout)\n      clearTimeout(this.mouseTimeout);\n    this.mouseTimeout = setTimeout(() => this.onMouseTimeout(), NAVIGATIONMENU_CLOSE_TIMEOUT);\n  }\n\n  onMouseTimeout() {\n    this.toggleMenu(false);\n    this.mouseTimeout = 0;\n  }\n\n  onMouseDown(event) {\n    if (event.button != 0)\n      return;\n    const closing = event.target.closest(\".partnermenu__close\");\n    this.toggleMenu(!closing);\n  }\n\n  onTouchStart(event) {\n    if (!event.target.closest(\".contentpart__topsubmenu\"))\n      dompack.stop(event);\n  }\n\n  onTouchEnd(event) {\n    if (dompack.debugflags[\"ut-nomenuclose\"])\n      return;\n\n    // a touch outside the pulldown panel of a n topmenuitem must close the menu\n    if (!event.target.closest(\".contentpart__topsubmenu\")) {\n      if (this.isPartnerMenu) {\n        const closing = event.target.closest(\".partnermenu__close\");\n        this.toggleMenu(!closing);\n      } else\n        this.toggleMenu();\n    }\n  }\n}\n\ndompack.register(\".contentpart__topmenuitem--hasmenu\", node => new NavigationMenu(node));\n\n\n// -----------------------------------------------------------------------------\n//\n// Showing/hiding navbar container on scroll\n//\n\nclass NavBarContainerScroller {\n  constructor(node) {\n    // FIXME: when we force the menu to be closed the height or positioning of the .contentpart__navbar-container\n    //        gets messed up when you scroll\n    if (document.documentElement.classList.contains(\"ut--menuhiddenbydefault\"))\n      return;\n\n    this.node = node;\n    this.hamburgerNode = this.node.querySelector(\".contentpart__hamburger-container\");\n    this.lastScrollY = -1;\n    this.lastScrollDown = null;\n    // Check on scroll\n    window.addEventListener(\"scroll\", event => this.onScroll(event));\n    getHiddenMenuMedia().then(media => {\n      // Setup an onchange listener\n      media.addEventListener(\"change\", event => this.onMenuActive(event.matches));\n      // Directly check the query\n      this.onMenuActive(media.matches);\n    });\n    getCSSVariable(\"--breakpoint-deeplinks\").then(breakpoint_deeplinks => {\n      const media = matchMedia(`(max-width: ${breakpoint_deeplinks})`);\n      // Setup an onchange listener\n      media.addEventListener(\"change\", event => this.onDeeplinksHidden(event.matches));\n      // Directly check the query\n      this.onDeeplinksHidden(media.matches);\n    });\n  }\n\n  onMenuActive(visible) {\n    this.menuActive = visible;\n    // If the menu is not active (desktop mode), reset the height to fall back to intrinsic height, check the scroll state\n    if (!this.menuActive)\n      this.node.style.height = null;\n    else if (this.lastScrollDown !== null)\n      this.handleScroll();\n  }\n\n  onDeeplinksHidden(hidden) {\n    // When the deeplinks are hidden and the h2 are collapsed, reset and recalculate the height (prevent the page from being\n    // scrolled beyond the footer when the browser resizes)\n    if (hidden) {\n      this.node.style.height = null;\n      this.handleScroll();\n    }\n  }\n\n  onScroll(event) {\n    // Skip when menu is not active (desktop mode) or this is an initial window scroll event\n    if (!this.menuActive || (event && event.target == window))\n      return;\n\n    // Throttle scroll callback through animation frame\n    this.waiting = this.waiting || requestAnimationFrame(() => {\n      this.handleScroll();\n      this.waiting = null;\n    });\n  }\n\n  handleScroll() {\n    if (window.scrollY != this.lastScrollY) {\n      // Check vertical overshoot (bounce)\n      if (window.scrollY < 0 || window.scrollY + window.innerHeight > document.body.scrollHeight)\n        return;\n\n      // Check scroll direction\n      const scrollDown = window.scrollY > this.lastScrollY;\n      if (scrollDown != this.lastScrollDown) {\n        this.lastScrollDown = scrollDown;\n        // Only update if the navbar isn't partially scrolled into view\n        if (this.lastScrollY < (this.node.clientHeight - this.node.firstChild.clientHeight) || this.lastScrollY > this.node.clientHeight) {\n          // When scrolling down, set the height of the navbar container to the current scroll top + the navbar block height,\n          // so the navbar will scroll out of view when further scrolling down\n          // When scrolling up, set the height of the navbar container to the scroll height, so the navbar will scroll into\n          // view when further scrolling up and stay at the top of the page\n\n          //console.log(scrollDown, window.scrollY, this.node.firstChild.clientHeight);\n          const nodeHeight = scrollDown ? window.scrollY + this.node.firstChild.clientHeight : window.scrollY;\n          this.node.style.height = `${nodeHeight}px`;\n          this.hamburgerNode.style.height = `${this.node.parentNode.clientHeight - nodeHeight}px`;\n        }\n      }\n      this.lastScrollY = window.scrollY;\n    }\n  }\n}\n\ndompack.register(\".contentpart__navbar-container\", node => new NavBarContainerScroller(node));\n\n\n// -----------------------------------------------------------------------------\n//\n// Update header top margin upon navbar height change\n//\n\nclass HeaderResizer {\n  constructor(node) {\n    this.node = node;\n\n    // The padding is needed to quickly calculate the total height of the element using contentRect if borderBoxSize is\n    // not available on older browsers\n    const style = getComputedStyle(this.node);\n    this.padding = parseInt(style.paddingTop) + parseInt(style.paddingBottom);\n\n    setCSSVariable(\"--header-navbar-height\", `${this.node.getBoundingClientRect().height}px`);\n\n    //TODO: If we're sure the header doesn't change in height, we don't have to observe\n    observeNodeResize(this.node, entry => this.onResize(entry));\n  }\n\n  onResize(entry) {\n    let navbarHeight;\n    if (entry.borderBoxSize) // spec\n      navbarHeight = entry.borderBoxSize[0].blockSize;\n    else if (entry.contentRect) // fallback for older browsers that don't have borderBoxSize\n      navbarHeight = entry.contentRect.height + this.padding;\n    else // polyfilled for even older browsers that don't have ResizeObserver\n      navbarHeight = entry.boundingClientRect.height;\n\n    setCSSVariable(\"--header-navbar-height\", `${navbarHeight}px`);\n  }\n}\n\ndompack.register(\".contentpart__navbar-block\", node => new HeaderResizer(node));\n\n\n// -----------------------------------------------------------------------------\n//\n// Position mobile partner menu at bottom of screen\n//\n\n// If the mobile menu is visible, position the 'partner' menu at the bottom of the screen. We cannot use 'bottom: 0' or\n// 'top: calc(10vw - height)' or something like that, as these properties are all based on the maximum size, with the address\n// bar hidden. If the address bar is visible, the item would be obscured by browser chrome.\nclass PartnerMenuPositioner {\n  constructor(node) {\n    this.node = node;\n\n    this.menuActive = false;\n    this.menuOpen = false;\n    this.resizeHandler = () => this.onResize();\n\n    getHiddenMenuMedia().then(media => {\n      // Setup an onchange listener\n      media.addEventListener(\"change\", event => this.onMenuActive(event.matches));\n      // Directly check the query\n      this.onMenuActive(media.matches);\n    });\n    window.addEventListener(\"ws:menu-open\", event => this.onMenuOpen(event.detail.open));\n    this.handleResize();\n  }\n\n  onMenuActive(visible) {\n    this.menuActive = visible;\n    this.checkEventHandlers();\n  }\n\n  onMenuOpen(open) {\n    this.menuOpen = open;\n    if (this.menuActive && this.menuOpen)\n      this.handleResize();\n    this.checkEventHandlers();\n  }\n\n  checkEventHandlers() {\n    if (this.menuActive && this.menuOpen) {\n      window.addEventListener(\"resize\", this.resizeHandler);\n      window.addEventListener(\"scroll\", this.resizeHandler);\n    } else {\n      window.removeEventListener(\"resize\", this.resizeHandler);\n      window.removeEventListener(\"scroll\", this.resizeHandler);\n    }\n  }\n\n  onResize() {\n    // Throttle resize/scroll callback through animation frame\n    this.waiting = this.waiting || requestAnimationFrame(() => {\n      this.handleResize();\n      this.waiting = null;\n    });\n  }\n\n  handleResize() {\n    if (window.innerHeight != this.curHeight) {\n      this.curHeight = window.innerHeight;\n      setCSSVariable(\"--vh\", `${this.curHeight / 100}px`);\n    }\n  }\n}\n\ndompack.register(\".contentpart__topmenuitem--partners\", node => new PartnerMenuPositioner(node));\n\n\n// -----------------------------------------------------------------------------\n//\n// Deeplinks scrollbar\n//\n\ndompack.register(\".main__deeplinks\", node => {\n  if (browser.getPlatform() != \"ios\" && browser.getPlatform() != \"android\") {\n    const ps = new PerfectScrollbar(node, {\n      swipePropagation: false,\n      wheelPropagation: false,\n      suppressScrollX: true\n    });\n    window.addEventListener(\"resize\", () => requestAnimationFrame(() => ps.update()));\n  }\n});\n\nsetupLanguageSwitch();\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"@webhare/dompack\";\nimport KeyboardHandler from \"dompack/extra/keyboard\";\nimport { debugFlags } from \"@webhare/env\";\nimport { JustifiedImageGrid } from \"@webhare/dompack-justifiedcontentgrid\";\nimport { getTid, getHTMLTid } from \"@webhare/gettid\";\nimport * as pxl from \"@mod-consilio/js/pxl\";\nimport PerfectScrollbar from \"@mod-utwente_design/vendor/perfect-scrollbar-wh\";\nimport searsia from \"@mod-utwente_base/web/pub/ws2016/searsia\";\nimport {\n  MIN_SUGGEST_LENGTH,\n  NUM_SUGGESTIONS,\n  NUM_RELATED,\n  SEARSIA_SOURCES,\n  SEARSIA_DUPLICATE_RESOURCES,\n  QUERY_STOPWORDS\n} from \"@mod-utwente_base/web/pub/ws2016/searsiaconfig\";\nimport * as managedctas from \"@mod-utwente_base/webdesigns/ws2016/src/shared/crm/managedctas\";\n\nimport * as crm from \"../crm\";\nimport setupShowAllLinks from \"../showalllinks\";\nimport SearsiaAutoSuggest from \"./searsiasuggest\";\nimport * as searsiaTypes from \"./searsiatypes\";\nimport { showSearsiaWidgets } from \"./searsiawidgets\";\n\nimport \"./searchsheet.scss\";\nimport '../fonts/ut-search-iconfont.css';\n\n\nconst resultScoreProp = Symbol(\"result-score\");\nconst resultLangProp = Symbol(\"result-lang\");\nconst resultSourceProp = Symbol(\"result-source\");\n\nlet searsiaClient;\nexport let defaultSearchType = \"all\";\n\n//ADDME: Certainly not the most optimized implementation...\nfunction isSubArray(master, sub) {\n  for (let i = 0; i < master.length; ++i) {\n    if (master[i] === sub[0]) {\n      let j;\n      for (j = 0; j < sub.length; ++j)\n        if (master[i + j] !== sub[j])\n          break;\n      if (j === sub.length) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nclass SearsiaClient {\n  inputNode: HTMLInputElement;\n\n  constructor(public node: HTMLElement) {\n    this.inputNode = dompack.qR(node, \".searchsheet__searchfield\");\n    this.headerNode = node.querySelector(\".searchsheet__searchform\");\n    this.statusNode = node.querySelector(\".searchsheet__status\");\n    this.resultsNode = node.querySelector(\".searsia__results\");\n    this.suggestNode = node.querySelector(\".searchsheet__suggestions\");\n    this.ctaslots = [];\n\n    this.haveResults = false;\n    this.searsiaSession = \"\";\n\n    this.headerNode.addEventListener(\"transitionend\", event => this.onTransitioned(event));\n    this.inputNode.addEventListener(\"focus\", event => this.onInputFocus(event));\n    this.inputNode.addEventListener(\"blur\", event => this.onInputFocus(event));\n    this.inputNode.addEventListener(\"searsia:showsuggestions\", event => this.onShowSuggestions(event));\n    this.inputNode.addEventListener(\"searsia:hidesuggestions\", event => this.onHideSuggestions(event));\n    this.inputNode.addEventListener(\"searsia:searchsuggestion\", event => this.onStartSearch(event));\n    this.inputNode.form.addEventListener(\"submit\", event => this.onStartSearch(event));\n    new KeyboardHandler(this.inputNode, { \"Escape\": () => this.reset() });\n    this.statusNode.addEventListener(\"click\", event => this.onClickStatus(event));\n    this.resultsNode.addEventListener(\"click\", event => this.onClickResult(event));\n\n    this.lang = (document.documentElement.lang || \"\").split(\"-\")[0];\n    this.stopwordfilters = (QUERY_STOPWORDS[this.lang] || []).map(_ => new RegExp(`((^|\\\\s+)${_}(\\\\s+|$))`, \"i\"));\n\n    // Collect user data for search CTA matching\n    this.userCountry = crm.getUserCountry();\n    if (!this.userCountry) {\n      if (debugFlags.umc)\n        console.log(`[umc] Requesting user country`);\n      void crm.requestGeoIP().then(country => {\n        this.userCountry = country;\n        console.log(`[umc] User country '${this.userCountry}'`);\n      });\n    } else if (debugFlags.umc)\n      console.log(`[umc] User country '${this.userCountry}'`);\n    this.userBeacons = crm.getUserBeacons();\n    if (debugFlags.umc)\n      console.log(`[umc] User beacons`, this.userBeacons);\n\n    this.url = new URL(location.href);\n\n    this.searchType = this.url.searchParams.get(\"t\");\n    this.tabWidgets = false;\n    this.tabNodes = [];\n    this.tabs = new Map();\n    const tabsNode = this.node.querySelector(\".searchsheet__tabs\");\n    new PerfectScrollbar(tabsNode, {\n      swipePropagation: true,\n      wheelPropagation: true,\n      suppressScrollY: true\n    });\n\n    //ADDME: Tab nodes are added dynamically throught the search configuration. Statically published files can contain tab\n    //       nodes if they haven't been published yet since the change to dynamically added tabs, so we'll just remove the\n    //       static tabs. This code can be removed after all files have been published once after this change.\n    for (const tabNode of this.node.querySelectorAll(\".searchsheet__tab\"))\n      tabNode.remove();\n\n    const q = this.url.searchParams.get(\"q\");\n    if (q) {\n      this.doSearchFor(q);\n    } else if (document.documentElement.classList.contains(\"searchsheet--fixed\")) {\n      this.toggle(true);\n      this.reset();\n    }\n\n    //unload is deprecated and breaks B-F cache. I'm not sure the utwente_base:searsia_unload event actually matters though\n    window.addEventListener(\"pagehide\", event => this.onUnload(event));\n  }\n\n  async initSearsiaClient(t) {\n    if (t) {\n      defaultSearchType = t;\n      if (!this.searchType)\n        this.searchType = t;\n    }\n    if (!this.configPromise)\n      this.configPromise = this.fetchSearchConfig();\n    await this.configPromise;\n  }\n\n  async fetchSearchConfig() {\n    if (debugFlags.searsia)\n      console.log(\"[searsia] Fetching search configuration\");\n\n    const configlang = document.documentElement.lang.substring(0, 2);\n    const searchconfigurl = `/.st/utwente_base/searchsettings.${configlang}.json?` + Math.random(); //TODO if we want to CDN this, make more specific\n    const response = await fetch(searchconfigurl, { credentials: 'same-origin' });\n    if (response.status !== 200) {\n      if (debugFlags.searsia)\n        console.warn(\"[searsia] Did not receive search configuration\");\n      return;\n    }\n    const searchconfig = await response.json();\n\n    const apitemplate = localStorage.searsiaApiTemplate || searchconfig.settings.apitemplate;\n    this.client = searsia.initClient(apitemplate);\n    if (!this.client) {\n      // If initClient didn't return an object, there is not 'mother' stored yet (i.e. there hasn't been a search yet), so we\n      // can just run a search to have it filled\n      if (debugFlags.searsia)\n        console.warn(\"[searsia] Searsia not yet connected, retrieving client\");\n      this.client = await new Promise(resolve => searsia.connectToServer(resolve));\n      if (debugFlags.searsia)\n        console.warn(\"[searsia] We have a client now!\");\n    }\n    if (this.client && this.client.status !== \"error\") {\n      this.suggest = new SearsiaAutoSuggest(this.inputNode, this.suggestNode,\n        {\n          template: this.client.resource.suggesttemplate,\n          minlength: MIN_SUGGEST_LENGTH,\n          numsuggestions: NUM_SUGGESTIONS\n        });\n    }\n\n    // Read the CTA configuration\n    if (searchconfig.searchcta_highlight)\n      this.ctaslots.push({ type: \"highlight\", cta: searchconfig.searchcta_highlight });\n    if (searchconfig.searchcta_widget)\n      this.ctaslots.push({ type: \"widget\", cta: searchconfig.searchcta_widget });\n    // Rewrite CTA configurations\n    for (const ctaslot of this.ctaslots) {\n      for (const cta of ctaslot.cta.ctas) {\n        try {\n          cta.ctaconfig = managedctas.parseManagedCTAConfig(cta.ctaconfig);\n        } catch {\n          cta.ctaconfig = null;\n        }\n      }\n    }\n\n    // Get the 'all events' link\n    this.eventsurl = searchconfig.events_url;\n\n    // Get the manipulated queries\n    this.manipulatedqueries = searchconfig.queries.filter(_ => _.lang === this.lang).map(_ => {\n      return { ..._, terms: this.getQueryTerms(_.query) };\n    });\n\n    // Get the tabs to show\n    const tabsNode = this.node.querySelector(\".searchsheet__tabscontainer\");\n    for (const tab of searchconfig.tabs) {\n      const tabNode = <a href=\"#\" class=\"searchsheet__tab\" data-tab={tab.name}>{tab.title}</a>;\n      if (tab.showwidgets)\n        tabNode.dataset.widgets = \"\";\n      this.tabNodes.push(tabNode);\n      this.tabs.set(tabNode.dataset.tab, { node: tabNode });\n      tabNode.addEventListener(\"click\", event => this.onShowTab(event));\n      if (tabNode.dataset.tab === this.searchType || (!this.searchType && tabNode.dataset.tab === defaultSearchType)) {\n        tabNode.classList.add(\"searchsheet__tab--current\");\n        this.tabWidgets = \"widgets\" in tabNode.dataset;\n      } else\n        tabNode.classList.remove(\"searchsheet__tab--current\");\n      tabsNode.append(tabNode);\n    }\n\n    if (debugFlags.searsia)\n      console.info(\"[searsia] Search configuration\", this.ctaslots, this.eventsurl);\n  }\n\n  getQueryTerms(query) {\n    const words = query.match(/(\\+|\")?\\b\\w+\\b\"?/g);\n    const terms = [];\n    let phrase = null;\n    for (let word of words) {\n      let phrasestart = false;\n      if (word.startsWith(`\"`)) {\n        word = word.substr(1);\n        // start phrase, if not within a phrase yet (otherwise ignore the opening quote)\n        if (!phrase)\n          phrasestart = true;\n      }\n      if (word.endsWith(`\"`)) {\n        word = word.substr(0, word.length - 1);\n        if (phrasestart) {\n          // just a single word\n          phrasestart = false;\n          word = \"+\" + word;\n        } else {\n          // end of phrase?\n          if (phrase) {\n            phrase.push(word);\n            terms.push(phrase);\n            phrase = null;\n            continue;\n          }\n          // just a single word\n        }\n      }\n      // if this is the start of a new phrase, initialize a phrase\n      if (phrasestart)\n        phrase = [];\n      // if parsing a phrase, add the word to the phrase\n      if (phrase)\n        phrase.push(word);\n      else if (word.startsWith(\"+\")) {\n        // add the required word as a term\n        terms.push(word);\n      } else\n        // just add the word term\n        terms.push(word);\n    }\n    // the phrase we're parsing wasn't closed\n    if (phrase) {\n      // if this is a one-word phrase, add the word as a required word\n      if (phrase.length === 1)\n        terms.push(\"+\" + phrase[0]);\n      // add the phrase\n      else\n        terms.push(phrase);\n    }\n    return terms.map(_ => typeof _ === \"string\" ? _.toLowerCase() : _.map(__ => __.toLowerCase()));\n  }\n\n  toggle(show, searchType) {\n    const doshow = !document.documentElement.classList.contains(\"searchsheet--open\");\n    if (doshow) {\n      this.initSearsiaClient(searchType);\n\n      dompack.dispatchCustomEvent(this.node, \"searsia:showsearchsheet\", { bubbles: true, cancelable: false });\n      pxl.sendPxlEvent(\"utwente_base:searsia_open\");\n\n      document.documentElement.classList.remove(\"searchsheet--closing\");\n      document.documentElement.classList.add(\"searchsheet--opening\");\n      this.node._wsTmpTransition = getComputedStyle(this.node).transition;\n      document.documentElement.classList.add(\"searchsheet--open\");\n      this.node._wsTmpTransition = getComputedStyle(this.node).transition;\n    } else if (!show) {\n      dompack.dispatchCustomEvent(this.node, \"searsia:hidesearchsheet\", { bubbles: true, cancelable: false });\n      pxl.sendPxlEvent(\"utwente_base:searsia_close\");\n      this.node.classList.remove(\"searchsheet--show\");\n\n      document.documentElement.classList.remove(\"searchsheet--opening\");\n      document.documentElement.classList.add(\"searchsheet--closing\");\n      this.node._wsTmpTransition = getComputedStyle(this.node).transition;\n      document.documentElement.classList.add(\"searchsheet--close\");\n      document.documentElement.classList.remove(\"searchsheet--open\");\n      this.node._wsTmpTransition = getComputedStyle(this.node).transition;\n\n      this.updateUrl(true);\n    }\n    return doshow;\n  }\n\n  showSheet(toshow) {\n    for (const sheet of [\"quicklinks\", \"quickresults\", \"results\"])\n      if (sheet === toshow)\n        this.node.classList.add(\"searchsheet--show\" + sheet);\n      else\n        this.node.classList.remove(\"searchsheet--show\" + sheet);\n  }\n\n  showTab(toshow, nosearch) {\n    if (this.tabs.has(toshow)) {\n      const tab = this.tabs.get(toshow);\n      this.tabWidgets = false;\n      for (const tabNode of this.tabNodes) {\n        if (tabNode === tab.node) {\n          tabNode.classList.add(\"searchsheet__tab--current\");\n          this.tabWidgets = \"widgets\" in tabNode.dataset;\n        } else\n          tabNode.classList.remove(\"searchsheet__tab--current\");\n      }\n      pxl.sendPxlEvent(\"utwente_base:searsia_showtab\", { ds_tab: toshow });\n      this.searchType = toshow !== \"all\" ? toshow : \"\";\n      if (!nosearch) {\n        this.doSearch();\n        this.updateUrl();\n      }\n    }\n  }\n\n  setStyles(style) {\n    for (const prop of Object.keys(style))\n      this.node.style[prop] = style[prop];\n  }\n\n  reset() {\n    if (this.suggest)\n      this.suggest.cancel();\n    this.inputNode.form.reset();\n    this.inputNode.focus();\n    this.haveResults = false;\n    this.showSheet(\"quicklinks\");\n    this.showTab(defaultSearchType, true);\n    this.updateUrl(true);\n  }\n\n  updateUrl(reset) {\n    if (reset) {\n      this.url.searchParams.delete(\"q\");\n      this.url.searchParams.delete(\"t\");\n    } else {\n      const params = { q: this.inputNode.value, t: this.searchType };\n      this.url.searchParams.set(\"q\", params.q);\n      if (params.t)\n        this.url.searchParams.set(\"t\", params.t);\n      else\n        this.url.searchParams.delete(\"t\");\n    }\n    window.history.replaceState(null, \"\", this.url.toString());\n  }\n\n  onShowTab(event) {\n    event.preventDefault();\n    const tabNode = event.target.closest(\".searchsheet__tab\");\n    if (tabNode)\n      this.showTab(tabNode.dataset.tab);\n  }\n\n  onTransitioned(event) {\n    // When the closing transition ends for the haader node, remove the close class (which resets the transform)\n    if (event.propertyName === \"transform\" && event.target === this.headerNode && document.documentElement.classList.contains(\"searchsheet--close\")) {\n      document.documentElement.classList.remove(\"searchsheet--close\");\n      this.showSheet(\"quicklinks\");\n    }\n  }\n\n  onInputFocus(event) {\n    if (event.type === \"focus\")\n      this.node.classList.add(\"searchsheet--inputfocus\");\n    else\n      this.node.classList.remove(\"searchsheet--inputfocus\");\n  }\n\n  onShowSuggestions() {\n    this.showSheet(\"quickresults\");\n  }\n\n  onHideSuggestions() {\n    if (this.haveResults)\n      this.showSheet(\"results\");\n    else\n      this.showSheet(\"quicklinks\");\n  }\n\n  onStartSearch(event) {\n    event.preventDefault();\n    if (this.inputNode.value) {\n      this.inputNode.blur();\n      this.doSearch();\n      this.updateUrl();\n    }\n  }\n\n  doSearchFor(q, t) {\n    this.toggle(true, t); // toggle calls initSearsiaClient, so call it before calling doSearch\n    this.inputNode.value = q;\n    if (t)\n      this.showTab(t, true);\n    this.doSearch();\n    this.updateUrl();\n  }\n\n  async doSearch() {\n    await this.configPromise; //ensure we have the client initialized\n\n    if (this.suggest)\n      this.suggest.cancel();\n    this.orgQuery = this.getFilteredUserQuery();\n    const params = { q: this.orgQuery, t: this.searchType };\n    this.query = this.inputNode.value;\n    this.queryWords = this.getUserQueryWords(params.q);\n    this.queryFilter = null;\n    this.filteredResults = 0;\n    this.numResults = 0;\n    this.didYouMean = \"\";\n    this.relatedNode = null;\n    this.searsiaSession = searsia.searchFederated(params, result => this.onResults(result));\n    if (debugFlags.searsia)\n      console.info(\"[searsia] searchFederated\", params, this.searsiaSession);\n    pxl.sendPxlEvent(\"utwente_base:searsia_search\", { ds_session: this.searsiaSession, ds_query: params.q, ds_type: params.t });\n  }\n\n  getFilteredUserQuery() {\n    let query = this.inputNode.value;\n    for (const filter of this.stopwordfilters)\n      query = query.replace(filter, \" \");\n    return query.trim();\n  }\n\n  getUserQueryWords(query) {\n    return query ? new RegExp(`\\\\b${query.match(/\\b\\w+\\b/g).join(\"\\\\b|\\\\b\")}\\\\b`, \"i\") : null;\n  }\n\n  getQueryFilter() {\n    if (!this.queryFilter) {\n      this.queryFilter = null;\n      const words = this.orgQuery.match(/\\b\\w+\\b/g).map(_ => _.toLowerCase());\n      for (const filter of this.manipulatedqueries) {\n        if (filter.terms.every(term => {\n          if (typeof term === \"string\") {\n            if (term.startsWith(\"+\"))\n              return words.includes(term.substring(1));\n            else\n              return words.includes(term); //ADDME: Also search misspellings etc\n          } else\n            return isSubArray(words, term);\n        })) {\n          this.queryFilter = filter;\n          break;\n        }\n      }\n\n      if (!this.queryFilter)\n        this.queryFilter = [];\n      else {\n        this.queryFilter = this.queryFilter.urls;\n        if (debugFlags.searsia && this.queryFilter.length)\n          console.info(\"[searsia] Using queryFilter\", this.queryFilter);\n      }\n    }\n    return this.queryFilter;\n  }\n\n  async onResults(result) {\n    // Wait for CTA config before showing results, so we can show CTA's based on the user query and determine query filters\n    await this.configPromise;\n\n    this.queryFilter = this.getQueryFilter();\n\n    if (debugFlags.searsia)\n      console.info(\"[searsia]\", result);\n    if (result.sessionid !== this.searsiaSession) {\n      if (debugFlags.searsia)\n        console.warn(`[searsia] Ignoring search results for old session '${result.sessionid}'`);\n      return;\n    }\n    switch (result.status) {\n      case \"start\":\n        {\n          pxl.sendPxlEvent(\"utwente_base:searsia_start\", { ds_session: this.searsiaSession });\n          this.allhits = [];\n          this.haveResults = true;\n          this.showSheet(\"results\");\n          this.resultsNode.replaceChildren();\n          this.grid = null;\n          this.statusNode.innerHTML = getHTMLTid(\"utwente_base:frontend.ws2016.js.searchsheet.searching\", this.query);\n          if (this.searchType === \"images\")\n            this.resultsNode.appendChild(<div class=\"searsia__imagegrid\"></div>);\n\n          if (this.tabWidgets)\n            this.showWidgets();\n          dompack.registerMissed();\n        } break;\n      case \"hits\":\n        {\n          const source = { ...SEARSIA_SOURCES[result.resource.id], resource: result.resource.id, rank: result.rank };\n          pxl.sendPxlEvent(\"utwente_base:searsia_hits\", { ds_session: this.searsiaSession, ds_resource: result.resource.id, dn_hits: result.hits.length, db_hidden: source.display === false });\n          if (source.display === false)\n            break;\n\n          if (source.type === \"didyoumean\") {\n            if (!this.didYouMean && result.hits.length) {\n              this.didYouMean = result.hits[0].title;\n              this.updateStatusNode();\n              pxl.sendPxlEvent(\"utwente_base:searsia_didyoumean\", { ds_session: this.searsiaSession, ds_suggestion: this.didYouMean });\n            }\n            break;\n          }\n          if (source.type === \"related\") {\n            const relatedHits = result.hits.slice(0, NUM_RELATED);\n            if (debugFlags.searsia)\n              console.info(\"[searsia] Show related searches\", relatedHits);\n            this.relatedNode = searsiaTypes.createRelatedResults(relatedHits, source, this.queryWords);\n            break;\n          }\n\n          // Get the resource score for url deduplication\n          const resourceDuplicateScore = SEARSIA_DUPLICATE_RESOURCES.indexOf(source.resource);\n\n          const hits = [];\n          for (const hit of result.hits) {\n            const manipulated = this.queryFilter.find(_ => _.url === hit.url);\n            if (manipulated && manipulated.pos < 0) {\n              if (debugFlags.searsia)\n                console.info(\"[searsia] Skipping filtered hit\", hit);\n              ++this.filteredResults;\n              continue;\n            }\n\n            // Check if this is a duplicate url\n            if (resourceDuplicateScore >= 0) {\n              const dupIdx = this.allhits.findIndex(_ => _.hit.url === hit.url);\n              if (dupIdx >= 0) {\n                if (this.allhits[dupIdx].score >= resourceDuplicateScore) {\n                  // Remove the existing url, adding the new url\n                  if (debugFlags.searsia)\n                    console.info(\"[searsia] Removing duplicate hit\", this.allhits[dupIdx].hit);\n                  this.allhits[dupIdx].node.remove();\n                  this.allhits.splice(dupIdx, 1);\n                } else {\n                  // Skip the new url, keeping the existing url\n                  if (debugFlags.searsia)\n                    console.info(\"[searsia] Skipping duplicate hit\", hit);\n                  continue;\n                }\n              }\n            }\n\n            hit.rankscore = hit.score;// * Math.max(10 - result.rank, 1);\n            hit.urllang = this.getResultLanguage(hit, source);\n            if (manipulated) {\n              if (debugFlags.searsia)\n                console.info(\"[searsia] Promoting hit\", hit, manipulated.pos);\n              hit.rankscore = 5 - manipulated.pos; // pos has range [ 1, 3 ], rankscore has range [ 0, 1 ]\n              hit.urllang = this.lang;\n            }\n            hits.push({ hit, source });\n            ++this.numResults;\n\n            let resultContainer = this.resultsNode;\n            if (this.searchType === \"images\") {\n              // Add image results to the justified image grid\n              resultContainer = this.resultsNode.querySelector(\".searsia__imagegrid\");\n            } else if (source.group) {\n              // Add a container for the grouped results\n              resultContainer = this.resultsNode.querySelector(`.searsia__resultgroup--${source.group}`);\n              if (!resultContainer) {\n                resultContainer = <div class={\"searsia__resultgroup searsia__resultgroup--\" + source.group}></div>;\n                resultContainer[resultScoreProp] = Infinity;\n                const refNode = Array.from(this.resultsNode.childNodes).find(_ => _[resultScoreProp] < resultContainer[resultScoreProp]);\n                this.resultsNode.insertBefore(resultContainer, refNode);\n              }\n            }\n\n            let resultNode;\n            switch (source.type) {\n              case \"news\":\n                {\n                  resultNode = searsiaTypes.createNewsResult(hit, source, this.searchType === \"news\", this.queryWords);\n                } break;\n              case \"event\":\n                {\n                  resultNode = searsiaTypes.createEventResult(hit, source, this.searchType === \"news\", this.queryWords);\n                } break;\n              case \"people\":\n                {\n                  resultNode = searsiaTypes.createPeopleResult(hit, source, this.searchType === \"people\", this.queryWords);\n                } break;\n              case \"video\":\n                {\n                  resultNode = searsiaTypes.createVideoResult(hit, source, this.searchType === \"videos\", this.queryWords);\n                } break;\n              case \"image\":\n                {\n                  resultNode = searsiaTypes.createImageResult(hit, source, this.searchType === \"images\", this.queryWords);\n                } break;\n              default:\n                {\n                  resultNode = searsiaTypes.createGeneralResult(hit, source, this.queryWords);\n                }\n            }\n\n            resultNode[resultScoreProp] = hit.rankscore;\n            resultNode[resultLangProp] = hit.urllang;\n            resultNode[resultSourceProp] = source.resource;\n            const refNode = Array.from(resultContainer.childNodes).find(_ => {\n              // Skip over widget nodes\n              if (_.classList.contains(\"searsia__widget\"))\n                return false;\n              // If this isn't the Dutch search page, we're sorting Dutch results after non-Dutch results\n              if (this.lang !== \"nl\" && resultNode[resultLangProp] !== _[resultLangProp])\n                return resultNode[resultLangProp] !== \"nl\"; // Non-Dutch before Dutch results\n              // Sort 'serviceportal' results before 'googlecustom' results\n              //Temporarily disabled for #2698\n              //if (resultNode[resultSourceProp] == \"serviceportal\" && _[resultSourceProp] == \"googlecustom\")\n              //  return true;\n              //if (resultNode[resultSourceProp] == \"googlecustom\" && _[resultSourceProp] == \"serviceportal\")\n              //  return false;\n              return _[resultScoreProp] < resultNode[resultScoreProp];\n            });\n            resultContainer.insertBefore(resultNode, refNode);\n            if (resourceDuplicateScore >= 0)\n              this.allhits.push({ hit, node: resultNode, score: resourceDuplicateScore });\n          }\n          this.updateStatusNode();\n          if (!this.searchType)\n            this.showWidgets(hits);\n          dompack.registerMissed();\n        } break;\n      case \"done\":\n        {\n          pxl.sendPxlEvent(\"utwente_base:searsia_done\", { ds_session: this.searsiaSession, dn_results: this.numResults });\n          if (this.searchType === \"images\") {\n            const gridNode = this.resultsNode.firstChild;\n\n            this.grid = new JustifiedImageGrid(gridNode, this.getDefaultGridOptions(this.resultsNode));\n\n            if (!this.imggridresizetimer) {\n              window.addEventListener(\"resize\", () => {\n                if (!this.grid || !this.grid.container.clientWidth) //must be active and visible\n                  return;\n                clearTimeout(this.imggridresizetimer);\n                this.imggridresizetimer = setTimeout(function () {\n                  const defaultoptions = this.getDefaultGridOptions(this.resultsNode);\n                  this.grid.setOptions(defaultoptions);\n                  this.grid.refresh();\n                }.bind(this), 100);\n              });\n            }\n\n            this.imggridresizetimer = setTimeout(function () {\n              this.grid.refresh();\n            }.bind(this), 100);\n          } else if (this.relatedNode) {\n            // Insert the related searches after the 10th result (i.e. before the 11th result)\n            const refNode = this.resultsNode.querySelector(\".searsia__result:nth-of-type(11)\");\n            // refNode == null => insertBefore(node, null) == appendChild(node)\n            this.resultsNode.insertBefore(this.relatedNode, refNode);\n          }\n          if (this.filteredResults > 0) {\n            const filteredNode = searsiaTypes.createFilteredResult();\n            this.resultsNode.appendChild(filteredNode);\n          }\n          this.updateStatusNode(true);\n          if (this.numResults)\n            this.resultsNode.appendChild(<div class=\"searsia__resultsdone\"><p>{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.searchdone\")}</p></div>);\n        } break;\n      case \"error\":\n        {\n          throw new Error(result.error);\n        }\n    }\n  }\n\n  getResultLanguage(hit, _source) {\n    // For utwente.nl URLs, non-Dutch URLs have a path starting with \"/de/\" or \"/en/\"\n    // Treat utwente.nl subdomains (like \"people.utwente.nl\") as non-Dutch\n    if (/:\\/\\/(www\\.)?utwente.nl\\/en\\//.test(hit.url))\n      return \"en\";\n    if (/:\\/\\/(www\\.)?utwente.nl\\/de\\//.test(hit.url))\n      return \"de\";\n    if (/:\\/\\/(www\\.)?utwente.nl\\//.test(hit.url))\n      return \"nl\";\n    return \"en\";\n  }\n\n  updateStatusNode(force) {\n    if (this.numResults || force) {\n      let html = getHTMLTid(\"utwente_base:frontend.ws2016.js.searchsheet.results\", this.numResults, this.query, this.didYouMean);\n      if (!this.numResults && !this.didYouMean && this.searchType)\n        html = html + getHTMLTid(\"utwente_base:frontend.ws2016.js.searchsheet.searchall\");\n      html = html.split(\"%S%\").join('<span class=\"searchsheet__didyoumean\">').split(\"%/S%\").join('</span>');\n      this.statusNode.innerHTML = html;\n\n      // See https://gitlab.webhare.com/utwente/utwente_base/-/issues/2266\n      const isstudent = Boolean(this.userBeacons && this.userBeacons[\"usertype-student\"]);\n      const isemployee = Boolean(this.userBeacons && this.userBeacons[\"usertype-employee\"]);\n      if (!document.documentElement.classList.contains(\"loggedin\") && (isstudent || isemployee) && [\"\", \"people\", \"serviceportal\"].includes(this.searchType)) {\n        const loginmsg = <div class=\"searchsheet__login-msgbox\">\n          <div class=\"searchsheet__login-msgbox__content\">\n            {this.lang === \"nl\" ? <p><a href=\"x-serviceportal:login\">Log in</a> om interne/afgeschermde pagina&apos;s van de Service Portal aan de zoekresultaten toe te voegen.</p> : this.lang === \"de\" ? <p>Bitte <a href=\"x-serviceportal:login\">logge dich ein</a> um abgeschirmte Seiten aus dem internen Service Portal in den Suchergebnissen zu sehen.</p> : <p>Please <a href=\"x-serviceportal:login\">log in</a> if you also want to see internal/protected pages from the Service Portal.</p>}\n          </div>\n        </div>;\n        this.statusNode.prepend(loginmsg);\n      }\n    }\n  }\n\n  showWidgets(hits) {\n    const node = showSearsiaWidgets(hits, this.ctaslots, { country: this.userCountry, beacons: this.userBeacons, url: location.href, query: this.query }, this.eventsurl);\n    if (node)\n      this.resultsNode.insertBefore(node, this.resultsNode.firstChild);\n  }\n\n  onClickStatus(event) {\n    const didyoumean = event.target.closest(\".searchsheet__didyoumean\");\n    if (didyoumean) {\n      pxl.sendPxlEvent(\"utwente_base:searsia_clickdidyoumean\", { ds_session: this.searsiaSession, ds_suggestion: this.didYouMean || \"\", ds_type: this.searchType });\n      if (this.didYouMean) {\n        this.inputNode.value = this.didYouMean;\n        this.doSearch();\n        this.updateUrl();\n      } else\n        this.showTab(\"all\");\n    }\n  }\n\n  onClickResult(event) {\n    const peopleResult = event.target.closest(\".searsia__result--people\");\n    if (peopleResult && !event.target.closest(\".searsia__peopledetails\")) {\n      event.preventDefault();\n      peopleResult.classList.toggle(\"searsia__result--open\");\n      return;\n    }\n\n    const relatedResult = event.target.closest(\".searsia__related__link\");\n    if (relatedResult) {\n      const suggestion = relatedResult.textContent;\n      pxl.sendPxlEvent(\"utwente_base:searsia_clickrelated\", { ds_session: this.searsiaSession, ds_suggestion: suggestion });\n      this.inputNode.value = suggestion;\n      this.doSearch();\n      this.updateUrl();\n      return;\n    }\n\n    const link = event.target.closest(\"a\");\n    if (link) {\n      const widget = event.target.closest(\".searsia__widget\");\n      this.linkClicked = true;\n      pxl.sendPxlEvent(\"utwente_base:searsia_clickresult\", { ds_session: this.searsiaSession, ds_url: link.href, ds_target: widget ? widget.dataset.widgetType : \"result\" }, { beacon: true });\n    }\n  }\n\n  getDefaultGridOptions(node) {\n    const options =\n    {\n      width: Math.round(node.clientWidth * window.devicePixelRatio) / window.devicePixelRatio,\n      row_height: 215,\n      gutter_x: 20,\n      gutter_y: 20,\n      debug: true,\n      debug_layout: true\n    };\n    return options;\n  }\n\n  onUnload() {\n    if (document.documentElement.classList.contains(\"searchsheet--open\") && !this.linkClicked)\n      pxl.sendPxlEvent(\"utwente_base:searsia_unload\", { ds_session: this.searsiaSession }, { beacon: true });\n  }\n}\n\n\nfunction initSearchSheet(node) {\n  const searchSheetContentNode = node.querySelector(\".searchsheet__content\");\n\n  node._wsTmpTransition = getComputedStyle(node).transition;\n  searchSheetContentNode._wsTmpTransition = getComputedStyle(searchSheetContentNode).transition;\n\n  node.classList.remove(\"searchsheet--init\");\n  setTimeout(() => searchSheetContentNode.classList.remove(\"searchsheet__content--init\"), 250);\n\n  node.querySelector(\".searchsheet__searchfield-clear\").addEventListener(\"click\", resetSearch);\n\n  /*  for (let section of node.querySelectorAll(\".searchsheet__section\"))\n      setupSection(section);*/\n\n  for (const section of node.querySelectorAll(\".searchsheet__section-links\"))\n    setupShowAllLinks(section, \"searchsheet__section-alllinks\", \"searchsheet__section-link\");\n\n  searsiaClient = new SearsiaClient(node);\n\n  node.querySelector(\".searchsheet__close\").addEventListener(\"click\", event => {\n    dompack.stop(event);\n    toggle();\n  });\n}\n\n/*function setupSection(sectionNode)\n{\n  // Open/close link sections when in accordion mode\n  sectionNode.querySelector(\".searchsheet__section-title\").addEventListener(\"click\", event =>\n  {\n    // Check if the footer is actually in accordion mode\n    let target = event.target.closest(\".searchsheet__section-title\");\n    if (getComputedStyle(target).display != \"block\") // The sectiontitle is hidden, no accordion\n      return;\n\n    // Save section height so it can be animated using transition (which only animates explicitly set height)\n    let links = sectionNode.querySelector(\".searchsheet__section-links\");\n    if (links.classList.contains(\"searchsheet__section-links--init\"))\n    {\n      links.setAttribute(\"data-height\", links.clientHeight + \"px\");\n      links.classList.remove(\"searchsheet__section-links--init\");\n\n      // Force a style recompute after the links 'init' class is removed, so the transition will work properly\n      links._wsTmpHeight = getComputedStyle(links).height;\n    }\n\n    // Toggle section open/close, update height to trigger height transition\n    requestAnimationFrame(() =>\n    {\n      if (target.classList.contains(\"searchsheet__section-title--open\"))\n      {\n        target.classList.remove(\"searchsheet__section-title--open\");\n        links.classList.remove(\"searchsheet__section-links--open\");\n        links.style.height = \"\";\n      }\n      else\n      {\n        target.classList.add(\"searchsheet__section-title--open\");\n        links.classList.add(\"searchsheet__section-links--open\");\n        links.style.height = links.getAttribute(\"data-height\");\n      }\n    });\n  });\n}*/\n\nfunction resetSearch(event) {\n  if (event) {\n    event.preventDefault();\n    event.stopPropagation();\n  }\n  if (searsiaClient)\n    searsiaClient.reset();\n}\n\n\nexport function toggle() {\n  if (searsiaClient && searsiaClient.toggle())\n    searsiaClient.reset();\n}\n\nexport function doSearch(query, searchType) {\n  if (searsiaClient)\n    searsiaClient.doSearchFor(query, searchType);\n}\n\nexport function setStyles(style) {\n  if (searsiaClient)\n    searsiaClient.setStyles(style);\n}\n\nexport async function initSearsiaClient(searchType) {\n  if (searsiaClient) {\n    await searsiaClient.initSearsiaClient(searchType);\n    return searsiaClient.client;\n  }\n}\n\n\ndompack.register(\".searchsheet\", node => {\n  if (!document.documentElement.classList.contains(\"site--itc\"))\n    initSearchSheet(node);\n});\n\ndompack.register(\"#searsiasearch\", node => {\n  if (!document.documentElement.classList.contains(\"site--itc\"))\n    node.parentNode.removeChild(node);\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport KeyboardHandler from \"dompack/extra/keyboard\";\nimport InternetRequester from \"@mod-system/js/net/requester\";\nimport searsia from \"@mod-utwente_base/web/pub/ws2016/searsia\";\n\nexport default class SearsiaAutoSuggest {\n  _node;\n\n  /** options.fixitemswidth Make the items container as wide as the pulldown. Defaults to true */\n  constructor(inputNode: HTMLInputElement, resultsNode, options) {\n    this._class = (options ? options.baseclass : '') || 'selectlist';\n    this._fixitemswidth = !(options && !options.fixitemswidth);\n    this._node = inputNode;\n    this._items = resultsNode;\n\n    this._connection = new InternetRequester();\n    this._connection.on(\"requestend\", event => this._gotSuggestions(event));\n\n    this._lookuppending = false;\n    this._lookuphistory = [];\n    this._lookuplock = null;\n    this._dontresuggest = false;\n\n    this.options = {\n      template: \"\",\n      noresultstext: \"\",\n      minlength: 3,\n      numsuggestions: 10,\n      immediateresuggest: false, //immediately resuggest\n      suggestdelay: 200, //how long to wait before we initiate suggestions\n      triminput: true,\n      ...options\n    };\n\n    this._node.addEventListener(\"input\", () => this._onInput());\n    this._node.addEventListener(\"blur\", event => this._onBlur(event));\n\n    this._items.addEventListener(\"click\", event => this._clickItem(event));\n\n    new KeyboardHandler(this._node, { \"ArrowDown\": event => this._onArrowDown(event) }, { captureunsafekeys: true });\n  }\n\n  cancel() {\n    if (this._updatetimer) {\n      clearTimeout(this._updatetimer);\n      this._updatetimer = 0;\n    }\n    this._endLock();\n  }\n\n  _clickItem(event) {\n    dompack.stop(event);\n\n    const selectitem = event.target.closest('.' + this._class + '__item');\n    if (selectitem)\n      this._doSelectItem(selectitem);\n  }\n\n  _onArrowDown(_event) {\n    //TODO: Select next suggestion?\n  }\n\n  _onInput() {\n    if (this._lookuppending || this._dontresuggest || this._node.disabled || this._node.readOnly)\n      return;\n\n    if (!this._lookuplock) {\n      this._lookuplock = dompack.flagUIBusy();\n      this._node.classList.add(this._class + \"--autosuggesting\");\n    }\n\n    if (this._updatetimer)\n      clearTimeout(this._updatetimer);\n\n    this._updatetimer = setTimeout(() => this._checkInput(), this.options.suggestdelay);\n  }\n\n  _endLock() {\n    if (this._lookuplock) {\n      this._lookuplock.release();\n      this._lookuplock = null;\n      this._node.classList.remove(this._class + \"--autosuggesting\");\n    }\n  }\n\n  _onBlur() {\n    this.cancel();\n  }\n\n  _safeToSuggest(value) {\n    if (value.length < this.options.minlength) //FIXME count last word, not full string\n      return false;\n\n    return true;\n  }\n\n  async _checkInput() {\n    try {\n      await this._offerSuggestions();\n    } finally {\n      this._endLock();\n    }\n  }\n\n  _getCurrentInput() {\n    let input = this._node.value;\n    if (this.options.triminput)\n      input = input.trim();\n    return input;\n  }\n\n  async _offerSuggestions() {\n    let input, values;\n    do //loop until what we looked up matches what we were looking for\n    {\n      input = this._getCurrentInput();\n      if (!this._safeToSuggest(input)) {\n        dompack.dispatchCustomEvent(this._node, \"searsia:hidesuggestions\", { bubbles: true, cancelable: false });\n        return;\n      }\n\n      values = await this._lookup(input);\n    } while (input != this._getCurrentInput());\n\n    if (!values || values.length == 0) {\n      dompack.dispatchCustomEvent(this._node, \"searsia:hidesuggestions\", { bubbles: true, cancelable: false });\n      return;\n    }\n\n    this._generateItems({ input, values });\n    dompack.dispatchCustomEvent(this._node, \"searsia:showsuggestions\", { bubbles: true, cancelable: false });\n  }\n\n  async _lookup(input) {\n    const historyhit = this._lookuphistory.find(entry => entry.input == input);\n    if (historyhit)\n      return historyhit.values;\n\n    this._lookuppending = true;\n\n    const url = searsia.fillUrlTemplate(this.options.template, searsia.encodedQuery(input));\n    this._connection.stopCurrentRequest();\n    this._connection.startXMLHTTPRequest(\"GET\", url);\n    this._deferred = dompack.createDeferred();\n    //TODO: Add timeout?\n\n    const lookupresult = await this._deferred.promise;\n\n    this._lookuphistory.push({ input: input, values: lookupresult });\n    this._lookuppending = false;\n    return lookupresult;\n  }\n\n  _gotSuggestions(event) {\n    if (event.responsejson && event.responsejson.length && event.responsejson.length > 1) {\n      const suggestions = event.responsejson[1].slice(0, this.options.numsuggestions);\n      this._deferred.resolve(suggestions);\n      return;\n    }\n    this._deferred.reject(new Error(\"Unexpected suggestion result\"));\n  }\n\n  _generateItems(options) {\n    this._items.replaceChildren();\n    for (let value of options.values) {\n      const matchIdx = value.toUpperCase().indexOf(options.input.toUpperCase());\n      const match = matchIdx >= 0 ? value.substr(0, options.input.length) : \"\";\n      value = value.substr(match.length);\n      this._items.appendChild(\n        <span class={this._class + \"__item searchsheet__section-link\"}>\n          <span class=\"searchsheet__section-link-icon UT-icon-UT_icon_70_search-16px\"></span>\n          <span class={this._class + \"__itemvalue\"}>\n            {match && <span class=\"searchsheet__suggestmatch\">{match}</span>}\n            {value}\n          </span>\n        </span>);\n    }\n  }\n\n  _doSelectItem(selectitem) {\n    const selectedvalue = selectitem.querySelector('.' + this._class + '__itemvalue').textContent;\n    if (!this.options.immediateresuggest) //prevent us from immediately processing our own input event\n      this._dontresuggest = true;\n    dompack.changeValue(this._node, selectedvalue);\n    this._dontresuggest = false;\n\n    dompack.dispatchCustomEvent(this._node,\n      \"searsia:searchsuggestion\",\n      {\n        bubbles: true,\n        cancelable: false,\n        detail: { value: selectedvalue }\n      });\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport { debugFlags } from \"@webhare/env\";\nimport { decodeString } from \"@webhare/std\";\nimport { getTid } from \"@webhare/gettid\";\n\nconst PHONE_UT_REGEX = /\\+3153489(\\d{4})/;\nconst PHONE_MOB_REGEX = /\\+316(\\d{2}){4}/;\n\nfunction addDebuggingInfo(hit, source) {\n  if (debugFlags.searsia) {\n    return (\n      <span class=\"searsia__debuginfo\">\n        {hit.rankscore} ({hit.score}|{source.rank}|{hit.urllang}|{source.resource})\n      </span>);\n  }\n}\n\nexport function createGeneralResult(hit, source, queryWords) {\n  let titleprefix = \"\";\n  let icon = \"ut-searchicon_01-ut-14px\";\n  if (source.type === \"serviceportal\") {\n    if (hit.isprivate)\n      icon = \"ut-searchicon_04-lock-12px\";\n    //ADDME: else icon = Service Portal icon\n  } else if (source.type === \"publication\") {\n    titleprefix = getTid(\"utwente_base:frontend.ws2016.js.searchsheet.publication\") + \" | \";\n    icon = \"ut-searchicon_08-book-12px\";\n  } else if (source.type === \"location\") {\n    titleprefix = getTid(\"utwente_base:frontend.ws2016.js.searchsheet.location\") + \" | \";\n    icon = \"UT-icon-UT_icon_16_pointer-24px\";\n  } else if (source.type === \"courses\") {\n    icon = \"UT-icon-UT_icon_93_education-16px\";\n  }\n\n  return (\n    <a class=\"searsia__result\" href={decodeString(hit.url, \"attribute\")}>\n      {addDebuggingInfo(hit, source)}\n      <span class=\"searsia__title\">{[titleprefix, highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")]}</span>\n      {hit.description &&\n        <span class=\"searsia__desc\">{highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}</span>\n      }\n      <span class=\"searsia__link\">\n        <span class={\"searsia__icon \" + icon}></span>\n        {hit.url && formatURL(decodeString(hit.url, \"attribute\"))}\n      </span>\n    </a>);\n}\n\nexport function createNewsResult(hit, source, extended, queryWords) {\n  if (extended)\n    return (\n      <div class=\"searsia__result searsia__result--news\" href={decodeString(hit.url, \"attribute\")}>\n        {addDebuggingInfo(hit, source)}\n        {hit.image && <a href={decodeString(hit.url, \"attribute\")} class=\"searsia__thumb\" style={`background-image: url(\"${hit.image}\")`}></a>}\n        <a href={decodeString(hit.url, \"attribute\")} class=\"searsia__title\">{highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")}</a>\n        <span class=\"searsia__desc\">\n          {<span class=\"searsia__desc-prefix\">\n            {source.resource === \"utoday\" ? getTid(\"utwente_base:frontend.ws2016.js.searchsheet.utoday\") + \": \" : \"\"}\n            {hit.date && decodeString(hit.date, \"attribute\")}\n          </span>}\n          {hit.description && highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}\n        </span>\n      </div>);\n  return (\n    <a class=\"searsia__result\" href={decodeString(hit.url, \"attribute\")}>\n      {addDebuggingInfo(hit, source)}\n      <span class=\"searsia__title\">{[getTid(\"utwente_base:frontend.ws2016.js.searchsheet.news\") + \" | \", highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")]}</span>\n      <span class=\"searsia__desc\">\n        {hit.date && <span class=\"searsia__desc-prefix\">{decodeString(hit.date, \"attribute\")}</span>}\n        {hit.description && highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}\n      </span>\n      <span class=\"searsia__link\">\n        <span class=\"searsia__icon ut-searchicon_03-news-12px\"></span>\n        {hit.url && formatURL(decodeString(hit.url, \"attribute\"))}\n      </span>\n    </a>);\n}\n\nexport function createEventResult(hit, source, extended, queryWords) {\n  if (extended)\n    return (\n      <div class=\"searsia__result searsia__result--news\" href={decodeString(hit.url, \"attribute\")}>\n        {addDebuggingInfo(hit, source)}\n        {hit.image && <a href={decodeString(hit.url, \"attribute\")} class=\"searsia__thumb\" style={`background-image: url(\"${hit.image}\")`}></a>}\n        <a href={decodeString(hit.url, \"attribute\")} class=\"searsia__title\">{highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")}</a>\n        <span class=\"searsia__desc\">\n          {hit.date && <span class=\"searsia__desc-prefix\">{decodeString(hit.date, \"attribute\")}</span>}\n          {hit.description && highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}\n        </span>\n      </div>);\n  return (\n    <a class=\"searsia__result\" href={decodeString(hit.url, \"attribute\")}>\n      {addDebuggingInfo(hit, source)}\n      <span class=\"searsia__title\">{[getTid(\"utwente_base:frontend.ws2016.js.searchsheet.event\") + \" | \", highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")]}</span>\n      <span class=\"searsia__desc\">\n        {hit.date && <span class=\"searsia__desc-prefix\">{decodeString(hit.date, \"attribute\")}</span>}\n        {hit.description && highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}\n      </span>\n      <span class=\"searsia__link\">\n        <span class=\"searsia__icon ut-searchicon_07-calendar-12px\"></span>\n        {hit.url && formatURL(decodeString(hit.url, \"attribute\"))}\n      </span>\n    </a>);\n}\n\nexport function createPeopleResult(hit, source, extended, queryWords) {\n  if (extended)\n    return (\n      <div class=\"searsia__result searsia__result--people\">\n        {addDebuggingInfo(hit, source)}\n        {hit.image && <span class=\"searsia__thumb\" style={`background-image: url(\"${hit.image}\")`}></span>}\n        <span class=\"searsia__toggle\"></span>\n        <span class=\"searsia__title\">{highlightQueryWords(decodeString(hit.name || hit.title, \"attribute\"), queryWords, \"searsia__title\")}</span>\n        <span class=\"searsia__desc\">\n          {hit.job && highlightQueryWords(decodeString(hit.job, \"attribute\"), queryWords, \"searsia__desc\")}\n        </span>\n        <div class=\"searsia__peopledetails\">\n          <div class=\"searsia__peopledetails-content\">\n            {hit.location &&\n              (hit.latitude && hit.longitude ?\n                <a href={getMapRouteLink(`${hit.latitude},${hit.longitude}`)} class=\"searsia__peopledetail\">\n                  <span class=\"searsia__peopledetail-icon UT-icon-UT_icon_16_pointer-24px\"></span>\n                  {decodeString(hit.location, \"attribute\")}\n                </a>\n                :\n                <span class=\"searsia__peopledetail\">\n                  <span class=\"searsia__peopledetail-icon UT-icon-UT_icon_16_pointer-24px\"></span>\n                  {decodeString(hit.location, \"attribute\")}\n                </span>\n              )\n            }\n            {hit.phone &&\n              <a href={`tel:${hit.phone}`} class=\"searsia__peopledetail\">\n                <span class=\"searsia__peopledetail-icon UT-icon-UT_icon_13_phone-24px\"></span>\n                {formatPhone(decodeString(hit.phone, \"attribute\"))}\n              </a>\n            }\n            {hit.mail &&\n              <a href={`mailto:${hit.mail}`} class=\"searsia__peopledetail\">\n                <span class=\"searsia__peopledetail-icon UT-icon-UT_icon_15_mail-24px\"></span>\n                {decodeString(hit.mail, \"attribute\")}\n              </a>\n            }\n            <a href={hit.url} class=\"searsia__peopledetail\">\n              <span class=\"searsia__peopledetail-icon UT-icon-UT_icon_40_avatar-24px\"></span>\n              {getTid(\"utwente_base:frontend.ws2016.js.searchsheet.peoplepage\")}\n            </a>\n          </div>\n        </div>\n      </div>);\n  return (\n    <a class=\"searsia__result\" href={decodeString(hit.url, \"attribute\")}>\n      {addDebuggingInfo(hit, source)}\n      <span class=\"searsia__title\">{[getTid(\"utwente_base:frontend.ws2016.js.searchsheet.people\") + \" | \", highlightQueryWords(decodeString(hit.name || hit.title, \"attribute\"), queryWords, \"searsia__title\")]}</span>\n      {hit.job &&\n        <span class=\"searsia__desc\">{highlightQueryWords(decodeString(hit.job, \"attribute\"), queryWords, \"searsia__desc\")}</span>\n      }\n      <span class=\"searsia__link\">\n        <span class=\"searsia__icon ut-searchicon_02-people-12px\"></span>\n        {hit.url && formatURL(decodeString(hit.url, \"attribute\"))}\n      </span>\n    </a>);\n}\n\nexport function createVideoResult(hit, source, extended, queryWords) {\n  if (extended)\n    return (\n      <div class=\"searsia__result searsia__result--video\">\n        {addDebuggingInfo(hit, source)}\n        <a href={decodeString(hit.url, \"attribute\")}>\n          {hit.image &&\n            <span class=\"searsia__thumb\" style={`background-image: url(\"${hit.image}\")`}>\n              <span class=\"searsia__playbutton themecolor--bg\"></span>\n              <span class=\"searsia__playbutton-icon themecolor--fg\"></span>\n            </span>\n          }\n          <span class=\"searsia__title\">{highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")}</span>\n          <span class=\"searsia__desc\">\n            {hit.date && <span class=\"searsia__desc-prefix\">{decodeString(hit.date, \"attribute\")}</span>}\n            {hit.description && highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}\n          </span>\n        </a>\n      </div>);\n  return (\n    <a class=\"searsia__result\" href={decodeString(hit.url, \"attribute\")}>\n      {addDebuggingInfo(hit, source)}\n      <span class=\"searsia__title\">{[getTid(\"utwente_base:frontend.ws2016.js.searchsheet.video\") + \" | \", highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")]}</span>\n      {hit.description &&\n        <span class=\"searsia__desc\">{highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}</span>\n      }\n      <span class=\"searsia__link\">\n        <span class=\"searsia__icon ut-searchicon_05-play-12px\"></span>\n        {hit.url && formatURL(decodeString(hit.url, \"attribute\"))}\n      </span>\n    </a>);\n}\n\nexport function createImageResult(hit, source, extended, queryWords) {\n  if (extended) {\n    return (\n      <a class=\"searsia__imagegrid__item\" href={hit.url} title={decodeString(hit.title, \"attribute\")}>\n        <img src={hit.image} class=\"searsia__imagegrid__item__image\" />\n        {addDebuggingInfo(hit, source)}\n      </a>);\n  }\n  return (\n    <a class=\"searsia__result\" href={decodeString(hit.url, \"attribute\")}>\n      {addDebuggingInfo(hit, source)}\n      <span class=\"searsia__title\">{[getTid(\"utwente_base:frontend.ws2016.js.searchsheet.image\") + \" | \", highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__title\")]}</span>\n      {hit.description &&\n        <span class=\"searsia__desc\">{highlightQueryWords(decodeString(hit.description, \"attribute\"), queryWords, \"searsia__desc\")}</span>\n      }\n      <span class=\"searsia__link\">\n        <span class=\"searsia__icon ut-searchicon_01-ut-14px\"></span>\n        {hit.url && formatURL(decodeString(hit.url, \"attribute\"))}\n      </span>\n    </a>);\n}\n\nexport function createRelatedResults(hits, _source, queryWords) {\n  return (\n    <div class=\"searsia__related\">\n      <div class=\"searsia__related__title\">{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.related\") + \":\"}</div>\n      <div class=\"searsia__related__links\">\n        {hits.map(hit =>\n          <span class=\"searsia__related__link\">\n            <span class=\"searsia__related__linkicon UT-icon-UT_icon_70_search-16px\"></span>\n            {highlightQueryWords(decodeString(hit.title, \"attribute\"), queryWords, \"searsia__related__link\")}\n          </span>)\n        }\n      </div>\n    </div>\n  );\n}\n\nexport function createFilteredResult() {\n  return (\n    <div class=\"searsia__filtered\">\n      {getTid(\"utwente_base:frontend.ws2016.js.searchsheet.filteredresults\")}\n    </div>\n  );\n}\n\nfunction highlightQueryWords(text, words, className) {\n  if (!words)\n    return text;\n\n  const result = [];\n  while (text) {\n    // Find the first matching word\n    const match = text.match(words);\n    result.push(match ? text.substr(0, match.index) : text);\n    if (!match)\n      break;\n\n    result.push(<span class={className + \"--match ut-querymatch\"}>{match[0]}</span>);\n    text = text.substr(match.index + match[0].length);\n  }\n  return result;\n}\n\nfunction formatURL(url) {\n  if (url.indexOf(\"http://\") === 0)\n    url = url.substr(7);\n  else if (url.indexOf(\"https://\") === 0)\n    url = url.substr(8);\n  if (url.indexOf(\"www.\") === 0)\n    url = url.substr(4);\n  return url;\n}\n\nexport function formatPhone(phone) {\n  let match = phone.match(PHONE_UT_REGEX);\n  if (match) {\n    return <span class=\"searsia__phone\">+31 (0)53 489 <b>{match[1]}</b></span>;\n  } else {\n    match = phone.match(PHONE_MOB_REGEX);\n    if (match) {\n      return <span class=\"searsia__phone\">+31 (0)6 {match.slice(1).join(\" \")}</span>;\n    }\n  }\n  return phone;\n}\n\nexport function getMapRouteLink(coord) {\n  return `https://maps.google.com/maps?hl=${encodeURIComponent(getTid.tidLanguage)}&daddr=${encodeURIComponent(coord)}&z=15`;\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport { debugFlags } from \"@webhare/env\";\nimport { decodeString } from \"@webhare/std\";\nimport { getTid } from \"@webhare/gettid\";\nimport * as searsiaTypes from \"./searsiatypes\";\nimport * as managedctas from \"../crm/managedctas\";\n\n\nlet shownWidget = null;\nlet locationRequestId = 0;\n\nexport function showSearsiaWidgets(hits, ctaslots, ctaprops, eventsurl) {\n  let node;\n  if (!hits) {\n    // If hits is null, this is the first call after the search was initiated\n    shownWidget = null;\n\n    const result = tryMatchSearsiaCTA(ctaslots, ctaprops);\n    if (result) {\n      node = result.node;\n      shownWidget = { type: result.type, node: result.node };\n    }\n  } else {\n    // Check for interesting result types\n    for (const result of hits) {\n      switch (result.source.type) {\n        case \"location\":\n          {\n            node = createLocationWidget(result) || node;\n          } break;\n        case \"event\":\n          {\n            node = createEventsWidget(result, eventsurl) || node;\n          } break;\n      }\n    }\n  }\n  return node;\n}\n\nfunction tryMatchSearsiaCTA(ctaslots, props) {\n  // Try to match search query with search CTAs\n  for (const ctaslot of ctaslots) {\n    for (const cta of ctaslot.cta.ctas) {\n      try {\n        managedctas.tryMatchCTAConfig(cta.ctaconfig, props);\n        if (debugFlags.umc)\n          console.info(`[umc] Showing ${ctaslot.type} CTA ${cta.ctaconfig.tag}`, cta);\n\n        let node;\n        switch (ctaslot.type) {\n          case \"highlight\":\n            {\n              node = createHighlightCTA(cta);\n            } break;\n          case \"widget\":\n            {\n              node = createWidgetCTA(cta);\n            } break;\n          default:\n            throw `Unknown CTA slot type '${ctaslot.type}'`;\n        }\n        if (node)\n          return { type: ctaslot.type, node };\n      } catch (e) {\n        if (e instanceof managedctas.CTAMatchError) {\n          if (debugFlags.umc)\n            console.warn(`[umc] Not showing ${ctaslot.type} CTA ${cta.ctaconfig.tag}: ${e.message}`);\n        } else\n          throw e;\n      }\n    }\n  }\n}\n\nfunction createHighlightCTA(cta) {\n  let title, description;\n  const widgetNode =\n    <div class=\"searsia__widget searsia__widget--highlight\" data-widget-type=\"highlight\">\n      <div class=\"searsia__highlight-text\">\n        {title = cta.title && (cta.buttonlink ?\n          <a class=\"searsia__highlight-title\" href={cta.buttonlink} target={cta.buttonnewwindow ? \"_blank\" : \"\"} rel=\"noreferrer\" />\n          :\n          <div class=\"searsia__highlight-title\" />\n        )}\n        {description = cta.description && <div class=\"searsia__highlight-description\" />}\n        {cta.buttonlink && cta.buttontitle &&\n          <a class=\"searsia__highlight-link\" href={cta.buttonlink} target={cta.buttonnewwindow ? \"_blank\" : \"\"} rel=\"noreferrer\">{cta.buttontitle}</a>\n        }\n      </div>\n      {cta.photo && (cta.buttonlink ?\n        <a class=\"searsia__highlight-image\" style={`background-image: url(\"${cta.photo.link}\");` + (cta.photo.refpoint_backgroundposition ? `background-position: ${cta.photo.refpoint_backgroundposition};` : \"\")} href={cta.buttonlink} target={cta.buttonnewwindow ? \"_blank\" : \"\"} rel=\"noreferrer\">\n          <span class=\"searsia__highlight-suggested\">{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.suggestedresult\")}</span>\n        </a>\n        :\n        <div class=\"searsia__highlight-image\" style={`background-image: url(\"${cta.photo.link}\");` + (cta.photo.refpoint_backgroundposition ? `background-position: ${cta.photo.refpoint_backgroundposition};` : \"\")}>\n          <span class=\"searsia__highlight-suggested\">{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.suggestedresult\")}</span>\n        </div>\n      )\n      }\n    </div>;\n  if (title)\n    title.innerHTML = cta.title;\n  if (description)\n    description.innerHTML = cta.description;\n  return widgetNode;\n}\n\nfunction createWidgetCTA(cta) {\n  let title, description;\n  const widgetNode =\n    <div class=\"searsia__widget searsia__widget--cta\" data-widget-type=\"cta\">\n      {title = cta.title && <div class=\"inlinecta__title\" />}\n      {cta.buttonlink && cta.buttontitle &&\n        <a class=\"inlinecta__button themecolor--bg\" href={cta.buttonlink} data-wh-datalayer-onclick-cta_type=\"inline-button-cta\" data-wh-datalayer-onclick-event=\"cta-click\" data-wh-datalayer-onclick-click_text={cta.buttontitle} data-wh-datalayer-onclick-click_url={cta.buttonlink} target={cta.buttonnewwindow ? \"_blank\" : \"\"} rel=\"noreferrer\">{cta.buttontitle}</a>\n      }\n      {description = cta.description &&\n        <div class=\"inlinecta__description\">\n          <div class=\"inlinecta__icon UT-icon-UT_icon_117_paperclip-64px\"></div>\n        </div>\n      }\n    </div>;\n  if (title)\n    title.innerHTML = cta.title;\n  if (description) {\n    const descriptionHTML = <span />;\n    descriptionHTML.innerHTML = cta.description;\n    description.append(...descriptionHTML.childNodes);\n  }\n  return widgetNode;\n}\n\nfunction createLocationWidget(result) {\n  let node;\n  if (!shownWidget) {\n    if (debugFlags.searsia)\n      console.info(\"[searsia] Showing location widget\", result);\n    node = <div class=\"widget searsia__widget searsia__widget--location searsia__widget--loading\" data-widget-type=\"location\" />;\n    shownWidget = { type: \"location\", result, node, locreqid: ++locationRequestId };\n    setTimeout(() => retrieveLocation(result.hit.title, locationRequestId).then(() => debugFlags.searsia && console.info(`[searsia] Done for '${result.hit.title}'`)));\n  } else if (shownWidget.type == \"location\") {\n    setTimeout(() => retrieveLocation(result.hit.title, locationRequestId).then(() => debugFlags.searsia && console.info(`[searsia] Done for '${result.hit.title}'`)));\n  }\n  return node;\n}\n\nasync function retrieveLocation(name, locreqid) {\n  if (!name || !shownWidget)\n    return;\n\n  if (debugFlags.searsia)\n    console.log(`[searsia] Fetching data for location '${name}'`);\n  const response = await fetch(\"/.publisher/sd/utwente_base/ws2016/location.shtml?name=\" + encodeURIComponent(name) + \"&lang=\" + encodeURIComponent(getTid.tidLanguage), { credentials: 'same-origin' });\n  if (response.status != 200) {\n    if (debugFlags.searsia)\n      console.warn(`[searsia] Location '${name}' not found`);\n    return;\n  }\n  const data = await response.json();\n\n  // A new search may have been started while we were waiting for the fetch result\n  if (!shownWidget || shownWidget.locreqid != locreqid) {\n    if (debugFlags.searsia)\n      console.log(`[searsia] Widget no longer shown`, shownWidget.locreqid, locreqid);\n    return;\n  }\n\n  const node =\n    <div class=\"widget__front\">\n      {data.img &&\n        <div class=\"widget__photos\">\n          <span class=\"widget__photoslide widget__photoslide--fullwidth\" style={`background-image: url(\"${data.img.link}\")`}></span>\n        </div>\n      }\n      <div class=\"widget__title widget__title--belowphotos\">\n        {decodeString(data.title, \"attribute\")}\n        {data.address &&\n          <span>\n            <br />{data.address.street + \" \" + data.address.nr_detail}\n            <br />{data.address.zip + \" \" + data.address.city}\n          </span>\n        }\n      </div>\n      <div class=\"widget__list\">\n        {data.phone &&\n          <a href={\"tel:\" + decodeString(data.phone, \"attribute\")} class=\"widget__listitem widget__listitem--link\">\n            <div class=\"overflow__container\">\n              <span class=\"widget__listitem-icon UT-icon-UT_icon_13_phone-24px\"></span>\n              <span class=\"widget__listitem-text\">{searsiaTypes.formatPhone(decodeString(data.phone, \"attribute\"))}</span>\n            </div>\n          </a>\n        }\n        {data.email &&\n          <a href={\"mailto:\" + decodeString(data.email, \"attribute\")} class=\"widget__listitem widget__listitem--link overflow\">\n            <div class=\"overflow__container\">\n              <span class=\"widget__listitem-icon UT-icon-UT_icon_15_mail-24px\"></span>\n              <span class=\"softbreak\">&nbsp;</span>\n              <span class=\"widget__listitem-text\" data-overflow={getTid(\"utwente_base:frontend.ws2016.js.searchsheet.overflow--email\")}>{decodeString(data.email, \"attribute\")}</span>\n            </div>\n          </a>\n        }\n        <a href={data.mappdfurl} class=\"widget__listitem widget__listitem--link\">\n          <div class=\"overflow__container\">\n            <span class=\"widget__listitem-icon UT-icon-UT_icon_22_file-pdf-24px\"></span>\n            <span class=\"widget__listitem-text\">{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.downloadmap\")}</span>\n          </div>\n        </a>\n        {data.coord &&\n          <a href={searsiaTypes.getMapRouteLink(data.coord)} class=\"widget__listitem widget__listitem--link\">\n            <span class=\"widget__listitem-icon UT-icon-UT_icons_164_navigate-24px\"></span>\n            <span class=\"widget__listitem-text\">{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.route\")}</span>\n          </a>\n        }\n      </div>\n    </div>;\n  shownWidget.node.appendChild(node);\n  shownWidget.node.classList.remove(\"searsia__widget--loading\");\n}\n\nfunction createEventsWidget(result, eventsurl) {\n  let node;\n  if (!shownWidget) {\n    if (debugFlags.searsia)\n      console.info(\"[searsia] Showing events widget\", result);\n\n    // If we don't have an explicit 'all events' url, try to extract it from the first result\n    // (Assume it is always a webhare events page with virtual subpath beginning with '!/')\n    const alleventsurl = eventsurl || result.hit.url.split(\"!/\")[0];\n    node =\n      <div class=\"widget searsia__widget searsia__widget--event\" data-widget-type=\"event\">\n        <div class=\"widget__front\">\n          <div class=\"widget__title widget__title--withicon\">\n            <span class=\"widget__title-icon UT-icon-UT_icon_11_events-24px\" />{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.events\")}\n          </div>\n          {result.hit.image &&\n            <div class=\"widget__photos\">\n              <span class=\"widget__photoslide widget__photoslide--fullwidth\" style={`background-image: url(\"${result.hit.image}\")`}></span>\n            </div>\n          }\n          <div class=\"widget__list\">\n            <a class=\"widget__listitem widget__listitem--link\" href={decodeString(result.hit.url, \"attribute\")}>\n              <span class=\"widget__listitem-text\">{decodeString(result.hit.title, \"attribute\")}</span>\n              {result.hit.date && <span class=\"widget__listitem-subtext\">{decodeString(result.hit.date, \"attribute\")}</span>}\n            </a>\n          </div>\n          <a class=\"widget__link\" href={alleventsurl}>{getTid(\"utwente_base:frontend.ws2016.js.searchsheet.allevents\")}</a>\n        </div>\n      </div>;\n    shownWidget = { type: \"event\", result, node };\n  } else if (shownWidget.type == \"event\") {\n    const eventNode =\n      <a class=\"widget__listitem widget__listitem--link\" href={decodeString(result.hit.url, \"attribute\")}>\n        <span class=\"widget__listitem-text\">{decodeString(result.hit.title, \"attribute\")}</span>\n        {result.hit.date && <span class=\"widget__listitem-subtext\">{decodeString(result.hit.date, \"attribute\")}</span>}\n      </a>;\n    //TODO: Order by date\n    shownWidget.node.querySelector(\".widget__list\").appendChild(eventNode);\n  }\n  return node;\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport * as browser from 'dompack/extra/browser';\nimport { applyTimeoutToPromise } from \"@mod-utwente_base/js/promisetimeout\";\nimport { getCSSVariable } from \"@mod-utwente_base/webdesigns/ws2016/src/shared/layout-tools\";\n// webdesign node modules aren't accessible from webfeatures, load them directly\nimport PerfectScrollbar from \"@mod-utwente_design/vendor/perfect-scrollbar-wh\";\n\n// If scrollTo accepts an options object (it doesn't in Safari, unless the 'CSSOM View Smooth Scrolling' experimental\n// feature is enabled)\nconst scrollToOptionsAvailable = \"scrollBehavior\" in document.documentElement.style;\n\nfunction calcNavLink(link, nav) {\n  const navurl = new URL(link);\n  navurl.pathname += 'utwente-navigation.rpc';\n  navurl.searchParams.set('nav', nav);\n  return navurl.toString();\n}\n\nasync function getMenuForPage(link) {\n  const res = (await fetch(calcNavLink(link, 'menu')));\n  return await res.json();\n}\n\nasync function getParentForPage(link) {\n  const res = (await fetch(calcNavLink(link, 'parent')));\n  return await res.json();\n}\n\nexport default class SiteMenu {\n  constructor(node) {\n    this.node = node;\n    this.menupartNode = this.node.closest(\".menupart\");\n    this.scrollingNode = this.node.closest(\".menupart__menu-container\");\n\n    // Store the current item, so it can be scrolled into view after the menu is opened\n    this.currentItem = null;\n    this.transitionDuration = 0;\n    getCSSVariable(\"--menu-transition-duration\", this.node).then(duration => {\n      if (duration.endsWith(\"ms\"))\n        this.transitionDuration = parseInt(duration);\n      else if (duration.endsWith(\"s\"))\n        this.transitionDuration = Math.floor(parseFloat(duration) * 1000);\n    });\n    window.addEventListener(\"ws:menu-open\", event => this.onMenuOpened(event));\n\n    let menuParent, // The 'back' link at the top\n      menuItems;  // The menu items to show initially\n    try {\n      if (this.node.dataset.menuParent)\n        menuParent = JSON.parse(this.node.dataset.menuParent);\n      menuItems = JSON.parse(this.node.dataset.menuItems);\n    } catch (e) {\n      console.error(\"Couldn't read menu items\", e);\n      return;\n    }\n    this.menus = new Map(); // A map from menu item id to its submenu item defs\n    this.menuItems = new Map(); // A map from menu item id to its item def\n    const menuParentId = menuParent && menuParent.id;\n    this.menuItems.set(menuParentId, menuParent);\n    this.menus.set(menuParentId, menuItems);\n\n    // Read the menu items (no need to recurse, it's at most two levels deep)\n    let submenuId, currentId;\n    for (const item of menuItems) {\n      item.parent = menuParentId;\n      if (item.menuitems) {\n        for (const subitem of item.menuitems) {\n          subitem.parent = item.id;\n          this.menuItems.set(subitem.id, subitem);\n          if (subitem.is_current)\n            currentId = subitem.id;\n        }\n        this.menus.set(item.id, item.menuitems);\n        submenuId = item.id;\n        delete item.menuitems;\n      }\n      this.menuItems.set(item.id, item);\n      if (!currentId && item.is_current)\n        currentId = item.id;\n    }\n    if (dompack.debugflags.umn)\n      console.log(\"[ut-menu] Read page menu\", menuItems, menuParentId, submenuId, currentId);\n\n    // Store the current page id and link\n    if (currentId) {\n      this.pageId = currentId;\n    }\n\n    this.menuScroll = browser.getPlatform() != \"ios\" && browser.getPlatform() != \"android\";\n    if (this.menuScroll) {\n      this.ps = new PerfectScrollbar(this.scrollingNode, {\n        swipePropagation: false,\n        wheelPropagation: false,\n        suppressScrollX: true\n      });\n      window.addEventListener(\"resize\", () => requestAnimationFrame(() => this.ps.update()));\n    }\n\n    // Show the current menu\n    this.showMenu(menuParentId, submenuId, currentId);\n\n    node.addEventListener(\"click\", event => this.onMenuClick(event));\n  }\n\n  async goUp(link) {\n    if (dompack.debugflags.umn)\n      console.log(\"[ut-menu] Going up\", link);\n    // Retrieve the parent menu of the current menu\n    const folderId = parseInt(link.dataset.id);\n    const parentItem = await this.retrieveParent(folderId, link.href);\n    if (parentItem) {\n      if (this.menus.has(parentItem.id)) {\n        this.showMenu(parentItem.id, this.curMenu, this.curMenu);\n        dompack.dispatchCustomEvent(this.node, \"ws:menustatus\", { bubbles: true, cancelable: false, detail: { action: \"up\" } });\n      } else\n        console.warn(\"parent menu not found\");\n    } else\n      console.warn(\"parent item not found\");\n  }\n\n  async openMenu(link) {\n    if (dompack.debugflags.umn)\n      console.log(\"[ut-menu] Opening submenu\", link);\n    // Retrieve the submenu of the given item node\n    const folderId = parseInt(link.dataset.id);\n    let menuItems;\n    try {\n      menuItems = await this.retrieveMenu(folderId, link.href);\n    } catch (error) {\n      // On error, navigate directly to the linked page\n      if (link.href) {\n        console.error(\"failed to retrieve menu for folder #\" + folderId, error);\n        location.href = link.href;\n      }\n      return;\n    }\n    if (menuItems && menuItems.length) {\n      // Show the submenu\n      const menuId = link.parentNode.classList.contains(\"menupart__submenu\") ? this.curSubmenu : this.curMenu;\n      this.showMenu(menuId, folderId, folderId);\n      dompack.dispatchCustomEvent(this.node, \"ws:menustatus\", { bubbles: true, cancelable: false, detail: { action: \"open\" } });\n    } else if (dompack.debugflags.umn)\n      console.log(\"[ut-menu] No items to show\");\n  }\n\n  closeMenu(link) {\n    // Close the currently opened submenu\n    if (dompack.debugflags.umn)\n      console.log(\"[ut-menu] Closing submenu\", link);\n    link.nextSibling.remove();\n    link.classList.remove(\"menupart__menuitem--opened\");\n    this.curSubmenu = null;\n    this.menupartNode.classList.remove(\"menupart--submenuopened\");\n    this.setSelectedMenu(link.dataset.id);\n    setTimeout(() => dompack.dispatchCustomEvent(this.node, \"ws:menustatus\", { bubbles: true, cancelable: false, detail: { action: \"close\" } }), 1);\n  }\n\n  async retrieveParent(folderId, link) {\n    const menuItem = this.menuItems.get(folderId);\n    if (!menuItem)\n      return;\n\n    let parentItem = this.menuItems.get(menuItem.parent);\n    if (!parentItem) {\n      try {\n        if (menuItem.folderid)\n          folderId = menuItem.folderid;\n        if (dompack.debugflags.umn)\n          console.log(\"[ut-menu] Retrieving parent for\", folderId);\n        this.showBusy();\n\n        const result = await applyTimeoutToPromise(getParentForPage(link), 2000);\n\n        if (dompack.debugflags.umn)\n          console.log(\"[ut-menu] Received parent\", result);\n\n        if (result) {\n          const parentId = result.parent ? result.parent.id : 0;\n          if (parentId) {\n            parentItem = result.parent;\n            this.menuItems.set(parentId, parentItem);\n          } else {\n            parentItem = { id: 0 }; // Show root menu\n          }\n\n          const menuItems = result.items;\n          for (const item of menuItems) {\n            item.parent = parentId;\n            // Cache the menu items\n            this.menuItems.set(item.id, item);\n          }\n\n          // Cache the menu\n          this.menus.set(parentId, menuItems);\n        }\n      } finally {\n        this.hideBusy();\n      }\n    } else {\n      if (dompack.debugflags.umn)\n        console.log(\"[ut-menu] Using cached parent for\", folderId);\n    }\n    return parentItem;\n  }\n\n  async retrieveMenu(folderId, link) {\n    let menuItems = folderId && this.menus.get(folderId);\n    if (!menuItems) {\n      try {\n        if (dompack.debugflags.umn)\n          console.log(\"[ut-menu] Retrieving menu for\", folderId);\n        this.showBusy();\n\n        const result = await applyTimeoutToPromise(getMenuForPage(link), 2000);\n\n        if (dompack.debugflags.umn)\n          console.log(\"[ut-menu] Received menu\", result);\n\n        menuItems = result.items;\n        for (const item of menuItems) {\n          item.parent = folderId;\n          // Cache the menu items\n          this.menuItems.set(item.id, item);\n        }\n\n        // Cache the menu\n        this.menus.set(folderId, menuItems);\n      } finally {\n        this.hideBusy();\n      }\n    } else {\n      if (dompack.debugflags.umn)\n        console.log(\"[ut-menu] Using cached menu for\", folderId);\n    }\n    return menuItems;\n  }\n\n  showMenu(menuId, submenuId, selectId) {\n    if (dompack.debugflags.umn)\n      console.log(\"[ut-menu] Showing menu\", menuId, submenuId);\n\n    // Clear the current menu item node, it will be replaced\n    if (this.currentItem)\n      this.currentItem = null;\n\n    // Get the menu items to show\n    const toshow = [...this.menus.get(menuId).map(item => this.getMenuItemNode(item, item.id == selectId))];\n    // If we're showing a submenu, show the parent ('back') link\n    if (menuId) {\n      const parentlink = this.getMenuParentNode(this.menuItems.get(menuId));\n      if (parentlink)\n        toshow.unshift(parentlink);\n    }\n    // Show the new menu\n    this.node.replaceChildren(...toshow);\n\n    // Show the opened submenu\n    if (submenuId) {\n      const menuNode = this.node.querySelector(`.menupart__menuitem[data-id=\"${submenuId}\"]`);\n      if (menuNode) {\n        const toshow = [...this.menus.get(submenuId).map(item => this.getMenuItemNode(item, item.id == selectId))];\n        menuNode.after(\n          <div class=\"menupart__submenu\">\n            {toshow}\n          </div>\n        );\n        menuNode.classList.add(\"menupart__menuitem--opened\");\n      }\n      this.menupartNode.classList.add(\"menupart--submenuopened\");\n    }\n\n    this.curSubmenu = submenuId;\n    this.curMenu = menuId;\n\n    if (this.menuScroll && this.ps)\n      this.ps.update();\n  }\n\n  setSelectedMenu(itemId) {\n    for (const item of this.node.querySelectorAll(\".menupart__menuitem\"))\n      item.classList.toggle(\"menupart__menuitem--selected\", item.dataset.id == itemId);\n  }\n\n  getMenuParentNode(item) {\n    if (!item || !item.title)\n      return;\n\n    return (\n      <a class=\"menupart__menuitem menupart__menuitem--parent\" href={item.link} data-id={item.id}>\n        <span class=\"menupart__menuitem-icon menupart__menuitem-icon--parent UT-icon-UT_icon_63_arrow-left-small-16px\"></span>\n        <span class=\"menupart__menuitem-text\">{item.title || \"##FIXME\"}</span>\n      </a>\n    );\n  }\n\n  getMenuItemNode(item, selected) {\n    if (!item)\n      console.error(item);\n    const itemNode = (\n      <a class={\"menupart__menuitem\" +\n        (item.has_subitems ? \" menupart__menuitem--subitems\" : \"\") +\n        (item.id == this.pageId ? \" menupart__menuitem--current\" : \"\") +\n        (selected ? \" menupart__menuitem--selected\" : \"\")}\n        href={item.link}\n        target={item.newwindow && item.browser ? \"_blank\" : null}\n        data-windowopen={item.newwindow && !item.browser ? `${item.width},${item.height}` : null}\n        data-id={item.id} rel=\"noreferrer\">\n        {\n          item.has_subitems\n            ? [\n              <span class=\"menupart__menuitem-icon menupart__menuitem-icon--closed UT-icon-UT_icon_68_plus-small-16px\"></span>,\n              <span class=\"menupart__menuitem-icon menupart__menuitem-icon--opened UT-icon-UT_icon_69_min-small-16px\"></span>\n            ]\n            : null\n        }\n        <span class=\"menupart__menuitem-text\">\n          {item.title}\n        </span>\n      </a>\n    );\n    if (item.id == this.pageId)\n      this.currentItem = itemNode;\n    return itemNode;\n  }\n\n  showBusy() {\n    if (this.busyTimer)\n      return;\n    // Show a modal layer to prevent more menu clicks\n    document.getElementById(\"menupart__menu\").classList.add(\"menupart__menu--modal\");\n    // Show the busy layer after a short timeout\n    this.busyTimer = setTimeout(() => document.getElementById(\"menupart__menu\").classList.add(\"menupart__menu--busy\"), 250);\n  }\n\n  hideBusy() {\n    // Reset short timeout timer\n    this.busyTimer = clearTimeout(this.busyTimer);\n    // Hide modal and busy layers\n    document.getElementById(\"menupart__menu\").classList.remove(\"menupart__menu--modal\");\n    document.getElementById(\"menupart__menu\").classList.remove(\"menupart__menu--busy\");\n  }\n\n  onMenuClick(event) {\n    const link = event.target.closest(\"a\");\n    if (dompack.debugflags.umn)\n      console.log(\"[ut-menu] Clicked link\", link);\n    if (link) {\n      if (link.classList.contains(\"menupart__menuitem--parent\"))\n        this.goUp(link);\n      else if (link.classList.contains(\"menupart__menuitem--opened\"))\n        this.closeMenu(link);\n      else if (link.classList.contains(\"menupart__menuitem--subitems\"))\n        this.openMenu(link);\n      else\n        return; // Let the browser follow the menu item link\n\n      event.preventDefault();\n      event.stopPropagation();\n    }\n  }\n\n  onMenuOpened(event) {\n    if (event.detail.open && this.currentItem) {\n      // Check if the current item is scrolled out of view\n      const scrollRect = this.scrollingNode.getBoundingClientRect();\n      const itemRect = this.currentItem.getBoundingClientRect();\n\n      if ((itemRect.top + itemRect.height > scrollRect.top + scrollRect.height)\n        || itemRect.top < scrollRect.top) {\n        if (dompack.debugflags.umn)\n          console.log(\"[ut-menu] Scroll current item into view\");\n        // Scroll the current item to the center of the menu after the menu has opened\n        const top = this.scrollingNode.scrollTop + (itemRect.top - scrollRect.top); // The top of the item within the menu\n        const pos = Math.round((scrollRect.height - itemRect.height) / 2); // The top of the centered item within the scroll area\n        if (scrollToOptionsAvailable)\n          setTimeout(() => this.scrollingNode.scrollTo({ behavior: \"smooth\", left: 0, top: top - pos }), this.transitionDuration);\n        else\n          setTimeout(() => this.scrollingNode.scrollTo(0, top - pos), this.transitionDuration);\n      }\n    }\n  }\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nclass PromiseTimeoutError extends Error {\n  constructor(timeout) {\n    super(`Timeout on promise after ${timeout}ms`);\n  }\n}\n\n/** @short Wrap a promise to support timeouts\n    @param promise Original promise\n    @param timeout Timeout duration in ms\n    @returns A promise that rejects if the timeout hits or resolves to the original promise otherwise */\nexport function applyTimeoutToPromise(promise, timeout) {\n  const timeoutpromise = new Promise((_, reject) => setTimeout(() => reject(new PromiseTimeoutError(timeout)), timeout));\n  return Promise.race([promise, timeoutpromise]);\n}\n","import { setLocal } from \"@webhare/dompack\";\n\nexport function setupLanguageSwitch() {\n  //Capture last selected language when explicitly switching\n  document.documentElement.addEventListener('click', (event) => {\n    const langlink = (event.target as HTMLElement)?.closest(\".js-langswitch[hreflang]\");\n    if (langlink)\n      setLocal(\"utwente-lastselectedlanguage\", langlink.getAttribute(\"hreflang\"));\n  }, { capture: true });\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport { fitFonts } from \"@mod-utwente_base/webdesigns/ws2016/src/shared/layout-tools\";\n\nlet callback = 0;\n\n// Give other code a chance to register for this event - we need all domreadys to run and THEN we run ourselves\ndompack.onDomReady(() => setTimeout(() => checkWindowSize({ forceevents: true }), 1));\n\n// Check window size on resize\nwindow.addEventListener(\"resize\", event => { callback = callback || requestAnimationFrame(() => checkWindowSize(event)); });\n\n// Make sure layouts are updated after all CSS files and Custom fonts have been loaded\nwindow.addEventListener(\"load\", checkWindowSize);\n\nfunction checkWindowSize(event) {\n  callback = 0;\n  fitFonts();\n  dompack.dispatchCustomEvent(window, \"ws:resize\",\n    {\n      bubbles: true,\n      cancelable: false,\n      detail: { event }\n    });\n}\n","// @ts-nocheck -- prototyping first\nimport \"./main.scss\";\nimport \"./main-foldable.scss\";\nimport \"./largelists-foldable.scss\";\n\nimport * as dompack from \"dompack\";\n\nlet openedParts: Element[] = [];\nlet initialLayout = true;\nlet prevAutoFold = true;\n\n\nwindow.addEventListener(\"resize\", evt => updateFoldableContentBlocks(evt));\ndompack.onDomReady(initFoldableContentBlocks);\n\n\n\nfunction initFoldableContentBlocks() {\n  console.info(\"initFoldableContentBlocks()\");\n\n  document.body.addEventListener(\"focusout\", evt => doCheckLostFocus(evt));\n\n  const hash = location.hash.substr(1);\n\n  // If the hash points to an existing element (by id)\n  // ensure all parent accordeons (<details>) are opened.\n  if (hash) {\n    openedParts = [];\n    let block = document.getElementById(hash)?.closest(\".ut-rtd-blocks\");\n    while (block) {\n      openedParts.push(block);\n      block = block.parentElement.closest(\".ut-rtd-blocks\");\n    }\n\n    // console.info(\"BLOCKS to open\", openedParts);\n\n    updateFoldableContentBlocks();\n\n    return;\n  }\n\n  // If there wasn't a target, open the first block\n  const firstBlock = document.querySelector(\".ut-rtd-blocks\");\n  if (firstBlock && firstBlock.tagName === \"DETAILS\")\n    openedParts = [firstBlock];\n\n  updateFoldableContentBlocks();\n\n  // Only after the initial open state of all blocks are set\n  // we enable animation (otherwise whe'll see accordeons\n  // animate closing when loading on mobile)\n  // document.clientWidth;\n  setTimeout(function () {\n    document.documentElement.classList.add(\"ut-rtd-blocks-initialized\");\n  }, 1);\n}\n\n\n/*\nCheck whether we lost focus due to <summary> getting display: contents;\nIn this case we move the focus to a new place we chose, because:\nA) We can restore the focus on the <summary> later when returning to mobile layout\nB) Otherwise Safari will reset the focus position back to the top of the page\n\nNOTE: We first get a focusout and than the window resize event.\n*/\nfunction doCheckLostFocus(evt) {\n  const block = evt.target.closest(\"details.ut-rtd-blocks\");\n  if (!block)\n    return;\n\n  const summary = evt.target.tagName === \"SUMMARY\";\n  if (!summary)\n    return;\n\n  /*\n  - navigating using tab - relatedTarget: (next target node)\n  - losing focus ability due to display: contents; - relatedTarget: null\n  - focus leaving browser - relatedTarget: null\n  */\n\n  // If we havn't lost focus we don't need to do our workaround to keep the focus near the <summary> element.\n  if (evt.relatedTarget !== null)\n    return;\n\n  /*\n  So evt.relatedTarget was null. This happens when:\n  - clicking outside a focused element - reaching the <body>\n  - focused element blurs() - may also be due the element not available anymore (for example due to display: contents;)\n  - the browser window lost focus (user working in another window)\n  */\n  const autoFold = window.getComputedStyle(document.documentElement).getPropertyValue(\"--headingsmode\") === \"autofold\";\n\n  // We have focus on <summary> which is only possible in mobile layout.\n  // So we seem to have moved to the desktop layout, causing the focusout event.\n  // To preserve the focus position for Safari whe'll temporary make the wrapper for out <details> content (.ut-rtd-blocks__body) the focused item.\n  if (!autoFold) {\n    const bodyNode = block.querySelector(\".ut-rtd-blocks__body\");\n    bodyNode.setAttribute(\"tabindex\", \"-1\");\n    bodyNode.focus();\n  }\n}\n\nfunction updateFoldableContentBlocks(evt) {\n  // console.info(\"updateFoldableContentBlocks(evt)\");\n\n  // Get all blocks we can toggle (if the page content doesn't start with a h2, the first block will be a normal div)\n  const blocks = Array.from(document.querySelectorAll(\"details.ut-rtd-blocks\"));\n  if (blocks.length === 0)\n    return;\n\n  const autoFold = window.getComputedStyle(document.documentElement).getPropertyValue(\"--headingsmode\") === \"autofold\";\n\n  if (!initialLayout && prevAutoFold === autoFold)\n    return; // no need to do an update\n\n  // When moving to desktop layout remember which blocks were opened\n  if (prevAutoFold && !autoFold) {\n    openedParts = [];\n    for (const node of blocks) {\n      if (node.hasAttribute(\"open\"))\n        openedParts.push(node);\n    }\n  }\n\n  /*\n  NOTE:\n\n  On Desktop we need the <summary> to act like a normal <h2>:\n\n  - Prevent interaction\n    - We use pointer-events: none; on the summary to prevent mouse interaction\n    - We use tabindex=\"-1\" to prevent focus on the h2's through keyboard navigation (tab)\n    - We use role=\"presentation\" on <summary> to prevent screenreaders from announcing it as an element you can interact with.\n      (screenreaders should still use the headings within)\n    - NOTE: We cannot use \"inert\" - although it would fully prevent interaction and screenreaders\n            This would hide the h2 from readreaders and prevent text selection and browser in-page text searches\n    - NOTE: The detail element's \"toggle\" event cannot be canceled and reopening upon a toggle event may cause a flicker\n\n  - Visually look like a normal heading (h2)\n    - hide the marker and toggle icon\n    - ensure margins mimicing the h2 as being a direct part of the RTD content\n\n  - Tricky\n    - When <summary> (is focused in the mobile layout) and we switch to the desktop layout focus will be lost.\n      Chrome and Firefox will remember the position in the DOM of the last focused element (even though it's not part of the focusable elements anymore due to display: contents;).\n      When tabbing they will look up the next focusable element in the DOM after the <summary>.\n      However Safari won't - so when focus was on a .ut-rtd-blocks <summary> and we switch to desktop layout, Safari will reset the focus to the top of the page/DOM.\n    - Using display: contents; on <summary> not only prevents getting focus, but also makes it blur() (so when it's applied we cannot test for focus on <summary> anymore to prevent it moving to body)\n  */\n  for (const node of blocks) {\n\n    // console.log((!autoFold || openedParts.includes(node)), node);\n\n    node.toggleAttribute(\"open\", !autoFold || openedParts.includes(node));\n\n    const summary = node.querySelector(\"summary\");\n\n    if (autoFold) {\n      summary?.removeAttribute(\"role\");\n      summary?.removeAttribute(\"tabindex\");\n\n      // Check if the focus was set on the contentwrapper as a workaround for Safari to keep the current tabnavigation position.\n      // If this is the case we want to restore this focus back to the <summary> now whe're in the mobile layout again.\n      const bodyNode = node.querySelector(\".ut-rtd-blocks__body\");\n      if (document.activeElement === bodyNode)\n        summary?.focus();\n    } else {\n      // Prevent interaction (without using inert - which kills text selection and in-page search)\n      summary?.setAttribute(\"role\", \"presentation\"); // prevent screenreader from announcing it's special role\n      summary?.setAttribute(\"tabindex\", \"-1\"); // prevent being part of keyboard navigation\n      //summary.style.pointerEvents = \"none\"; // prevent toggling through a pointer/mouse click\n    }\n\n    // FIXME: do we need to listen to toggle to prevent a toggle if the user still someone found a way to toggle it?\n  }\n\n  prevAutoFold = autoFold;\n  initialLayout = false;\n\n  // - height must be updated on .contentpart__navbar-container\n  // NavBarContainerScroller\n}\n","//TODO switch to WebHare 5.7s builtin function setupDataLayerTags\nfunction processClickDataLayerTags(event: MouseEvent) {\n  const entry: Record<string, unknown> = {};\n\n  for (let node = event.target as HTMLElement | undefined | null; node; node = node?.parentElement)\n    for (const attr of node.attributes)\n      if (attr.nodeName.startsWith(\"data-wh-datalayer-onclick-\")) {\n        const key = attr.nodeName.substring(26);\n        if (key !== \"__proto__\" && !(key in entry)) //as we're working upwards, don't overwrite already set keys\n          entry[key] = attr.nodeValue || \"\";\n      } else if (attr.nodeName === \"data-wh-datalayer-onclick\") { //JSON setter\n        const data = JSON.parse(attr.nodeValue!);\n        for (const [key, value] of Object.entries(data))\n          if (key !== \"__proto__\" && !(key in entry)) //as we're working upwards, don't overwrite already set keys\n            entry[key] = value;\n      }\n\n  if (Object.keys(entry).length)\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO switch to WebHare 5.7s builtin function setupDataLayerTags\n    window.dataLayer.push(entry as any);\n}\n\n/** Setup support for data-wh-datalayer-onclick-xxx=\"yyy\" attributes. When clicking an element with these attributes the JSON from the attribute and all parents are merged together and pushed to the dataLayer  */\nexport function setupDataLayerTags() {\n  //we capture so we can also simply set variables for any existing GTM handlers\n  window.addEventListener(\"click\", processClickDataLayerTags, { capture: true });\n}\n","/* This is the core of ws2016, as shared between UTAP, ITC and UTWENTE_BASE\n   do not add external module dependencies (other than utwente_design) here!\n   do not add 'shared/login' here as UTAP/ITC don't need it and may setup their own alternatives\n*/\n\nimport * as dialogapi from 'dompack/api/dialog';\n\n// FIXME: to support Yuja we temporary\n//        load our own video support\n// import \"@mod-publisher/js/richcontent/all\"; // Cannot use this for now, it loads the standard video handler (which doesn't support Yuja are adding custon videoproviders yet)\nimport \"@mod-publisher/js/richcontent/styling.css\";\nimport \"@mod-utwente_design/webfeatures/videoproviders\";\n\nimport \"@mod-utwente_design/theme/theme\";\n\n\n\nimport \"./shared/reset.css\";\nimport * as dialogs from \"./shared/dialog/index\";\nimport \"./site.scss\";\n// rtd.css is imported separately, because it's also loaded by the rich document editor. It cannot be imported by site.scss,\n// because the SASS parser cannot handle the external font from fonts.net.\nimport \"./rtd\";\nimport \"./shared/fonts/fonts.css\";\nimport \"@mod-utwente_design/web/utdesign/fonts/univers-next-async\";\nimport \"./shared/searchpage.scss\"; //searsia and studyfinder shared\nimport \"./shared/utforms\"; // must be inserted before widget/page CSS to avoid specificy issues\n\nimport \"./theme/colorschemeanimation\";\nimport \"./theme/identity-itc.scss\";\n\nimport \"./menu\";\nimport \"./header\";\nimport \"./main\";\nimport \"./footer\";\nimport \"./widgets\";\n\nimport \"./components/spinner.scss\";\nimport \"./components/preventzoomonfocus\";\nimport \"./filteredoverview/filteredoverview.scss\";\nimport \"./filteredoverview/filteredoverview-listview.scss\";\nimport \"./filteredoverview/filteredoverview-feedbackbar.scss\";\nimport \"./filteredoverview/filteredoverview-viewmodetoggle.scss\";\n\nimport \"./shared/peopleimages\";//People Image Replacements\nimport \"./shared/psa-chatbot\";\n\nimport \"../../../webfeatures/ws2021/header/header\";\nimport \"../../../webfeatures/ws2021/navigation/navigation\";\nimport \"../../../webfeatures/ws2021/shared/resizelistener\";\n\nimport \"../../../webfeatures/ws2021/header/header.scss\";\nimport \"../../../webfeatures/ws2021/header/header-inset.scss\";\nimport \"../../../webfeatures/ws2021/header/header-countdown.scss\";\nimport \"../../../webfeatures/ws2021/main\";\nimport \"../../../webfeatures/ws2021/navigation/navigation.scss\";\nimport \"../../../webfeatures/ws2021/ws2021.scss\";\n\nimport { setupDataLayerTags } from '@mod-utwente_design/js/wh-compatibility';\n\nimport * as forms from '@webhare/forms';\n\nforms.setupFriendlyCaptcha({ endpoint: \"eu\" });\nforms.setupGoogleRecaptcha();\nforms.setupForms({ captcha: \"onLoad\" });\n\n//setup dialog box. moved here so we don't conflict with shardportal in shared/dialog.es\ndialogapi.setupDialogs(options => new dialogs.UTDialog(options), { messageboxclassbase: 'wh-form__' });\n\n// @ts-ignore Make Yorick's piwik experiments more stable\nwindow._paq = window._paq || [];\n\nsetupDataLayerTags();\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./newsevents-detail.scss\";\nimport \"./newsevents-overview.scss\";\n\nimport * as whintegration from \"@mod-system/js/wh/integration\";\nimport * as dompack from 'dompack';\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\nimport { getTid } from \"@webhare/gettid\";\nimport { setEllipsisLines, fitFonts } from \"../../shared/layout-tools\";\nimport * as modaldialog from \"../../shared/dialog\";\nimport { UTRPCFormBase } from '../../shared/utforms';\nimport { registerHandler } from '@mod-publisher/js/forms';\nimport { getFormFilters, setFormFilters } from './formfilters';\n\nimport \"./index-new\";\n\n/*\n\nWarning:\n- Colloquia works through the News & Events pages, but has no filters.\n  Make sure the JS code can handle this. (because filter + pagination code is combined)\n\n*/\n\n\nclass EventsFormHandler extends UTRPCFormBase {\n  constructor(formnode, requesttype) {\n    super(formnode);\n\n    this.formnode = formnode;\n    this.requesttype = requesttype;\n\n    this.container = document.createElement(\"div\");\n    this.container.appendChild(this.formnode);\n    this.formnode.style.display = \"block\";\n\n    for (const node of document.querySelectorAll(\".inlinecta__button[href='#showeventform']\"))\n      node.addEventListener(\"click\", this.show.bind(this));\n  }\n\n  show(ev) {\n    if (ev)\n      ev.preventDefault();\n    this.reset();\n    this.dialognode = modaldialog.showModalDialog(\"\", this.formnode, { theme: \"withbackground dialog--small\" });\n  }\n\n  reset() {\n    super.reset();\n  }\n\n  onSubmitSuccess(res) {\n    const dialogcontentnode = this.dialognode.querySelector(\".dialog__content\");\n    if (dialogcontentnode)\n      dialogcontentnode.textContent = this.requesttype == 'cultural' ? getTid(\"utwente_base:frontend.ws2016.js.newsevents.thanks-cultural\")\n        : getTid(\"utwente_base:frontend.ws2016.js.newsevents.thanks-event\");\n  }\n}\n\n\nclass SummaryNavigation {\n  constructor() {\n    this.initPrevNextNav();//on detail page\n\n    this.summarycontainer = document.querySelector(\"main .summary\");\n    this.form = document.querySelector(\".filteredoverview__form\");\n\n    this.initFilters();\n\n    this.hasfoldableitems = this.summarycontainer.classList.contains(\"summary--foldable\");\n\n    if (this.hasfoldableitems)\n      this.initFoldableContent();\n\n    this.updatePageTitle();\n  }\n\n  initFoldableContent() {\n    const items = this.summarycontainer.querySelectorAll(\".summary__items .summary__link\");\n    for (const node of items) {\n      const btnnode = node.querySelector(\".summary__arrow\");\n\n      node.addEventListener(\"click\", ev => {\n\n        if (ev.target.nodeName == \"A\" || ev.target.classList.contains(\"addtocalendar\") || ev.target.closest(\".addtocalendar\"))\n          return;//just do normal things\n\n        if (node.classList.contains(\"foldablecontent--active\")) {\n          btnnode.style.top = \"\";\n          node.classList.remove(\"foldablecontent--active\");\n          return;\n        }\n\n        for (const item of items)\n          item.classList.remove(\"foldablecontent--active\"); //hide others\n\n        //set close/open button position fixed before openening (and add offset 0.5 size of button)\n        //btnnode.style.top = (btnnode.getBoundingClientRect().top - node.getBoundingClientRect().top + 8) + \"px\";\n        node.classList.add(\"foldablecontent--active\");\n      });\n    }\n  }\n\n  initFilters() {\n    this.rpc = new JSONRPC();\n\n    // Initialize 'more results' button\n    this.moreresults = document.querySelector(\".moreresults\");\n    if (this.moreresults) {\n      this.moreresults.querySelector(\"a\").addEventListener(\"click\", this.doLoadMore.bind(this), false);\n      this.lastresult = parseInt(this.moreresults.dataset.skip, 10);\n    }\n    if (!this.form)\n      return;\n\n    this.archivecheck = this.form.querySelector(\"input[name='archive']\");\n\n    //get and set initial filter settings\n    let filtersettings = sessionStorage.summaryfilters ? JSON.parse(sessionStorage.summaryfilters) : {};\n\n    if (filtersettings.id != whintegration.config.obj.summary_id)\n      filtersettings = {};//reset if sessionStorage if from other page\n\n    if (!document.referrer || document.referrer.indexOf(document.location.href) == -1)\n      filtersettings = {};//reset if sessionStorage if referrer not within current path\n\n    //overrule sessionStorage if url params set\n    const urlparamsdone = [];\n    for (const node of this.form.querySelectorAll(\"input[name], select[name]\")) {\n      const val = urlparamsdone.indexOf(node.name) == -1 ? this.getUrlParam(node.name) : \"\";\n      if (val != \"\") {\n        if (urlparamsdone.length == 0) //reset before using url data\n          filtersettings = { id: whintegration.config.obj.summary_id, filters: {} };\n\n        const inptype = node.nodeName == \"INPUT\" ? node.getAttribute(\"type\") : \"\";\n        if (inptype == \"checkbox\") {\n          if (node.value == \"yes\")\n            filtersettings.filters[node.name] = val == node.value;\n          else\n            filtersettings.filters[node.name] = val.split(\",\");\n        } else if (inptype == \"radio\")\n          filtersettings.filters[node.name] = val == \"true\";\n        else\n          filtersettings.filters[node.name] = val;\n        urlparamsdone.push(node.name);\n      }\n    }\n\n    // If not already explicitly set through url params, switch to archive if the archivecheck is checked (i.e. there are no\n    // items to show)\n    if (this.archivecheck && this.archivecheck.checked && (!filtersettings.filters || !Object.keys(filtersettings.filters).length))\n      filtersettings.filters = { archive: this.archivecheck.checked };\n\n    setFormFilters(this.form, filtersettings.filters);\n    const moreitems = this.form.parentNode.classList.contains(\"summaryfilters--moreitems\");\n\n    if (this.form && filtersettings.filters && Object.keys(filtersettings.filters).length) {\n      if (urlparamsdone.length) { //items already server side loaded via url params, so no need to update\n        sessionStorage.summaryfilters = JSON.stringify(filtersettings);\n        this.prevfilters = sessionStorage.summaryfilters;\n        this.showFilters(getFormFilters(this.form), moreitems);\n      } else {\n        this.doFilter(null);\n      }\n\n      this.form.classList.add(\"foldablecontent--open\");\n    } else {\n      this.prevfilters = JSON.stringify(filtersettings);\n      if (this.archivecheck)\n        this.showFilters({}, moreitems); // Show correct current/archive navigation links\n    }\n\n    //Events\n    for (const node of this.form.querySelectorAll(\"select\"))\n      node.addEventListener(\"change\", this.doFilter.bind(this), false);\n\n    for (const node of this.form.querySelectorAll(\"input[type=date]\"))\n      node.addEventListener(\"change\", this.doFilter.bind(this), false);\n\n    this.form.addEventListener(\"submit\", this.doFilter.bind(this), false);\n\n    //catch click on tags within summary items\n    this.summarycontainer.addEventListener(\"click\", ev => {\n      if (ev.target.classList.contains(\"tag\")) {\n        const filter = ev.target.getAttribute(\"data-filter\");\n        const id = ev.target.getAttribute(\"data-id\");\n        if (filter != \"\" && id != \"\") {\n          ev.preventDefault();\n          location.href = location.href.split(\"?\")[0] + \"?\" + encodeURIComponent(filter) + \"=\" + encodeURIComponent(id);\n        }\n      }\n    });\n\n    for (const node of this.form.querySelectorAll(\".resetfilters\")) {\n      node.addEventListener(\"click\", ev => {\n        let newfilters;\n        if (this.archivecheck)\n          newfilters = { archive: this.archivecheck.checked };\n        this.resetFilters(newfilters);\n      }, false);\n    }\n\n    if (this.archivecheck) {\n      document.querySelector(\".filterlink--upcoming\").addEventListener(\"click\", ev => this.resetFilters({ archive: false }), false);\n      document.querySelector(\".filterlink--archive\").addEventListener(\"click\", ev => this.resetFilters({ archive: true }), false);\n    }\n  }\n\n  resetFilters(newfilters) {\n    setFormFilters(this.form, newfilters);\n    this.lastresult = 0;\n    this.doFilter(null);\n  }\n\n  getUrlParam(name) {\n    const urlparamstr = location.search.replace(/\\+/g, \"%20\");\n    if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(urlparamstr))\n      return decodeURIComponent(name[1]);\n    return \"\";\n  }\n\n  showFilters(filters, have_more_results) {\n    /*\n        let have_active_filters = filters && filters.settings && filters.settings.filters;\n        if (have_active_filters)\n        {\n          let numfilters = Object.keys(filters.settings.filters).length;\n          have_active_filters = numfilters > 0 && !(numfilters == 1 && \"archive\" in filters.settings.filters);\n        }\n        if (this.form)\n        {\n          if (have_active_filters || have_more_results)\n            this.form.parentNode.classList.remove(\"summaryfilters--nofilters\");\n          else\n            this.form.parentNode.classList.add(\"summaryfilters--nofilters\");\n        }\n    */\n    if (filters.titles) {\n      const feedbacknode = document.getElementById(\"summaryfilterfeedback\");\n      if (feedbacknode) {\n        feedbacknode.style.display = filters.titles.length ? \"block\" : \"none\";\n        feedbacknode.querySelector(\".filters\").textContent = filters.titles.join(\", \");\n      }\n    }\n\n    if (this.archivecheck) {\n      // The link to upcoming events is visible if the archive is currently active and v.v.\n      document.querySelector(\".filterlink--upcoming\").style.display = this.archivecheck.checked ? \"\" : \"none\";\n      document.querySelector(\".filterlink--archive\").style.display = this.archivecheck.checked ? \"none\" : \"\";\n    }\n  }\n\n  doLoadMore(ev) {\n    this.doFilter(ev, true);\n  }\n\n  async doFilter(ev, moreresults) {\n    if (ev)\n      ev.preventDefault();\n\n    if (this.rpc.activerequest) {\n      for (let c = 0; c < this.rpc.requestqueue.length; c++)\n        if (this.rpc.requestqueue[c].request.method == 'GetItems') {\n          console.log(\"Cancelling request \", this.rpc.requestqueue[c]);\n          this.rpc.requestqueue[c].cancel();//cancel active rpc request\n        }\n    }\n\n    const filters = getFormFilters(this.form, whintegration.config.obj.summary_id);\n    const filtersettings = filters.settings;\n    this.showFilters(filters, moreresults);\n\n    if (history.replaceState) {\n      const urlparams = [];\n      for (const name in filtersettings.filters) {\n        const val = filtersettings.filters[name];\n        if (typeof val === \"string\" || typeof val === \"number\")\n          urlparams.push(name + \"=\" + val);\n        else if (typeof val === \"boolean\") {\n          if (val)\n            urlparams.push(name + \"=yes\");\n        } else\n          urlparams.push(name + \"=\" + val.join(\",\"));\n      }\n\n      history.replaceState(null, whintegration.config.obj.title, whintegration.config.obj.summary_url + (urlparams.length ? \"?\" + urlparams.join(\"&\") : \"\"));\n    }\n\n    sessionStorage.summaryfilters = JSON.stringify(filtersettings);\n\n    if (this.prevfilters && sessionStorage.summaryfilters == this.prevfilters && !moreresults)\n      return;//no changes\n\n    if (this.form) {\n      this.setSpinnerEnabled(true);\n    }\n    if (moreresults && this.moreresults.style.display != \"none\") {\n      this.moreresults.classList.add(\"loading\");\n      filtersettings.filters.skip = this.lastresult;\n    }\n\n    try {\n      const result = await this.rpc.async(\"GetItems\", Object.keys(filtersettings.filters).length ? filtersettings.filters : null);\n      this.prevfilters = sessionStorage.summaryfilters;\n\n      if (this.form)\n        this.setSpinnerEnabled(false);\n\n      if (this.moreresults && this.moreresults.style.display != \"none\")\n        this.moreresults.classList.remove(\"loading\");\n\n      sessionStorage.summary = JSON.stringify({ \"id\": whintegration.config.obj.summary_id, \"links\": result.links });//for prev/next nav in detailpage\n\n      if (moreresults)\n        this.lastresult += result.items.length;\n      else\n        this.lastresult = result.items.length;\n\n      let introblocks = '';\n\n      if (result.emptyfilters && !moreresults) {\n        for (let c = 0; c < result.items.length && c < 2; ++c) {\n          const item = result.items[c];\n          introblocks += '<li class=\"summary__introblock\"><a class=\"summary__link\" href=\"' + item.link + '\">';\n          if (item.photolink)\n            introblocks += '<img class=\"summary__image\" src=\"' + item.photolink + '\" srcset=\"' + item.photolink + ' 1x, ' + item.photolink_2x + ' 2x\" alt=\"' + (item.photoalt ? item.photoalt : item.title) + '\" />';\n          introblocks += '<span class=\"summary__title\">' + item.title + '</span>';\n          if (item.description)\n            introblocks += '<span class=\"summary__description\" data-ellipsislines=\"\"><span>' + item.description + '</span></span>';\n          introblocks += '<div class=\"summary__date\">' + item.dateformatted + '</div>';\n          if (item.location)\n            introblocks += '<span class=\"location\">' + item.location + '</span>';\n          if (item.tags.length) {\n            introblocks += '<span class=\"tags\">';\n            for (let t = 0; t < item.tags.length; ++t) {\n              if (item.tags[t].filter)\n                introblocks += '<span class=\"tag\" data-filter=\"' + item.tags[t].filter + '\" data-id=\"' + item.tags[t].id + '\">' + item.tags[t].tag + '</span>';\n              else\n                introblocks += '<span class=\"tag\">' + item.tags[t].tag + '</span>';\n            }\n            introblocks += '</span>';\n          }\n          introblocks += '<span class=\"summary__readmore\">' + getTid(\"utwente_base:frontend.ws2016.js.readmore\") + '</span>';\n          introblocks += '</a></li>';\n        }\n        if (introblocks != \"\")\n          introblocks = '<ul class=\"summary__introblocks\">' + introblocks + '</ul>';\n      }\n\n\n      let otherblocks = '';\n      for (let c = 0; c < result.items.length; ++c) {\n        const item = result.items[c];\n        otherblocks += '<li class=\"summary__item ' + (result.emptyfilters && !moreresults && c < 2 ? 'summary__item--mobileonly' : '') + '\">';\n        otherblocks += this.hasfoldableitems ? '<span class=\"summary__link\">' : '<a class=\"summary__link\" href=\"' + item.link + '\">';\n        if (item.summaryphotolink)\n          otherblocks += '<img class=\"summary__image\" src=\"' + item.summaryphotolink + '\" srcset=\"' + item.summaryphotolink + ' 1x, ' + item.summaryphotolink_2x + ' 2x\" alt=\"' + (item.summaryphotoalt ? item.summaryphotoalt : item.title) + '\" />';\n\n        otherblocks += '<span class=\"summary__meta\"><span class=\"date\">' + item.dateformatted + '</span>';\n        if (item.location)\n          otherblocks += '<span class=\"location\">' + item.location + '</span>';\n        otherblocks += '</span>';\n\n        otherblocks += '<span class=\"summary__title\">' + item.title + '</span>';\n\n        if (this.hasfoldableitems) {\n          otherblocks += '<div class=\"summary__foldablecontent\">';\n          if (item.subtitle)\n            otherblocks += '<span class=\"summary__subtitle\">' + item.subtitle + '</span>';\n          if (item.description)\n            otherblocks += '<span class=\"summary__description\">' + item.description + '</span>';\n          otherblocks += '</div>';\n        }\n\n        if (item.tags.length) {\n          otherblocks += '<span class=\"tags\">';\n          for (let t = 0; t < item.tags.length; ++t) {\n            if (item.tags[t].filter)\n              otherblocks += '<span class=\"tag\" data-filter=\"' + item.tags[t].filter + '\" data-id=\"' + item.tags[t].id + '\">' + item.tags[t].tag + '</span>';\n            else\n              otherblocks += '<span class=\"tag\">' + item.tags[t].tag + '</span>';\n          }\n          otherblocks += '</span>';\n        }\n\n        if (this.hasfoldableitems) {\n          otherblocks += '<div class=\"summary__foldablecontent\">';\n          if (item.addthisdata) {\n            otherblocks += '<div class=\"summary__calendar\">';\n            otherblocks += '<span class=\"icon UT-icon-UT_icon_84_calendar-16px\"></span>';\n            otherblocks += '<span class=\"addtocalendar addthisevent\">';\n            otherblocks += getTid(\"utwente_base:frontend.ws2016.js.addtocalendar\"); //'[gettid frontend.ws2016.site.newsevents.addtocalendar]';\n            otherblocks += '<span class=\"start\" style=\"display:none;\">' + item.addthisdata.startdate + '</span>';\n            otherblocks += '<span class=\"end\" style=\"display:none;\">' + item.addthisdata.enddate + '</span>';\n            otherblocks += '<span class=\"timezone\" style=\"display:none;\">Europe/Amsterdam</span>';\n            otherblocks += '<span class=\"title\" style=\"display:none;\">' + item.title + '</span>';\n            otherblocks += '<span class=\"description\" style=\"display:none;\">' + item.addthisdata.description + '</span>';\n            if (item.location)\n              otherblocks += '<span class=\"location\" style=\"display:none;\">' + item.location + '</span>';\n            otherblocks += '<span class=\"all_day_event\" style=\"display:none;\">' + (item.addthisdata.allday ? 'true' : 'false') + '</span>';\n            otherblocks += '<span class=\"date_format\" style=\"display:none;\">DD/MM/YYYY</span>';\n            otherblocks += '</span>';\n            otherblocks += '</div>';\n          }\n          otherblocks += '<a href=\"' + item.link + '\" class=\"summary__readmore\">' + getTid(\"utwente_base:frontend.ws2016.js.readmore\") + '</a>';\n          otherblocks += '</div>';\n\n          otherblocks += '<span class=\"summary__arrow\"><span class=\"open UT-icon-UT_icon_54_arrow-down-round-16px\"></span><span class=\"close UT-icon-UT_icon_53_arrow-up-round-16px\"></span></span>';\n        } else\n          otherblocks += '<span class=\"summary__arrow UT-icon-UT_icon_52_arrow-right-round-16px\"></span>';\n\n        otherblocks += this.hasfoldableitems ? '</span>' : '</a>';\n        otherblocks += '</li>';\n      }\n      if (otherblocks != \"\" && !moreresults)\n        otherblocks = '<ul class=\"summary__items\">' + otherblocks + '</ul>';\n\n      //fade in/out animation summary\n      clearTimeout(this.summarytimer);\n      if (!moreresults)\n        this.summarycontainer.style.opacity = 0;\n      this.summarytimer = setTimeout(() => {\n        if (moreresults) {\n          let summarycontainer = this.summarycontainer.querySelector(\".summary__items\");\n          if (!summarycontainer) {\n            summarycontainer = document.createElement(\"ul\");\n            summarycontainer.className = \"summary__items\";\n            this.summarycontainer.appendChild(summarycontainer);\n          }\n          summarycontainer.innerHTML += otherblocks;\n\n          this.initFoldableContent();\n        } else {\n          if (result.items.length == 0) {\n            const noresults = this.archivecheck && !this.archivecheck.checked\n              ? getTid(\"utwente_base:frontend.ws2016.js.newsevents.noupcoming\")\n              : getTid(\"utwente_base:frontend.ws2016.js.newsevents.noresults\");\n            this.summarycontainer.innerHTML = `<div class=\"noresults\">${noresults}</div>`;\n\n            for (const node of document.querySelectorAll(\".summaryintro\"))\n              node.style.display = \"none\";\n          } else {\n            this.summarycontainer.innerHTML = introblocks + otherblocks;\n            if (this.hasfoldableitems) {\n              this.initFoldableContent();\n            }\n          }\n\n          this.updatePageTitle();\n        }\n        this.moreresults.style.display = result.moreitems ? \"block\" : \"none\";\n\n        if (introblocks != \"\")\n          setEllipsisLines(true);\n        if (!moreresults)\n          this.summarycontainer.style.opacity = 1;\n\n        this.showFilters(filters, moreresults || Boolean(result.moreitems));\n      }, 400);\n    } catch (e) {\n      if (this.form)\n        this.setSpinnerEnabled(false);\n\n      console.error(e);\n    }\n\n    return false;\n  }\n\n  updatePageTitle() {\n    if (this.archivecheck) {\n      document.querySelector(\".header__title, .contentpart__title\").innerText = this.archivecheck.checked ? whintegration.config.obj.pagetitles.archive : whintegration.config.obj.pagetitles.upcoming;\n      fitFonts(true);\n    }\n  }\n\n  setSpinnerEnabled(enabled) {\n    document.documentElement.classList[enabled ? \"add\" : \"remove\"](\"loading\");\n    document.documentElement.classList[enabled ? \"add\" : \"remove\"](\"ut-spinner--showembeddedspinner\");\n  }\n\n  initPrevNextNav() {\n    if (whintegration.config.obj.summary)\n      sessionStorage.summary = JSON.stringify(whintegration.config.obj.summary);\n\n    const pagenavnodes = document.querySelectorAll(\".article__pagenav .previous,.article__pagenav .next\");\n    if (!pagenavnodes.length)\n      return;\n\n    if (!sessionStorage.summary) {\n      for (const node of pagenavnodes) {\n        if (node.getAttribute(\"href\") != \"\")\n          node.classList.add(\"active\");//show chronological prev/next\n      }\n      return;\n    }\n\n    const summary = sessionStorage.summary ? JSON.parse(sessionStorage.summary) : {};\n    //replace prev.next link\n    for (let i = 0; summary.id == whintegration.config.obj.summary_id && i < summary.links.length; ++i) {\n      if (whintegration.config.obj.pageid == summary.links[i].id) {\n        for (const node of pagenavnodes) {\n          if (node.classList.contains(\"previous\")) {\n            if (i > 0) {\n              node.setAttribute(\"href\", whintegration.config.obj.summary_url + summary.links[i - 1].link);\n              node.classList.add(\"active\");\n            } else {\n              node.setAttribute(\"href\", \"#\");\n              node.classList.remove(\"active\");\n            }\n          } else { //next\n            if (i < summary.links.length - 1) {\n              node.setAttribute(\"href\", whintegration.config.obj.summary_url + summary.links[i + 1].link);\n              node.classList.add(\"active\");\n            } else {\n              node.setAttribute(\"href\", \"#\");\n              node.classList.remove(\"active\");\n            }\n          }\n        }\n        break;\n      }\n    }\n  }\n}\n\n//set first paragraph of news as introtext\ndompack.register(\".article--news div[data-autointrotext] > p:first-of-type\", node => {\n  if (!node.classList.contains(\"introtext\") && !node.classList.contains(\"introtext-news\"))\n    node.className = \"introtext-news\";\n});\n\ndompack.onDomReady(() => {\n  const newsevents_filters = document.querySelector(\".filterbar--newsevents\");\n  if (newsevents_filters || document.documentElement.classList.contains(\"page--newseventsoverview\")) {\n    // seems to be a news or events overview page\n    new SummaryNavigation();\n  }\n});\n\nregisterHandler(\"utwente_base:event_registration\", registrationform => new EventsFormHandler(registrationform, \"event\"));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from 'dompack';\nimport * as whintegration from \"@mod-system/js/wh/integration\";\n\n//type=number ignores the subfields of the datetimes\nconst filterinputselector = \"input[name]:not([type=number]), select[name]\";\n\n/*\n\n!! Please use functionality from filteredoverviews instead!\n\nNOTE: This functionality is used by:\n- newsevents\n\nNOTES on usage:\n- for formfilters.es an <input type=\"hidden\" /> is assumed to contain a JSON value\n\n\n*/\n\nexport function getFormFilters(form, id) {\n  const filtertitles = [];\n  const filtersettings = { filters: {} };\n  if (id)\n    filtersettings.id = id;\n\n  let extrafilters;\n\n  if (\"extrafilters\" in whintegration.config.obj)\n    extrafilters = whintegration.config.obj.extrafilters;\n  else if (form && form.hasAttribute(\"data-formfilters\"))\n    extrafilters = JSON.parse(form.getAttribute(\"data-formfilters\"));\n\n  // NOTE: extrafilters must be an array with objects:\n  // { name: \"tag\", filtertitle: \"\", value: \"\", label: \"\" }\n\n  // Create titles to show in the summary of selected filters\n  if (extrafilters) {\n    for (const filter of extrafilters) {\n      filtertitles.push(`${filter.filtertitle ? filter.filtertitle + \": \" : \"\"}${filter.label}`);\n\n      if (filtersettings.filters[filter.name])\n        filtersettings.filters[filter.name].push(filter.value);\n      else\n        filtersettings.filters[filter.name] = [filter.value];\n    }\n  }\n\n\n  // Check whether we have a form to get more fields from.\n  // IMPORTANT: place this check AFTER extrafilters, because some news/events pages don't have any form\n  if (!form) {\n    console.warn(\"No form specified for getFormFilters\");\n    return {\n      titles: filtertitles,\n      settings: filtersettings\n    };\n  }\n\n\n  for (const node of form.querySelectorAll(filterinputselector)) {\n    const inptype = node.nodeName === \"INPUT\" ? node.getAttribute(\"type\") : node.nodeName;\n    const filtertitle = node.getAttribute(\"data-filtertitle\");\n\n    if (inptype === \"checkbox\") {\n      if (!node.checked)\n        continue;\n\n      let label = node.parentNode.querySelector(\"label:not(:empty)\");\n      if (node.classList.contains(\"ut-toggle\"))\n        label = label.nextSibling;\n      if (node.value === \"yes\")\n        filtersettings.filters[node.name] = node.checked;\n      else {\n        const labeltxt = label ? label.textContent : \"??\";\n        filtertitles.push(`${filtertitle ? filtertitle + \": \" : \"\"}${labeltxt}`);\n\n        if (filtersettings.filters[node.name])\n          filtersettings.filters[node.name].push(node.value);\n        else\n          filtersettings.filters[node.name] = [node.value];\n      }\n    } else if (inptype === \"radio\") {\n      if (!node.checked)\n        continue;\n\n      filtertitles.push(`${filtertitle ? filtertitle + \":\" : \"\"}${node.parentNode.querySelector(\"label\").textContent}`);\n      filtersettings.filters[node.name] = node.checked;\n    } else if (inptype === \"date\") {\n      //let val = node.previousSibling.value;\n      const val = node.value;\n      if (val !== \"\") {\n        filtertitles.push(`${filtertitle ? filtertitle + \": \" : \"\"}${val}`);//localized date\n        filtersettings.filters[node.name] = node.value;\n      }\n    } else if (inptype === \"hidden\") {\n      const nodeval = node.value ? JSON.parse(node.value) : null;\n      if (nodeval) {\n        filtertitles.push(`${filtertitle ? filtertitle + \": \" : \"\"}${nodeval.title}`);\n        filtersettings.filters[node.name] = nodeval.id;\n      }\n    } else if (inptype === \"SELECT\") {\n      if (node.selectedOptions.length) {\n        filtertitles.push(`${filtertitle ? filtertitle + \": \" : \"\"}\"${node.selectedOptions[0]?.textContent}\"`);\n        filtersettings.filters[node.name] = node.value;\n      }\n    } else if (node.value !== \"\") {\n      filtertitles.push(`${filtertitle ? filtertitle + \": \" : \"\"}\"${node.value}\"`);\n      filtersettings.filters[node.name] = node.value;\n    }\n  }\n\n  return {\n    titles: filtertitles,\n    settings: filtersettings\n  };\n}\n\nexport function setFormFilters(form, filters) {\n  if (!form)\n    return;\n\n  filters = filters || {};\n  for (const node of form.querySelectorAll(filterinputselector)) {\n    const inptype = node.nodeName === \"INPUT\" ? node.getAttribute(\"type\") : \"\";\n    if (inptype === \"checkbox\") {\n      if (filters[node.name]) {\n        if (typeof filters[node.name] === \"boolean\")\n          node.checked = filters[node.name];\n        else\n          node.checked = filters[node.name] && (\",\" + filters[node.name] + \",\").indexOf(\",\" + node.value + \",\") !== -1;\n      } else\n        node.checked = false;\n    } else if (inptype === \"radio\")\n      node.checked = filters[node.name] ? true : false;\n    else if (inptype === \"date\") {\n      dompack.changeValue(node, filters[node.name] ? filters[node.name] : \"\");\n      if (node.splitcontrol)\n        node.splitcontrol.daynode.value = node.splitcontrol.monthnode.value = node.splitcontrol.yearnode.value = \"\";\n    } else if (inptype === \"hidden\") {\n      const nodeval = node.value ? JSON.parse(node.value) : null;\n      if (nodeval && nodeval.id !== filters[node.name])\n        node.value = \"\";\n    } else\n      node.value = filters[node.name] ? filters[node.name] : \"\";\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from 'dompack';\nimport FilteredOverview from \"../../filteredoverview\";\n\n\ndompack.onDomReady(() => {\n  const filterform = document.querySelector(\".filterbar--newsevents\");\n  if (!filterform)\n    return;\n\n  window.overview_newsevents = new FilteredOverview({ filterpagetype: 'newsevents' });\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport * as videotools from \"../../components/video\";\nimport \"./toplevelhome.scss\";\n\nlet videos = [], curVideo = -1;\nlet videoActive = false, windowMode;\nlet fallbackTimeout, autoplaySupported = null, slideTimeout = 8000;\n\nfunction resumeVideo() {\n  videoActive = true;\n  // There is no video loaded yet, load the first video, otherwise play the\n  // current video\n  if (curVideo < 0)\n    nextVideo();\n  else if (autoplaySupported === false)\n    fallbackTimeout = setTimeout(nextVideoSlide, slideTimeout);\n  else\n    videos[curVideo].player.play();\n}\n\nfunction pauseVideo() {\n  videoActive = false;\n  // If there is a video loaded, pause it\n  if (autoplaySupported === false)\n    clearTimeout(fallbackTimeout);\n  else if (curVideo >= 0)\n    videos[curVideo].player.pause();\n}\n\nfunction nextVideo() {\n  if (!videoActive)\n    return;\n\n  if (++curVideo >= videos.length)\n    curVideo = 0;\n\n  const video = videos[curVideo];\n  if (!videotools.isVideoNodeInitialized(video.node)) {\n    // Initialize and load the video\n    videotools.initializeVideoNode(video.node).then(player => {\n      video.player = player;\n\n      // If the video started playing, we know autoplay is supported\n      video.node.addEventListener(\"video:play\", videoStarted);\n\n      // If the video has finished playing, show the next video\n      video.node.addEventListener(\"video:finish\", nextVideo);\n\n      // Start the video when it's ready\n      video.node.addEventListener(\"video:ready\", playVideo);\n    });\n  } else if (video.player) {\n    // Resume/replay the video\n    playVideo();\n  }\n}\n\nfunction playVideo() {\n  const video = videos[curVideo];\n\n  // Show the current video's poster image\n  video.node.classList.remove(\"toplevelhome__video--noposter\");\n  video.node.classList.add(\"toplevelhome__video--current\");\n\n  // Hide the previous video\n  let prevVideo = curVideo - 1;\n  if (prevVideo < 0)\n    prevVideo = videos.length - 1;\n  videos[prevVideo].node.classList.remove(\"toplevelhome__video--current\");\n\n  // Start the video\n  video.player.play();\n  // Remove the poster image\n  requestAnimationFrame(() => videos[curVideo].node.classList.add(\"toplevelhome__video--noposter\"));\n\n  // Set a timeout to check if the video is actually playing\n  if (!fallbackTimeout)\n    fallbackTimeout = setTimeout(videoFallback, slideTimeout);\n}\n\nfunction videoStarted() {\n  // Clear the fallback timeout, fallback isn't needed\n  clearTimeout(fallbackTimeout);\n  autoplaySupported = true;\n}\n\nfunction videoFallback() {\n  // If this function is called, the video never actually started playing\n  console.warn(\"Video fallback mode activated\");\n  autoplaySupported = false;\n  const container = document.querySelector(\".toplevelhome__videos\");\n  container.classList.add(\"toplevelhome__videos--fallback\");\n  // Force css recalculation\n  videos[curVideo].node._wsTmpTransition = getComputedStyle(videos[curVideo].node).transition;\n\n  // Show next video poster slide\n  nextVideoSlide();\n}\n\nfunction nextVideoSlide() {\n  if (!videoActive)\n    return;\n\n  if (++curVideo >= videos.length)\n    curVideo = 0;\n\n  // Show the new video poster slide\n  videos[curVideo].node.classList.add(\"toplevelhome__video--current\");\n\n  // Hide the previous video poster slide\n  let prevVideo = curVideo - 1;\n  if (prevVideo < 0)\n    prevVideo = videos.length - 1;\n  videos[prevVideo].node.classList.remove(\"toplevelhome__video--current\");\n\n  // Show next video poster slide after timeout\n  fallbackTimeout = setTimeout(nextVideoSlide, slideTimeout);\n}\n\nfunction checkWindowSize(event) {\n  if (event.detail.level < 4) // medium\n  {\n    if (windowMode != \"mobile\") {\n      // When switching to mobile mode, pause the current video (if any)\n      pauseVideo();\n      windowMode = \"mobile\";\n    }\n  } else {\n    if (windowMode != \"desktop\") {\n      // When switch to desktop mode, resume the current video (or load and play\n      // the first video)\n      resumeVideo();\n      windowMode = \"desktop\";\n    }\n  }\n}\n\n\n\ndompack.register(\".toplevelhome__videos\", container => {\n  for (const node of container.querySelectorAll(\".toplevelhome__video\"))\n    if (node.hasAttribute(\"data-video\"))\n      videos.push({ node: node });\n  if (videos.length)\n    window.addEventListener(\"ws:responsivemode\", checkWindowSize);\n});\n","import * as dompack from '@webhare/dompack';\nimport * as frontend from \"@webhare/frontend\";\n\nif (document.documentElement.classList.contains(\"utwente--loginrouter\")) {\n  dompack.register('#oidc_ut', loginbutton => {\n    loginbutton.addEventListener(\"click\", e => {\n      void frontend.startSSOLogin(\"UTAZURE\");\n    });\n  });\n\n  dompack.register<HTMLFormElement>('form.ut-specialaccount-loginform', form => {\n    form.action += location.hash; //keep the hash while redirecting\n  });\n\n  dompack.register<HTMLFormElement>('.wh-wrdauth-forgotpassword__form', form => { //apply DOM fix:\n    //one day subgrids may fix this and just allow the form to took take full width inside its 2 divs\n    (form.parentNode?.parentNode as HTMLElement).replaceWith(form);\n  });\n}\n\nfrontend.setupWebHareSSOTrigger();\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport './donaties.scss';\nimport * as dompack from 'dompack';\nimport * as whintegration from '@mod-system/js/wh/integration';\nimport { registerHandler } from '@mod-publisher/js/forms';\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\nimport { getTid } from \"@webhare/gettid\";\nimport * as modaldialog from \"../../shared/dialog\";\nimport { UTRPCFormBase } from '../../shared/utforms';\n\nclass uFondsForm extends UTRPCFormBase {\n  constructor(formnode) {\n    super(formnode);\n\n    this.amountoptions = this.node.querySelectorAll(\"input[name='amount']\");\n    //Check for other amount\n    for (const chknode of this.amountoptions)\n      chknode.addEventListener(\"change\", this.setAdditionalAmountFields.bind(this));\n\n    this.paymentmethodoptions = this.node.querySelectorAll(\"input[name='payment_method']\");\n    //Check if paymentmethod is 'incasso'\n    for (const chknode of this.paymentmethodoptions)\n      chknode.addEventListener(\"change\", this.setAdditionalPaymentMethodFields.bind(this));\n\n    //Check if donation is from organization\n    this.elements.isorganization.addEventListener(\"change\", this.setAdditionalOrganizationFields.bind(this));\n\n    this.setAdditionalFields();\n\n    if (this.getUrlParam(\"payment\") == \"1\" && whintegration.config.obj.payment)//redirect after payment\n    {\n      if (whintegration.config.obj.payment.status == \"failed\")\n        this.showErrorDialog();\n      else\n        this.showSuccessDialog(whintegration.config.obj.payment.destination);\n    }\n\n    this.elements.amount_other.addEventListener(\"change\", ev => this.sanitizeOtherAmount());\n  }\n\n  sanitizeOtherAmount() {\n    let val = this.elements.amount_other.value;\n    let decsep = val.lastIndexOf(\".\") >= val.lastIndexOf(\",\") ? \".\" : \",\";\n    val = decsep == \".\" ? val.replace(/[^0-9\\.]/g, '') : val.replace(/[^0-9,]/g, '');\n\n    if (val.indexOf(decsep) == -1)\n      val += decsep + \"00\";\n\n    const parts = val.split(decsep);\n    let cents = parts.pop().substr(0, 2);\n    if (cents.length < 2)\n      cents += (cents.length == 0 ? \"00\" : \"0\");\n    const full = parts.join(\"\");\n\n    decsep = document.documentElement.lang.indexOf(\"en\") == -1 ? \",\" : \".\";\n\n    this.elements.amount_other.value = (1 * full + 1 * cents) > 0 ? full + decsep + cents : \"\";\n  }\n\n  setAdditionalFields() {\n    this.setAdditionalAmountFields();\n    this.setAdditionalPaymentMethodFields();\n    this.setAdditionalOrganizationFields();\n  }\n\n  setAdditionalAmountFields() {\n    let selval = this.getValue(\"amount\");\n    if (!selval)\n      selval = \"\";\n\n    if (1 * selval > 0 || selval == \"\") {\n      this.elements.amount_other.closest(\".wh-form__fieldgroup\").style.display = \"none\";\n      this.elements.amount_other.required = false;\n    } else {\n      this.elements.amount_other.closest(\".wh-form__fieldgroup\").style.display = \"\";\n      this.elements.amount_other.required = true;\n    }\n  }\n\n  setAdditionalPaymentMethodFields() {\n    const toggleincassofieldsnames = [\"iban\", \"bankaccount_name\", \"agree\"];\n\n    let selval = this.getValue(\"payment_method\");\n    if (!selval)\n      selval = \"\";\n\n    if (selval == \"incasso\") {\n      for (const fieldname of toggleincassofieldsnames) { //show fields needed for incasso\n        this.elements[fieldname].closest(\".wh-form__fieldgroup\").style.display = \"\";\n        this.elements[fieldname].required = true;\n      }\n    } else {\n      for (const fieldname of toggleincassofieldsnames) { //hide fields needed for incasso\n        this.elements[fieldname].closest(\".wh-form__fieldgroup\").style.display = \"none\";\n        this.elements[fieldname].required = false;\n      }\n    }\n  }\n\n  setAdditionalOrganizationFields() {\n    if (this.elements.isorganization.checked) {\n      this.elements.organization.closest(\".wh-form__fieldgroup\").style.display = \"\";\n      this.elements.organization.required = true;\n    } else {\n      this.elements.organization.closest(\".wh-form__fieldgroup\").style.display = \"none\";\n      this.elements.organization.required = false;\n    }\n  }\n\n  getUrlParam(name) {\n    const urlparamstr = location.search.replace(/\\+/g, \"%20\");\n    if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(urlparamstr))\n      return decodeURIComponent(name[1]);\n    return \"\";\n  }\n\n  onSubmitSuccess(res) {\n    if (res.success) {\n      this.reset();\n      this.setAdditionalFields();\n\n      if (res.redirect) {\n        whintegration.executeSubmitInstruction(res.redirect);\n        return;\n      }\n\n      this.showSuccessDialog(res.destination);\n    }\n  }\n\n  showErrorDialog() {\n    const title = getTid(\"utwente_base:frontend.ws2016.js.ufondsdonaties.error-title\");\n    const description = getTid(\"utwente_base:frontend.ws2016.js.ufondsdonaties.error-description\");\n\n    this.dialognode = modaldialog.showModalDialog(title, description, { theme: \"dialog--small\" });\n  }\n\n  showSuccessDialog(destination) {\n    const title = getTid(\"utwente_base:frontend.ws2016.js.ufondsdonaties.thanks-title\");\n    const description = getTid(\"utwente_base:frontend.ws2016.js.ufondsdonaties.thanks-description\");\n    this.dialognode = modaldialog.showModalDialog(title, description, { theme: \"dialog--small\" });\n  }\n}\n\nregisterHandler(\"utwente_base:ufonds_donatie\", node => new uFondsForm(node));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport './meetings.scss';\nimport * as dompack from 'dompack';\nimport { getTid } from \"@webhare/gettid\";\nimport * as modaldialog from \"../../shared/dialog\";\nimport { UTRPCFormBase } from '../../shared/utforms';\nimport * as textfunctions from \"dompack/types/text\";\nimport * as forms from \"@mod-publisher/js/forms\";\n\nclass cMeetingsForm extends UTRPCFormBase {\n  constructor(formnode) {\n    super(formnode);\n\n    for (const node of this.node.querySelectorAll(\".wh-form__questiongroup__introtext\")) {\n      let html = node.innerHTML;\n      if (html.indexOf(\"[participantscount]\") !== -1 || html.indexOf(\"[bhvcount]\") !== -1) {\n        html = html.replace(\"[participantscount]\", \"<span class=\\\"participantscount\\\"></span>\");\n        html = html.replace(\"[bhvcount]\", \"<span class=\\\"bhvcount\\\"></span>\");\n        node.innerHTML = html;\n      }\n    }\n\n    formnode.querySelector('#meetingsform-step2').addEventListener(\"wh:form-pagechange\", () => this.showbhvcount());\n    formnode.querySelector('#meetingsform-step3').addEventListener(\"wh:form-pagechange\", () => this.generateOverview());\n  }\n\n  showbhvcount() {\n    const participantscount = this.elements.nrparticipants.value;\n    let bhvcount = 0;\n    if (participantscount > 20)\n      bhvcount = Math.ceil(participantscount / 50);\n    for (const node of this.node.querySelectorAll(\".wh-form__questiongroup__introtext .participantscount\"))\n      node.textContent = String(participantscount);\n    for (const node of this.node.querySelectorAll(\".wh-form__questiongroup__introtext .bhvcount\"))\n      node.textContent = String(bhvcount);\n  }\n\n  generateOverview() {\n    const overviewnode = document.getElementById(\"meetingsform-step3-content\");\n    overviewnode.replaceChildren();\n\n    const lines = [];\n    let prevtitle = \"\";\n    for (let i = 0; i < this.elements.length; ++i) {\n      const el = this.elements[i];\n\n      if (el.type !== \"hidden\") {\n        let title = \"\";\n        let value = \"\";\n        const groupnode = el.closest(\".wh-form__fieldgroup\");\n        if (groupnode) {\n          const labelnode = groupnode.querySelector(\"label\");\n          title = labelnode ? groupnode.querySelector(\"label\").textContent : groupnode.dataset.title;\n\n          if (el.nodeName === \"SELECT\")\n            value = el.options[el.selectedIndex].textContent;\n          else\n            value = String(el.value);\n        }\n\n        if (title && value) {\n          if (title === prevtitle && (el.name.indexOf(\"hour\") > -1 || el.name.indexOf(\"minute\") > -1)) { //combine\n            let separator = \" \";\n            if (el.name.indexOf(\"hour\") > -1) {\n              if (value.length === 1)\n                value = \"0\" + value;\n            }\n            if (el.name.indexOf(\"minute\") > -1) {\n              if (value.length === 1)\n                value = \"0\" + value;\n              separator = \":\";\n            }\n\n            lines[lines.length - 1].value += separator + value;\n          } else {\n            lines.push({ \"title\": title, \"value\": value, \"name\": el.name });\n          }\n\n          prevtitle = title;\n        }\n      }\n    }\n\n    let prevbhv_nr = -1;\n    let bhv_active = false;\n    for (let i = 0; i < lines.length; ++i) {\n      const isbhv = lines[i].name.indexOf(\"bhv_\") === 0;\n      if (isbhv) {\n        const bhvnr = Number(lines[i].name.replace(/[^0-9]/g, \"\"));\n        if (prevbhv_nr !== bhvnr) {\n          bhv_active = lines[i].name.indexOf(\"_name\") > 0 && lines[i].value !== \"\";\n          if (bhv_active)\n            overviewnode.appendChild(dompack.create(\"div\", { \"class\": \"line bhv\", \"innerHTML\": \"<strong>BHV'er \" + bhvnr + \"</strong>\" }));\n        }\n        prevbhv_nr = bhvnr;\n\n        if (bhv_active) {\n          const linecontent = '<strong>' + textfunctions.encodeTextNode(lines[i].title) + '</strong><span>' + textfunctions.encodeTextNode(lines[i].value) + '</span>';\n          overviewnode.appendChild(dompack.create(\"div\", { \"class\": \"line\", \"innerHTML\": linecontent }));\n        }\n      } else {\n        bhv_active = false;\n        const linecontent = '<strong>' + textfunctions.encodeTextNode(lines[i].title) + '</strong><span>' + textfunctions.encodeTextNode(lines[i].value) + '</span>';\n        overviewnode.appendChild(dompack.create(\"div\", { \"class\": \"line\", \"innerHTML\": linecontent }));\n      }\n    }\n\n  }\n\n  reset() {\n    super.reset();\n\n    const overviewnode = document.getElementById(\"meetingsform-step3-content\");\n    overviewnode.replaceChildren();\n\n    this.gotoPage(0);\n\n    for (let i = 0; i < this.elements.length; ++i) {\n      const el = this.elements[i];\n      if (el.type !== \"hidden\") {\n        if (el.nodeName === \"SELECT\") {\n          el.selectedIndex = -1;\n          el.value = \"\";\n        } else\n          el.value = \"\";\n      }\n    }\n  }\n\n  onSubmitSuccess(res) {\n    if (res.success) {\n      if (!res.isedit)\n        this.reset();\n\n      this.showSuccessDialog();\n    } else {\n      this.showErrorDialog();\n    }\n  }\n\n  showErrorDialog() {\n    const title = getTid(\"utwente_base:frontend.ws2016.js.meetings.error-title\");\n    const description = getTid(\"utwente_base:frontend.ws2016.js.meetings.error-description\");\n\n    this.dialognode = modaldialog.showModalDialog(title, description, { theme: \"dialog--small\" });\n  }\n\n  showSuccessDialog() {\n    const title = getTid(\"utwente_base:frontend.ws2016.js.meetings.thanks-title\");\n    const description = getTid(\"utwente_base:frontend.ws2016.js.meetings.thanks-description\");\n\n    this.dialognode = modaldialog.showModalDialog(title, description, { theme: \"dialog--small\" });\n  }\n}\n\nforms.registerHandler(\"utwente_base:meetingsform\", node => new cMeetingsForm(node));\n","export function encodeTextNode(str: string) {\n  return str.split('&').join('&amp;')\n    .split('<').join('&lt;')\n    .split('>').join('&gt;');\n}\n\n/** @deprecated You should use encodeString(str, 'attribute') */\nexport function encodeValue(str: string) {\n  return encodeEntities(str, false);\n}\n\n/** @deprecated You should use decodeString(str, 'attribute') */\nexport function decodeValue(str: string) {\n  return str.replace(/<br *\\/?>/g, \"\\n\")\n    .replace(/&#(\\d+);/g, (_, dec) => String.fromCharCode(dec))\n    .replace(/&lt;/g, \"<\")\n    .replace(/&gt;/g, \">\")\n    .replace(/&quot;/g, '\"')\n    .replace(/&apos;/g, \"'\")\n    .replace(/&amp;/g, \"&\");\n}\n\n/** @deprecated You should use encodeString(str, 'html') */\nexport function encodeHTML(str: string) {\n  return encodeEntities(str, true);\n}\n\nfunction encodeEntities(str: string, html: boolean) {\n  let s = \"\";\n  for (const char of str) {\n    const curch = char.codePointAt(0);\n    if (curch === undefined || isHTMLUnrepresentableChar(curch))\n      continue;\n    if (curch >= 32 && curch < 128 && curch !== 38 && curch !== 60 && curch !== 62) {\n      s += String.fromCodePoint(curch);\n      continue;\n    }\n\n    switch (curch) {\n      case 10:\n        {\n          if (html) {\n            s += \"<br />\";\n            continue;\n          }\n          break;\n        }\n      case 13:\n        {\n          if (html)\n            continue;\n          break;\n        }\n      case 34:\n        {\n          s += \"&quot;\";\n          continue;\n        }\n      case 38:\n        {\n          s += \"&amp;\";\n          continue;\n        }\n      case 39:\n        {\n          s += \"&apos;\";\n          continue;\n        }\n      case 60:\n        {\n          s += \"&lt;\";\n          continue;\n        }\n      case 62:\n        {\n          s += \"&gt;\";\n          continue;\n        }\n    }\n\n    s += \"&#\" + curch + \";\";\n  }\n  return s;\n}\n\nfunction isHTMLUnrepresentableChar(curch: number) {\n  return (curch < 32 && curch !== 9 && curch !== 10 && curch !== 13)\n    || (curch >= 128 && curch <= 159);\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as whintegration from \"@mod-system/js/wh/integration\";\nimport * as dompack from 'dompack';\nimport \"../../site.lang.json\";\nimport \"./people.scss\";\nimport FilteredOverview from \"../../filteredoverview\";\n\n\n/*\nFor people overview we have a single JSON containing all persons.\nThis way we don't have to duplicate the JSON between all views (list, tile, summary),\nsearching will be more effecient and our result count doesn't get multiplicated due to copies\nof the person in multiple views.\n*/\nclass PeopleOverview extends FilteredOverview {\n  constructor() {\n    const options = { additionalform: document.querySelector(\".peopleoverview__categoryselection\"), filterpagetype: 'people' };\n    super(options);\n\n    this.resize();\n    window.addEventListener(\"resize\", this.resize.bind(this));\n\n\n    // Get the JSON items defined in the pageconfig\n    // and then find all associated nodes in each view\n    const items = whintegration.config.obj.filteredoverview.persons;\n\n    const itemmap = [];\n    for (const item of items) {\n      item.nodes = [];\n      itemmap.push(item.personid);\n    }\n\n\n    // Enrich the array of persons with all nodes (list view, grid view or summary view version) showing this person\n    const nodes = document.querySelectorAll(\".widget[data-options], .peopleoverview__summary a[data-personid]\");\n\n    for (const node of Array.from(nodes)) {\n      let personid = node.getAttribute(\"data-personid\"); // summary <a>\n      if (!personid) {\n        // might be a person widget (in list or tile mode) which has an options JSON\n        const parsedoptions = dompack.getJSONAttribute(node, \"data-options\");\n        if (!parsedoptions || !(\"personid\" in parsedoptions)) {\n          //console.log(\"SKIP\");\n          continue; // not a contactperson widget which is generated by the peoplepage\n        }\n\n        personid = parsedoptions.personid;\n      }\n\n      const itemidx = itemmap.indexOf(personid);\n      //console.log(personid, 'idx:', itemidx, items[itemidx]);\n      if (itemidx === -1) {\n        console.error(\"personid\", personid, \"not found in filteredoverview data.\");\n        continue;\n      }\n\n      items[itemidx].nodes.push(node);\n    }\n\n\n    // console.log(\"Items enriched with nodes:\", items);\n    this.items = items;\n\n    this.setFeedback(items.length);\n\n    document.querySelector(\".peopleoverview__showaslist\").addEventListener(\"click\", this.switchToView.bind(this, \"list\"));\n    document.querySelector(\".peopleoverview__showasgrid\").addEventListener(\"click\", this.switchToView.bind(this, \"grid\"));\n    document.querySelector(\".peopleoverview__showassummary\").addEventListener(\"click\", this.switchToView.bind(this, \"summary\"));\n\n\n    // We need to do this here, because we need our initialization to be ready for initial filtering\n    if (this.isFilterActive())\n      this.doFilter();\n  }\n\n  resize() {\n    const htmlelem = document.documentElement;\n\n    // if less room than required to get a two-column grid, use the list view as default\n    //if (window.screen.availWidth < 645 && htmlelem.classList.contains(\"peopleoverview__showasgrid\"))\n    if (document.body.clientWidth < 645 && htmlelem.classList.contains(\"peopleoverview--showasgrid\")) {\n      htmlelem.classList.remove(\"peopleoverview--showasgrid\");\n      htmlelem.classList.add(\"peopleoverview--showaslist\");\n    }\n  }\n\n  switchToView(type, evt) {\n    document.documentElement.classList[type === \"list\" ? \"add\" : \"remove\"](\"peopleoverview--showaslist\");\n    document.documentElement.classList[type === \"grid\" ? \"add\" : \"remove\"](\"peopleoverview--showasgrid\");\n    document.documentElement.classList[type === \"summary\" ? \"add\" : \"remove\"](\"peopleoverview--showassummary\");\n  }\n\n  showResults() {\n    console.log(\"showResults\", this.filters);\n\n    //let activefilters = Object.keys(this.filters).length;\n    let totalfound = 0;\n\n    console.log(\"Searching through\", this.items.length, \"items.\");\n\n    // Keep a list of categories under which we have matches,\n    // so we know which categories/categoryheaders to hide\n    const seen_catidx = [];\n\n    for (const item of this.items) {\n      const ismatch = (!this.filters.category || item.category === this.filters.category)\n        && (!this.filters.query || item.textcontent.indexOf(this.filters.query.toLowerCase()) > -1);\n\n      /*\n      console.log(\"Person\", item);\n      console.log(this.filters.category, item.category);\n      console.log(\"Match\", ismatch);\n      */\n\n      for (const node of item.nodes)\n        node.classList[ismatch ? \"remove\" : \"add\"](\"hidden\");\n\n      if (ismatch) {\n        // Add the category of the person to the list of seen categories\n        const catidx = parseInt(item.personid.split(\"_\")[0]);\n        if (seen_catidx.indexOf(catidx) === -1)\n          seen_catidx.push(catidx);\n\n        ++totalfound;\n      }\n    }\n\n    // Hide headers and containers for categories which are empty due to filtering\n    const gridheaders = document.querySelectorAll(\".widget__break, .peopleoverview__summary__category\");\n    for (const item of gridheaders) {\n      const options = JSON.parse(item.dataset.options);\n      const seen = seen_catidx.indexOf(options.catidx) > -1;\n      item.style.display = seen ? \"block\" : \"none\";\n    }\n\n    this.setFeedback(totalfound);\n  }\n}\n\n\n\ndompack.onDomReady(() => {\n  const filterform = document.querySelector(\".filterbar--peoplepage\");\n  if (!filterform)\n    return;\n\n  window.peopleoverview = new PeopleOverview();\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport './medical.scss';\nimport * as dompack from 'dompack';\nimport { registerHandler } from '@mod-publisher/js/forms';\nimport { UTRPCFormBase } from '../../shared/utforms';\nimport * as dialogapi from \"dompack/api/dialog\";\n\nclass UTMedicalFormHandler extends UTRPCFormBase {\n  constructor(node) {\n    super(node);\n\n    const cancelbutton = this.node.querySelector('.ut-medical__cancel');\n    if (cancelbutton)\n      cancelbutton.addEventListener('click', evt => this.cancelAppointment());\n\n    this.timeoptions = dompack.qSA(this.elements.time, \"option\");\n\n    if (this.elements.date) {\n      this.elements.date.addEventListener('change', evt => this.updateTimes());\n      this.updateTimes();\n    }\n  }\n  updateTimes() {\n    const currentdate = this.elements.date.value;\n    //    let firstallowed;\n\n    //Workaround because ios doesn't hide options:\n    const selection = this.elements.time.options[this.elements.time.selectedIndex];\n    this.elements.time.replaceChildren();\n    this.timeoptions.forEach(opt => {\n      if (JSON.parse(opt.dataset.fordates).includes(currentdate)) {\n        this.elements.time.appendChild(opt);\n        if (selection && selection.textContent === opt.textContent)\n          this.elements.time.value = opt.value;\n      }\n    });\n\n    /*\n        for(let opt of Array.from(this.elements.time.options))\n        {\n          let show = JSON.parse(opt.dataset.fordates).includes(currentdate);\n          if(!firstallowed && show)\n            firstallowed = opt.value;\n\n          opt.classList[show?'remove':'add']('ut-pulldown--hiddenitem');\n        }\n        let selection = this.elements.time.options[this.elements.time.selectedIndex];\n        if(selection && selection.classList.contains('ut-pulldown--hiddenitem'))\n          this.elements.time.value = firstallowed;\n    */\n  }\n  async cancelAppointment() {\n    if (await dialogapi.runMessageBox(\"Weet u zeker dat u uw afspraak wil annuleren ?\", [{ result: \"no\", title: \"Nee\" }, { result: \"yes\", title: \"Ja\" }]) !== 'yes')\n      return;\n    await this.invokeRPC('cancelappointment');\n    document.querySelector('#medical-form-page1').style.display = 'none';\n    document.querySelector('#medical-form-cancelled').style.display = 'block';\n  }\n  onSubmitSuccess(result) {\n    document.querySelector('#medical-form-page1').style.display = 'none';\n    document.querySelector('#medical-form-success').style.display = 'block';\n  }\n}\n\nregisterHandler('utwente_base:medicalsignupform', node => new UTMedicalFormHandler(node));\n","import * as dompack from \"@webhare/dompack\";\n//@ts-ignore - does not exist on 5.5\nimport { ImgEditElement } from \"@webhare/forms\";\nimport { getTid } from \"@webhare/gettid\";\nimport { RPCFormBase, registerHandler, setFieldError, setupValidator } from \"@mod-publisher/js/forms\";\nimport \"./neoform.scss\";\n\nconst MIN_HEADERIMAGE_HEIGHT = 640;\nconst MIN_HEADERIMAGE_WIDTH = 1600;\n\n\n//FIXME: Import from @webhare/upload once it's supported\nexport async function getImageDimensions(file: File): Promise<{ width: number; height: number }> {\n  return new Promise((resolve, reject) => {\n    const reader = new FileReader();\n    reader.addEventListener(\"load\", () => {\n      const img = document.createElement(\"img\");\n      img.addEventListener(\"load\", () => {\n        resolve({ width: img.naturalWidth, height: img.naturalHeight });\n      });\n      img.addEventListener(\"error\", error => reject(new Error(error.message)));\n      img.src = reader.result as string;\n    });\n    reader.addEventListener(\"error\", () => reject(new Error(\"readAsDataURL failed\")));\n    reader.readAsDataURL(file);\n  });\n}\n\ntype PublocLanguages = Array<{ id: string; languages: string[] }>;\ntype TypedPublocLanguages = { news: PublocLanguages; event: PublocLanguages };\n\nclass NEOForm extends RPCFormBase {\n  #errorObserver?: MutationObserver;\n  #publocs: TypedPublocLanguages = { news: [], event: [] };\n  #validatedAuthorizationOnce = false;\n\n  constructor(node: HTMLFormElement) {\n    super(node);\n\n    if (this.node.dataset.publocs)\n      this.#publocs = JSON.parse(this.node.dataset.publocs) as TypedPublocLanguages;\n\n    this.#errorObserver = new MutationObserver(mutationList => this.#handleMutations(mutationList));\n\n    // Show the blurry preview when checking the 'blurry background' checkbox\n    for (const fieldGroup of dompack.qSA(node, \".ut-neoform-showblurrybg\")) {\n      const checkbox = dompack.qS<HTMLInputElement>(fieldGroup, \"input[type='checkbox']\");\n      if (checkbox && (fieldGroup.previousSibling as HTMLElement)?.classList.contains(\"ut-neoform-headerphoto\"))\n        checkbox.addEventListener(\"change\", () => (fieldGroup.previousSibling as HTMLElement).classList.toggle(\"ut-neoform-headerphoto--blurrybg\", checkbox.checked));\n    }\n\n    // Implement our own visible/required condition for alt text fields (cannot use FCIsSet on imgedit fields)\n    for (const fieldGroup of dompack.qSA(node, \".ut-neoform-headerphoto\")) {\n      let imgedit = dompack.qS(fieldGroup, \"wh-imgedit\");\n      if (imgedit) {\n        imgedit.addEventListener(\"change\", () => this.#updateAltVisibility(imgedit!));\n        this.node.addEventListener(\"wh:form-pagechange\", () => this.#updateAltVisibility(imgedit!));\n\n        // Add a mutation observer to remove the warning if an error is shown\n        this.#errorObserver.observe(fieldGroup, { childList: true });\n      } else { //FIXME: This legacy support can be removed once UT runs 5.6\n        imgedit = dompack.qS(fieldGroup, \"div.wh-form__imgedit\");\n        if (imgedit) {\n          imgedit.addEventListener(\"change\", () => this.#updateAltVisibility(imgedit!, true));\n          this.node.addEventListener(\"wh:form-pagechange\", () => this.#updateAltVisibility(imgedit!));\n        }\n      }\n    }\n\n    // Hide all alt text fields by default\n    for (const fieldGroup of dompack.qSA(node, \".ut-neoform-headeralt\"))\n      this.#toggleAltEnabled(fieldGroup, false);\n\n    // Move checkboxgroup infotext and errors out of the options wrapper\n    for (const fields of dompack.qSA(node, \".ut-neoform-checkboxgroup .wh-form__fields\")) {\n      const infotextwrapper = dompack.qS(fields, \":scope > .wh-form__infotextwrapper\");\n      if (infotextwrapper)\n        fields.after(infotextwrapper);\n\n      // Add a mutation observer to move errors out of the option wrapper\n      this.#errorObserver.observe(fields, { childList: true });\n    }\n\n    // Link 'UT - all' to other checkboxes\n    for (const fieldGroup of dompack.qSA(node, \".wh-form__fieldgroup[data-wh-form-group-for=mp_receivers]\")) {\n      let changing = false;\n      fieldGroup.addEventListener(\"change\", event => {\n        if (!event.target || changing)\n          return;\n        changing = true;\n\n        if ((event.target as HTMLInputElement).dataset.isemployeesrole === \"true\") {\n          // (De)select all other options\n          for (const input of dompack.qSA(fieldGroup, \"input[type=checkbox][data-isemployeesrole=false]\")) {\n            if ((input as HTMLInputElement).dataset.isemployeesrole !== \"true\")\n              (input as HTMLInputElement).checked = (event.target as HTMLInputElement).checked;\n          }\n        } else {\n          // Set 'UT - all' checked to all other checked\n          const allChecked = dompack.qSA(fieldGroup, \"input[type=checkbox][data-isemployeesrole=false]\").every(input => (input as HTMLInputElement).checked);\n          const allEmployees = dompack.qS(fieldGroup, \"input[type=checkbox][data-isemployeesrole=true]\");\n          if (allEmployees)\n            (allEmployees as HTMLInputElement).checked = allChecked;\n        }\n\n        changing = false;\n      });\n    }\n\n    // Make sure either mp_authorized or mp_persontypes is filled if mp_authorized_public is set\n    // We'll add the validator to mp_authorized and will validate explicitly when mp_persontypes changes (after the validator\n    // has run at least once)\n    const mpAuthorizedField = dompack.qS(node, \".wh-form__fieldgroup[data-wh-form-group-for=mp_authorized]\");\n    if (mpAuthorizedField) {\n      setupValidator(mpAuthorizedField, () => this.#checkRequiredAuthorizedPersonTypes());\n    }\n    const mpPersonTypesField = dompack.qS(node, \".wh-form__fieldgroup[data-wh-form-group-for=mp_persontypes]\");\n    if (mpPersonTypesField && mpAuthorizedField) {\n      mpPersonTypesField.addEventListener(\"change\", () => this.#validatedAuthorizationOnce && this.validate([mpAuthorizedField]));\n    }\n  }\n\n  async getPublocLanguages() {\n    const value = await this.getFormValue() as {\n      newstype: string[];\n      orgpubloc_news: string;\n      publocations_news: string[];\n      orgpubloc_event: string;\n      publocations_event: string[];\n    };\n    const languages = new Set();\n    const newstype = value.newstype[0] as \"news\" | \"event\" | undefined;\n    if (newstype) {\n      const publocids = newstype === \"news\" ? [value.orgpubloc_news, ...value.publocations_news] : [value.orgpubloc_event, ...value.publocations_event];\n      const publocs = this.#publocs[newstype].filter(_ => publocids.includes(_.id));\n      for (const publoc of publocs)\n        for (const lang of publoc.languages)\n          languages.add(lang);\n    }\n    return [...languages.values()];\n  }\n\n  #handleMutations(mutationList: MutationRecord[]) {\n    for (const mutation of mutationList) {\n      const target = mutation.target as HTMLElement;\n      if (target.classList.contains(\"ut-neoform-headerphoto\")) {\n        // If an imgedit error node was added...\n        if ([ ...mutation.addedNodes ].some(_ => (_ as HTMLElement).classList.contains(\"wh-form__error\"))) {\n          const warningNode = target.querySelector(\".ut-neoform__warning\");\n          // ...remove the warning node, if any\n          if (warningNode)\n            warningNode.remove();\n        }\n      } else if (target.matches(\".ut-neoform-checkboxgroup .wh-form__fields\"))\n        // Move the error node out of the options wrapper\n        for (const errorNode of mutation.addedNodes)\n          target.after(errorNode);\n    }\n  }\n\n  async #updateAltVisibility(node: HTMLElement, legacy = false) {\n    let hasImage = false;\n    let name = \"\";\n    if (legacy) { //FIXME: This legacy support can be removed once UT runs 5.6\n      // The imgedit has a value if the 'wh-form__imgedit--hasimage' class is set\n      hasImage = node.classList.contains(\"wh-form__imgedit--hasimage\");\n      name = node.dataset.whFormName ?? \"\";\n    } else {\n      hasImage = (node as ImgEditElement).isSet();\n      name = (node as ImgEditElement).name;\n      this.#checkHeaderPhoto(node as ImgEditElement);\n    }\n    // If name == \"photo2\", we're looking for \"alt_en2\", etc.\n    const languages = await this.getPublocLanguages();\n    const altEN = dompack.qS(`[data-wh-form-group-for=\"${name.replace(/photo/, \"alt_en\")}\"]`);\n    if (altEN)\n      this.#toggleAltEnabled(altEN, hasImage && languages.includes(\"en\"));\n    const altNL = dompack.qS(`[data-wh-form-group-for=\"${name.replace(/photo/, \"alt_nl\")}\"]`);\n    if (altNL)\n      this.#toggleAltEnabled(altNL, hasImage && languages.includes(\"nl\"));\n  }\n\n  async #checkHeaderPhoto(node: ImgEditElement) {\n    // Remove current warning\n    const fieldGroup = node.closest(\".wh-form__fieldgroup\")!;\n    let warningNode = fieldGroup.querySelector(\".ut-neoform__warning\");\n    if (warningNode)\n      warningNode.remove();\n\n    const file = node.value[0]?.file;\n    if (file) {\n      try {\n        const size = await getImageDimensions(file);\n        //FIXME: This height check can be replaced with the 'minheight' attribute on the imgedit field once that's supported on all UT servers\n        if (size.height < MIN_HEADERIMAGE_HEIGHT)\n          setFieldError(node, getTid(\"utwente_base:frontend.ws2016.js.neoform.minheight\", size.height, MIN_HEADERIMAGE_HEIGHT));\n        else if (size.width < MIN_HEADERIMAGE_WIDTH) {\n          // Show a warning if the image is high enough, but not wide enough\n          const warning = <span>{getTid(\"utwente_base:frontend.ws2016.js.neoform.image-invalid-width\", size.width, MIN_HEADERIMAGE_WIDTH)}</span>;\n          warningNode = warningNode || <div class=\"ut-neoform__warning\"></div>;\n          warningNode!.replaceChildren(warning!);\n          fieldGroup.querySelector(\".wh-form__fields\")!.after(warningNode!);\n        }\n      } catch (e) {\n        console.error(e);\n        setFieldError(node, getTid(\"utwente_base:frontend.ws2016.js.neoform.image-read-error\"));\n      }\n    }\n  }\n\n  #toggleAltEnabled(node: HTMLElement, enabled: boolean) {\n    node.classList.toggle(\"wh-form__fieldgroup--disabled\", !enabled);\n    node.classList.toggle(\"wh-form__fieldgroup--required\", enabled);\n    const input = dompack.qS<HTMLInputElement>(node, \"input\");\n    if (input) {\n      input.disabled = !enabled;\n      input.required = enabled;\n    }\n    requestAnimationFrame(() => node.classList.toggle(\"wh-form__fieldgroup--hidden\", !enabled));\n  }\n\n  async #checkRequiredAuthorizedPersonTypes() {\n    this.#validatedAuthorizationOnce = true;\n    const value = await this.getFormValue() as {\n      mp_authorized_public: string[];\n      mp_authorized: string[];\n      mp_persontypes: string[];\n    };\n    if (value.mp_authorized_public?.includes(\"1\") && !value.mp_authorized?.length && !value.mp_persontypes?.length) {\n      return getTid(\"utwente_base:frontend.ws2016.js.neoform.authorizednotset\");\n    }\n  }\n}\n\nregisterHandler(\"utwente_base:neoform\", node => new NEOForm(node));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./tablewithfilter.scss\";\nimport * as FO from \"../../filteredoverview\";\nimport * as dompack from 'dompack';\nimport rpc from \"./tablewithfilter.rpc.json?proxy\";\n\nimport { getResultsFeedbackText } from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview\";\n\n\nconst initializedforms = new Set();\n\nclass cTableFilter {\n  constructor(node) {\n    this.formnode = node.closest(\"form\");\n    this.allrows = document.querySelectorAll(\".tablewithfilter tbody > tr\");\n    if (this.allrows.length == 0)\n      return;\n\n    this.baseurl = document.location.href.split(/[?#]+/)[0];\n\n    this.container = document.querySelector(\".tablewithfilter__scrollcontainer\");\n\n    this.tablenode = this.container.querySelector(\"table\");\n\n    this.formnode.addEventListener(\"submit\", evt => {\n      evt.preventDefault();\n      this.showResults();\n      return false;\n    });\n\n    let hasinitialvalue = false;\n\n    for (const inpnode of node.querySelectorAll(\"input\")) {\n      if (inpnode.name) {\n        const val = this.getUrlParam(inpnode.name);\n        if (val != \"\") {\n          inpnode.value = val;\n          hasinitialvalue = true;\n        }\n      }\n      inpnode.addEventListener(\"change\", () => this.showResults());\n    }\n\n    for (const selnode of node.querySelectorAll(\"select\")) {\n      if (selnode.name) {\n        const val = this.getUrlParam(selnode.name);\n        if (val != \"\" && selnode.querySelector(\"option[value='\" + val + \"']\")) {\n          selnode.value = val;\n          hasinitialvalue = true;\n        }\n      }\n      selnode.addEventListener(\"change\", () => this.showResults());\n    }\n\n    if (hasinitialvalue)\n      this.showResults();\n\n    // Make sure the filtered overview is only initialized once for the form\n    if (!initializedforms.has(this.formnode)) {\n      new FO.FilteredOverviewHeader();\n      initializedforms.add(this.formnode);\n    }\n\n    for (const selnode of node.querySelectorAll(\".downloadxlsx\"))\n      selnode.addEventListener(\"click\", () => this.downloadXlsx());\n    /*\n        let version = this.getUrlParam(\"version\");\n        let category = this.getUrlParam(\"category\");\n        let query = this.getUrlParam(\"query\");\n    */\n    this.setStripes();\n\n    window.addEventListener(\"resize\", () => this.onResize());\n    window.addEventListener(\"load\", () => this.onResize());\n    this.onResize();\n  }\n\n  onResize() {\n    this.container.parentNode.classList.remove(\"overflow\");//first reset\n    const w1 = this.container.clientWidth;\n    const w2 = this.tablenode.clientWidth;\n    if (w1 < w2)\n      this.container.parentNode.classList.add(\"overflow\");\n  }\n\n  async downloadXlsx() {\n    if (this.loading)\n      return;\n\n    const idxlist = [];\n    let i = 0;\n    for (const node of this.allrows) {\n      if (!node.style.display)\n        idxlist.push(i);\n      ++i;\n    }\n\n    this.overlay = <div class=\"tablewithfilter__overlay\"><span>Loading...</span></div>;\n    document.body.appendChild(this.overlay);\n    this.loading = true;\n\n    const result = await rpc.GetXLSXExport(document.location.href, idxlist);\n\n    this.overlay.parentNode.removeChild(this.overlay);\n    this.loading = false;\n\n    if (!result || !result.data)\n      return;\n\n    const filedata = this.dataURLtoBlob(result.data);\n\n\n    const file = window.URL.createObjectURL(filedata);\n    const link = <a download={result.filename} />;\n    link.href = file;\n    document.body.appendChild(link);\n    link.click();\n\n    window.URL.revokeObjectURL(file);\n    link.remove();\n  }\n\n  dataURLtoBlob(dataurl) {\n    let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],\n      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);\n    while (n--)\n      u8arr[n] = bstr.charCodeAt(n);\n    return new Blob([u8arr], { type: mime });\n  }\n\n  setStripes() {\n    let count = 0;\n    for (const node of this.allrows) {\n      if (node.style.display == \"none\")\n        node.classList.remove(\"even\");\n      else {\n        ++count;\n        if (count % 2)\n          node.classList.add(\"even\");\n        else\n          node.classList.remove(\"even\");\n      }\n    }\n  }\n\n  getUrlParam(name) {\n    const urlparamstr = location.search.replace(/\\+/g, \"%20\");\n    const val = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(urlparamstr);\n    return val ? decodeURIComponent(val[1]) : \"\";\n  }\n\n  showResults() {\n    let resultscount = 0;\n    for (const node of this.allrows) {\n      let invalid = false;\n      if (this.formnode.query.value != \"\") { //text search\n        const chkstr = this.formnode.query.value.toUpperCase();\n        let found = false;\n        for (let c = 0; c < node.children.length; ++c) { //Check seperate cells\n          const txt = node.children[c].textContent.toUpperCase();\n          found = txt.indexOf(chkstr) > -1;\n          if (found)\n            break;\n        }\n        invalid = !found;\n      }\n\n      if (!invalid && this.formnode.category && this.formnode.category.value != \"\")\n        invalid = node.dataset.category != this.formnode.category.value;\n\n      if (!invalid && this.formnode.version && this.formnode.version.value != \"\" && this.formnode.version.value != \"all\")\n        invalid = node.dataset.version != this.formnode.version.value;\n\n      node.style.display = invalid ? \"none\" : \"\";\n      if (!invalid)\n        resultscount++;\n    }\n\n    if (history.replaceState) {\n      const param = [];\n      if (this.formnode.query.value)\n        param.push(\"query=\" + this.formnode.query.value);\n      if (this.formnode.category && this.formnode.category.value != \"\")\n        param.push(\"category=\" + this.formnode.category.value);\n      if (this.formnode.version && this.formnode.version.value != \"\")\n        param.push(\"version=\" + this.formnode.version.value);\n\n      history.replaceState(null, \"\", this.baseurl + (param.length ? \"?\" + param.join(\"&\") : \"\") + location.hash);\n    }\n\n    this.setStripes();\n\n    const feedbacknode = document.querySelector(\".filteredoverview__feedback\");\n    feedbacknode.textContent = getResultsFeedbackText(resultscount, resultscount, this.allrows.length);\n  }\n}\n\ndompack.register(\".tablewithfilter__filters\", node => new cTableFilter(node));\n","const { createService } = require(\"@mod-system/js/wh/rpc.ts\"); export default createService(\"utwente_base:rpc_tablewithfilter\");","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n/*\nlive: https://www.utwente.nl/en/education/scholarship-finder/\ntest: https://utwente.moe.sf.webhare.nl/en/education/scholarship-finder/\n*/\n\nimport * as dompack from 'dompack';\nimport \"./filteredfolder.scss\";\nimport { getTid } from \"@webhare/gettid\";\nimport { ClientSideFilteredOverview } from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview\";\n\n//TODO can we avoid  *ALL* exceptions and directly use a  ClientSideFilteredOverview?  we shouldn't have unique features but be an example of the default\nclass FilteredFolder extends ClientSideFilteredOverview {\n  constructor(node, options) {\n    super({ ...options, filterpagetype: 'filteredfolder' }); //filterpagetype is used for GTM\n\n    this.node = node;\n    this.listnode = dompack.qS(node, \".filteredoverview__items\");\n    //this.listview();\n    // this.lastedutype = '';\n    // this.setProgrammeFilter();\n    //    this.doFilter(); // FIXME: we need another way.. (a forcefilter option or default 'initialized' class?)\n\n    //Add viewmode toggles\n    let listtoggle = dompack.qS(\".filteredoverview__viewmode\");\n    if (!listtoggle) {\n      const resultsbar = dompack.qS(\".filteredoverview__feedbackandviewbar__content\");\n      if (resultsbar) {\n        listtoggle = <div class=\"filteredoverview__viewmode\">\n          <div class=\"filteredoverview__viewmode__items\">\n            <button class=\"listtoggle__detailview\" data-viewmode=\"detailview\" type=\"button\">\n              <i class=\"uticon UT-icon-UT_icon_138_detail-view-16px\"></i>\n              {getTid(\"utwente_base:frontend.ws2016.js.details\")}\n            </button>\n            <span class=\"spacer\"></span>\n            <button class=\"listtoggle__listview\" data-viewmode=\"listview\" type=\"button\">\n              <i class=\"uticon UT-icon-UT_icon_139_list-view-16px\"></i>\n              {getTid(\"utwente_base:frontend.ws2016.js.list\")}\n            </button>\n          </div>\n        </div>;\n        resultsbar.appendChild(listtoggle);\n      }\n    }\n\n    this.sortcol = 0;//Default first column\n    this.sortasc = true;\n    const listviewheader = dompack.qS(this.node, \".filteredoverview__listviewheader\");\n    if (listviewheader) {\n      listviewheader.addEventListener(\"click\", ev => {\n        const col = ev.target.closest(\".filteredoverview__item__listviewcol\");\n        if (!col)\n          return;\n\n        let idx = this.sortcol;\n        for (let c = 0; c < listviewheader.children.length; ++c) {\n          if (listviewheader.children[c] === col) {\n            idx = c;\n            break;\n          }\n        }\n\n        if (this.sortcol === idx)\n          this.sortasc = !this.sortasc;//reverse ordering if click on same column\n        this.sortcol = idx;\n\n        this.sortList();\n      });\n    }\n\n    if (listtoggle) {\n      const feedbackbar = listtoggle.closest(\".filteredoverview__feedbackandviewbar\");\n      feedbackbar.classList.add(this.listnode.classList.contains(\"filteredoverview__items--listview\") ? \"filteredoverview--listview\" : \"filteredoverview--detailview\");//initial detailview\n\n      listtoggle.addEventListener(\"click\", ev => {\n        const togglenode = ev.target.closest(\"[data-viewmode]\");\n        if (!togglenode)\n          return;\n\n        if (togglenode.dataset.viewmode === \"detailview\" && feedbackbar.classList.contains(\"filteredoverview--detailview\"))\n          return;//already in detailview\n\n        if (togglenode.dataset.viewmode !== \"detailview\" && !feedbackbar.classList.contains(\"filteredoverview--detailview\"))\n          return;//already in listview\n\n        if (togglenode.dataset.viewmode === \"detailview\") {\n          feedbackbar.classList.remove(\"filteredoverview--listview\");\n          feedbackbar.classList.add(\"filteredoverview--detailview\");\n\n          this.listnode.classList.remove(\"filteredoverview__items--listview\");\n        } else {\n          feedbackbar.classList.add(\"filteredoverview--listview\");\n          feedbackbar.classList.remove(\"filteredoverview--detailview\");\n\n          this.listnode.classList.add(\"filteredoverview__items--listview\");\n        }\n\n        this.sortList();\n      });\n    }\n  }\n\n  sortList() {\n    const items = dompack.qSA(this.listnode, \".filteredoverview__item\");\n    if (this.listnode.classList.contains(\"filteredoverview__items--listview\")) { //use sort column\n      items.sort((a, b) => {\n        const a_i = Number(a.dataset.ordering); //original ordering\n        const b_i = Number(b.dataset.ordering);\n\n        // + 1 to skip (first) hidden element\n        const a_c = a.children[this.sortcol + 1].textContent.toUpperCase().trim();\n        const b_c = b.children[this.sortcol + 1].textContent.toUpperCase().trim();\n\n        if (this.sortasc) {\n          if (a_c < b_c)\n            return -1;\n          if (a_c > b_c)\n            return 1;\n          return a_i < b_i ? -1 : 1;//If equal, then check original ordering\n        } else { //sort desc\n          if (a_c > b_c)\n            return -1;\n          if (a_c < b_c)\n            return 1;\n          return a_i > b_i ? -1 : 1;//If equal, then check original ordering\n        }\n      });\n\n      items.forEach(e => this.listnode.appendChild(e));\n    } else {\n      //Just use original ordering when in detail view\n      items.sort((a, b) => {\n        return Number(a.dataset.ordering) < Number(b.dataset.ordering) ? -1 : 1;//If equal, then check original ordering\n      });\n\n      items.forEach(e => this.listnode.appendChild(e));\n    }\n  }\n\n  showResults() {\n    // if( this.fadetimer )\n    // clearTimeout(this.fadetimer);\n\n    // this.setProgrammeFilter();//toggle programme pulldowns\n\n    // this.itemscontainer.classList.remove(\"scholarshipfinder--show\");\n    // this.itemscontainer.clientWidth;//force css update\n    this.runFilterByDataTags(); //TODO why doesn't our parent do this for us ?\n\n    // this.fadetimer = setTimeout(function(){ this.itemscontainer.classList.add(\"scholarshipfinder--show\"); }.bind(this), 500);\n  }\n}\n\nfunction setupFilteredFolder(node) {\n  new FilteredFolder(node, { itemsselector: \".filteredoverview__item\" });\n}\n\ndompack.register(\".filteredfolder__results\", setupFilteredFolder);\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport './btor.scss';\nimport * as dompack from 'dompack';\nimport FilteredOverview from \"../../filteredoverview\";\nimport * as whintegration from \"@mod-system/js/wh/integration\";\n\n\nclass BTOROverview extends FilteredOverview {\n  constructor(options) {\n    super({ ...options, filterpagetype: 'btor' });\n\n    this.form.addEventListener('change', evt => this.form.submit(evt));\n\n    document.addEventListener(\"click\", function (evt) {\n      if (!evt.target.hasAttribute(\"data-btoryear\"))\n        return;\n\n      this.form.year.value = evt.target.getAttribute(\"data-btoryear\");\n      this.form.submit();\n    });\n\n    this.setFeedback(whintegration.config.obj.overviewdata.resultscount\n      , whintegration.config.obj.overviewdata.resultsshown\n    );\n  }\n}\n\n\n\ndompack.onDomReady(() => {\n  const filterform = document.querySelector(\".filterbar--btor\");\n  if (!filterform)\n    return;\n\n  window.overview_btor = new BTOROverview(filterform);\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport './btor';\nimport './itcpages.css';\nimport * as dompack from 'dompack';\n\nfunction setupITCYearControl(node) {\n  node.addEventListener('change', function () {\n    location.href = '?year=' + node.value;\n  });\n}\n\ndompack.register('select.ut-itcintranet-selectyear', setupITCYearControl);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./itcforms.scss\";\nimport * as dompack from 'dompack';\n\ndompack.register(\".itcform--fromto-to\", node => {\n  if (node.previousSibling.classList.contains(\"itcform--fromto-from\")) {\n    // Move the to field into the from fieldgroup, to place them next to each\n    // other on one line\n    node.previousSibling.querySelector(\".wh-form__fieldline\").appendChild(node);\n  }\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./search.scss\";\n\nimport * as dompack from \"dompack\";\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\nimport { getTid } from \"@webhare/gettid\";\n\nclass cConsilioResults {\n  constructor(node) {\n    this.node = node;\n    this.moredata = JSON.parse(node.dataset.more);\n    if (!this.moredata || this.moredata.page >= this.moredata.pagecount - 1)\n      return;\n\n    this.morenode = document.getElementById(\"consiliomore\");\n    if (!this.morenode)\n      return;\n\n    this.morenode.addEventListener(\"click\", ev => this.loadMore(ev));\n\n    this.rpc = new JSONRPC();\n    this.pageurl = window.location.href.split('?')[0];\n    this.words = this.getUrlParam(\"q\");\n    this.site = this.getUrlParam(\"site\");\n  }\n\n  loadMore(ev) {\n    if (this.busy)\n      return;\n\n    this.busy = true;\n    ++this.moredata.page;\n\n    if (history.replaceState) {\n      const urlparams = [];\n\n      if (this.words != \"\")\n        urlparams.push(\"q=\" + encodeURIComponent(this.words));\n\n      if (this.site != \"\")\n        urlparams.push(\"site=\" + encodeURIComponent(this.site));\n\n      if (this.moredata.page > 0)\n        urlparams.push(\"page=\" + this.moredata.page);\n\n      history.replaceState(null, \"\", this.pageurl + (urlparams.length ? \"?\" + urlparams.join(\"&\") : \"\"));\n    }\n\n    this.rpc.request(\"GetSearchResults\", [this.moredata.page]\n      , this.onSearchResult.bind(this)\n      , this.onRpcError.bind(this)\n    );\n  }\n\n  getUrlParam(name) {\n    const urlparamstr = location.search.replace(/\\+/g, \"%20\");\n    const val = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(urlparamstr);\n    return val ? decodeURIComponent(val[1]) : \"\";\n  }\n\n  onSearchResult(res) {\n    this.moredata.page = res.pagenr;\n    this.moredata.pagecount = res.pagecount;\n\n    for (let i = 0; i < res.items.length; ++i) {\n      const itemnode = <li class=\"beforeshow\">\n        <a href={res.items[i].link} className={res.items[i].image1x ? \"withimage\" : \"\"}>\n          <strong class=\"title\">\n            {res.items[i].title}\n            {res.items[i].filesize\n              ? <span class=\"filesize\"> ({res.items[i].filetype}, {res.items[i].filesize})</span>\n              : null\n            }\n          </strong>\n          <span class=\"link\">{res.items[i].link}</span>\n          <span class=\"description\">{res.items[i].description}</span>\n          {res.items[i].image1x\n            ? <span class=\"image\" style={res.items[i].bgcolor ? \"background-color:\" + res.items[i].bgcolor : \"\"}>\n              <img src={res.items[i].image1x} srcset={res.items[i].image1x + \" 1x,\" + res.items[i].image2x + \" 2x\"} />\n            </span>\n            : null\n          }\n        </a>\n      </li>;\n\n      this.highlightSearchWords(itemnode.querySelector(\".description\"));\n\n      this.node.appendChild(itemnode);\n      itemnode.clientWidth;\n      itemnode.classList.remove(\"beforeshow\");\n    }\n\n    if (this.moredata.page >= this.moredata.pagecount - 1)\n      this.morenode.parentNode.removeChild(this.morenode);\n    else\n      this.busy = false;\n  }\n\n  highlightSearchWords(node) {\n    if (!node)\n      return;\n\n    let descr = node.textContent;\n    descr = descr.replace(\"\\x1D\", \"<span class=\\\"match\\\">\");\n    descr = descr.replace(\"\\x1C\", \"</span>\");\n    node.innerHTML = descr;\n  }\n\n  onRpcError(res) {\n    console.log(res);\n  }\n}\n\ndompack.register(\".consilioresults[data-more]\", node => new cConsilioResults(node));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./shared.scss\";\nimport \"./overview.scss\";\nimport \"./majorprojects.scss\";\nimport \"./partners.scss\";\nimport \"./phdprojects-overview.scss\";\nimport \"./phdprojects-project.scss\";\nimport * as dompack from 'dompack';\nimport \"../../site.lang.json\";\n\nimport * as filteredoverview from \"../../filteredoverview\";\n\n\n\nclass ProjectsOverviewFilter extends filteredoverview.ClientSideFilteredOverview {\n  // give the oppertunity to override/change\n  processFiltersFromURL(filters) {\n    this.onFormFiltersUpdate();\n  }\n\n\n  onFormFiltersUpdate(filters, evt) {\n    //console.info(\"OverviewFilter:onFormFiltersUpdate()\");\n\n    const gradcheckbox = document.getElementById(\"phdstate_graduated\");\n    if (gradcheckbox) // meaning we are on the PHD projects overview page\n    {\n      if (evt && evt.target == this.form.graduationyear) {\n        gradcheckbox.checked = this.form.graduationyear.value != \"\";\n\n        if (!filters.status)\n          filters.status = [\"graduated\"];\n        else\n          filters.status.push(\"graduated\");\n      } else if (!gradcheckbox.checked)\n        delete this.filters.graduationyear;\n    }\n\n    //console.log(\"Filters\", this.filters);\n  }\n\n\n  onMapFilterTags(tags, filters) {\n    const newtags = [];\n\n    //console.info(\"onMapFilterTags\", tags, filters);\n\n    for (const tagref of tags) {\n      // Clone the tag (since an array is an object it'll be a reference...\n      // so if we remove an item (\"graduated\" in this case) it would otherwise also be removed from the filters.\n      const tag = {\n        name: tagref.name,\n        title: Array.isArray(tagref.title) ? Array.from(tagref.title) : tagref.title,\n        value: Array.isArray(tagref.value) ? Array.from(tagref.value) : tagref.value\n      }; // clone\n\n      if (tag.name == \"status\") {\n        const gradidx = tag.value.indexOf(\"graduated\");\n        if (gradidx > -1 && this.filters.graduationyear > 0) {\n          tag.title = \"Completed\";\n          //    tag.value.splice(gradidx, 1);\n          continue;\n        }\n      }\n\n      if (tag.name == \"graduationyear\")\n        tag.title = \"Completed in \" + tag.title;\n\n      newtags.push(tag);\n    }\n\n    return newtags;\n  }\n}\n\n\n\ndompack.onDomReady(() => {\n  // This filterclass is meant for the following pages:\n  const hecl = document.documentElement.classList;\n  if (!hecl.contains(\"page--itcmajorprojectsoverview\")\n    && !hecl.contains(\"page--itcphdprojectsoverview\")\n    && !hecl.contains(\"page--itcpartnersoverview\")\n  )\n    return;\n\n  window.filteredoverview = new ProjectsOverviewFilter({ itemsselector: \".filteredoverview__listview__item,.filteredoverview__detailview__item,.itcpartner\", filterpagetype: 'projectsoverview' });\n});\n","import \"./osiris.scss\";\nimport * as dompack from 'dompack';\nimport * as dialogapi from 'dompack/api/dialog';\nimport { getTid } from \"@webhare/gettid\";\nimport type { UTDialog } from \"../../shared/dialog\";\nimport { createClient } from \"@webhare/jsonrpc-client\";\n\nfunction importHTML(html: string) {\n  const node = <div />;\n  node.innerHTML = html;\n  return [...node.childNodes];\n}\n\nasync function showOsirisLink(id: string) {\n  const language = document.documentElement.lang.indexOf(\"nl\") >= 0 ? \"nl\" : \"en\";\n  // \"main.contentpart__main\" for WS2021\n  const mainnode = document.querySelector(\"main > .main__contents, main.contentpart__main\");\n  if (!mainnode) {\n    console.warn(\"Osiris link found without main contents\");\n    return;\n  }\n\n  //Open popup with loading message\n  const osiriscontentnode = <div class=\"loading\">{getTid(\"utwente_base:frontend.ws2016.js.osiris.loading\")}</div>;\n  const dialog = dialogapi.createDialog({ allowcancel: true }) as UTDialog;\n  if (!dialog.contentnode)\n    throw new Error(\"Dialog content node is not available\");\n\n  dialog.contentnode.appendChild(osiriscontentnode);\n  dialog.contentnode.classList.add(\"osiris\");\n  dialog.runModal();\n\n  const result = await createClient(\"utwente_base:rpc\").getOsirisCourse(id, language);\n  if (result && result.success) {\n    dialog.utheadernode.append(<h2 class=\"osiris__title\">{result.title}</h2>);\n    if (result.maxpoints)\n      dialog.utheadernode.append(<div class=\"osiris__maxpoints\">{result.maxpoints}</div>);\n\n    dialog.contentnode.replaceChildren(<div class=\"osiris__description\">{importHTML(result.contents)}</div>);\n    if (result.goal)\n      dialog.contentnode.append(<h3>{getTid(\"utwente_base:frontend.ws2016.js.osiris.goal\")}</h3>, ...importHTML(result.goal));\n    dialog.contentnode.append(<p class=\"normal\">{importHTML(getTid(\"utwente_base:frontend.ws2016.js.osiris.moredetailslink\", result.link))}</p>);\n  } else {\n    osiriscontentnode.textContent = getTid(\"utwente_base:frontend.ws2016.js.osiris.nocoursefound\");\n  }\n}\n\nfunction onOsirisLink(event: MouseEvent) {\n  const utcourselink = event.target instanceof HTMLElement ? event.target.closest<HTMLAnchorElement>(\"a[href^='x-ut-courselink:']\") : null;\n  if (!utcourselink)\n    return true;\n\n  event.preventDefault();\n\n  const id = utcourselink.getAttribute(\"href\")?.split(\":\")[1];\n  if (id)\n    void showOsirisLink(id);\n\n  return false;\n}\n\n//Note: click doesn't work correctly on Explorer, application handler is started before preventDefault\nwindow.addEventListener('click', onOsirisLink);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\nimport \"./notificationbar.scss\";\n\n/* to reset all hidden CTas:\nlocalStorage[\"ws-notifications\"]=\"\"\n*/\n\nconst notificationDelay = 250;\nlet notificationNode, notificationId, closedNotifications;\n\nfunction onShowNotification(event) {\n  if (event.target === notificationNode) {\n    // Check if this notification has already been shown\n    closedNotifications = localStorage.getItem(\"ws-notifications\");\n    if (closedNotifications)\n      closedNotifications = closedNotifications.split(\";\").filter(_ => Boolean(_));\n    else\n      closedNotifications = [];\n    if (dompack.debugflags.umc)\n      console.log(`[umc] Closed notification CTA's`, closedNotifications);\n    notificationId = event.detail.cta.config.id;\n    if (closedNotifications.includes(notificationId)) {\n      // This notification has already been seen and closed by this user\n      if (dompack.debugflags.umc)\n        console.warn(`[umc] Not showing closed notification CTA ${notificationId}`);\n      dompack.remove(notificationNode);\n      return;\n    }\n\n    setTimeout(() => {\n      // Force a style recalculation before getting the current height (hopefully fixes #1483)\n      notificationNode._wsTmpHeight = getComputedStyle(notificationNode).height;\n      const rect = notificationNode.getBoundingClientRect();\n      /* For debugging the notification header problem of #1483: set the 'notificationdebug' debug option to reload the page in a\n         loop until the problem occurs, after which some diagnostics are logged to the console\n      */\n      if (dompack.debugflags.notificationdebug) {\n        if (notificationNode._wsTmpHeight !== \"60px\" || rect.height !== 60) {\n          console.info(\"_wsTmpHeight\", notificationNode._wsTmpHeight);\n          console.info(\"rect\", rect);\n          console.info(\"html\", notificationNode.outerHTML);\n\n        } else {\n          setTimeout(() => {\n            const u = new URL(location.href);\n            let c = parseInt(u.search.substr(1)) || 0;\n            u.search = ++c;\n            location.href = u.toString();\n          }, 1000);\n        }\n        return;\n      }\n      notificationNode.style.height = `0`;\n\n      notificationNode.classList.remove(\"notification__container--init\");\n      document.documentElement.classList.add(\"utwente--notificationvisible\");\n\n      notificationNode.classList.add(\"notification__container--animate\");\n      // Force a style recalculation before setting the new height\n      notificationNode._wsTmpHeight = getComputedStyle(notificationNode).height;\n      notificationNode.style.height = `${rect.height}px`;\n      notificationNode.style.opacity = `1`;\n\n      dompack.dispatchCustomEvent(window, \"wh:notification-change\", { bubbles: false, cancelable: false, detail: { visible: true, height: rect.height } });\n    }, notificationDelay);\n  }\n}\n\nfunction onHideNotification(event) {\n  event.preventDefault();\n\n  const rect = notificationNode.getBoundingClientRect();\n  notificationNode.style.height = `${rect.height}px`;\n\n  notificationNode.classList.add(\"notification__container--close\");\n  // Force a style recalculation before setting the new height\n  notificationNode._wsTmpHeight = getComputedStyle(notificationNode).height;\n  notificationNode.style.height = `0`;\n  notificationNode.style.opacity = `0`;\n\n  dompack.dispatchCustomEvent(window, \"wh:notification-change\", { bubbles: false, cancelable: false, detail: { visible: false, height: rect.height } });\n\n  closedNotifications.push(notificationId);\n  localStorage.setItem(\"ws-notifications\", closedNotifications.join(\";\"));\n  if (dompack.debugflags.umc)\n    console.info(`[umc] Closed notification CTA ${notificationId}`);\n}\n\nfunction onNotificationTransitionEnd(event) {\n  if (!notificationNode.parentNode || event.target !== notificationNode || event.propertyName !== \"height\")\n    return;\n\n  if (notificationNode.classList.contains(\"notification__container--close\")) {\n    dompack.remove(notificationNode);\n    document.documentElement.classList.remove(\"utwente--notificationvisible\");\n  } else {\n    notificationNode.style.height = \"\";\n  }\n}\n\n\ndompack.register(\".notification__container\", node => {\n  notificationNode = node;\n\n  document.documentElement.addEventListener(\"ws:managed-cta\", onShowNotification);\n  //there may be multiple CTAs. we might want to listen at a higer level\n  dompack.qSA(\".notification__close-icon\").forEach(icon => icon.addEventListener(\"click\", onHideNotification));\n  node.addEventListener(\"transitionend\", onNotificationTransitionEnd);\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n//We needed this hack to get PowerBI fullscreen mode to work on Edge\n\nimport * as dompack from 'dompack';\nimport * as browser from 'dompack/extra/browser';\nimport \"./edge-fullscreen.scss\";\n\nlet infullscreen = false;\n\nfunction checkFullscreen() {\n  //fullscreenevent is not emitted on eg. chrome, and IE doesn't set document.fullscreenElement for iframes, so let's just poll 0,0\n  const el = document.elementFromPoint(0, 0);\n  const nowfullscreen = el && el.nodeName === 'IFRAME';\n  if (nowfullscreen !== infullscreen)\n    document.documentElement.classList.toggle(\"ut--edgeinfullscreen\", nowfullscreen);\n  infullscreen = nowfullscreen;\n}\n\n//this hack needs explicit optin (ut--edgefullscreenfix on an <iframe>\nif (browser.getName() === \"edge\") {\n  dompack.register(\"iframe.ut--edgefullscreenfix\", node => {\n    console.log(\"activating edge fullscreen workarounds\");\n    setInterval(checkFullscreen, 300);\n  });\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n// Addthisevent integration, see https://www.addevent.com/add-to-calendar-button\n\nimport * as dompack from \"dompack\";\nimport { getTid } from \"@webhare/gettid\";\nimport \"./addthisevent.css\";\n\nlet eventscriptloaded = false;\nexport function onAddThisClick(eventnode) {\n  if (!eventscriptloaded) {\n    eventscriptloaded = true;\n\n    window.addeventasync = function () {\n      addeventatc.settings(\n        {\n          license: \"aHGbRdipTzsgMbuxYmdh49124\",\n          mouse: false,\n          css: false,           //WARNING if you change/move the below texts, studentunion module relies on them too!\n          outlook: { show: true, text: getTid(\"utwente_base:frontend.ws2016.js.calendar.outlook\") },\n          google: { show: true, text: getTid(\"utwente_base:frontend.ws2016.js.calendar.google\") },\n          yahoo: { show: true, text: getTid(\"utwente_base:frontend.ws2016.js.calendar.yahoo\") },\n          outlookcom: { show: true, text: getTid(\"utwente_base:frontend.ws2016.js.calendar.outlookcom\") },\n          appleical: { show: true, text: getTid(\"utwente_base:frontend.ws2016.js.calendar.appleical\") },\n          facebook: { show: true, text: getTid(\"utwente_base:frontend.ws2016.js.calendar.facebook\") },\n          dropdown: { order: \"google,appleical,outlook,outlookcom,facebook,yahoo\" },\n          callback: \"\"\n        });\n\n      //update and open the node\n      addeventatc.refresh(eventnode);\n\n      setTimeout(() => {\n        eventnode.click();\n      }, 10);//small delay else click event to close calendar won't work\n    };\n\n\n    const addThisScript = document.createElement(\"script\");\n    addThisScript.src = \"https://addevent.com/libs/atc/1.6.1/atc.min.js\";\n    document.querySelector(\"head\").appendChild(addThisScript);\n  }\n}\n\n//TODO cleanup unused addthisevent classes from witty (and css?)\ndompack.register(\".addeventatc\", eventnode => {\n  eventnode.addEventListener(\"click\", event => onAddThisClick(eventnode));\n});\n","import \"./login.scss\";\nimport * as wrdauth from \"@mod-wrd/js/auth\";\nimport * as dompack from \"@webhare/dompack\";\n\nexport interface UTLoginOptions {\n  loginLink: string;\n  loginText: string;\n  onGetMenuItems: () => Array<{\n    link: string;\n    title: string;\n    onClick?: (evt: MouseEvent) => void;\n  }>;\n}\n\nfunction setupLogin(topmenu: HTMLElement, loginoptions: UTLoginOptions) {\n  const userinfo = wrdauth.getDefaultAuth()?.getUserInfo();\n  if (userinfo) {\n    const menuitems = loginoptions.onGetMenuItems();\n\n    //zie https://gitlab.webhare.com/utwente/utwente_base/-/issues/1592#note_141471 voor het menuplan\n    topmenu.append(<div class=\"contentpart__topsubmenu\">\n      <div class=\"contentpart__toptextitem\">\n        {userinfo.fullname ? <div class=\"ut-login__fullname\">{userinfo.fullname}</div> : null}\n        {userinfo.username ? <div class=\"ut-login__loginname\">{userinfo.username}</div> : null}\n      </div>\n      {menuitems.map(item => <a class=\"contentpart__topsubitem\" href={item.link} onClick={item.onClick}>{item.title}</a>)}\n    </div>);\n  } else {\n    topmenu.append(<div class=\"contentpart__topsubmenu\">\n      <a class=\"contentpart__topsubitem\" href={loginoptions.loginLink}>{loginoptions.loginText}\n        <span class=\"contentpart__topsubitem-icon UT-icon-UT_icons_174_lock-16px\"></span>\n      </a>\n    </div>);\n  }\n}\n\nexport function defineLoginMenu(opts: UTLoginOptions) {\n  dompack.register(\".ut-login__topmenu\", node => setupLogin(node, opts));\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from 'dompack';\nimport \"./recipientsfield.scss\";\n\nfunction deleteRow() {\n  const recipientsfield = this.closest(\".utforms-recipientsfield\").propField;\n  this.closest(\".utforms-recipientsfield__row\").replaceWith();\n  if (recipientsfield.getValue().length == 0)\n    recipientsfield.addRow(true);\n}\n\nclass RecipientsField {\n  constructor(node) {\n    this.node = node;\n    this.name = this.node.dataset.whFormName;\n    this.nextnr = 0;\n    this.node.propField = this;\n    this.rowsholder = <div class=\"utforms-recipientsfield__rows\"></div>;\n    const buttonsholder = <div class=\"utforms-recipientsfield__buttons\">\n      <span class=\"utforms-recipientsfield__button utforms-recipientsfield__button--add\" onClick={() => this.addRow(true)}>\n        <i class=\"utforms-recipientsfield__button__icon UT-icon-UT_icon_48_plus-16px\" />\n        <span class=\"utforms-recipientsfield__button__text\">Add</span>\n      </span>\n    </div>;\n\n    this.node.addEventListener('wh:form-getvalue', evt => this._getValueEvent(evt));\n\n    this.addRow(false);\n    this.node.append(this.rowsholder, buttonsholder);\n  }\n\n  getValue() {\n    const rows = [];\n    for (const row of this.node.querySelectorAll(\".utforms-recipientsfield__row\"))\n      rows.push({\n        name: row.querySelector(\".utforms-recipientsfield__name\").value,\n        email: row.querySelector(\".utforms-recipientsfield__email\").value\n      });\n    return rows;\n  }\n\n  _getValueEvent(evt) {\n    dompack.stop(evt);\n    evt.detail.deferred.resolve(this.getValue());\n  }\n\n  addRow(focus) {\n    const fieldbasename = `${this.name}[${this.nextnr++}].`;\n\n    const newrow = <div class=\"utforms-recipientsfield__row\">\n      <input name={fieldbasename + 'name'} class=\"utforms-recipientsfield__name\" type=\"text\" placeholder=\"Name\" required />\n      <input name={fieldbasename + 'email'} class=\"utforms-recipientsfield__email\" type=\"email\" placeholder=\"Email\" required />\n      <span class=\"utforms-recipientsfield__deleterow\" title=\"Delete\" onClick={deleteRow}><i class=\"UT-icon-UT_icon_55_cross-round-16px\" /></span>\n    </div>;\n\n    this.rowsholder.append(newrow);\n    if (focus)\n      newrow.querySelector('input').focus();\n  }\n}\n\ndompack.register(\".utforms-recipientsfield\", node => new RecipientsField(node));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport \"./skiplinks.css\";\n\n\n// distance we want to keep to the sticky navigationbar when scrolling to an element\nconst tonavbardistance = 30;\nlet temporaryfocusednode = null;\nlet temporaryscrolledtonode = null;\n\n\ndompack.onDomReady(init);\n\nwindow.addEventListener(\"focusout\", checkLeavingTemporaryFocusableElement);\n\n\nfunction checkLeavingTemporaryFocusableElement() {\n  if (temporaryfocusednode != null) {\n    // FIXME: check if it's the <header> or <main> in case we ever use an element which actually\n    //        is allowed to have focus and has a tabindex attribute ?\n\n    // We only want this element focusable through the skiplinks button,\n    // so remove it to prevent it being focused again through a mouse or touch interaction.\n    temporaryfocusednode.removeAttribute(\"tabindex\");\n\n    temporaryscrolledtonode.style.scrollMarginTop = \"\";\n    temporaryfocusednode = null;\n  }\n}\n\n\nfunction init() {\n  const button = document.querySelector(\".skiplinksbutton\");\n  if (button) // NOTE: for widget previews we don't render the skiplinks button\n    button.addEventListener(\"click\", doSkipLinks);\n}\n\nfunction doSkipLinks(evt) {\n  evt.preventDefault();\n\n  const main = document.querySelector(\"main\");\n  const header = document.querySelector(\".contentpart__header\");\n  let node_headermessagesarea = document.querySelector(\".contentpart__header-messagesarea\"); // (also contains .utwente-cookiebar)\n  const node_headercta = document.querySelector(\".headercta\");\n  const node_titlecontainerbg = document.querySelector(\".contentpart__title-background\"); // used on F&F\n  const node_titlecontainer = document.querySelector(\".contentpart__title-container\");\n\n  // Ignore the headermessagesarea if it's currently empty\n  // (it can also contain a managedcta which isn't shown, so instead of\n  // checking the nodes within we check the size of the visible content)\n  if (node_headermessagesarea && node_headermessagesarea.clientHeight == 0)\n    node_headermessagesarea = null;\n\n  /*\n  By focussing the header we ensure:\n  - a screenreader may start to read there (reading the CTA and title)\n  - tab navigation also be able to go through the header elements (such as CYA)\n\n  Suggestions for possible improvements:\n  - ADDME: research whether we would want to also skip header slideshow links\n  - ADDME: .contentpart__title uses the full height of the header meant for text,\n           so we cannot scroll to the visible title. So we don't scroll as far as we want.\n  */\n\n\n  // We need to scroll to the first relevant content.\n  // Hopefully at least enough to signal to the user that the skip action has been performanced (feedback).\n  const scrolltonode_inheader = node_headermessagesarea ?? node_headercta ?? node_titlecontainerbg ?? node_titlecontainer;\n  let focusnode = header;\n  let scrolltonode = null;\n\n  if (scrolltonode_inheader) // no textual content in this header? then focus the main\n  {\n    focusnode = header; // focus on the whole header\n    scrolltonode = scrolltonode_inheader; // but scroll to the specific part in the header where there's text (so it looks like something happens when clicking the button)\n  } else {\n    scrolltonode = main;\n    focusnode = main;\n  }\n\n  // the <header> and <main> by default don't have a tabindex.\n  // We want them to only receive focus from the skiplinks features,\n  // we don't want them to recieve focus by either keyboard or mouse interaction.\n  if (!focusnode.hasAttribute(\"tabindex\"))\n    focusnode.setAttribute(\"tabindex\", \"-1\"); // temporary grant ability to focus (on focusout event whe'll remove it)\n\n  console.log(\"Set focus to\", focusnode);\n  console.log(\"Scroll to\", scrolltonode);\n\n\n  try {\n    // prevent focus jumping directly (without smooth scroll) to the node (and then our scrollTo causing a bit upwards again)\n    focusnode.focus({ preventScroll: true });\n  } catch (err) {\n    focusnode.focus(); // Safari & iOS < 15.5 (may 2022)\n  }\n\n  temporaryfocusednode = focusnode;\n  temporaryscrolledtonode = scrolltonode;\n\n\n\n  // If the navigationbar is sticky compensate for the part of the viewport (at the top) which is blocked\n  const navcontainer = document.querySelector(\".contentpart__navbar-container\");\n  const navposition = getComputedStyle(navcontainer).getPropertyValue(\"--navbar-position\").trim();\n\n  let obscuredareaheight = 0;\n  if (navposition == \"sticky\")\n    obscuredareaheight = navcontainer.clientHeight;\n\n  //console.log(navcontainer, navposition, obscuredareaheight);\n\n  scrolltonode.style.scrollMarginTop = (obscuredareaheight + tonavbardistance) + \"px\";\n  scrolltonode.scrollIntoView({ behavior: \"smooth\" });\n}\n","/* UT auth library\n\n   This library is shared between utwente_base and serviceportal and implements the UT Global login\n\n   The menu/button in the WS2020 header is implemented in webdesigns/ws2016/src/shared/login/index.es\n\n   Classes\n   .ut-login--clicktologin   convert any element to a login button\n*/\n\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as wrdauth from \"@mod-wrd/js/auth\";\nimport { getLocal, getSession, setLocal, setSession } from '@webhare/dompack';\nimport { getLoginLink, getUTUserInfo } from \"@mod-utwente_design/js/crm/auth\";\nexport { getLoginLink, getUTUserInfo } from \"@mod-utwente_design/js/crm/auth\";\n\nexport function catchServicePortalLoginLink() {\n  /* Any click to x-serviceportal:login is handled by a Just In Time Link Replacement™. This solution should work as long as\n   noone messages with history.pushState & co.*/\n  window.addEventListener(\"click\", ev => {\n    const link = (ev.target as HTMLElement).closest(\"a[href]\") as HTMLAnchorElement;\n    if (!link)\n      return;\n\n    const linktarget = link.href.split('?')[0];\n    if (linktarget === 'x-serviceportal:login') {\n      const user = getUTUserInfo();\n      link.href = getLoginLink({ prompt: (user ? true : false) }); //if you hit a login link while logged in, you probably need to switch accounts\n    }\n  });\n}\n\nexport function utSilentLogin(why: string) {\n  setSession(\"utwente-triedsilentlogin\", why || \"explicit user request\"); //anti-loop flag\n  console.log(\"[ut-login] Attempting silent login because: \" + getSession(\"utwente-triedsilentlogin\"));\n  location.href = getLoginLink({ silent: true });\n}\n\nfunction getReasonforSilentLogin() {\n  const ls = getLocal<string>(\"utwente-lastseenlogin\");\n  if (ls)\n    return \"You were logged in at \" + new Date(parseInt(ls)).toLocaleString();\n\n  const beacons = crm.getUserBeacons();\n  if (beacons && beacons[\"usertype-employee\"])\n    return `You have beacon 'usertype-employee' with value '${beacons[\"usertype-employee\"]}`;\n  if (beacons && beacons[\"usertype-student\"])\n    return `You have beacon 'usertype-student' with value '${beacons[\"usertype-student\"]}`;\n\n  return null;\n}\n\nfunction isFrame() {\n  if (window.top === window)\n    return false; //we're toplevel\n  try {\n    //@ts-ignore only WH5.7 defines this __testframework. TODO @webhare/frontend will have isiNTestFramework once all in WH5.7+\n    if (window.parent.__testframework)\n      return false; //we're inside a testframe, pretend to be the parent\n  } catch (e) {\n\n  }\n  return true;\n}\n\n/** @returns true if we're redirecting awawy from the page */\nfunction handleAutoLogin(): boolean {\n  if (document.documentElement.dataset.noutlogin  //eg. webhare login page uses noutlogin to prevent the 'special account' from becoming unreachable for us\n    || isFrame()  //don't autologin in eg managed cta preview either\n    || location.origin === 'alumniportal.utwente.nl') //and although alumniportal lives under utwente.nl - it's not part of the same server and should'n't SSO\n    return false;\n\n  if (!wrdauth.getDefaultAuth()?.isLoggedIn() && !getSession(\"utwente-triedsilentlogin\")) {\n    const reason = getReasonforSilentLogin();\n    if (reason) {\n      utSilentLogin(reason);\n      return true;\n    }\n  }\n  if (getSession(\"utwente-triedsilentlogin\") && getSession(\"utwente-triedsilentlogin\") !== \"done\") {\n    console.log(\"[ut-login] We tried a silent login earlier because: \" + getSession(\"utwente-triedsilentlogin\") + \". It looks like it \" + (wrdauth.getDefaultAuth()?.isLoggedIn() ? \"succeeded\" : \"failed\"));\n    setSession(\"utwente-triedsilentlogin\", \"done\"); //don't retry this session\n  }\n  return false;\n}\n\n/**\n * Handle the UT Global Login process.\n * This function checks if the user is already logged in and handles auto-login if necessary.\n * @returns true if we're redirecting away from the page\n */\nexport function handleUTGLobalLogin(): boolean {\n  //WARNING dom may not yet be ready when we run here\n  const auth = wrdauth.getDefaultAuth();\n  if (!auth)\n    return false;\n\n  if (handleAutoLogin())\n    return true;\n\n  if (wrdauth.getDefaultAuth()?.isLoggedIn())\n    setLocal(\"utwente-lastseenlogin\", Date.now().toString());\n\n  return false;\n}\n","/*\nwebdesigns/ws2016/src/site (this file) is the entrypoint for\n- the \"WS2016\" (UT / Webdesign2020)\n\n- Stuff here is NOT shared with the \"apdesign\" (UT AlumniPortal) webdesign.\n*/\nimport \"@mod-publisher/js/analytics/gtm\"; //load as early as possible\n\nimport \"@mod-utwente_base/src/nextpager/nextpager\"; //experimental page prediction library\nimport * as wrdauth from \"@mod-wrd/js/auth\";\n\nimport \"@mod-utwente_design/scss/config-colors.css\";\n\nimport \"./ws2016\";\nimport \"./pages\";\nimport \"./shared/summary.scss\"; // lists with lines (such as contentlistings, news summaries)\nimport \"./shared/summary-overrides.scss\";\n\nimport \"./cobrowserchat\";\nimport \"./components/osiris\";\nimport \"./notificationbar\";\nimport './shared/edge-fullscreen'; //workarounds for Power BI on edge\nimport \"./shared/addthisevent\";\nimport { defineLoginMenu } from \"./shared/login/index\";\nimport \"./forms/recipientsfield\";\nimport \"./forms/slimselect.scss\";\n\nimport \"./components/skiplinks\";\n\nimport { getLoginLink } from \"@mod-utwente_design/js/crm/auth\";\nimport { handleUTGLobalLogin, utSilentLogin, catchServicePortalLoginLink } from \"@mod-utwente_base/js/frontendauth\";\nimport { getLocal } from \"@webhare/dompack\";\nimport { dtapStage } from \"@webhare/env\";\nimport { setupAuthorMode } from \"@webhare/frontend\";\nimport { requestGeoIP } from \"./shared/crm\";\n\n/** Are we the TOP level homepage? ie the toplevel equivalent of 'www.utwente.nl' eg 'www.utwente.nl/en/'\n * @param lang - If set, only return true if the page is in the specified language\n*/\nfunction isTopLevelHomepage(lang?: \"nl\" | \"en\") {\n  if (!document.documentElement.classList.contains(\"page--toplevelhome\"))\n    return false;\n  return !lang || document.documentElement.lang.startsWith(lang);\n}\n\nfunction getUTMenuItems() {\n  const userinfo = wrdauth.getDefaultAuth()?.getUserInfo();\n  if (!userinfo)\n    return [];\n\n  /* As showing .ut-login__topmenu is limited in the pageconfig to this->targetsite->webroot LIKE this->toplevelsite->webroot || \"*\"\n     we can assume paths pointing to / go to the corporate NL site\n  */\n\n  const dutch = document.documentElement.lang.startsWith('nl');\n  const menu = [];\n  if (!userinfo.isstudent)\n    menu.push({ link: \"/serviceportal\", title: \"Service Portal\" });\n  if (userinfo.isemployee)\n    menu.push({ link: \"https://people.utwente.nl/editprofile\", title: dutch ? \"Profiel bewerken\" : \"Edit profile\" });\n\n  if (userinfo.studies)\n    for (let study of userinfo.studies.split(',')) {\n      study = study.trim();\n      menu.push({ link: \"/.utwente_base/auth/gotostudy.shtml?study=\" + encodeURIComponent(study), title: `${study} website` });\n    }\n\n  if (userinfo.isstudent)\n    menu.push({ link: \"/students\", title: 'Student Services' });\n\n  menu.push({ link: \"/mycourses\", title: userinfo.isemployee ? dutch ? \"Mijn cursussen\" : \"My courses\" : dutch ? \"Mijn (taal)cursussen\" : \"My (language) courses\" });\n\n  menu.push({ link: dutch ? \"/mijn-eventregistraties/\" : \"/en/my-event-registrations/\", title: dutch ? \"Mijn eventregistraties\" : \"My event registrations\" });\n  return menu;\n}\n\ndefineLoginMenu({\n  loginText: \"UT Login\",\n  loginLink: getLoginLink(),\n  onGetMenuItems: getUTMenuItems\n});\n\nif (dtapStage === 'development')\n  setupAuthorMode({ allowFeedback: false, orientation: \"left\" });\n\nif (!handleUTGLobalLogin()) {\n  //not redirecting. check if its a hit for utwente.nl/, NL was not explicitly selected and this is a not a NL/BE user - then we direct to utwente.nl/en/\n  if (getLocal<string>(\"utwente-lastselectedlanguage\") !== 'nl' && isTopLevelHomepage('nl')) {\n    requestGeoIP().then(country => {\n      if (country !== \"NL\" && country !== \"BE\")\n        location.href = location.pathname + \"en/\";\n    }).catch(() => { });\n  }\n}\n\ncatchServicePortalLoginLink();// Catch 'x-serviceportal:login'\n\n//UT Debug API\nObject.assign(window, {\n  utSilentLogin\n});\n","import { register } from \"@webhare/dompack\";\nimport { loadAssetPack } from \"@webhare/frontend\";\n\n/*\n  We replace the original:\n    <addtoassetpack assetpack=\"utwente_base:ws2016\" entrypoint=\"webfeatures/aiexperts/aiexperts.es\" />\n    <addtoassetpack assetpack=\"utwente_base:ws2016\" entrypoint=\"webfeatures/transport/transportexperts.es\" />\n    <addtoassetpack assetpack=\"utwente_base:ws2016\" entrypoint=\"webfeatures/robotics/roboticsexperts.es\" />\n    <addtoassetpack assetpack=\"utwente_base:ws2016\" entrypoint=\"webfeatures/climate/climateexperts.tsx\" />\n    <addtoassetpack assetpack=\"utwente_base:ws2016\" entrypoint=\"webfeatures/chip/chipexperts.tsx\" />\n\n  and load the datacloud bundle async so we can avoid the JS code until the datacloud is actually accessed\n\n  We're split up in two parts:\n  - datacloud-loader - this gets included in the ws2016 bundle and needs to be as compact as possible\n  - datacloud-async - this part is loaded asynchronously and contains all the three Expertfinders, plus the datacloud\n\n  we can't do 'await import(\"./aiexperts/aiexperts\")' etc here, as then we'd get three chunks for all the async imports, and a shared datacloud import=\n*/\n\nlet assetPackPromise: ReturnType<typeof loadAssetPack> | null = null;\n\nregister(\".datacloud-header\", node => {\n  if (!assetPackPromise)\n    assetPackPromise = loadAssetPack(\"datacloud:datacloud\");\n});\n","/* eslint-disable */\n/// @ts-nocheck -- Rrenamed to enable TypeScript validation\n\nimport './coursefinder.scss';\nimport * as dompack from 'dompack';\nimport * as domevents from \"dompack/src/events\";\nimport * as dialogapi from 'dompack/api/dialog';\nimport FilteredOverview from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview\";\nimport { RPCFormBase, registerHandler } from \"@mod-publisher/js/forms\";\n//@ts-expect-error not typed yet\nimport { cCalendar } from \"./components/calendar\";\n//@ts-expect-error not typed yet\nimport { cCourseDetailsList } from \"./components/detail\";\nimport \"./coursefinder.lang.json\";\nimport getTid from \"@mod-tollium/js/gettid\";\nimport \"./pages\";\nimport * as wrdauth from '@mod-wrd/js/auth';\n\nimport consiliosearch from \"@mod-consilio/js/internal/search.rpc.json\";\nimport UTAutoComplete from '@mod-utwente_base/webdesigns/ws2016/src/components/autocompleter2/autocompleter';\n\nlet __autocompleteclose = false;\n\nclass FilterCourses extends FilteredOverview {\n  language: string;\n  hashparts: string[] = [];\n\n  constructor(public pagenode: HTMLElement) {\n    super({ filterpagetype: 'courses' });\n\n    if (document.location.hash)\n      this.hashparts = document.location.hash.split(\".\");\n\n    this.language = document.documentElement.lang.split(\"-\")[0];\n\n    this.initCoursesView();\n\n    const calendarwrapper = this.pagenode.querySelector(\".coursefinder__calendar\");\n    if (calendarwrapper) {\n      let initialdate = new Date();//Today\n      if (this.hashparts.length > 2) {\n        const year = Number(this.hashparts[1]);\n        const month = Number(this.hashparts[2]);\n        const curym = (initialdate.getFullYear() * 12) + initialdate.getMonth();\n\n        if (month > 0 && month <= 12 && (year * 12) + (month - 1) >= curym)//should be mininal current month\n          initialdate = new Date(year, month - 1, 1, 0, 0, 0);\n      }\n\n      this.calendar = new cCalendar(calendarwrapper, { \"date\": initialdate });\n    }\n\n    const detaillistwrapper = this.pagenode.querySelector(\".coursefinder__detaillist\");\n    if (detaillistwrapper)\n      new cCourseDetailsList(detaillistwrapper); //Controls animations/effects in detail/list\n\n    this.itemlist = [];\n    for (const itemnode of this.pagenode.querySelectorAll(\".coursefinder__detaillist > ul > li\")) {\n      this.itemlist.push({\n        domain: itemnode, //for dataset.domain\n        courses: itemnode.querySelectorAll(\".coursefinder__detaillist__courses__line\") //for dataset.credits/for\n      });\n    }\n\n    this.feedbacknode = this.pagenode.querySelector(\".coursefinder__filterresults\");\n    this.activetagsnode = this.pagenode.querySelector(\".coursefinder__activetags\");\n\n    this.initAutoSuggest();\n\n    if (this.filters && this.filters.words)\n      this.doFilterForced();//trigger filters including rpc for freesearch\n    else\n      this.showResults();//initial filtering based on url params\n\n    this.pagenode.classList.add(\"coursefinder__page--loaded\");//fadein content\n    dompack.qSA(\"a.coursefinder__detaillist__courses__line\").forEach(\n      link => link.addEventListener(\"click\",\n        () => window.dataLayer.push({\n          coursefinder_course_title: link.title,\n          coursefinder_organization_tag: link.dataset.organizationTag,\n          coursefinder_organization_title: link.dataset.organizationTitle,\n          event: \"coursefinder.courseclick\"\n        }), true) //capture so we get this click first!\n    ); //ends foreach\n  }\n\n  initAutoSuggest() {\n    // A slightly modified version of initSearchSuggestions to highlight matches within suggestions, not just the first x characters\n    const searchnode = this.form.querySelector(\"input[name='words']\");\n\n    /*\n          if (this.suggestionrpc)\n            consiliosearch.rpcResolve(this.suggestionrpc, null);\n\n          this.suggestionrpc = consiliosearch.suggest(\n            {\n              type: \"catalog\",\n              catalog: this.options.catalog\n            },\n            this.words,\n            {\n              doccount: \"\",\n              count: 10\n            });\n\n          const results = await this.suggestionrpc;\n          if (results)\n            this.updateSuggestions(results.values);\n\n\n    */\n\n    if (searchnode) {\n      const catalogtag = \"utwente_courses:coursefinder_\" + (this.language == \"nl\" ? \"nl\" : \"en\");//just nl or en\n\n      UTAutoComplete({\n        input: searchnode,\n        className: 'ut-autocomplete',\n        preventSubmit: 1,\n        fetch: async (text, update) => {\n          const consiliosource = await consiliosearch.suggest({ type: \"catalog\", catalog: catalogtag }, text, { doccount: \"\", count: 10 });\n          const suggestions = consiliosource.values ? this.suggestCourses(consiliosource.values, text) : [];\n          update(suggestions.map(_ => { return { label: _, value: _ }; }));\n        },\n        onSelect: (item) => {\n          searchnode.value = item.value;\n          this.doFilter();\n        }\n      });\n    }\n  }\n\n  suggestCourses(consiliosource, request) {\n    // Create a regex containing the words in the request term if there are at least 3 characters to search for\n    let title_regex;\n    const term_words = request.match(/\\w+/g);\n    if (term_words.length)\n      title_regex = RegExp(`${term_words.join(\"|\")}`, \"i\"); // no 'g' flag, or the regex lastIndex must be reset before each new title!\n\n    let suggestions = consiliosource.map(_ => _.value);\n\n    // First, get the Consilio suggestions\n    // Find titles matching the title regex\n    const title_matches = [];\n    const dupchecklist = []; //Uppercase list for checking duplicates\n    if (title_regex) {\n      for (const item of this.itemlist) {\n        const uc_domain = item.domain.title.toUpperCase();\n        if (title_regex.test(item.domain.title) && dupchecklist.indexOf(uc_domain) == -1) {\n          title_matches.push(item.domain.title);\n          dupchecklist.push(uc_domain);\n        }\n        for (const course of item.courses) {\n          const uc_course = course.title.toUpperCase();\n          if (title_regex.test(course.title) && dupchecklist.indexOf(uc_course) == -1) {\n            title_matches.push(course.title);\n            dupchecklist.push(uc_course);\n          }\n        }\n      }\n    }\n\n    // Return the title matches, followed by the Consilio suggestions that are not title matches, limit at 10 suggestions\n    return title_matches.concat(suggestions.filter(match => title_matches.indexOf(match) < 0)).slice(0, 10);\n  }\n\n  initCoursesView() {\n    for (const item of this.pagenode.querySelectorAll(\".coursefinder__views li\")) {\n      if (this.hashparts.length) {\n        if (this.hashparts[0] == \"#list\")\n          this.setView(\"list\");\n        else if (this.hashparts[0] == \"#calendar\")\n          this.setView(\"calendar\");\n      }\n\n      item.addEventListener(\"click\", ev => {\n        this.setView(item.className);\n      });\n    }\n  }\n\n  setView(name) {\n    const newclass = \"coursefinder__page--\" + name;\n    document.location.hash = \"#\" + name;\n\n    if (this.pagenode.classList.contains(newclass))\n      return;//already active\n\n    if (this.calendar && name == \"calendar\")\n      this.calendar.setMonthName();//update hash with year.month\n\n    this.pagenode.classList.remove(\"coursefinder__page--detail\");\n    this.pagenode.classList.remove(\"coursefinder__page--list\");\n    this.pagenode.classList.remove(\"coursefinder__page--calendar\");\n\n    this.pagenode.classList.add(newclass);\n\n    dompack.dispatchCustomEvent(window, \"wh:refresh\", { bubbles: false, cancelable: true });\n  }\n\n  showResults() {\n    const coursematchids = [];//list to prevent double count if course is in multiple domains and for filtering calendar\n\n    const freesearchactive = this.rpccache && this.rpccache.words != \"\";\n\n    let domaincount = 0;\n    for (let i = 0; i < this.itemlist.length; ++i) {\n      let domainmatch = true;\n      if (this.filters.domain) {\n        domainmatch = this.filters.domain.indexOf(this.itemlist[i].domain.dataset.domain) > -1;\n        this.itemlist[i].domain.hidden = !domainmatch;\n      }\n\n      let coursematchcount = this.itemlist[i].courses.length;\n      for (let c = 0; c < this.itemlist[i].courses.length; ++c) {\n        const course = this.itemlist[i].courses[c];\n        const courseid = Number(course.dataset.id);\n        let ismatch = domainmatch;\n\n        if (freesearchactive && ismatch)\n          ismatch = this.rpccache.ids.indexOf(courseid) > -1;\n\n        if (this.filters.credits && ismatch) {\n          ismatch = false;\n          for (let f = 0; f < this.filters.credits.length; ++f) {\n            const lohi = this.filters.credits[f].split(\"-\");\n            if (lohi.length == 2) {\n              const lo = 100 * lohi[0];\n              let hi = lohi[1] ? 100 * lohi[1] : 9999;\n              if (hi < lo)\n                hi = lo;\n\n              const credits100 = Number(course.dataset.credits100);\n              ismatch = credits100 >= lo && credits100 <= hi;\n            }\n\n            if (ismatch)\n              break;\n          }\n        }\n\n        if (this.filters[\"lang\"] && ismatch) {\n          ismatch = false;\n          if (course.dataset[\"lang\"])//lamguage each course\n            ismatch = course.dataset[\"lang\"].split(\",\").filter(x => this.filters[\"lang\"].includes(x)).length > 0;\n        }\n\n        if (this.filters[\"for\"] && ismatch) {\n          ismatch = false;\n          if (course.dataset[\"for\"])//multiple targets each course\n            ismatch = course.dataset[\"for\"].split(\",\").filter(x => this.filters[\"for\"].includes(x)).length > 0;\n        }\n\n        if (this.filters[\"available\"] && ismatch) {\n          ismatch = false;\n          if (course.dataset[\"available\"])\n            ismatch = course.dataset[\"available\"] == this.filters[\"available\"];\n        }\n\n        if (this.filters[\"locationtype\"] && ismatch) {\n          ismatch = false;\n          if (course.dataset[\"locationtype\"])\n            ismatch = this.filters[\"locationtype\"].indexOf(course.dataset[\"locationtype\"]) > -1;\n        }\n\n        if (!ismatch)\n          --coursematchcount;\n\n        if (ismatch && coursematchids.indexOf(courseid) == -1)\n          coursematchids.push(courseid);\n\n        course.hidden = !ismatch;\n      }\n\n      //Update counters inside domains node\n      for (const countnode of this.itemlist[i].domain.querySelectorAll(\"span[data-coursecount]\")) {\n        if (countnode.dataset.coursecount == \"totalcoursecount\")\n          countnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.xcourses', coursematchcount);\n        else if (countnode.dataset.coursecount == \"utcoursecount\") {\n          const utwrapper = countnode.closest(\".coursefinder__detaillist__utcourses\");\n          const utcount = dompack.qSA(utwrapper, \".coursefinder__detaillist__courses__line:not([hidden])\").length;\n          countnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.xcourses', utcount);\n\n          utwrapper.hidden = utcount == 0; // hide wrapper if 0 results\n        } else if (countnode.dataset.coursecount.startsWith(\"externalcoursecount\")) {\n          const sourcewrapper = countnode.closest(\".coursefinder__detaillist__source\");\n          const sourcecount = dompack.qSA(sourcewrapper, \".coursefinder__detaillist__courses__line:not([hidden])\").length;\n          countnode.textContent = sourcecount;\n\n          sourcewrapper.hidden = sourcecount == 0; // hide wrapper if 0 results\n        }\n      }\n\n      //Hide/show domain\n      if (coursematchcount > 0 && domainmatch) {\n        ++domaincount;\n        this.itemlist[i].domain.hidden = false;\n\n        //Unfold courses within domain if filters is set\n        if (this.filtersIsSet())\n          this.toggleDomainCoursesView(this.itemlist[i].domain, true);\n      } else {\n        this.itemlist[i].domain.hidden = true;\n        this.toggleDomainCoursesView(this.itemlist[i].domain, false);\n      }\n    }\n\n    this.calendar.filterCourses(coursematchids);\n\n    this.showActiveTags();\n\n    this.feedbacknode.replaceChildren();\n\n    this.pagenode.classList.toggle(\"coursefinder__page--noresults\", coursematchids.length == 0);\n\n    const coursestxt = getTid('utwente_courses:webfeatures.frontend.js.results', coursematchids.length);\n    const domainstxt = getTid('utwente_courses:webfeatures.frontend.js.inxdomains', domaincount);\n\n    this.feedbacknode.appendChild(<span class=\"count\">\n      <span class=\"count__courses\" aria-live=\"polite\">{coursestxt}</span>\n      <span class=\"count__domains\">{domainstxt}</span>\n    </span>);//\n\n    dompack.dispatchCustomEvent(window, \"wh:refresh\", { bubbles: false, cancelable: true });\n  }\n\n  toggleDomainCoursesView(domainnode, show) {\n    const foldnode = domainnode.querySelector(\".coursefinder__detaillist__courses\");\n    if (foldnode)\n      foldnode.classList.toggle(\"showfullcontent\", show);\n  }\n\n  filtersIsSet(obj) {\n    for (const key in this.filters)\n      if (this.filters.hasOwnProperty(key))\n        return true;\n    return false;\n  }\n\n  showActiveTags() {\n    this.activetagsnode.replaceChildren();\n\n    for (const inpnode of this.form.querySelectorAll(\"input[type='checkbox']:checked,input[type='search']\")) {\n      if (inpnode.type == \"search\") {\n        if (inpnode.value != \"\") {\n          const tagnode = <span class=\"tag\">{inpnode.value}<span class=\"UT-icon-UT_icon_67_cross-small-16px\"></span></span>;//\n          this.activetagsnode.appendChild(tagnode);\n          tagnode.addEventListener(\"click\", ev => {\n            this.activetagsnode.removeChild(tagnode);\n            inpnode.value = \"\";\n            domevents.fireHTMLEvent(inpnode, 'change');\n          });\n        }\n      } else if (inpnode.type == \"checkbox\") {\n        const labelnode = inpnode.parentNode.querySelector(\".wh-form__optionlabel\");\n        if (labelnode) {\n          const tagnode = <span class=\"tag\">{labelnode.textContent}<span class=\"UT-icon-UT_icon_67_cross-small-16px\"></span></span>;//\n          this.activetagsnode.appendChild(tagnode);\n          tagnode.addEventListener(\"click\", ev => {\n            this.activetagsnode.removeChild(tagnode);\n            inpnode.checked = false;\n            domevents.fireHTMLEvent(inpnode, 'change');\n          });\n        }\n      }\n    }\n\n    if (this.activetagsnode.children.length > 0)\n      this.activetagsnode.insertBefore(<span class=\"title\">{getTid('utwente_courses:webfeatures.frontend.js.activefilters') + \":\"}</span>, this.activetagsnode.children[0]);//\n\n    this.activetagsnode.style.display = this.activetagsnode.children.length > 0 ? \"\" : \"none\";\n  }\n}\n\ndompack.register(\".embeddedobject--inlinecta a[href^='#coursealert'], .showcoursealert\", node => {\n  node.addEventListener(\"click\", ev => {\n    ev.preventDefault();\n    ev.target.blur();//remove focus from clicked element\n\n    let alertoptions;\n\n    let courseid = \"\";\n    let coursetitle = \"\";\n    if (node.nodeName == \"A\") {\n      const parts = node.getAttribute(\"href\").split(\":\");\n      if (parts.length == 2) {\n        courseid = parts[1].replace(/[^0-9]+/g, '');\n        const container = node.closest(\".embeddedobject--inlinecta\");\n        if (container)\n          coursetitle = dompack.qS(container, \".formheader__title\").textContent;\n      }\n    } else { //probably in course overview page\n      const overviewline = ev.target.closest(\".coursefinder__detaillist__courses__line\");\n      if (overviewline) {\n        coursetitle = overviewline.title;\n        courseid = overviewline.dataset.id;\n      }\n    }\n\n    if (courseid) { // alert for single course\n      alertoptions = {\n        title: coursetitle,\n        id: courseid,\n        singlecourse: true\n      };\n    }\n\n    showCourseAlertForm(alertoptions);\n  });\n});\n\nasync function showCourseAlertForm(options) {\n  const formnode = dompack.qS(\".coursefinder__coursealertdialog__form\");\n  if (!formnode) {\n    console.error(\"Missing Course Alert form\");\n    return;\n  }\n\n  formnode.singlecourse.value = \"0\";\n\n  if (options && options.singlecourse) {\n    formnode.singlecourse.value = options.id;\n    domevents.fireHTMLEvent(formnode.singlecourse, 'change');\n  } else if (options && options.categories && options.categories.length) {\n    dompack.qSA(formnode, \"input[name='categories']\").forEach(inpnode => {\n      inpnode.checked = options.categories.indexOf(inpnode.value) > -1;\n    });\n  }\n\n  const dialog = dialogapi.createDialog({ borrow: formnode, allowcancel: true });\n\n  dialog.utheadernode.appendChild(<h2>{getTid('utwente_courses:webfeatures.frontend.js.coursealert')}</h2>);\n  if (options && options.title)\n    dialog.utheadernode.appendChild(<h3>{options.title}</h3>);\n\n  if (options && options.singlecourse)\n    dialog.utheadernode.appendChild(<p>{getTid('utwente_courses:webfeatures.frontend.js.coursealert-singlecoursedescription')}</p>);\n  else\n    dialog.utheadernode.appendChild(<p>{getTid('utwente_courses:webfeatures.frontend.js.coursealert-description')}</p>);\n\n  dialog.contentnode.classList.add(\"courses-dialog--coursealert\");\n  dialog.holdernode.classList.add(\"courses-dialog__holder--coursealert\");\n\n  await dialog.runModal();\n\n  dompack.dispatchCustomEvent(formnode, \"utwente_courses:closedialog\", { bubbles: false, cancelable: true });\n}\n\nasync function showCourseAlertSuccess(node, options) {\n  const dialog = dialogapi.createDialog({ borrow: node, allowcancel: true });\n\n  dialog.utheadernode.appendChild(<h2>{getTid('utwente_courses:webfeatures.frontend.js.coursealert')}</h2>);\n  if (options && options.title)\n    dialog.utheadernode.appendChild(<h3>{options.title}</h3>);\n\n  if (options && options.singlecourse)\n    dialog.utheadernode.appendChild(<p>{getTid('utwente_courses:webfeatures.frontend.js.coursealert-singlecoursedescription')}</p>);\n  else\n    dialog.utheadernode.appendChild(<p>{getTid('utwente_courses:webfeatures.frontend.js.coursealert-description')}</p>);\n\n  dialog.contentnode.classList.add(\"courses-dialog--coursealert\");\n  dialog.holdernode.classList.add(\"courses-dialog__holder--coursealert\");\n\n  await dialog.runModal();\n\n  node.remove();//just remove, just needed once when opening page\n}\n\ndompack.register(\".coursefinder__subscribedcoursealert[data-title]\", node => { //Shown sucess dialog after loggedin when user has registered for course alert\n  showCourseAlertSuccess(node, { title: node.dataset.title, singlecourse: (node.dataset.singlecourse && node.dataset.singlecourse != '0') });\n});\n\n\nclass CourseAlertForm extends RPCFormBase {\n  constructor(form) {\n    super(form);\n\n    if (wrdauth.getDefaultAuth().isLoggedIn())\n      this.userinfo = wrdauth.getDefaultAuth().getUserInfo();\n\n    this.node.addEventListener(\"utwente_courses:closedialog\", ev => {\n      if (ev.target == this.node)\n        this.reset();\n    });\n\n    if (this.getUrlParam(\"showcoursealert\")) //small delay so dialog init script has run before opening dialog\n      setTimeout(() => showCourseAlertForm(), 500);\n\n    const subscribeasoptoins = dompack.qSA(this.node, \"[name=subscribeas]\");\n    if (subscribeasoptoins.length) // (not loggedin)\n    {\n      subscribeasoptoins.forEach(node => node.addEventListener(\"change\", () => this.updateSubscribeAs()));\n      this.updateSubscribeAs();\n    }\n  }\n\n  reset() {\n    super.reset();\n    this.gotoPage(0);\n  }\n\n  onSubmitSuccess(param) {\n    super.onSubmitSuccess(param);\n\n    const dialog = this.node.closest(\".ut-dialog__holder\");\n    if (dialog) // Remove intro tekst from dialog header\n      dompack.qSA(dialog, \".ut-dialog__header p\").forEach(p => p.remove());\n\n    if (!window.dataLayer)\n      window.dataLayer = [];\n\n    const categories = [];\n    dompack.qSA(this.node, \"input[name='categories']:checked\").forEach(node => {\n      categories.push(node.parentNode.textContent);\n    });\n\n    let subscribeas = \"external\";\n    if (this.userinfo) {\n      if (this.userinfo.isemployee)\n        subscribeas = \"employee\";\n      else if (this.userinfo.isstudent)\n        subscribeas = \"student\";\n    }\n\n    window.dataLayer.push({\n      \"event\": \"coursealert-submitted\",\n      \"coursealert-categories\": categories.join(\";\"),\n      \"coursealert-subscribeas\": subscribeas\n    });\n  }\n\n  updateSubscribeAs() {\n    const subscribeas = dompack.qS(this.node, \"input[name='subscribeas']:checked\");\n    const loginbtngroup = this.node.querySelector(\".wh-form__fieldgroup--loginbtn\");\n\n    if (subscribeas && subscribeas.value == \"utlogin\") {\n      loginbtngroup.classList.remove(\"wh-form__fieldgroup--hidden\");\n      this.node.classList.remove(\"wh-form--allowsubmit\");\n    } else {\n      loginbtngroup.classList.add(\"wh-form__fieldgroup--hidden\");\n      this.node.classList.add(\"wh-form--allowsubmit\");\n    }\n  }\n\n  getUrlParam(name) {\n    const val = new URL(location.href).searchParams.get(name);\n    return val ? decodeURIComponent(val) : \"\";\n  }\n}\n\n\ndompack.register(\".coursefinder__page\", node => new FilterCourses(node));\n\nregisterHandler(\"utwente_courses:coursealert\", form => new CourseAlertForm(form));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./calendar.scss\";\nimport * as whintegration from \"@mod-system/js/wh/integration\";\nimport * as dompack from 'dompack';\nimport getTid from \"@mod-tollium/js/gettid\";\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\nimport * as dialogapi from 'dompack/api/dialog';\n\nexport class cCalendar {\n  constructor(container, options) {\n    this.node = container;\n\n    this.pagenode = container.closest(\".coursefinder__page\");\n\n    this.rpc = new JSONRPC();\n\n    this.titlenode = <div class=\"monthname\"></div>;//\n\n    this.filterids = [];\n    this.language = whintegration.config.locale.split(\"-\")[0];\n\n    this.navnode = <div class=\"coursefinder__calendar__nav\">\n      {this.titlenode}\n      <div class=\"previousmonth UT-icon-UT_icon_43_arrow-left-16px\"></div>\n      <div class=\"nextmonth UT-icon-UT_icon_44_arrow-right-16px\"></div>\n    </div>;//\n    this.node.appendChild(this.navnode);\n\n    let timetable = JSON.parse(this.node.dataset.timetable);\n    if (!timetable) timetable = [];\n\n    //Before we start building calendar first check viewmode\n    this.mobileview = this.checkViewMode(true);\n\n    let firstdate = null;\n    let lastdate = null;\n    if (timetable.length) {\n      firstdate = new Date(timetable[0].timestamp * 1000);\n      lastdate = new Date(timetable[timetable.length - 1].timestamp * 1000);\n    }\n\n    this.calendardata = [];\n\n    let daycontent = null;\n    let prevdate = -1;\n    for (let i = 0; i < timetable.length; ++i) {\n      const dt = new Date(timetable[i].timestamp * 1000);\n      const time = this.getFormattedTime(dt);\n\n      const timestamp = getRoundedDayTimestamp(dt);\n      if (prevdate != timestamp) {\n        if (daycontent && daycontent.node.children.length > 5)\n          daycontent.node.insertBefore(<li class=\"course course--more\">{(daycontent.node.children.length - 4) + ' more'}</li>, daycontent.node.children[4]);//\n\n        daycontent = { \"node\": <ul class=\"coursefinder__calendar__courses\" />, \"timestamp\": timestamp };\n        this.calendardata.push(daycontent);\n\n        prevdate = timestamp;\n      }\n      if (daycontent)\n        daycontent.node.appendChild(<li title={timetable[i].title} data-tag={timetable[i].tag} data-courseid={timetable[i].courseid} class={'course course--' + timetable[i].type} data-id={timetable[i].id}><span class=\"name\">{timetable[i].title}</span></li>);//\n      //daycontent.node.appendChild(<li title={timetable[i].title} data-courseid={timetable[i].courseid} class={'course course--' + timetable[i].type } data-id={timetable[i].id}><span class=\"time\">{time}</span><span class=\"name\">{timetable[i].title}</span></li>);//\n    }\n    if (daycontent) {\n      if (daycontent.node.children.length > 5)\n        daycontent.node.insertBefore(<li class=\"course course--more\">{getTid('utwente_courses:webfeatures.frontend.js.xmore', daycontent.node.children.length - 4)}</li>, daycontent.node.children[4]);//\n\n      this.calendardata.push(daycontent);\n    }\n\n    const maxdate = lastdate ? { month: lastdate.getMonth(), year: lastdate.getFullYear() } : { month: new Date().getMonth(), year: new Date().getFullYear() };\n    this.maxmonths = (maxdate.year * 12) + maxdate.month; //month starts with 0\n\n    this.tablenode = <div class=\"coursefinder__calendar__tablewrapper\" />;\n    this.node.appendChild(this.tablenode);\n\n    if (options.date) { //Check if initial date is within today/max date\n      const today = new Date();\n      const todaymonths = (today.getFullYear() * 12) + today.getMonth();\n      const setmonths = (options.date.getFullYear() * 12) + options.date.getMonth();\n\n      if (setmonths < todaymonths)\n        options.date = today;\n      else if (setmonths > this.maxmonths)\n        options.date = new Date(maxdate.year, maxdate.month, 1, 0, 0, 0);\n    }\n\n    this.monthtable = new cMonthTable(this.tablenode, {\n      hideweekdays: [0, 6], //hide sunday and saturday\n      agendaitems: this.calendardata,\n      date: options.date\n    });\n\n    if (!this.mobileview)\n      this.monthtable.loadTable();\n    else\n      this.loadMobileCalendar();\n\n    this.setMonthName();\n    this.reachedNavLimit(0);\n\n    //Some keyboard handling\n    window.addEventListener(\"keydown\", ev => {\n      if (this.mobileview)\n        return;\n\n      if (ev.keyCode == 27)\n        this.hideMore();\n      else if (ev.keyCode == 37)\n        this.previousMonth();\n      else if (ev.keyCode == 39)\n        this.nextMonth();\n    });\n\n    //handle mouseclick inside calendar day\n    this.tablenode.addEventListener(\"wh:dateclick\", ev => {\n      const coursenode = ev.detail.target.closest(\".course\");\n      if (!coursenode)\n        return;\n\n      if (ev.detail.target.classList.contains(\"course--close\")) {\n        this.hideMore();\n        return;\n      }\n\n      if (coursenode.classList.contains(\"course--more\"))\n        this.showMore(ev, coursenode.closest(\".day-container\"));\n      else if (coursenode.dataset.id)\n        this.showSerieOptions(1 * coursenode.dataset.id, coursenode.title);\n    });\n\n    this.navnode.addEventListener(\"click\", ev => {\n      if (ev.target.classList.contains(\"previousmonth\"))\n        this.previousMonth();\n      else if (ev.target.classList.contains(\"nextmonth\"))\n        this.nextMonth();\n    });\n\n    window.addEventListener(\"resize\", ev => this.checkViewMode(false));\n  }\n\n  checkViewMode(initial) {\n    const viewwidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;\n    const ismobileview = viewwidth < 768;\n    const prevview = this.mobileview;\n\n    this.mobileview = ismobileview;\n\n    this.pagenode.classList.toggle(\"coursefinder__page--mobile\", this.mobileview);\n\n    if (ismobileview != prevview && !initial)\n      this.switchView();\n\n    return this.mobileview;\n  }\n\n  switchView() {\n    if (this.mobileview) {\n      //remove calendar table from dom\n      this.tablenode.replaceChildren();\n\n      //Add listcalendar\n      this.loadMobileCalendar();\n    } else {\n      //remove listcalendar\n      if (this.listcalendarnode)\n        this.listcalendarnode.remove();\n      this.listcalendarnode = null;\n\n      //reload calendar table\n      this.tablenode.appendChild(this.monthtable.generateTable(this.monthtable.year, this.monthtable.month));\n      this.setMonthName();//update titke above calendar table\n      if (this.courseids)\n        this.filterCourses(this.courseids);\n    }\n  }\n\n  loadMobileCalendar() {\n    this.listcalendarnode = <div class=\"coursefinder__listcalendar\" />;\n    this.node.appendChild(this.listcalendarnode);\n    this.listcalendarnode.addEventListener(\"click\", ev => {\n      const coursenode = ev.target.closest(\"li.course\");\n      if (coursenode) {\n        document.location.href = \"./\" + coursenode.dataset.courseid + \"/\" + coursenode.dataset.tag + \"/?serie=\" + coursenode.dataset.id + \"#signup\";\n        return;\n      }\n      const titlenode = ev.target.closest(\".month__title\");\n      if (titlenode)\n        this.toggleListMonth(titlenode.parentNode);\n    });\n\n    const translations = getCalendarTranslations(this.language);\n\n    const todaytimestamp = getRoundedDayTimestamp(new Date());\n\n    const activeym = this.monthtable.year + 12 * this.monthtable.month;\n\n    let prevym = -1;\n    let monthnode = null;\n    for (let i = 0; i < this.calendardata.length; ++i) {\n      if (todaytimestamp > this.calendardata[i].timestamp)\n        continue;\n\n      //node, timestamp\n      const date = new Date(this.calendardata[i].timestamp);\n      const month = date.getMonth();\n      const year = date.getFullYear();\n      const day = date.getDate();\n      const weekday = date.getDay();\n\n      const ym = year + month * 12;\n      if (ym != prevym || !monthnode) {\n        monthnode = <div class={\"month\" + (activeym == ym ? \" active\" : \"\")} data-year={year} data-month={month}>\n          <div class=\"month__title\">\n            {translations.months[month] + \" \" + year}\n            <span class=\"month__toggle\">\n              <span class=\"more UT-icon-UT_icon_46_arrow-down-16px\"></span>\n              <span class=\"less UT-icon-UT_icon_45_arrow-up-16px\"></span>\n            </span>\n          </div>\n        </div>;//\n        this.listcalendarnode.appendChild(monthnode);\n      }\n\n      const monthdaynode = <div class=\"month__day\">\n        <div class={\"month__day__title\" + (todaytimestamp == this.calendardata[i].timestamp ? \" today\" : \"\")}>\n          {translations.days_short[weekday] + \" \" + day + \" \" + translations.months[month]}\n        </div>\n      </div>;//\n      monthdaynode.appendChild(this.calendardata[i].node);\n      monthnode.appendChild(monthdaynode);\n\n      prevym = ym;\n    }\n\n    this.filterCourses(this.courseids);\n  }\n\n  toggleListMonth(monthnode) {\n    if (monthnode.classList.contains(\"active\")) { //hide\n      monthnode.style.maxHeight = monthnode.clientHeight + \"px\";\n      monthnode.classList.remove(\"active\");\n      monthnode.clientHeight;//force css update\n      monthnode.style.maxHeight = \"\";\n    } else { //show\n\n      const year = 1 * monthnode.dataset.year;\n      const month = 1 * monthnode.dataset.month;\n      if (month > -1 && month < 12 && year > 0) { //set last selected year/month as initial values for calendar table\n        this.monthtable.year = year;\n        this.monthtable.month = month;\n      }\n\n      let h = 0;\n      for (let i = 0; i < monthnode.children.length; ++i)\n        h += monthnode.children[i].clientHeight;\n      monthnode.style.maxHeight = h + \"px\";\n      monthnode.classList.add(\"active\");\n      setTimeout(function () {\n        monthnode.style.maxHeight = \"\";\n      }, 300);\n    }\n  }\n\n  filterCourses(courseids) { //show only courses with given courseids\n    if (!courseids)\n      courseids = [];\n\n    this.courseids = courseids;\n\n    const filtereditems = [];\n    let monthnode = null;\n    let monthcount = 0;\n    for (let i = 0; i < this.calendardata.length; ++i) {\n      let matchcount = 0;\n      for (let c = 0; c < this.calendardata[i].node.children.length; ++c) {\n        if (this.listcalendarnode && !this.calendardata[i].node.parentNode)\n          continue;//Items before today are not attached to dom if listcalendarnode\n\n        const coursenode = this.calendardata[i].node.children[c];\n        if (coursenode.dataset.courseid) {\n          const id = 1 * coursenode.dataset.courseid;\n          if (courseids.indexOf(id) > -1) {\n            coursenode.style.display = \"\";\n            ++matchcount;\n          } else\n            coursenode.style.display = \"none\";\n        } else\n          this.calendardata[i].node.removeChild(coursenode);//remove more node (will be added later if needed)\n      }\n\n      if (this.listcalendarnode) {\n        const daynode = this.calendardata[i].node.parentNode;\n        if (daynode) {\n          const curmonthnode = daynode.parentNode;\n          if (!monthnode || monthnode != curmonthnode || i >= this.calendardata.length - 1) {\n            if (monthcount == 0 && monthnode)\n              monthnode.style.display = \"none\";//Hide month of no matches within month\n            else if (monthnode)\n              monthnode.style.display = \"\";\n\n            monthcount = 0;\n            monthnode = curmonthnode;\n          }\n          monthcount += matchcount;\n\n          daynode.style.display = matchcount ? \"\" : \"none\";\n        }\n      } else {\n        if (matchcount > 5)\n          this.calendardata[i].node.insertBefore(<li class=\"course course--more\">{getTid('utwente_courses:webfeatures.frontend.js.xmore', matchcount - 4)}</li>, this.calendardata[i].node.children[4]);//\n\n        if (matchcount > 0)\n          filtereditems.push(this.calendardata[i]);\n      }\n    }\n\n    if (!this.listcalendarnode)\n      this.monthtable.refreshData(filtereditems);\n  }\n\n  createSpinner() { //Spinner for loading indicator courses in dialog\n    const diameter = 50;\n    const strokewidth = 5;\n\n    const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n    svg.setAttributeNS(null, \"width\", diameter + \"px\");\n    svg.setAttributeNS(null, \"height\", diameter + \"px\");\n    svg.setAttributeNS(null, \"viewBox\", \"0 0 \" + diameter + \" \" + diameter);\n\n    const symbol = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n    symbol.setAttributeNS(null, \"cx\", ~~(diameter / 2));\n    symbol.setAttributeNS(null, \"cy\", ~~(diameter / 2));\n    symbol.setAttributeNS(null, \"r\", ~~(diameter / 2 - strokewidth));\n    symbol.setAttributeNS(null, \"fill\", \"none\");\n    symbol.setAttributeNS(null, \"stroke\", \"#ccc\");\n    symbol.setAttributeNS(null, \"stroke-width\", strokewidth);\n    symbol.setAttributeNS(null, \"stroke-dasharray\", \"110,160\");\n    symbol.setAttributeNS(null, \"stroke-linecap\", \"round\");\n\n    svg.appendChild(symbol);\n\n    return svg;\n  }\n\n  async showSerieOptions(serieid, title) {\n    const dialog = dialogapi.createDialog();\n    dialog.holdernode.classList.add(\"coursefinder__dialog\");\n    dialog.contentnode.appendChild(<div class=\"coursefinder__dialog__loading\">\n      <h3 class=\"coursefinder__loadertitle\">{title}</h3>\n      <div class=\"coursefinder__loader\">{this.createSpinner()}</div>\n    </div>\n    ); //\n    dialog.runModal();\n\n    //Cancel previous rpc request if any\n    if (this.rpc.activerequest) {\n      for (let c = 0; c < this.rpc.requestqueue.length; ++c)\n        if (this.rpc.requestqueue[c].request.method == 'GetSerieOptions')\n          this.rpc.requestqueue[c].cancel();//cancel active rpc request\n    }\n\n    const result = await this.rpc.async(\"GetSerieOptions\", serieid);\n\n    dialog.contentnode.replaceChildren();\n\n    let dialogcontent;\n    if (result) {\n      //Note: only items where you can register are shown\n      dialogcontent = <div class=\"coursefinder__dialog__courseoptions\">\n        <div class=\"courseoptions__header\">\n          <div class=\"courseoptions__image\">\n            {result.image ? (\n              <img src={result.image.normal.link} srcset={result.image.normal.link + \" 1x,\" + result.image.retina.link + \" 2x\"} alt=\"\" />\n            )\n              : null\n            }\n          </div>\n          <div class=\"courseoptions__title\">\n            <h3>{result.title}</h3>\n            <div>{result.subtitle}</div>\n            <a href={result.link}>{getTid('utwente_courses:webfeatures.frontend.js.moreinfo')}</a>\n          </div>\n        </div>\n        {result.series.length ? (\n          <form class=\"courseoptions__form wh-styledinput\" action={result.link + \"#signup\"} method=\"get\">\n            <ul>\n              {result.series.map(item => <li class={(item.canregister ? (item.isfull ? \"waitinglist\" : \"open\") : \"isfull\") + (item.multiplesessions ? \" multiplesessions\" : \"\")}>\n                <input id={\"serie-\" + item.id} disabled={!item.canregister} checked={item.canregister && item.isselected} name=\"serie\" type=\"radio\" value={item.id} />\n                <label class=\"radiobtn\" for={\"serie-\" + item.id}></label>\n                <label class=\"wh-form__optionlabel\" for={\"serie-\" + item.id}>\n                  <div class=\"sessions\">\n                    {item.sessions.map(session =>\n                      <div class=\"session\">\n                        <span class=\"weekday\">{session.weekday}</span>\n                        <span class=\"date\">{session.date}</span>\n                        <span class=\"time\">{session.time}</span>\n                      </div>\n                    )}\n                  </div>\n                  <span class=\"note\">\n                    {item.canregister ? (item.isfull ? getTid('utwente_courses:webfeatures.frontend.js.waitinglist') + \"*\" : \"\") : getTid('utwente_courses:webfeatures.frontend.js.isfull')}\n                  </span>\n                  <span class=\"duration\">{getTid('utwente_courses:webfeatures.frontend.js.xdaycourse', item.sessioncount)}</span>\n                </label>\n              </li>\n              )}\n            </ul>\n            {result.showmore ? (<div class=\"courseoptions__more\">\n              <a href={result.link + '#signup'}>View more</a>\n            </div>\n            ) : null}\n            <button class=\"wh-form__button\" type=\"submit\">{getTid('utwente_courses:webfeatures.frontend.js.signup')}</button>\n\n          </form>\n        ) : (\n          <div class=\"courseoptions__nooptions\">{getTid('utwente_courses:webfeatures.frontend.js.nooptionsavailable')}</div>\n        )}\n\n        {result.waitinglistactive ? (\n          <div class=\"courseoptions__footer\">\n            *{getTid('utwente_courses:webfeatures.frontend.js.notewaitinglist')}\n          </div>\n        ) : null\n        }\n      </div>;//\n\n      for (const itemnode of dialogcontent.querySelectorAll(\"li\")) {\n        const togglenode = itemnode.querySelector(\".duration\");\n        const sessionswrapper = itemnode.querySelector(\".sessions\");\n        if (togglenode && sessionswrapper) {\n          togglenode.addEventListener(\"click\", ev => {\n            sessionswrapper.style.maxHeight = \"\";\n            sessionswrapper.classList.toggle(\"showall\");\n            if (sessionswrapper.classList.contains(\"showall\")) {\n              let h = 0;\n              for (let i = 0; i < sessionswrapper.children.length; ++i)\n                h += sessionswrapper.children[i].clientHeight;\n              sessionswrapper.style.maxHeight = h + \"px\";\n\n              setTimeout(function () {\n                sessionswrapper.style.maxHeight = \"none\";\n              }, 300);\n            }\n          });\n        }\n      }\n    } else {\n      dialogcontent = <div class=\"coursefinder__dialog__error\">Error: no course dates found.</div>;//\n    }\n\n    //Add close button\n    const closebtn = <div class=\"coursefinder__dialog__close UT-icon-UT_icon_47_cross-16px\" />;\n    closebtn.addEventListener(\"click\", ev => dialog.resolve());\n    dialog.contentnode.appendChild(closebtn);\n\n    dialog.contentnode.appendChild(dialogcontent);\n  }\n\n  getFormattedTime(dt) {\n    const h = dt.getHours();\n    const m = dt.getMinutes();\n    return (h < 10 ? \"0\" : \"\") + h + \":\" + (m < 10 ? \"0\" : \"\") + m;\n  }\n\n  previousMonth() {\n    if (this.reachedNavLimit(-1))\n      return;\n\n    this.monthtable.previousMonth();\n    this.setMonthName();\n  }\n\n  nextMonth() {\n    if (this.reachedNavLimit(1))\n      return;\n\n    this.monthtable.nextMonth();\n    this.setMonthName();\n  }\n\n  showMore(ev, node) {\n    const date = ev.detail.date;\n\n    if (this.popupnode)\n      this.hideMore();//Hide previous\n\n    this.popupnode = node.cloneNode(true);\n\n    //add dayofweek\n    this.popupnode.insertBefore(<span class=\"dayofweek\">{this.monthtable.translations.days_short[date.getDay()]}</span>, this.popupnode.children[0]);//\n\n    this.closefn = this.hideMore.bind(this);\n    document.body.addEventListener(\"click\", this.closefn);\n\n    //add close\n    const closebtn = <span class=\"course--close UT-icon-UT_icon_47_cross-16px\"></span>;//\n    closebtn.addEventListener(\"click\", ev => this.hideMore());\n    this.popupnode.appendChild(closebtn);\n\n    //remove more node\n    const morenode = this.popupnode.querySelector(\"course--more\");\n    if (morenode)\n      morenode.parentNode.removeChild(morenode);\n\n    this.popupnode.className = \"coursefinder__calendar__daypopup\";\n    node.parentNode.appendChild(this.popupnode);\n    this.popupnode.clientWidth;\n    this.popupnode.classList.add(\"show\");\n  }\n\n  hideMore(ev) {\n    if (ev) {\n      if (this.popupnode && ev.target.closest(\".wh-monthtable__day\") == this.popupnode.closest(\".wh-monthtable__day\"))\n        return;//Ignore if click is inside current popup/day element\n    }\n\n    document.body.removeEventListener(\"click\", this.closefn);\n\n    if (!this.popupnode)\n      return;\n\n    this.popupnode.parentNode.removeChild(this.popupnode);\n    this.popupnode = null;\n  }\n\n  reachedNavLimit(offset) {\n    const today = new Date();\n    const todaymonths = (today.getFullYear() * 12) + today.getMonth();\n    const activemonths = (this.activemonth.year * 12) + this.activemonth.month;\n\n    if (activemonths + offset <= todaymonths)\n      this.navnode.classList.add(\"coursefinder__calendar__nav--minlimit\");\n    else\n      this.navnode.classList.remove(\"coursefinder__calendar__nav--minlimit\");\n\n    if (activemonths + offset >= this.maxmonths)\n      this.navnode.classList.add(\"coursefinder__calendar__nav--maxlimit\");\n    else\n      this.navnode.classList.remove(\"coursefinder__calendar__nav--maxlimit\");\n\n    return activemonths + offset < todaymonths || activemonths + offset > this.maxmonths;\n  }\n\n  setMonthName() {\n    this.activemonth = this.monthtable.getActiveMonth();\n    this.titlenode.textContent = this.activemonth.monthname + \" \" + this.activemonth.year;\n    if (document.location.hash.indexOf(\"#calendar\") == 0)\n      document.location.hash = \"#calendar.\" + this.activemonth.year + \".\" + (this.activemonth.month + 1);\n  }\n}\n\n\nfunction getCalendarTranslations(language) {\n  let translations = {};\n\n  if (language.toUpperCase() == \"DE\") {\n    translations = {\n      months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],\n      months_short: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],\n      days: ['Sontag', 'Montag', 'Dienstag', 'Mitwoch', 'Donnerstag', 'Freitag', 'Samstag'],\n      days_short: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']\n    };\n  } else if (language.toUpperCase() == \"NL\") {\n    translations = {\n      months: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],\n      months_short: ['Jan', 'Feb', 'Ma', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],\n      days: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'],\n      days_short: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za']\n    };\n  } else // EN\n  {\n    translations = {\n      months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],\n      months_short: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n      days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n      days_short: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']\n    };\n  }\n  return translations;\n}\n\nclass cMonthTable {\n  constructor(node, options) {\n    this.node = node;//parentNode where month table is appended\n\n    this.options = {\n      selecteddate: options && options.selecteddate ? options.selecteddate : null, //date object\n      mindate: options && options.mindate ? options.mindate : new Date(),     //date object\n      maxdate: options && options.maxdate ? options.maxdate : null,           //date object\n      date: options && options.date ? options.date : new Date(),           //date object\n      showweekdays: options && options.showweekdays ? options.showweekdays : true, //boolean\n      startweekday: options && typeof options.startweekday !== 'undefined' ? options.startweekday : 1, // integer [0-6], 0: Sunday, 1: Monday etc..\n      hideweekdays: options && options.hideweekdays ? options.hideweekdays : [],   //Array with weeknr's to hide, sunday = 0;\n      agendaitems: options && options.agendaitems ? options.agendaitems : []   //Array with objects\n    };\n\n    if (this.options.agendaitems.length)//set in chronological order\n      this.options.agendaitems.sort(function (a, b) { return a.timestamp - b.timestamp; });\n\n    this.setMinDate(this.options.mindate);\n    this.setMaxDate(this.options.maxdate);\n    this.setSelectedDate(this.options.selecteddate);\n\n    this.language = whintegration.config.locale.split(\"-\")[0];\n\n    this.setTranslations(this.language);\n\n    this.year = this.options.date.getFullYear();\n    this.month = this.options.date.getMonth(); //zero based\n  }\n\n  loadTable() {\n    if (this.node)\n      this.node.appendChild(this.generateTable(this.year, this.month));\n  }\n\n  getTranslations() {\n    return this.translations;\n  }\n\n  setTranslations(language) {\n    this.translations = getCalendarTranslations(language);\n  }\n\n  refreshData(agendaitems) {\n    this.options.agendaitems = agendaitems;\n    this.setMonth(this.year, this.month);\n  }\n\n  setMinDate(mindate) {\n\n    if (mindate && typeof mindate === \"object\") {\n      mindate = new Date(mindate.getFullYear(), mindate.getMonth(), mindate.getDate(), 0, 0, 0);//begin of day\n      this.mindate = {\n        \"year\": mindate.getFullYear(),\n        \"month\": mindate.getMonth(), //zero based\n        \"day\": mindate.getDate(),\n        \"timestamp\": mindate.getTime()\n      };\n    } else\n      this.mindate = null;\n  }\n\n  setMaxDate(maxdate) {\n    if (maxdate && typeof maxdate === \"object\") {\n      maxdate = new Date(maxdate.getFullYear(), maxdate.getMonth(), maxdate.getDate(), 23, 59, 59);//end of day\n      this.maxdate = {\n        \"year\": maxdate.getFullYear(),\n        \"month\": maxdate.getMonth(), //zero based\n        \"day\": maxdate.getDate(),\n        \"timestamp\": maxdate.getTime()\n      };\n    } else\n      this.maxdate = null;\n  }\n\n  setSelectedDate(seldate) {\n    if (seldate && typeof seldate === \"object\") {\n      seldate = new Date(seldate.getFullYear(), seldate.getMonth(), seldate.getDate(), 0, 0, 0);//begin of day\n\n      this.selecteddate = {\n        \"year\": seldate.getFullYear(),\n        \"month\": seldate.getMonth(), //zero based\n        \"day\": seldate.getDate(),\n        \"timestamp\": seldate.getTime(),\n        \"date\": seldate\n      };\n      if (this.mindate && this.selecteddate.timestamp < this.mindate.timestamp)\n        this.selecteddate = null;\n      else if (this.maxdate && this.selecteddate.timestamp > this.maxdate.timestamp)\n        this.selecteddate = null;\n    } else\n      this.selecteddate = null;\n  }\n\n  getSelectedDate() {\n    return this.selecteddate;\n  }\n\n  nextMonth() {\n    if (!this.tablenode)\n      return;\n\n    const d = new Date(this.year, this.month + 1, 1);\n    this.year = d.getFullYear();\n    this.month = d.getMonth();\n\n    this.generateTable(this.year, this.month);\n  }\n\n  previousMonth() {\n    if (!this.tablenode)\n      return;\n\n    const d = new Date(this.year, this.month - 1, 1);\n    this.year = d.getFullYear();\n    this.month = d.getMonth();\n\n    this.generateTable(this.year, this.month);\n  }\n\n  setMonth(year, month) {\n    if (!this.tablenode)\n      return;\n\n    const d = new Date(year, month, 1);\n    this.year = d.getFullYear();\n    this.month = d.getMonth();\n\n    this.generateTable(this.year, this.month);\n  }\n\n  getActiveMonth() {\n    return {\n      \"month\": this.month,\n      \"monthname\": this.translations.months[this.month],\n      \"year\": this.year\n    };\n  }\n\n  generateTable(year, month) {\n    //start of week\n    let startweekday = new Date(year, month, 1).getDay();//zero based, 0 = sunday\n\n    let orgstartday = this.options.startweekday - startweekday;\n    if (orgstartday > 0)\n      orgstartday = orgstartday - 7;\n\n    // adjust startday if startweekday is in  hideweekdays\n    while (this.options.hideweekdays.indexOf(startweekday) > -1) {\n      ++startweekday;\n      if (startweekday > 6)\n        startweekday = 0;\n    }\n\n    let startday = this.options.startweekday - startweekday;\n    if (startday > 0)\n      startday = startday - 7;\n\n    let monthdaycount = new Date(year, month + 1, 0).getDate();\n\n    //Adjust enddaycount if last day of current month are hidden\n    let endweekday = new Date(year, month, monthdaycount).getDay();\n    while (this.options.hideweekdays.indexOf(endweekday) > -1) {\n      --monthdaycount;\n      --endweekday;\n      if (endweekday < 0)\n        endweekday = 6;\n    }\n    const enddaycount = monthdaycount + (7 - (monthdaycount - orgstartday) % 7);\n\n    if (!this.tablenode) {\n      this.tablenode = <table class=\"wh-monthtable\" />;\n      this.tablenode.addEventListener(\"click\", ev => this.onDateClick(ev));\n    } else\n      this.tablenode.replaceChildren();\n\n    let rownode;\n    if (this.options.showweekdays) //The table header with the weekday names\n    {\n      rownode = <tr />;\n      for (let i = 0; i < 7; ++i) {\n        let d = i + this.options.startweekday;\n        if (d >= 7)\n          d -= 7;\n\n        if (this.options.hideweekdays.indexOf(d) == -1)\n          rownode.appendChild(<th class=\"wh-monthtable__weekday\"><div>{this.translations.days_short[d]}</div></th>);\n      }\n      this.tablenode.appendChild(rownode);\n    }\n\n    const todaytimestamp = getRoundedDayTimestamp(new Date());\n    let lastagendaitem_idx = 0;\n    for (let d = startday + this.options.startweekday; d <= enddaycount; ++d) {\n      const celldate = new Date(year, month, d);\n\n      const cellday = celldate.getDate();\n      const cellmonth = celldate.getMonth(); //zero based\n      const cellyear = celldate.getFullYear();\n      const celltimestamp = celldate.getTime();\n\n      if ((d - (startday + this.options.startweekday)) % 7 == 0) {\n        rownode = dompack.create('tr');\n        this.tablenode.appendChild(rownode);\n      }\n\n      if (this.options.hideweekdays.indexOf(celldate.getDay()) == -1) {\n        let classstr = \"wh-monthtable__day\";\n        if (cellmonth < month || cellyear < year)\n          classstr += \" wh-monthtable__day--previousmonth\";\n        else if (cellmonth > month || cellyear > year)\n          classstr += \" wh-monthtable__day--nextmonth\";\n\n        if (celltimestamp == todaytimestamp)\n          classstr += \" wh-monthtable__day--today\";\n\n        if (this.maxdate && celltimestamp > this.maxdate.timestamp)\n          classstr += \" wh-monthtable__day--disabled\";\n        else if (this.mindate && celltimestamp < this.mindate.timestamp)\n          classstr += \" wh-monthtable__day--disabled\";\n\n        if (this.selecteddate && cellmonth == this.selecteddate.month && cellday == this.selecteddate.day && cellyear == this.selecteddate.year)\n          classstr += \" wh-monthtable__day--selected\";\n\n        let infonode = null;\n        for (let i = lastagendaitem_idx; i < this.options.agendaitems.length; ++i) {\n          if (celltimestamp == this.options.agendaitems[i].timestamp) {\n            infonode = this.options.agendaitems[i].node;\n            lastagendaitem_idx = i + 1;\n\n            break;\n          }\n        }\n\n\n        const daynode = <td class={classstr} data-date={cellyear + \"-\" + (cellmonth + 1) + \"-\" + cellday}>\n          <div class=\"day-container\">\n            <span class=\"day\">{cellday}</span>\n            {infonode}\n          </div>\n        </td>;//\n\n        rownode.appendChild(daynode);\n\n      }\n    }\n\n    return this.tablenode;\n  }\n\n  onDateClick(ev) {\n    const datenode = ev.target.closest(\".wh-monthtable__day\");\n    if (datenode) {\n      if (ev)\n        ev.preventDefault();\n\n      const parts = datenode.getAttribute(\"data-date\").split(\"-\");\n      const celldate = new Date(1 * parts[0], 1 * parts[1] - 1, 1 * parts[2]);\n\n      dompack.dispatchCustomEvent(this.node ? this.node : this.tablenode, \"wh:dateclick\", {\n        bubbles: false,\n        cancelable: true,\n        detail: {\n          date: celldate,\n          day: celldate.getDate(),\n          month: celldate.getMonth(), //zero based\n          year: celldate.getFullYear(),\n          timestamp: celldate.getTime(),\n          target: ev ? ev.target : null,\n          disabled: datenode.classList.contains(\"wh-monthtable__day--disabled\")\n        }\n      });\n    }\n  }\n}\n\n//Helper functions:\nfunction getRoundedDayTimestamp(dateobj) {\n  const roundeddate = new Date(dateobj.getFullYear(), dateobj.getMonth(), dateobj.getDate());\n  return roundeddate.getTime();\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./detail.scss\";\nimport * as dompack from 'dompack';\n\nexport class cCourseDetailsList {\n  constructor(node) {\n    this.node = node;\n\n    this.pagenode = node.closest(\".coursefinder__page\");\n\n    //Toggle content\n    for (const footernode of this.node.querySelectorAll(\".coursefinder__detaillist__footer\")) {\n      const itemnode = footernode.closest(\"li\");\n      footernode.addEventListener(\"click\", ev => {\n        let foldnode = null;\n\n        if (ev.target.closest(\".toggle-description\"))\n          foldnode = itemnode.querySelector(\".coursefinder__detaillist__description\");\n        else if (ev.target.closest(\".toggle-courses\"))\n          foldnode = itemnode.querySelector(\".coursefinder__detaillist__courses\");\n\n        if (foldnode)\n          this.toggleContent(foldnode);\n      });\n    }\n\n    for (const headernode of this.node.querySelectorAll(\".coursefinder__detaillist__compacttitle\")) {\n      headernode.addEventListener(\"click\", ev => {\n        const foldnode = headernode.parentNode.querySelector(\".coursefinder__detaillist__courses\");\n        if (foldnode)\n          this.toggleContent(foldnode);\n      });\n    }\n\n    for (const closenode of this.node.querySelectorAll(\".close\")) {\n      closenode.addEventListener(\"click\", ev => {\n        const foldnode = ev.target.closest(\".showfullcontent\");\n        if (foldnode)\n          this.toggleContent(foldnode);\n      });\n    }\n\n    window.addEventListener(\"resize\", ev => this.onRefresh(ev));\n    window.addEventListener(\"load\", ev => this.onRefresh(ev));\n    window.addEventListener(\"wh:refresh\", ev => this.onRefresh(ev));\n\n    this.onRefresh();\n  }\n\n  onRefresh(ev) {\n    if (!this.pagenode.classList.contains(\"coursefinder__page--detail\"))\n      return; //Only needed for detail view\n    this.shortenDescriptions();\n    this.checkDescriptionHeight();\n  }\n\n  shortenDescriptions() {\n    for (const fulldescriptionnode of this.node.querySelectorAll(\".fulldescription\"))\n      this.shortenDescription(fulldescriptionnode);\n  }\n\n  shortenDescription(fulldescriptionnode) {\n    const maxh = 65; //Just check height with 5px margin\n    let h_inner = fulldescriptionnode.clientHeight;\n\n    if (h_inner < maxh) {\n      fulldescriptionnode.parentNode.classList.remove(\"hasshortdescription\");\n      if (fulldescriptionnode.parentNode.children.length > 1)//remove short description\n        fulldescriptionnode.parentNode.removeChild(fulldescriptionnode.parentNode.children[1]);\n\n      return;\n    }\n\n    fulldescriptionnode.parentNode.classList.add(\"hasshortdescription\");\n\n    let shortdescriptionnode = fulldescriptionnode.parentNode.children.length > 1 ? fulldescriptionnode.parentNode.children[1] : null;\n    if (!shortdescriptionnode) {\n      shortdescriptionnode = <span class=\"shortdescription\" />;\n      fulldescriptionnode.parentNode.appendChild(shortdescriptionnode);\n    }\n\n    shortdescriptionnode.textContent = \"\";\n    const words = fulldescriptionnode.textContent.split(\" \");\n\n    h_inner = shortdescriptionnode.clientHeight;\n    let prevcontent = \"\";\n    while (h_inner <= maxh && words.length) {\n      const newcontent = prevcontent + (prevcontent != \"\" ? \" \" : \"\") + words.shift();\n      shortdescriptionnode.textContent = newcontent;\n      h_inner = shortdescriptionnode.clientHeight;\n      if (h_inner > maxh) {\n        shortdescriptionnode.textContent = prevcontent.substr(0, prevcontent.length - 3);//space for ...\n        return;\n      }\n\n      prevcontent = newcontent;\n    }\n  }\n\n  toggleContent(foldnode) {\n    const h_outer = foldnode.clientHeight;\n    const h_inner = foldnode.children[0].clientHeight;\n\n    if (foldnode.classList.contains(\"showfullcontent\")) {\n      foldnode.style.maxHeight = h_outer + \"px\";\n      foldnode.clientHeight;//force css update\n      foldnode.classList.add(\"onhidefullcontent\");\n      foldnode.style.maxHeight = \"\";\n      foldnode.classList.remove(\"showfullcontentready\");\n\n      if (foldnode.classList.contains(\"coursefinder__detaillist__courses\"))\n        foldnode.closest(\"li\").classList.remove(\"showcourses\");\n\n      setTimeout(function () {\n        foldnode.classList.remove(\"showfullcontent\");\n        foldnode.classList.remove(\"onhidefullcontent\");\n      }, 300);\n    } else {\n      foldnode.classList.remove(\"onhidefullcontent\");\n      if (h_inner > h_outer) {\n        foldnode.style.maxHeight = h_outer + \"px\";\n        foldnode.clientHeight;//force css update\n        foldnode.style.maxHeight = h_inner + \"px\";\n\n        if (foldnode.classList.contains(\"coursefinder__detaillist__courses\"))\n          foldnode.closest(\"li\").classList.add(\"showcourses\");\n\n        setTimeout(function () {\n          foldnode.style.maxHeight = \"\";\n        }, 300);\n      }\n\n      foldnode.classList.add(\"showfullcontent\");\n\n      setTimeout(function () {\n        foldnode.classList.add(\"showfullcontentready\");\n      }, 300);\n    }\n  }\n\n  checkDescriptionHeight() {\n    for (const foldnode of this.node.querySelectorAll(\".coursefinder__detaillist__description\"))\n      this.toggleMoreVisibility(foldnode);\n  }\n\n  toggleMoreVisibility(foldnode) {\n    const btnnode = foldnode.parentNode.querySelector(\".toggle-description\");\n    if (!btnnode)\n      return;\n\n    const maxh = 65;//just check height with a bit of margin\n    const h_inner = foldnode.children[0].clientHeight;\n\n    if (h_inner < maxh)\n      btnnode.style.display = \"none\";\n    else\n      btnnode.style.display = \"\";\n  }\n}\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/webfeatures/courses/coursefinder.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_courses\",\"en\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"nl\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Actieve filters\",\"cancel\":\"Annuleren\",\"closeregistration\":\"Registratie afsluiten\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"Na inschrijving ontvang je regelmatig onze nieuwe cursussen.\",\"coursealert-description-noresults\":\"Op dit moment hebben we geen cursussen beschikbaar voor deze selectie. Vul je gegevens in en je krijgt als eerste een bericht als er één beschikbaar komt.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Kan je niet wachten om deel te nemen aan deze cursus? We sturen je graag een mail als deze opnieuw ingepland wordt of wanneer er een plek in een reeds geplande cursus vrij komt.\",\"\\n\",\"We zullen je slechts één keer mailen. Als je er dan geen gebruik van maakt, zul je je opnieuw moeten aanmelden voor deze alert.\"],\"coursenotyetopen\":\"Sorry, de registratie voor deze cursus is nog niet geopend.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domein\"],\"subselse\":[\"domeinen\"]}],\"isfull\":\"Vol\",\"moreinfo\":\"Meer info\",\"nextstep\":\"Volgende stap\",\"no\":\"Nee\",\"noavailableoptions\":\"Sorry, er zijn op dit moment  geen opties voor registratie beschikbaar\",\"nooptionsavailable\":\"Sorry, er zijn geen opties beschikbaar.\",\"notewaitinglist\":\"Deze cursus is volgeboekt, als je je nu registreert, word je op de wachtlijst geplaatst en automatisch ingeschreven als er een plek vrijkomt.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"U heeft zich al aangemeld voor deze cursus.\",\"registrationerror_full\":\"Geselecteerde datum/tijd is vol\",\"registrationerror_nocourse\":\"Cursus is niet beschikbaar\",\"registrationerror_nosession\":\"Geselecteerde datum/tijd is niet beschikbaar\",\"registrationerror_title\":\"Fout bij verwerken registratie\",\"registrationerror_waitinglistfull\":\"Wachtlijst is vol\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"cursus\"],\"subselse\":[\"cursussen\"]},\" gevonden\"],\"retry\":\"Retry\",\"signup\":\"Inschrijven\",\"signupfor\":\"Schrijf in voor:\",\"start\":\"Start\",\"submiterror-failed\":\"Mislukt\",\"submiterror-prefix\":\"Uw registratie is:\",\"submitsuccess-description\":\"U ontvangt een e-mail met verdere informatie.\",\"submitsuccess-followupdescription\":[\"Dit is een begeleidende cursus bij '\",1,\"'\"],\"submitsuccess-prefix\":\"Uw registratie is:\",\"submitsuccess-title\":\"Gelukt\",\"submitsuccess-waitinglist\":\"U staat nu op de wachtlijst. U ontvangt een e-mail met verdere informatie.\",\"waitinglist\":\"Wachtlijst\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Cursus\"],\"subselse\":[\"Cursussen\"]}],\"xdaycourse\":[1,\" daagse cursus\"],\"xmore\":[1,\" meer\"],\"yes\":\"Ja\"}}}});\nregisterTexts(\"utwente_courses\",\"de\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"ar\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"bg\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"el\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"es\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"id\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"pt\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"ro\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\nregisterTexts(\"utwente_courses\",\"zh\",{\"webfeatures\":{\"frontend\":{\"js\":{\"activefilters\":\"Active filters\",\"cancel\":\"Cancel\",\"closeregistration\":\"Close registration\",\"coursealert\":\"Course alert\",\"coursealert-description\":\"After registration you will regularly receive our new courses.\",\"coursealert-description-noresults\":\"We currently have no curssen available for this selection. Enter your details and you will be the first to be notified when one becomes available.\",\"coursealert-login\":\"Login\",\"coursealert-singlecoursedescription\":[\"Can’t wait to join this course? Sign up for the waiting list. You will receive an alert as soon as a new course is organised or a seat in one of the current courses becomes available.\",\"\\n\",\"We will only alert you \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"once\"},\". If you do not use this opportunity, you will have to sign up again for this alert.\"],\"coursenotyetopen\":\"Sorry, you cannot register for this course yet.\",\"inxdomains\":[\"in \",1,\"  \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"domain\"],\"subselse\":[\"domains\"]}],\"isfull\":\"Full\",\"moreinfo\":\"More info\",\"nextstep\":\"Next step\",\"no\":\"No\",\"noavailableoptions\":\"Sorry, there are at this time no options for registration available\",\"nooptionsavailable\":\"Sorry, no options available\",\"notewaitinglist\":\"This course is fully booked, if you register now, you will be placed on the waiting list and you will be enrolled if a place becomes available.\",\"ok\":\"Ok\",\"registrationerror_already_registered\":\"You have already registered for this course.\",\"registrationerror_full\":\"Selected date/time is full\",\"registrationerror_nocourse\":\"Course not available\",\"registrationerror_nosession\":\"Selected date/time not available\",\"registrationerror_title\":\"Error while saving registration\",\"registrationerror_waitinglistfull\":\"Waiting list full\",\"results\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"course\"],\"subselse\":[\"courses\"]},\" found\"],\"retry\":\"Retry\",\"signup\":\"Sign up\",\"signupfor\":\"Sign up for:\",\"start\":\"Start\",\"submiterror-failed\":\"Failed\",\"submiterror-prefix\":\"Your registration has:\",\"submitsuccess-description\":\"You will receive an email with further information.\",\"submitsuccess-followupdescription\":[\"This is an accompanying course for '\",1,\"'\"],\"submitsuccess-prefix\":\"Your registration is:\",\"submitsuccess-title\":\"Successful\",\"submitsuccess-waitinglist\":\"You're on the waiting list. You will receive an email with further information.\",\"waitinglist\":\"Waiting list\",\"xcourses\":[1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"Course\"],\"subselse\":[\"Courses\"]}],\"xdaycourse\":[1,\" day course\"],\"xmore\":[1,\" more\"],\"yes\":\"Yes\"}}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/language/default.xml\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./course.scss\";\nimport * as dompack from 'dompack';\nimport getTid from \"@mod-tollium/js/gettid\";\nimport { RPCFormBase, registerHandler } from '@mod-publisher/js/forms';\n\nclass RegistrationForm extends RPCFormBase {\n  constructor(node) {\n    super(node);\n\n    this.addSignupDeeplink();\n\n    //Get nodes within inlinecta header for altering texts\n    this.header = {\n      prefixnode: this.node.querySelector(\".formheader__prefix\"),\n      titlenode: this.node.querySelector(\".formheader__title\"),\n      descriptionnode: this.node.querySelector(\".formheader__description\")\n    };\n\n    const nextbtn = this.node.querySelector(\".wh-form__button--nextlabel, .wh-form__button--submit .wh-form__buttonlabel\");\n    if (nextbtn)\n      nextbtn.textContent = getTid('utwente_courses:webfeatures.frontend.js.nextstep');\n\n    this.resulttxtnode = this.node.querySelector(\".resulttext\");\n\n    if (this.elements[\"loggedinuser\"].value && this.getValue(\"serie\"))\n      this.gotoPage(1);\n\n    if (this.node.classList.contains(\"wh-form--disabledsubmit\")) { //If login required and not loggedin, block submit\n      this.node.addEventListener(\"wh:form-beforesubmit\", ev => {\n        ev.preventDefault();\n      });\n    }\n\n    this.node.addEventListener(\"wh:form-pagechange\", ev => this.onPageChange(ev.target));\n\n    this.loginbtn = document.getElementById(\"coursefinder-login\");\n    if (this.loginbtn)\n      this.loginbtn.addEventListener(\"click\", ev => this.login(ev));\n\n    this.initFoldableSeries();\n  }\n\n  addSignupDeeplink() {\n    const deeplinklist = document.querySelector(\".main__deeplinklist\");\n    if (deeplinklist) {\n      deeplinklist.appendChild(<li class=\"main__deeplinkitem\">\n        <a class=\"main__deeplink\" href=\"#signup\">{getTid('utwente_courses:webfeatures.frontend.js.signup')}</a>\n      </li>);\n    }\n  }\n\n  login(ev) {\n    ev.preventDefault();\n    document.location.href = this.loginbtn.dataset.url + \"?serie=\" + this.getValue(\"serie\") + \"#signup\";\n  }\n\n  onPageChange(page) {\n    if (page.dataset.whFormPagerole == \"thankyou\")\n      return;\n\n    this.header.prefixnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.signupfor');\n    this.header.titlenode.textContent = this.node.dataset.coursetitle;\n\n    if (page.classList.contains(\"wh-form__page--series\")) {\n      this.header.descriptionnode.textContent = \"\";\n      this.node.classList.remove(\"hidefootnote\");\n    } else //Set selected serie into header description\n    {\n      const selectedserie = this.getSelectedOption(\"serie\");\n      let description = \"\";\n      if (selectedserie) {\n        this.node.classList.toggle(\"hidefootnote\", !selectedserie.inputnode.dataset.waitinglist);\n\n        for (const node of selectedserie.fieldline.querySelectorAll(\".session:first-child > .weekday, .session:first-child > .date, .session:first-child > .time, .note, .duration\")) {\n          if (node.textContent != \"\") {\n            if (node.classList.contains(\"duration\"))\n              description += \" (\" + node.textContent + \")\";\n            else {\n              if (description != \"\")\n                description += \", \";\n              description += node.textContent;\n            }\n          }\n        }\n      }\n      this.header.descriptionnode.textContent = description;\n    }\n  }\n\n  initFoldableSeries() {\n    for (const node of this.node.querySelectorAll(\".fieldgroup-serie .fieldgroup-serie__month\")) {\n      node.addEventListener(\"click\", ev => this.toggleSerieMonth(node));\n\n      //And foldable serie within:\n      const monthitemswrapper = node.nextSibling;\n\n      for (const itemnode of monthitemswrapper.querySelectorAll(\".wh-form__optiondata\")) {\n        const togglenode = itemnode.querySelector(\".duration\");\n        const sessionswrapper = itemnode.querySelector(\".sessions\");\n        if (togglenode && sessionswrapper) {\n          togglenode.addEventListener(\"click\", ev => {\n            sessionswrapper.style.maxHeight = \"\";\n            sessionswrapper.classList.toggle(\"showall\");\n            if (sessionswrapper.classList.contains(\"showall\")) {\n              let h = 0;\n              for (let i = 0; i < sessionswrapper.children.length; ++i)\n                h += sessionswrapper.children[i].clientHeight;\n              sessionswrapper.style.maxHeight = h + \"px\";\n\n              setTimeout(function () {\n                sessionswrapper.style.maxHeight = \"none\";\n              }, 300);\n            }\n          });\n        }\n      }\n    }\n  }\n\n  toggleSerieMonth(titlenode) {\n    const foldnode = titlenode.nextSibling;\n\n    foldnode.style.overflow = \"\";\n    if (titlenode.classList.contains(\"active\")) {\n      foldnode.style.height = foldnode.clientHeight + \"px\";\n      titlenode.classList.remove(\"active\");\n      foldnode.clientHeight;\n      foldnode.style.height = \"\";\n    } else {\n      let h = 0;\n      for (let i = 0; i < foldnode.children.length; ++i)\n        h += foldnode.children[i].clientHeight;\n\n      foldnode.style.height = h + \"px\";\n      titlenode.classList.add(\"active\");\n      foldnode.clientHeight;\n\n      setTimeout(function () {\n        foldnode.style.height = \"\";\n        foldnode.style.overflow = \"visible\"; //Needed for duration mouseover popup\n      }, 300);\n    }\n  }\n\n  onSubmitSuccess(result) {\n    this.resulttxtnode.replaceChildren();\n\n    if (result.success) {\n      this.header.prefixnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.submitsuccess-prefix');\n      this.header.titlenode.textContent = getTid('utwente_courses:webfeatures.frontend.js.submitsuccess-title');\n      if (result.onwaitinglist)\n        this.resulttxtnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.submitsuccess-waitinglist');\n      else if (result.parentcourse)\n        this.header.descriptionnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.submitsuccess-followupdescription', result.parentcoursetitle);\n      else\n        this.header.descriptionnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.submitsuccess-description');\n\n      if (result.paymentlink) //Goto payment page\n        document.location.href = result.paymentlink;\n      else if (result.followupcourselink)\n        document.location.href = result.followupcourselink;\n      else\n        this.node.scrollIntoView();\n\n      /*\n      let closebutton = <button class=\"wh-form__button\">{getTid('utwente_courses:webfeatures.frontend.js.closeregistration')}</button>;//\n      closebutton.addEventListener(\"click\", ev => {\n        ev.preventDefault();\n        document.location.reload();\n      });\n      this.resulttxtnode.appendChild(closebutton);\n      */\n    } else {\n      // let title = getTid('utwente_courses:webfeatures.frontend.js.registrationerror_title');\n      let description = '';\n      switch (result.code) {\n        case 'nosuchcourse':\n          description = getTid('utwente_courses:webfeatures.frontend.js.registrationerror_nocourse');\n          break;\n        case 'nosuchserie':\n          description = getTid('utwente_courses:webfeatures.frontend.js.registrationerror_nosession');\n          break;\n        case 'full':\n          description = getTid('utwente_courses:webfeatures.frontend.js.registrationerror_full');\n          break;\n        case 'already_registered':\n          description = getTid('utwente_courses:webfeatures.frontend.js.registrationerror_already_registered');\n          break;\n        case 'fullwaitinglist':\n          description = getTid('utwente_courses:webfeatures.frontend.js.registrationerror_waitinglistfull');\n          break;\n        default:\n          description = result.code + (result.name ? ' : ' + result.name : '');\n      }\n\n      this.header.prefixnode.textContent = getTid('utwente_courses:webfeatures.frontend.js.submiterror-prefix');\n      this.header.titlenode.textContent = getTid('utwente_courses:webfeatures.frontend.js.submiterror-failed');\n      this.header.descriptionnode.textContent = description;\n\n      this.resulttxtnode.appendChild(<div class=\"errortitle\">{getTid('utwente_courses:webfeatures.frontend.js.registrationerror_title')}</div>);\n\n      const retrybutton = <button class=\"wh-form__button\">{getTid('utwente_courses:webfeatures.frontend.js.retry')}</button>;//\n      retrybutton.addEventListener(\"click\", ev => {\n        ev.preventDefault();\n        document.location.reload();\n      });\n      this.resulttxtnode.appendChild(retrybutton);\n    }\n  }\n}\n\nregisterHandler(\"utwente_courses:registrationform\", node => new RegistrationForm(node));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./mycourses.scss\";\nimport * as dompack from 'dompack';\nimport * as whintegration from \"@mod-system/js/wh/integration\";\nimport { cancelCourseDialog, payCourseDialog, showPaymentResult } from '../../components/dialogs';\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\n\ndompack.register(\".coursefinder__mycourses__tabs\", node => {\n  const pagecontainer = node.parentNode;\n\n  if ([\"#history\", \"#coursealert\"].includes(location.hash)) {\n    const activetab = location.hash.substr(1);\n\n    for (let i = 0; i < node.children.length; ++i) {\n      if (node.children[i].dataset.view === activetab) {\n        node.children[i].classList.add(\"active\");\n        pagecontainer.classList.add(\"coursefinder__mycourses--\" + node.children[i].dataset.view);\n      } else {\n        node.children[i].classList.remove(\"active\");\n        pagecontainer.classList.remove(\"coursefinder__mycourses--\" + node.children[i].dataset.view);\n      }\n    }\n  }\n\n  node.addEventListener(\"click\", ev => {\n    for (let i = 0; i < node.children.length; ++i) {\n      if (ev.target === node.children[i]) {\n        node.children[i].classList.add(\"active\");\n        pagecontainer.classList.add(\"coursefinder__mycourses--\" + node.children[i].dataset.view);\n      } else {\n        node.children[i].classList.remove(\"active\");\n        pagecontainer.classList.remove(\"coursefinder__mycourses--\" + node.children[i].dataset.view);\n      }\n    }\n  });\n});\n\ndompack.register(\".coursefinder__mycourses__showcanceled\", node => {\n  node.addEventListener(\"click\", () => {\n    const tabcountnode = dompack.qS(\".coursefinder__mycourses__tabs > li[data-view='history'] > .count\");\n\n    if (node.parentNode.classList.contains(\"coursefinder__mycourses--showcanceled\")) {\n      node.parentNode.classList.remove(\"coursefinder__mycourses--showcanceled\");\n      if (tabcountnode && node.dataset.count)\n        tabcountnode.textContent = node.dataset.count;\n    } else {\n      node.parentNode.classList.add(\"coursefinder__mycourses--showcanceled\");\n      if (tabcountnode && node.dataset.totalcount)\n        tabcountnode.textContent = node.dataset.totalcount;\n    }\n  });\n});\n\n//Below is also used by cancel and payment page\ndompack.register(\"#coursefinder-paymentresult\", node => void showPaymentResult(node));\n\ndompack.register(\".coursefinder__registration\", node => {\n  node.addEventListener(\"click\", ev => {\n    if (ev.target.classList.contains(\"cancel-registration\") && ev.target.dataset.id)\n      cancelCourseDialog(ev.target.dataset);\n    else if (ev.target.classList.contains(\"pay-registration\") && ev.target.dataset.id)\n      payCourseDialog(ev.target.dataset);\n  });\n});\n\n\nasync function updateCourseAlert(categories, unsubscibecourses) {\n  const rpc = new JSONRPC();\n  const lock = dompack.flagUIBusy({ ismodal: true });\n  let result;\n  let token = whintegration.config.site.token;\n  if (!token)\n    token = \"\";\n\n  try {\n    result = await rpc.async(\"UpdateCourseAlert\", { categories, unsubscibecourses }, token);\n  } finally {\n    lock.release();\n  }\n\n  if (!result || !result.success)\n    console.error(\"Error updating course alert\");\n  else if (unsubscibecourses.length) {\n    const coursealertnodes = dompack.qSA(\".coursefinder__mycourses__coursealertform__courseline\");\n    const removenodes = coursealertnodes.filter(_ => unsubscibecourses.includes(Number(_.dataset.id)));\n    if (removenodes.length && coursealertnodes.length === removenodes.length)\n      coursealertnodes[0].closest(\".coursefinder__mycourses__coursealertform__col\").remove();\n    else if (removenodes.length)\n      removenodes.forEach(courselinenode => courselinenode.remove());\n  }\n}\n\nasync function unsubscribeCourseAlert() {\n  const rpc = new JSONRPC();\n  const lock = dompack.flagUIBusy({ ismodal: true });\n  let result;\n  let token = whintegration.config.site.token;\n  if (!token)\n    token = \"\";\n\n  try {\n    result = await rpc.async(\"UnsubscribeCourseAlert\", token);\n  } finally {\n    lock.release();\n  }\n\n  if (!result || !result.success)\n    console.error(\"Error while unsubscribe course alert\");\n  else\n    dompack.qS(\".coursefinder__mycourses\").classList.add(\"coursefinder__mycourses--unsubscribedcoursealert\");\n}\n\ndompack.register(\".coursefinder__mycourses__coursealertunsubscribeform\", form => {\n  form.addEventListener(\"submit\", ev => {\n    ev.preventDefault();\n\n    void unsubscribeCourseAlert();\n  });\n});\n\ndompack.register(\".coursefinder__mycourses__coursealertform\", form => {\n  form.addEventListener(\"submit\", ev => {\n    ev.preventDefault();\n\n    const categories = dompack.qSA(form, \"input[name='categories']:checked\").map(_ => parseInt(_.value));\n    const unsubscibecourses = dompack.qSA(form, \"input[name='course']:not(:checked)\").map(_ => parseInt(_.value));\n    void updateCourseAlert(categories, unsubscibecourses);\n  });\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./dialogs.scss\";\nimport * as dompack from 'dompack';\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\nimport getTid from \"@mod-tollium/js/gettid\";\nimport * as dialogapi from 'dompack/api/dialog';\n\nclass cCancelCourse {\n  constructor(data) {\n    this.data = data;\n    void this.showDialog();\n  }\n\n  async showDialog() {\n    const dialog = dialogapi.createDialog();\n    dialog.contentnode.appendChild(<div class=\"coursefinder__canceldialog\">\n      <h3>{getTid('utwente_courses:webfeatures.frontend.js.cancel') + \" '\" + this.data.title + \"'?\"}</h3>\n      <div class=\"course_date\">{\"( \" + getTid('utwente_courses:webfeatures.frontend.js.start') + \" \" + this.data.date + \" )\"}</div>\n      <div class=\"buttons\">\n        <button data-action=\"ok\" class=\"wh-form__button\">{getTid('utwente_courses:webfeatures.frontend.js.yes')}</button>\n        <button data-action=\"cancel\" class=\"wh-form__button\">{getTid('utwente_courses:webfeatures.frontend.js.no')}</button>\n      </div>\n    </div>);//\n\n    const id = Number(this.data.id);\n    const hash = this.data.hash;\n\n    dialog.contentnode.addEventListener(\"click\", ev => {\n      if (ev.target.nodeName === \"BUTTON\") {\n        dialog.resolve();\n        if (ev.target.dataset.action === \"ok\" && id > 0 && hash)\n          this.doCancel(id, hash).catch(e => console.error(e));\n      }\n    });\n\n    void dialog.runModal();\n  }\n\n  async doCancel(id, hash) {\n    const rpc = new JSONRPC();\n    const lock = dompack.flagUIBusy({ ismodal: true });\n    try {\n      await rpc.async(\"CancelCourse\", id, hash);\n    } finally {\n      lock.release();\n    }\n\n    document.location.reload();\n  }\n}\n\n\nclass cPayCourse {\n  constructor(data) {\n    this.data = data;\n    void this.showDialog();\n  }\n\n  async showDialog() {\n    const formnode = document.getElementById(\"coursefinder-paymentform\");\n    const dialog = dialogapi.createDialog({ borrow: formnode });\n\n    formnode.elements[\"id\"].value = this.data.id;\n    formnode.elements[\"pay\"].value = this.data.hash;\n\n    dialog.contentnode.querySelector(\".course_title\").textContent = this.data.title;\n    dialog.contentnode.querySelector(\".course_date\").textContent = this.data.date;\n    dialog.contentnode.querySelector(\".course_price\").textContent = this.data.price;\n    formnode.style.display = \"\";\n\n    dialog.contentnode.addEventListener(\"click\", ev => {\n      if (ev.target.nodeName === \"BUTTON\") {\n        dialog.resolve();\n        if (ev.target.dataset.action === \"pay\" && Number(this.data.id) > 0 && this.data.hash)\n          formnode.submit();\n      }\n    });\n\n    await dialog.runModal();\n  }\n}\n\nexport async function showPaymentResult(node) {\n  const dialog = dialogapi.createDialog();\n  dialog.contentnode.appendChild(node);\n  node.style.display = \"\";\n\n  const btn = node.querySelector(\"button\");\n  if (btn)\n    btn.addEventListener(\"click\", ev => dialog.resolve());\n\n  void dialog.runModal();\n}\n\nexport function cancelCourseDialog(data) {\n  new cCancelCourse(data);\n}\n\nexport function payCourseDialog(data) {\n  new cPayCourse(data);\n}\n","import \"./studyfinder-filters-itc.scss\";\nimport \"./studyfinder.scss\";\nimport \"./studyfinder-viewmode-list.scss\";\nimport \"./studyfinder-viewmode-details.scss\";\nimport \"./studyfinder-widget.scss\";\n\nimport { SearchIndex } from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview/searchindex\";\nimport * as whintegration from \"@mod-system/js/wh/integration\";\nimport * as dompack from '@webhare/dompack';\nimport \"./studyfinder.lang.json\";\nimport { getTid } from \"@mod-tollium/js/gettid\";\nimport UTAutoComplete from '@mod-utwente_base/webdesigns/ws2016/src/components/autocompleter2/autocompleter';\n\n// webdesign node modules aren't accessible from webfeatures, load them directly\nimport FilteredOverview from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview\";\nimport { navigateTo } from \"@webhare/env\";\n\ninterface Specialization {\n  id: string;\n  details: HTMLElement;\n  compact: HTMLElement;\n  title: HTMLElement;\n  description: HTMLElement;\n}\n\ninterface IndexedItem {\n  id: string;\n  specid: string;\n  title: string;\n  description: string;\n  titleNode: HTMLElement;\n  descriptionNode: HTMLElement;\n}\n\ntype RPCCache = {\n  ids: string[];\n  progtitleids: string[];\n  expandids: string[];\n  expandtitleids: string[];\n  specids: string[];\n  words: string;\n};\n\n\n/*\nTo make listview work:\n- set the correct table names\n- be sure the content from the normal view is copyable for the list view\n- be sure to setup tid's for the header\n*/\n\n\nclass FilterStudyFinder extends FilteredOverview {\n  isdetailsview = true;\n  programmescontainer: HTMLElement;\n  scorecolumn = <div style=\"display: none;\"></div>;\n  tablecellnames_programme: string[];\n  tablecellnames_specialization;\n  items = new Array<{\n    id: string;\n    details: HTMLElement;\n    compact: HTMLElement;\n    specializations: Specialization[];\n    title: HTMLElement;\n    description: HTMLElement;\n  }>();\n\n  searchIndex = new SearchIndex<IndexedItem>();\n  tableheader = dompack.create(\"li\", { className: \"filteredoverview__listview__header studyfinder__listview__header\" });\n  sortcolumn: HTMLElement | null = null;\n  activeitem: HTMLElement | null = null;\n\n  constructor() {\n    super({ filterpagetype: 'studyfinder' });\n\n    this.programmescontainer = dompack.qR(\".studyfinderprogrammes > ul\");\n    this.programmescontainer.style.display = \"none\";\n\n    this.programmescontainer.parentNode!.append(this.scorecolumn);\n\n    this.tablecellnames_programme = whintegration.config.obj.columns_listview_programme as string[];\n    this.tablecellnames_specialization = whintegration.config.obj.columns_listview_specialization as string[];\n\n    // keep an internal list of all items AND\n    // generate the list view based on content of the normal view\n    let specializationstotalcount = 0;\n    let idx = 0;\n    let specid = 0;\n    for (const node of this.programmescontainer.querySelectorAll<HTMLElement>(\".studyfinder__programme\")) {\n      const specializations: Specialization[] = [];\n      const snode = node.querySelector(\".programme_specializations\");\n      if (snode) {\n        for (const infonode of snode.querySelectorAll<HTMLElement>(\".specialization\")) {\n          const rownode = this.buildRow(infonode, node.dataset);\n          (infonode.parentNode! as HTMLElement).dataset.specid = String(++specid);\n          rownode.dataset.specid = String(specid);\n          specializations.push({\n            id: String(specid),\n            details: infonode.parentNode! as HTMLElement,\n            compact: rownode,\n            title: (infonode.querySelector(\".specialization__title__text\")) as HTMLElement,\n            description: infonode.querySelector(\".description\") as HTMLElement\n          });\n        }\n      }\n\n      const compactnode = this.buildRow(dompack.qR(node, \".programme__content\"), node.dataset);\n      compactnode.setAttribute(\"data-idx\", String(idx));\n\n      if (!node.dataset.specializations)\n        compactnode.classList.add(\"nospecializations\");\n\n      specializationstotalcount += specializations.length;\n\n      this.items.push({\n        \"id\": node.dataset.id!,\n        \"details\": node,\n        \"compact\": compactnode,\n        \"specializations\": specializations,\n        \"title\": node.querySelector(\".programme__title__text\") as HTMLElement,\n        \"description\": node.querySelector(\".description\") as HTMLElement\n      });\n\n      ++idx;\n    }\n\n    if (specializationstotalcount === 0) { // there are no programme's with specializations so remove the column \"specializations\"\n      for (let i = this.tablecellnames_programme.length - 1; i >= 0; --i) {\n        if (this.tablecellnames_programme[i] === \"specializations\") {\n          this.tablecellnames_programme.splice(i, 1);\n          break;\n        }\n      }\n    }\n\n    this.programmescontainer.addEventListener(\"click\", ev => this.toggleSpecializations(ev));\n\n\n    for (const node of dompack.qSA(\".listtoggle__detailview,.listtoggle__listview\")) {\n      node.addEventListener(\"click\", ev => this.setViewByButton(node));\n    }\n\n    this.initSearchIndex();\n    this.initAutoSuggest();\n\n\n    //if( node.classList.contains(\"listview\") &&\n    if (location.hash === \"#listview\") {\n      this.setView(false);\n      this.doFilterForced();\n    } else {\n      // FIXME: not happy this is not generic\n      if (this.isFilterActive())\n        this.doFilter();\n      else\n        this.setFeedback(this.items.length);\n    }\n\n\n    // We can show the content once we are sure we have the final filtered result\n    this.programmescontainer.style.display = \"\";\n  }\n\n  buildRow(node: HTMLElement, dataset: DOMStringMap) {\n    // The node from which we harvest content knows if this is an specialization\n    const isspecialization = node.classList.contains(\"specialization\");\n    const cellnames = isspecialization ? this.tablecellnames_specialization : this.tablecellnames_programme;\n\n    const rownode = dompack.create(\"li\", { className: \"studyfinder__programme filteredoverview__listview__item\", \"dataset\": dataset });\n\n    if (isspecialization)\n      rownode.classList.add(\"specialization\");\n    else\n      rownode.classList.add(\"isprogramme\");\n\n    if (node.dataset.link) {\n      rownode.setAttribute(\"data-link\", node.dataset.link);\n\n      rownode.addEventListener(\"click\", ev => {\n        if (dataset.specializations && (ev.target as HTMLElement).closest(\".togglespecializations\"))\n          return;\n\n        ev.preventDefault();\n        //window.open(node.dataset.link);\n        navigateTo(node.dataset.link!);\n      });\n    }\n\n    for (let i = 0; i < cellnames.length; ++i) {\n      //console.log(node, isspecialization, currentcellname);\n      const currentcellname = cellnames[i];\n\n      const cellnode = dompack.create(\"div\", { className: \"cell--\" + currentcellname });\n\n      const fieldnode = node.querySelector<HTMLElement>(\".\" + currentcellname);\n      if (fieldnode) {\n        if (fieldnode.dataset.sort)\n          cellnode.setAttribute(\"data-sort\", fieldnode.dataset.sort);\n\n        cellnode.appendChild(fieldnode.cloneNode(true));\n      } else if (currentcellname === \"specializations\" || currentcellname === \"duration\")\n        cellnode.setAttribute(\"data-sort\", \"0\");\n\n      if (!fieldnode)\n        cellnode.appendChild(dompack.create(\"span\", { textContent: \"\\u00A0\" }));//IE fix (IE doesn't like empty tablecells)\n\n      if (currentcellname === \"specializations\" && fieldnode)\n        cellnode.classList.add(\"togglespecializations\");\n\n      rownode.appendChild(cellnode);\n    }\n\n    return rownode;\n  }\n\n  initSearchIndex() {\n    this.searchIndex.searchFields = [\"title\", \"description\"];\n    this.searchIndex.completeSuggestFields = [\"title\"];\n\n    for (const item of this.items) {\n      this.searchIndex.indexItem(\n        {\n          id: item.id,\n          specid: \"0\",\n          title: item.title.textContent || '',\n          description: item.description.textContent || '',\n          titleNode: item.title,\n          descriptionNode: item.description\n        });\n      for (const spec of item.specializations) {\n        this.searchIndex.indexItem(\n          {\n            id: item.id,\n            specid: spec.id,\n            title: spec.title.textContent || '',\n            description: spec.description.textContent || '',\n            titleNode: spec.title,\n            descriptionNode: spec.description\n          });\n      }\n    }\n  }\n\n  setViewByButton(node: HTMLElement) {\n    const isdetailsview = node.getAttribute(\"data-viewmode\") === \"detailview\";\n    this.setView(isdetailsview);\n    this.doFilterForced();\n  }\n\n  // FIXME: move to utwente_education FilterStudyFinder class\n  applyViewModeClass(viewmode: \"list\" | \"details\") {\n    if (viewmode === \"list\") {\n      this.feedbackcontainer.classList.add(\"filteredoverview--listview\");\n      this.feedbackcontainer.classList.remove(\"filteredoverview--detailview\");\n      this.programmescontainer.classList.add(\"filteredoverview__listview\");\n      this.programmescontainer.classList.remove(\"filteredoverview__detailview\");\n    } else if (viewmode === \"details\") {\n      this.feedbackcontainer.classList.remove(\"filteredoverview--listview\");\n      this.feedbackcontainer.classList.add(\"filteredoverview--detailview\");\n      this.programmescontainer.classList.remove(\"filteredoverview__listview\");\n      this.programmescontainer.classList.add(\"filteredoverview__detailview\");\n    }\n  }\n\n  setView(isdetailsview: boolean) {\n    //    if (this.isdetailsview = isdetailsview)\n    //      return;//Nothing changed\n\n    this.isdetailsview = isdetailsview;\n\n    if (this.isdetailsview) {\n      this.tableheader.remove();\n      this.applyViewModeClass(\"details\");\n\n      this.programmescontainer.classList.remove(\"studyfinderprogrammes--listview\");\n      this.programmescontainer.classList.add(\"studyfinderprogrammes--detailview\");\n    } else {\n      // Generate the table header row\n      this.tableheader.replaceChildren();\n      for (let i = 0; i < this.tablecellnames_programme.length; ++i) {\n        let coltitle = \"\";\n        switch (this.tablecellnames_programme[i]) {\n          case \"degree\": coltitle = getTid('utwente_education:site.studyfinder.js.degree'); break;\n          case \"title\": coltitle = getTid('utwente_education:site.studyfinder.js.study'); break;\n          case \"duration\": coltitle = getTid('utwente_education:site.studyfinder.js.duration'); break;\n          case \"time\": coltitle = getTid('utwente_education:site.studyfinder.js.workload'); break;\n          case \"languages\": coltitle = getTid('utwente_education:site.studyfinder.js.language'); break;\n          case \"specializations\": coltitle = getTid('utwente_education:site.studyfinder.js.specializations'); break;\n          case \"workload_curiousu\": coltitle = getTid('utwente_education:site.studyfinder.js.workload'); break;\n        }\n\n        const cellnode = dompack.create(\"div\", {\n          className: \"col--\" + this.tablecellnames_programme[i],\n          textContent: coltitle,\n          dataset: { name: this.tablecellnames_programme[i] }\n        });\n\n        cellnode.addEventListener(\"click\", ev => this.sortColumn(cellnode));\n        this.tableheader.appendChild(cellnode);\n      }\n\n      this.programmescontainer.insertBefore(this.tableheader, this.programmescontainer.firstChild);\n\n      this.applyViewModeClass(\"list\");\n\n      this.programmescontainer.classList.add(\"studyfinderprogrammes--listview\");\n      this.programmescontainer.classList.remove(\"studyfinderprogrammes--detailview\");\n    }\n  }\n\n  sortDetails(colnode: HTMLElement) {\n    //    let isothercolumn = colnode != this.sortcolumn;\n    this.sortcolumn = colnode;\n\n    const sortasc = true;\n\n    let sortedprogrammes = [];\n    for (const node of this.programmescontainer.querySelectorAll<HTMLElement>(\".studyfinder__programme\")) {\n      let specializations = [];\n      let specParent;\n      for (const specNode of node.querySelectorAll<HTMLElement>(\".specialization__container\")) {\n        if (!specParent)\n          specParent = specNode.parentNode;\n        specializations.push(\n          {\n            text: specNode.dataset.sort ? this.getSortText(specNode) : (1000 + Number(specNode.dataset.specid)),\n            node: specNode\n          });\n      }\n\n      if (specializations.length) {\n        // Set specialization nodes in correct order\n        specializations = this.sortList(specializations, sortasc);\n        for (const spec of specializations)\n          specParent!.appendChild(spec.node);\n        // Move all unmatched specializations to the end (skipping the first 'header' row)\n        for (let i = 1; i < specParent!.childNodes.length - specializations.length; ++i)\n          specParent!.appendChild(specParent!.childNodes[1]);\n      }\n\n      sortedprogrammes.push(\n        {\n          text: this.getSortText(node),\n          node: node\n        });\n    }\n\n    // Set programme nodes in correct order\n    sortedprogrammes = this.sortList(sortedprogrammes, sortasc);\n    for (const prog of sortedprogrammes)\n      this.programmescontainer.appendChild(prog.node);\n    //ADDME: When to reset to original order?\n  }\n\n  sortColumn(colnode: HTMLElement) {\n    const isothercolumn = colnode !== this.sortcolumn;\n\n    if (isothercolumn && this.sortcolumn)\n      this.sortcolumn.classList.remove(\"sortactive\");\n\n    this.sortcolumn = colnode;\n    this.sortcolumn.classList.add(\"sortactive\");\n\n    let sortasc = colnode.classList.contains(\"sort-asc\");\n    if (!isothercolumn) { //If same column, invert ordering\n      if (!sortasc) {\n        colnode.classList.add(\"sort-asc\");\n        sortasc = true;\n      } else {\n        colnode.classList.remove(\"sort-asc\");\n        sortasc = false;\n      }\n    }\n\n    const scoresort = this.sortcolumn === this.scorecolumn;\n    let sortedprogrammes = [];\n    for (const node of this.programmescontainer.querySelectorAll<HTMLElement>(scoresort ? \".isprogramme[data-sort]\" : \".isprogramme .cell--\" + colnode.dataset.name)) {\n      // we are a programme, any specializations rows following this row belong to this programme\n      const specializations = [];\n      let snode: HTMLElement | null = (scoresort ? node.nextSibling : (node.parentNode as HTMLElement)!.nextElementSibling) as HTMLElement;\n      while (snode && snode.classList.contains(\"specialization\")) {\n        specializations.push({\n          text: scoresort\n            ? (snode.dataset.sort ? this.getSortText(snode) : (1000 + Number(snode.dataset.specid)))\n            : this.getSortText(dompack.qS<HTMLElement>(snode, \".cell--\" + colnode.dataset.name)),\n          row: snode\n        });\n        snode = snode.nextElementSibling as HTMLElement;\n      }\n\n      sortedprogrammes.push(\n        {\n          text: this.getSortText(node),\n          row: (scoresort ? node : node.parentNode) as HTMLElement,\n          specializations: this.sortList(specializations, sortasc)\n        });\n    }\n\n    sortedprogrammes = this.sortList(sortedprogrammes, sortasc);\n\n    //Now set nodes in correct order\n    for (let i = 0; i < sortedprogrammes.length; ++i) {\n      this.programmescontainer.appendChild(sortedprogrammes[i].row);\n      for (let s = 0; s < sortedprogrammes[i].specializations.length; ++s)\n        this.programmescontainer.appendChild(sortedprogrammes[i].specializations[s].row);\n    }\n  }\n\n  getSortText(node: HTMLElement | null): string | number {\n    if (!node)\n      return \"\"; // \" - \" + node.parentNode.dataset.idx;\n    if (node.dataset.sort)\n      return Number(node.dataset.sort);\n    return node.innerHTML.replace(/<\\/?[^>]+(>|$)/g, \"\").toUpperCase() + \" - \" + (node.parentNode as HTMLElement).dataset.idx;\n  }\n\n  sortList<T extends { text: string | number }>(list: T[], sortasc: boolean): T[] {\n    return [...list].sort((a: { text: string | number }, b: { text: string | number }) => {\n      if (typeof a.text === \"number\" && typeof b.text === \"number\")\n        return (a.text - b.text) * (sortasc ? 1 : -1);\n\n      return String(a.text).localeCompare(String(b.text)) * (sortasc ? 1 : -1);\n    });\n  }\n\n\n  toggleSpecializations(ev: Event | null, programmenode?: HTMLElement) {\n    if (ev && !(ev.target! as HTMLElement).closest(\".togglespecializations\"))\n      return;\n\n    if (ev)\n      ev.preventDefault();\n\n    const itemnode = programmenode ? programmenode : (ev?.target as HTMLElement).closest<HTMLElement>(\".studyfinder__programme\");\n    if (!itemnode)\n      return;\n\n\n    if (!this.isdetailsview) {\n      if (itemnode.classList.contains(\"expanded\")) { //remove specialization rows\n        while (itemnode.nextElementSibling?.classList.contains(\"specialization\"))\n          itemnode.nextElementSibling.remove();\n\n        itemnode.classList.remove(\"expanded\");\n\n        this.activeitem = null;\n\n        return;\n      }\n\n      //  if( this.activeitem && ev ) //close previous if from click action\n      //    this.toggleSpecializations( null, this.activeitem );\n\n      //Add specialization rows\n      let specializations = [];\n      if (this.sortcolumn) {//if ordering is set, use this\n        const sortasc = this.sortcolumn.classList.contains(\"sort-asc\");\n\n        for (let i = 0; i < this.items[Number(itemnode.dataset.idx)].specializations.length; ++i) {\n          const snode = this.items[Number(itemnode.dataset.idx)].specializations[i].compact;\n          specializations.push({\n            text: this.getSortText(dompack.qS<HTMLElement>(snode, \".cell--\" + this.sortcolumn.dataset.name)),\n            row: snode\n          });\n        }\n        specializations = this.sortList(specializations, sortasc);\n        for (let i = specializations.length - 1; i >= 0; --i)\n          itemnode.after(specializations[i].row);\n      } else {//no ordering, just push\n        for (let i = this.items[Number(itemnode.dataset.idx)!].specializations.length - 1; i >= 0; --i)\n          itemnode.after(this.items[Number(itemnode.dataset.idx)!].specializations[i].compact);\n      }\n\n      itemnode.classList.add(\"expanded\");\n\n      this.activeitem = itemnode;\n\n      return;\n    }\n\n    const spnode = itemnode.querySelector<HTMLElement>(\".programme_specializations\");\n    if (!spnode)\n      return;\n\n    if (spnode.classList.contains(\"show\")) {\n      (spnode.parentNode! as HTMLElement).classList.remove(\"studyfinder__programme--specializationsvisible\");\n      spnode.style.height = spnode.clientHeight + \"px\";\n      spnode.classList.add(\"beforehide\");\n      void (spnode.clientWidth); //force css update\n      spnode.classList.remove(\"show\");\n      spnode.style.height = \"0px\";\n\n      setTimeout(() => spnode.classList.remove(\"beforehide\"), 300);\n    } else {\n      spnode.style.height = spnode.children[0].clientHeight + \"px\";\n      void (spnode.clientWidth); //force css update\n      spnode.classList.add(\"show\");\n      (spnode.parentNode! as HTMLElement).classList.add(\"studyfinder__programme--specializationsvisible\");\n      setTimeout(function () {\n        if (spnode.classList.contains(\"show\"))\n          spnode.style.height = \"auto\";\n      }, 300);\n    }\n  }\n\n\n  initAutoSuggest() {\n    // A slightly modified version of initSearchSuggestions to highlight matches within suggestions, not just the first x characters\n    const searchnode = this.form.querySelector<HTMLInputElement>(\"input[data-autocomplete-studyfinder]\");\n    if (searchnode) {\n      //  const catalogtag = searchnode.getAttribute(\"data-autocomplete-studyfinder\");\n      //  if (!catalogtag)\n      //    return;\n\n      UTAutoComplete({\n        input: searchnode,\n        className: 'ut-autocomplete',\n        preventSubmit: 1,\n        fetch: async (text, update) => {\n          const suggestions = this.searchIndex.suggest(text).slice(0, 10);\n\n          update(suggestions.map(_ => { return { label: _, value: _ }; }));\n        },\n        onSelect: (item) => {\n          searchnode.value = item.label ?? \"\";\n          this.doFilter();\n        }\n      });\n    }\n  }\n\n  suggestProgrammes(request: { term: string }, callback: (hits: unknown[]) => void) {\n    const suggestions = this.searchIndex.suggest(request.term);\n    callback(suggestions.slice(0, 10));\n  }\n\n  refreshFilterFeedbackUI() {\n    // Reset highlighted search terms before searching\n    for (const item of this.items) {\n      item.title.textContent = String(item.title.textContent);\n      item.description.textContent = String(item.description.textContent);\n\n      const itemNode = this.isdetailsview ? item.details : item.compact;\n      delete itemNode.dataset.sort;\n\n      for (const spec of item.specializations) {\n        spec.title.textContent = String(spec.title.textContent);\n        spec.description.textContent = String(spec.description.textContent);\n\n        const specNode = this.isdetailsview ? spec.details : spec.compact;\n        delete specNode.dataset.sort;\n      }\n    }\n    super.refreshFilterFeedbackUI();\n  }\n\n  rpccache: RPCCache | null = null;\n\n  showResults() {\n    const activefilters = Object.keys(this.filters).length;\n    let totalfound = 0;\n\n    if (this.isdetailsview)\n      this.programmescontainer.replaceChildren();\n    else {//table, keep first row\n      const firstnode = this.tableheader;\n      while (firstnode.nextSibling)\n        firstnode.nextSibling.remove();\n    }\n\n    //console.log(\"RPC CACHE\", this.rpccache);\n\n    for (const item of this.items) {\n      const itemNode = this.isdetailsview ? item.details : item.compact;\n\n      let matchcount = 0;\n      for (const key of Object.keys(this.filters)) {\n        if (key === \"words\") {\n          if (this.rpccache) {\n            const progscore = this.rpccache.ids.indexOf(itemNode.dataset.id!);\n            const progtitlescore = this.rpccache.progtitleids.indexOf(itemNode.dataset.id!);\n            const specscore = this.rpccache.expandids.indexOf(itemNode.dataset.id!);\n            const spectitlescore = this.rpccache.expandtitleids.indexOf(itemNode.dataset.id!);\n            if (progscore > -1 || specscore > -1) { // if the programme title matches, the programme also matches, so we don't have to check the title score\n              let score = 1;\n              if (progtitlescore > -1) // sort programme title results first\n                score += progtitlescore;\n              else if (spectitlescore > -1) // sort specialization title results after programme title results\n                score += this.rpccache.progtitleids.length + spectitlescore;\n              else if (progscore > -1) // sort programme description results after specialization title results\n                score += this.rpccache.progtitleids.length + this.rpccache.expandtitleids.length + progscore;\n              else // sort specialization description results last\n                score += this.rpccache.progtitleids.length + this.rpccache.expandtitleids.length + this.rpccache.ids.length + specscore;\n              itemNode.dataset.sort = String(score);\n              this.sortcolumn = this.scorecolumn;\n              //is result found within a specialization, then expand view\n              if (itemNode.dataset.specializations && specscore > -1) {\n                itemNode.classList.add(\"expanded\");\n                for (const spec of item.specializations) {\n                  const specNode = this.isdetailsview ? spec.details : spec.compact;\n                  const score2 = 1 + this.rpccache.specids.indexOf(spec.compact.dataset.specid!);\n                  if (score2)\n                    specNode.dataset.sort = String(score2);\n                }\n              }\n\n              ++matchcount;\n            }\n          }\n          continue;\n        }\n\n        const itemdata = JSON.parse(itemNode.dataset.filterdata!);\n\n        let tags = null;\n        if (key in itemdata) {\n          tags = itemdata[key];\n        } else { // deprecated, please don't add attributes for the search anymore.  (arnold: I wouldn't deprecate this, separate data- attributes are way easier to read in the DOM and thus debug)\n          const attr = itemNode.dataset[key]; // find a data-<key> attribute which matches the name of the filter input/select's name=\"<key>\"\n\n          if (!attr) {\n            console.log(\"Cannot find search key '\" + key + \"'\");\n            console.log(\"Got\", itemdata);\n            continue; // the item has no data associated to this filter\n          }\n\n          tags = attr.split(\" \");\n        }\n\n\n        const itemvalue = tags;\n        const searchvalue = this.filters[key];\n\n\n        if (Array.isArray(searchvalue) && Array.isArray(itemvalue)) {\n          // Find multiple values in multiple values\n          if (this.debug)\n            console.log(\"(search)\", searchvalue, \"ANYIN\", itemvalue);\n\n          for (let i = 0; i < this.filters[key].length; ++i) {\n            if (itemvalue.indexOf(this.filters[key][i]) > -1) {\n              ++matchcount;\n              break;\n            }\n          }\n        } else if (Array.isArray(itemvalue)) {\n          if (this.debug)\n            console.log(\"(search)\", searchvalue, \"IN\", itemvalue);\n\n          // lookup single value (pulldown or text) in array\n          if (itemvalue.indexOf(this.filters[key]) > -1)\n            ++matchcount;\n        } else if (Array.isArray(searchvalue)) {\n          if (this.debug)\n            console.log(itemvalue, \"IN (search)\", searchvalue);\n\n          if (searchvalue.indexOf(itemvalue) > -1)\n            ++matchcount;\n        } else { // 1 op 1\n          if (this.debug)\n            console.log(itemvalue, \"==\", searchvalue);\n\n          // lookup single value (pulldown or text) in a non-array (number of string)\n          const matchvalue = (typeof itemvalue === \"number\" ? parseInt(this.filters[key] as string) : this.filters[key]);\n          //console.info(\"match\", matchvalue, typeof(matchvalue));\n          if (itemvalue === matchvalue)\n            ++matchcount;\n        }\n      }\n\n\n      if (matchcount === activefilters) {\n        ++totalfound;\n\n        itemNode.style.opacity = '0';\n        this.programmescontainer.appendChild(itemNode);\n\n        if ( /*!this.isdetailsview && */ itemNode.classList.contains(\"expanded\")) {\n          itemNode.classList.remove(\"expanded\");//remove so in toggle it get actived again\n          this.toggleSpecializations(null, itemNode);\n        }\n\n        void (itemNode.clientHeight);//force css refresh\n        itemNode.style.opacity = '1';\n      }\n    }\n\n    if (!this.isdetailsview) {\n      if (this.sortcolumn)\n        this.sortColumn(this.sortcolumn);\n    } else if (this.isdetailsview && this.sortcolumn)\n      this.sortDetails(this.sortcolumn);\n\n    this.setFeedback(totalfound);\n  }\n\n  async doSearchWords(words: string) {\n    this.resetFilters(true);\n    const value: RPCCache = { ids: [], progtitleids: [], expandids: [], expandtitleids: [], specids: [], words };\n    const result = this.searchIndex.search(words);\n    for (const item of result.items) {\n      const title_result = this.highlightSearchTerms(result.terms, item.title, item.titleNode);\n      if (title_result) {\n        if (!item.specid && !value.progtitleids.includes(item.id))\n          value.progtitleids.push(item.id);\n        else if (item.specid && !value.expandtitleids.includes(item.id))\n          value.expandtitleids.push(item.id);\n      }\n      this.highlightSearchTerms(result.terms, item.description, item.descriptionNode);\n      if (item.specid) {\n        if (!value.expandids.includes(item.id))\n          value.expandids.push(item.id);\n        if (!value.specids.includes(item.specid))\n          value.specids.push(item.specid);\n      } else if (!value.ids.includes(item.id))\n        value.ids.push(item.id);\n    }\n    return value;\n  }\n\n  highlightSearchTerms(terms: string[], text: string, node: HTMLElement) {\n    const regex = new RegExp(`\\\\b(${terms.join(\"|\")})\\\\b`, \"ig\");\n    const descriptionNodes = [];\n    let lastIndex = 0;\n    let match;\n    while ((match = regex.exec(text)) !== null) {\n      descriptionNodes.push(text.substring(lastIndex, match.index));\n      descriptionNodes.push(<span class=\"ut-querymatch\" > {match[0]} </span>);\n      lastIndex = match.index + match[0].length;\n    }\n    if (!lastIndex) {\n      node.textContent = text;\n    } else {\n      if (lastIndex < text.length)\n        descriptionNodes.push(text.substr(lastIndex));\n\n      node.replaceChildren();\n      for (const descNode of descriptionNodes)\n        if (typeof descNode === \"string\")\n          node.append(descNode);\n        else\n          node.appendChild(descNode);\n    }\n    return lastIndex > 0;\n  }\n}\n\ndompack.register(\".filteredoverview__filterholder.filteredoverview--studyfinder\", node => new FilterStudyFinder());\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/webfeatures/studyfinder/studyfinder.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_education\",\"en\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"nl\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duur\",\"language\":\"Taal\",\"specializations\":\"Specialisaties\",\"study\":\"Studie\",\"workload\":\"Werkdruk\"}}}});\nregisterTexts(\"utwente_education\",\"de\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Dauer\",\"language\":\"Sprache\",\"specializations\":\"Spezialisierungen\",\"study\":\"Studie\",\"workload\":\"Arbeitsbelastung\"}}}});\nregisterTexts(\"utwente_education\",\"ar\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"bg\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"el\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"es\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"id\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"pt\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"ro\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\nregisterTexts(\"utwente_education\",\"zh\",{\"site\":{\"studyfinder\":{\"js\":{\"degree\":\"Programme\",\"duration\":\"Duration\",\"language\":\"Language\",\"specializations\":\"Specialisations\",\"study\":\"Study\",\"workload\":\"Workload\"}}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n/*\nlive:         https://www.utwente.nl/en/education/scholarship-finder/\ntest (Moe):   https://utwente.moe.sf.webhare.nl/en/education/scholarship-finder/\ntest (Kodos): https://site.kodos.sf.webhare.nl/ut-pages/filterpages/scholarship-finder/\n*/\n\nimport \"./scholarshipfinder.scss\";\nimport * as dompack from 'dompack';\nimport * as filteredoverview from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview\";\n\n\nclass ScholarshipFinderFilter extends filteredoverview.ClientSideFilteredOverview {\n  constructor(options) {\n    super({ ...options, filterpagetype: 'scholarshipfinder' });\n    this.lastedutype = '';\n    this.itemscontainer.classList.add(\"scholarshipfinder--show\");\n    // this.setProgrammeFilter(); // Not needed ClientSideFilteredOverview does this already\n    // this.doFilter(); // FIXME: we need another way.. (a forcefilter option or default 'initialized' class?)\n  }\n\n  setProgrammeFilter() {\n    const edutype = this.form.elements.edutype.value;\n    if (this.lastedutype == edutype)\n      return;\n\n    if (!this.savedprogrammeoptions)\n      this.savedprogrammeoptions = Array.from(this.form.elements.programme.children);\n\n    this.lastedutype = edutype;\n    if (!edutype)\n      return;\n\n    dompack.qSA(this.form.elements.programme, \"option\").forEach(node => {\n      node.hidden = !(!node.dataset.edutype || node.dataset.edutype == edutype);\n      node.classList.toggle(\"ut-pulldown--hiddenitem\", !(!node.dataset.edutype || node.dataset.edutype == edutype));\n    });\n\n    //DON'T!!(this breaks filtering):\n    //recreate but filter options\n    //    dompack.empty(this.form.elements.programme);\n    //    this.form.elements.programme.append(...this.savedprogrammeoptions.filter(node => !node.dataset.edutype || node.dataset.edutype == edutype));\n  }\n\n  // override me to check/change/delete filters before new results are calculated\n  onFormFiltersUpdate(filters) {\n    if (filters.query) // checking both the existing and whether it's an empty string\n    {\n      delete filters.country;\n      delete filters.edutype;\n      delete filters.programme;\n    }\n\n    document.querySelector(\".scholarshipfinder__textsearch-explain\").style.display = \"\";\n    document.querySelector(\".scholarshipfinder__textsearch-explain\").classList.toggle(\"textsearchactive\", Boolean(filters.query));\n  }\n\n  showResults() {\n    if (this.fadetimer)\n      clearTimeout(this.fadetimer);\n\n    this.setProgrammeFilter();//toggle programme pulldowns\n\n    this.itemscontainer.classList.remove(\"scholarshipfinder--show\");\n    void (this.itemscontainer.clientWidth);//force css update\n\n    this.runFilterByDataTags();\n\n    this.fadetimer = setTimeout(function () { this.itemscontainer.classList.add(\"scholarshipfinder--show\"); }.bind(this), 500);\n  }\n}\n\ndompack.onDomReady(() => {\n  // This filterclass is meant for the following pages:\n  const hecl = document.documentElement.classList;\n  if (!hecl.contains(\"page--scholarshipfinder\"))\n    return;\n\n  window.filteredoverview = new ScholarshipFinderFilter(\n    { itemsselector: \".grantfinder__scholarship\" });\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from 'dompack';\nimport \"./transfer.scss\";\nimport \"./studyroute.scss\";\nimport services from \"../../shared/services.rpc.json?proxy\";\nimport * as whintegration from '@mod-system/js/wh/integration';\nimport * as widgets from \"@mod-utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects\";\nimport \"./transfer.lang.json\";\nimport { getTid, getHTMLTid } from \"@mod-tollium/js/gettid\";\nimport cPIR from \"@mod-utwente_base/webdesigns/ws2016/src/shared/peopleimages\";\n\nclass transferWidget {\n  constructor(node) {\n    this.node = node;\n\n    this.targetprogramme = this.node.dataset.targetprogramme;\n    if (!this.targetprogramme)\n      this.targetprogramme = \"\";\n\n    this.language = whintegration.config.locale.split(\"-\")[0];\n    this.baseurl = window.location.href.split('?')[0];\n\n    this.instituteselector = this.node.querySelector(\"select[name='edutype']\");\n    this.programmeselectors = this.node.querySelectorAll(\"select[name|='programme']\");\n    this.resultscontainer = this.node.querySelector(\".embeddedobject__transfer__results\");\n\n    this.istransferfrom = this.node.classList.contains(\"embeddedobject__transfer--from\");\n\n    this.activeprogrammes = null;\n\n    const institute = this.getUrlParam(\"edutype\");\n    if (this.instituteselector) {\n      if (institute && this.instituteselector.querySelector(\"option[value='\" + institute + \"']\")) {\n        this.institute = institute;\n        this.instituteselector.value = institute;\n        this.onOrgChange(this.getUrlParam(\"programme\"));\n      }\n\n      this.instituteselector.addEventListener(\"change\", ev => this.onOrgChange());\n    } else {\n      this.institute = this.node.dataset.edutype;\n\n      if (!this.programmeselectors.length && this.node.dataset.programme)\n        this.loadResults(this.institute, this.node.dataset.programme);\n    }\n\n    for (const selnode of this.programmeselectors)\n      selnode.addEventListener(\"change\", ev => this.onProgChange(selnode));\n  }\n\n  onProgChange(node) {\n    this.setUrlParam();\n    if (this.institute && node.value)\n      this.loadResults(this.institute, node.value);\n  }\n\n  async loadResults(institute, programme) {\n    const busylock = dompack.flagUIBusy({ ismodal: false, component: this.node });\n    this.node.classList.add(\"loading\");\n\n    const opt = {\n      targetprogramme: this.istransferfrom ? this.targetprogramme : \"\",\n      language: this.language\n    };\n\n    //let selprogrammetitle = this.activeprogrammes ? this.activeprogrammes.options[this.activeprogrammes.selectedIndex].textContent : \"\";\n\n    const result = await services.GetStudyRoutes(institute, programme, opt);\n\n    this.node.classList.remove(\"loading\");\n    busylock.release();\n\n    this.resultscontainer.replaceChildren();\n    if (result && result.routes) {\n      this.node.classList.add(\"hasresults\");\n      this.showRoutes(result.routes);\n    } else if (result && !result.routes) {\n      this.node.classList.remove(\"hasresults\");\n      this.resultscontainer.appendChild(\n        <div class=\"noresults\">\n          <div class=\"studyroute__route-desc\">\n            <b>{this.setHtmlContent(getHTMLTid('utwente_education:site.transferwidget.js.noroutes'))}</b>\n          </div>\n        </div>);\n    } else {\n      this.node.classList.remove(\"hasresults\");\n      this.resultscontainer.appendChild(\n        <div class=\"noresults\">\n          <div class=\"studyroute__route-header\">\n            <div class=\"studyroute__route-icon\" data-icon=\"no-results\"></div>\n            {this.setHtmlContent(getTid('utwente_education:site.transferwidget.js.noresults_title'))}\n          </div>\n          <div class=\"studyroute__route-desc\">\n            {this.setHtmlContent(result?.destination_title ? getHTMLTid('utwente_education:site.transferwidget.js.noresults_this', result.destination_title)\n              : getHTMLTid('utwente_education:site.transferwidget.js.noresults'))}\n          </div>\n        </div>);\n    }\n  }\n\n  setHtmlContent(content, className) {\n    if (!content)\n      return null;\n    const node = <div />;\n    node.innerHTML = content;\n    if (className)\n      node.className = className;\n    return node;\n  }\n\n  showRoutes(routes) {\n    for (let c = 0; c < routes.length; ++c) {\n      if (routes[c].programmes.length === 1 && routes[c].programmes[0].destination_programmeid === this.targetprogramme)\n        routes[c].programmes = [];//Don't show programme if one and is targetprogramme\n\n      const node = <div class=\"studyroute__route\">\n        <div class=\"studyroute__route-header\">\n          <div class=\"studyroute__route-icon\" data-icon={routes[c].icon}></div>\n          {this.setHtmlContent(routes[c].title + (this.istransferfrom ? '' : '<span class=\"studyroute__route-count\">(' + routes[c].programmes.length + ')</span>'))}\n        </div>\n        <div class=\"studyroute__route-desc\">{this.setHtmlContent(routes[c].description)}</div>\n        {routes[c].conditions\n          ? <div class=\"studyroute__route__conditions\">{this.setHtmlContent(routes[c].conditions)}</div>\n          : null\n        }\n\n        {routes[c].studyadvisor\n          ? this.setHtmlContent(routes[c].studyadvisor)\n          : null\n        }\n        {routes[c].show_ec && routes[c].programmes.length\n          ? <div class=\"studyroute__route-header-ec\">EC</div>\n          : null\n        }\n        {routes[c].programmes.map(item =>\n          <div class=\"studyroute__route-programme foldableprog\">\n            <div class=\"foldableprog__title\">\n              <div class=\"studyroute__route-icon\" data-icon={item.icon} data-ec={item.deficiencycredits}></div>\n              <div class=\"studyroute__route-title\">{item.title}</div>\n              {routes[c].show_ec\n                ? <div class=\"studyroute__route-ec\">{item.deficiencycredits}</div>\n                : null\n              }\n            </div>\n            <div class=\"foldableprog__foldcontainer\">\n              <div class=\"foldableprog__text\">\n                <div class=\"studyroute__route-intro\">\n                  {item.imagelink\n                    ? <div class=\"studyroute__route-intro__image\"><img src={item.imagelink} alt=\"\" /></div>\n                    : null\n                  }\n                  <div class=\"studyroute__route-intro__text\">\n                    {this.setHtmlContent(item.description)}\n                    {this.setHtmlContent(item.conditions, \"studyroute__route__conditions\")}\n\n                    {this.istransferfrom && item.link && !item.ishbo\n                      ? <a class=\"studyroute__route-link\" href={item.link}>{getTid('utwente_education:site.transferwidget.js.gotomaster')}</a>\n                      : null\n                    }\n                  </div>\n                </div>\n\n                {item.studyadvisor\n                  ? this.setHtmlContent(item.studyadvisor)\n                  : null\n                }\n\n              </div>\n            </div>\n          </div>\n        )}\n      </div>;\n\n      this.resultscontainer.appendChild(node);\n    }\n\n    this.pir = new cPIR();//get people images\n    widgets.initFoldableContent(\"foldableprog\");\n  }\n\n  onOrgChange(programme) {\n    this.institute = this.instituteselector.value;\n\n    this.activeprogrammes = this.node.querySelector(\"select[name='programme-\" + this.instituteselector.value + \"']\");\n    for (const node of this.programmeselectors) {\n      if (node === this.activeprogrammes || (!this.activeprogrammes && node.name === \"programme\")) {\n        node.classList.add(\"active\");\n        if (programme) {\n          let opt = node.querySelector(\"option[value='\" + programme + \"']\");\n          if (!opt) //then try crohocode\n            opt = node.querySelector(\"option[data-crohocode*='_\" + programme + \"_']\");\n          if (opt)\n            node.value = opt.value;\n        }\n      } else\n        node.classList.remove(\"active\");\n    }\n\n    if (this.activeprogrammes && this.activeprogrammes.value)\n      this.onProgChange(this.activeprogrammes);\n    else\n      this.setUrlParam();\n  }\n\n  setUrlParam() {\n    if (window.history && window.history.replaceState) {\n      const url = new URL(this.baseurl);\n      if (this.institute)\n        url.searchParams.set(\"edutype\", this.institute);\n\n      if (this.activeprogrammes && this.activeprogrammes.value)\n        url.searchParams.set(\"programme\", this.activeprogrammes.value);\n\n      history.replaceState(undefined, undefined, url.toString());\n    }\n  }\n\n  getUrlParam(name) {\n    return new URL(location.href).searchParams.get(name);\n  }\n}\n\ndompack.register(\".embeddedobject__transfer\", node => new transferWidget(node));\n","const { createService } = require(\"@mod-system/js/wh/rpc.ts\"); export default createService(\"utwente_education:service\");","// Auto-generated language file from /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/webfeatures/widgets/transfer/transfer.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_education\",\"en\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"nl\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Ga naar deze masteropleiding\",\"gotopremaster\":\"Lees meer over het pre-masterprogramma\",\"noresults\":[\"Er zijn bij ons geen mogelijkheden bekend om met jouw vooropleiding door te stromen naar een masteropleiding aan de UT. Denk je dat je met jouw bachelor toch toegelaten kunt worden tot een bepaalde master? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/onderwijs/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Neem dan contact op.\"}],\"noresults_this\":[\"Er zijn bij ons geen mogelijkheden bekend om met jouw vooropleiding door te stromen naar de master \",1,\" aan de UT. Denk je dat je met jouw bachelor toch toegelaten kunt worden? \",{\"t\":\"a\",\"link\":\" https://www.utwente.nl/onderwijs/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Neem dan contact op.\"}],\"noresults_title\":\"Geen doorstroommogelijkheden gevonden\",\"noroutes\":[\"Voor deze opleiding is er op dit moment geen doorstroominformatie bekend. Voor vragen kun je altijd \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/onderwijs/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact\"},\" met ons opnemen.\"]}}}});\nregisterTexts(\"utwente_education\",\"de\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-master's programme\",\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"Für diesen Studiengang gibt es derzeit keine Informationen zum Transfer. Du kannst uns jederzeit \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"kontaktieren\"},\".\"],\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}]}}}});\nregisterTexts(\"utwente_education\",\"ar\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"bg\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"el\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"es\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"id\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"pt\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"ro\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\nregisterTexts(\"utwente_education\",\"zh\",{\"site\":{\"transferwidget\":{\"js\":{\"gotomaster\":\"Go to this master\",\"gotopremaster\":\"Read more about the pre-masters’s programme\",\"noresults\":[\"With your previous education, there are no transfer possibilities to UT master’s that we are aware of. Do you think your bachelor’s might still be sufficiently related to one of our master’s or do you have questions about your eligibility? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/student-services/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_this\":[\"We are not aware of any transfer possibilities to the Master’s in \",1,\" at UT with your current programme. Do you think your bachelor’s might still be sufficiently related? \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"Contact us!\"}],\"noresults_title\":\"No transfer options found\",\"noroutes\":[\"No transfer information is currently available for this study programme. For questions, you can \",{\"t\":\"a\",\"link\":\"https://www.utwente.nl/en/education/master/contact/\",\"linkparam\":0,\"target\":\"\",\"subs\":\"contact us\"},\".\"]}}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/language/default.xml\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./programmedetails.scss\";\nimport * as dompack from \"dompack\";\n\nfunction programmeYearFilter(node) {\n  const container = dompack.closest(node, \".embeddedobject__programmedetails\");\n  const dateitems = container.querySelectorAll(\".line__description-text[data-year]\");\n\n  node.addEventListener(\"change\", ev => {\n    const val = node.value;\n    for (const item of dateitems)\n      item.style.display = !val || item.dataset.year === val ? \"\" : \"none\";\n  });\n}\n\ndompack.register(\".programmedetails__yearfilter select\", node => programmeYearFilter(node));\n","import \"./programmeheader.scss\";\nimport * as dompack from \"@webhare/dompack\";\n\ndompack.register<HTMLButtonElement>(\".programmedetailsheader__items-button\", btn => {\n\n  let timer: NodeJS.Timeout | null;\n  const mediaTwoRows = window.matchMedia(\"(max-width: 900px)\");\n  const mediaMobile = window.matchMedia(\"(max-width: 450px)\");\n\n  const itemslist = dompack.qR(btn.parentNode as HTMLElement, \".programmedetailsheader__items\");\n\n  window.addEventListener(\"resize\", () => {\n    let hidebtn = false;\n    if (mediaMobile.matches) {\n      if (itemslist.children.length <= 2) // 2 rows / 1 column in collapsed mode\n        hidebtn = true;\n    } else if (itemslist.children.length <= 4) // 2 rows / 2 columns in collapsed mode\n      hidebtn = true;\n\n    btn.hidden = hidebtn;\n  });\n\n  let hidebtn = false;\n  if (mediaMobile.matches) {\n    if (itemslist.children.length <= 2) // 2 rows / 1 column in collapsed mode\n      hidebtn = true;\n  } else if (itemslist.children.length <= 4) // 2 rows / 2 columns in collapsed mode\n    hidebtn = true;\n\n  btn.hidden = hidebtn;\n\n  btn.addEventListener(\"click\", () => {\n    clearTimeout(timer!);\n    // Toggle the expanded state\n    if (itemslist.classList.contains(\"programmedetailsheader__items--expanded\")) {\n      itemslist.style.height = `${itemslist.clientHeight}px`;\n      let itemh = itemslist.children[0].clientHeight;\n      if (mediaMobile.matches) {\n        if (itemslist.children.length > 1) // 2 rows / 1 column\n          itemh += itemslist.children[1].clientHeight;\n      } else if (mediaTwoRows.matches && itemslist.children.length > 2) // 2 rows / 2 columns\n        itemh += itemslist.children[3].clientHeight;\n      itemslist.style.height = `${itemh}px`;\n      btn.setAttribute(\"aria-expanded\", \"false\");\n\n      timer = setTimeout(() => {\n        itemslist.style.height = \"\";\n        itemslist.classList.remove(\"programmedetailsheader__items--expanded\");\n        dompack.dispatchCustomEvent(itemslist, \"ws:programmedetailsheader-toggle\", { bubbles: true, cancelable: false });\n      }, 300);\n\n    } else {\n      itemslist.style.height = `${itemslist.clientHeight}px`;\n      itemslist.classList.add(\"programmedetailsheader__items--expanded\");\n      itemslist.style.height = `${itemslist.scrollHeight}px`;\n      btn.setAttribute(\"aria-expanded\", \"true\");\n\n      timer = setTimeout(() => {\n        itemslist.style.height = \"\";\n        dompack.dispatchCustomEvent(itemslist, \"ws:programmedetailsheader-toggle\", { bubbles: true, cancelable: false });\n      }, 300);\n    }\n  });\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./mastercareerprospects.scss\";\nimport * as dompack from \"dompack\";\n\ndompack.register(\".widget-mastercareerprospects__stats__nav\", node => {\n  node.addEventListener(\"click\", ev => {\n    const btn = ev.target.closest(\"span[data-action]\");\n    if (btn) {\n      const sel_action = btn.dataset.action;\n      dompack.qSA(node, \"span[data-action]\").forEach(btn => {\n        dompack.toggleClass(btn, \"active\", sel_action == btn.dataset.action);\n      });\n\n      const basenode = node.closest(\".widget-mastercareerprospects__stats\");\n\n      if (sel_action == \"ov\") {\n        dompack.qS(basenode, \".widget-mastercareerprospects__stats__nl\").classList.remove(\"active\");\n        dompack.qS(basenode, \".widget-mastercareerprospects__stats__ov\").classList.add(\"active\");\n      } else {\n        dompack.qS(basenode, \".widget-mastercareerprospects__stats__nl\").classList.add(\"active\");\n        dompack.qS(basenode, \".widget-mastercareerprospects__stats__ov\").classList.remove(\"active\");\n      }\n    }\n  });\n});\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./relatedmasterprogrammes.scss\";\nimport * as dompack from \"dompack\";\n\ndompack.register(\".widget-relatedmasterprogrammes\", node => {\n\n  node.addEventListener(\"click\", ev => {\n    const morebtn = ev.target.closest(\".widget-relatedmasterprogrammes__more\");\n    if (morebtn) {\n      dompack.qSA(node, \".widget-relatedmasterprogrammes__programme--hidden\").forEach((item, i) => {\n        setTimeout(() => {\n          item.style.opacity = \"0\";\n          item.classList.remove(\"widget-relatedmasterprogrammes__programme--hidden\");\n          void (item.clientWidth);//force css update\n          item.style.opacity = \"1\";\n        }, 100 * i);\n\n        dompack.remove(morebtn);\n      });\n    }\n  });\n});\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./studyinnumbers.scss\";\nimport * as dompack from \"dompack\";\n\nclass studyInNumbers {\n  constructor(node) {\n    node.addEventListener(\"wh:visibilitychange\", ev => {\n      if (!ev.detail.visible)\n        return;\n\n      if (!ev.target.classList.contains(\"animate--started\")) {\n        ev.target.classList.add(\"animate--started\");\n        setTimeout(() => this.animate(ev.target), 200);\n      }\n    });\n    /*\n        Ps.initialize( dompack.qS(node, \".widget-studyinnumbers__scrollcontainer\")\n                     , { swipePropagation: false\n                       , wheelPropagation: false\n                       , suppressScrollX: true\n                       });\n    */\n  }\n\n  animate(container) {\n    const valuelabels = dompack.qSA(container, \".ratingchart__chart__value, .ratingchart__chart__countryvalue, .widget-studyinnumbers__percentagecircle > div, .widget-studyinnumbers__line__countryvalue\");\n    valuelabels.forEach(node => {\n      const endval = 1 * (node.dataset.percentage ? node.dataset.percentage : node.parentNode.dataset.percentage);\n      const t = Math.round(800 / endval);//animation steps over 800ms\n      setTimeout(() => this.setValue(node, endval, t), t);\n    });\n\n    dompack.qSA(container, \".ratingchart__chart__bars span[data-percentage]\").forEach(el => {\n      el.style.width = el.dataset.percentage + \"%\";\n    });\n\n    const contoursize = 214; // (circumference of circle in px)\n    dompack.qSA(container, \".widget-studyinnumbers__percentagecircle[data-percentage]\").forEach(node => {\n      if (node.dataset.percentage != \"0\")\n        node.querySelector(\"svg\").style.strokeDashoffset = Math.round(contoursize - (0.01 * node.dataset.percentage * contoursize));\n    });\n  }\n\n  setValue(el, endval, t) {\n    let val = 1 * el.textContent;\n    val += 1;\n    el.textContent = val;\n    if (val < endval)\n      setTimeout(() => this.setValue(el, endval, t), t);\n  }\n}\n\ndompack.register(\".widget-studyinnumbers\", node => new studyInNumbers(node));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./cssstudies.scss\";\nimport * as dompack from \"dompack\";\n\nclass cssStudiesSorter {\n  constructor(node) {\n    this.node = node;\n    this.headnode = node.querySelector(\"thead\");\n    this.headnode.addEventListener(\"click\", ev => this.onSort(ev));\n\n    this.bodynode = node.querySelector(\"tbody\");\n  }\n\n  onSort(ev) {\n    const selcol = dompack.closest(ev.target, \"th\");\n    if (!selcol)\n      return;\n\n    for (const hnode of this.node.querySelectorAll(\"thead th\")) {\n      if (hnode === selcol) {\n        if (hnode.classList.contains(\"sort--down\")) {\n          hnode.classList.remove(\"sort--down\");\n          hnode.classList.add(\"sort--up\");\n        } else {\n          hnode.classList.remove(\"sort--up\");\n          hnode.classList.add(\"sort--down\");\n        }\n      } else {\n        hnode.classList.remove(\"sort--down\");\n        hnode.classList.remove(\"sort--up\");\n      }\n    }\n\n    this.sortTable(selcol);\n  }\n\n  sortTable(selcol) {\n    const colname = selcol.dataset.sort;\n\n    let group;\n    const groupedlines = [];\n    let previdx = -1;\n\n    for (const node of this.node.querySelectorAll(\"tbody > tr\")) {\n      const idx = parseInt(node.dataset.idx); //idx also groups lines\n      let sortval = idx;\n      if (colname !== \"title\") {\n        sortval = node.dataset[colname];\n        if (!sortval)\n          sortval = \"NODATE\";\n      }\n\n      if (idx !== previdx) {\n        if (group)\n          groupedlines.push(group);\n\n        group = {\n          idx: idx,\n          sortval: sortval,\n          lines: []\n        };\n      }\n      group.lines.push(node);\n\n      previdx = idx;\n    }\n    //And finaly add last item\n    groupedlines.push(group);\n\n    if (selcol.classList.contains(\"sort--up\"))\n      groupedlines.sort(this.doSortAsc);\n    else\n      groupedlines.sort(this.doSortDesc);\n\n    //Now rebuild table with sorted lines\n    for (let c = 0; c < groupedlines.length; ++c) {\n      for (let l = 0; l < groupedlines[c].lines.length; ++l) {\n        const row = groupedlines[c].lines[l];\n        if (c % 2)\n          row.classList.add(\"odd\");\n        else\n          row.classList.remove(\"odd\");\n\n        this.bodynode.appendChild(row);\n      }\n    }\n  }\n\n  doSortAsc(a, b) {\n    if (a.sortval > b.sortval)\n      return -1;\n    if (a.sortval < b.sortval)\n      return 1;\n\n    //If same then use idx\n    if (a.idx < b.idx)\n      return -1;\n    if (a.idx > b.idx)\n      return 1;\n\n    return 0;\n  }\n\n  doSortDesc(a, b) {\n    if (a.sortval < b.sortval)\n      return -1;\n    if (a.sortval > b.sortval)\n      return 1;\n\n    //If same then use idx\n    if (a.idx < b.idx)\n      return -1;\n    if (a.idx > b.idx)\n      return 1;\n\n    return 0;\n  }\n}\n\ndompack.register(\".embeddedobject__cssstudies\", node => new cssStudiesSorter(node));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./specializations.scss\";\nimport * as dompack from \"dompack\";\n\nclass ellipsisFoldout {\n  constructor(node, textcontainer) {\n    this.node = node;\n    this.textcontainer = dompack.qS(this.node, \".embeddedobject__specializations__specialization__ellipsis\");\n\n    this.node.addEventListener(\"click\", ev => {\n      if (!this.node.classList.contains(\"hasellipsis\"))\n        return;\n\n      if (ev.target.closest(\".embeddedobject__specializations__specialization__ellipsistoggle\")) {\n        dompack.stop(ev);\n        this.toggle();\n      } else if (!this.node.classList.contains(\"hasellipsis--open\")) { //click on item with active ellipsis then show full text (else just follow link)\n        dompack.stop(ev);\n        this.open();\n      }\n    });\n\n    window.addEventListener(\"load\", () => this.checkEllipsis());\n    window.addEventListener(\"resize\", () => this.checkEllipsis());\n    document.fonts.ready.then(() => this.checkEllipsis());\n    this.checkEllipsis();\n  }\n\n  checkEllipsis() {\n    // To keep it simple, remove open state when resizing\n    clearTimeout(this.timer);\n    this.node.classList.remove(\"hasellipsis--open\");\n    this.textcontainer.style.maxHeight = \"\";\n\n    //Check for ellipsis\n    this.ellipsisy = this.textcontainer.clientHeight;\n    this.node.classList.toggle(\"hasellipsis\", this.textcontainer.scrollHeight > this.ellipsisy);\n  }\n\n  toggle() {\n    if (this.node.classList.contains(\"hasellipsis--open\"))\n      this.close();\n    else\n      this.open();\n  }\n\n  open() {\n    clearTimeout(this.timer);\n\n    this.textcontainer.style.maxHeight = this.textcontainer.clientHeight + \"px\";\n    this.node.classList.add(\"hasellipsis--open\");\n    this.textcontainer.style.maxHeight = this.textcontainer.scrollHeight + \"px\";\n\n    this.timer = setTimeout(() => this.textcontainer.style.maxHeight = \"\", 300);\n  }\n\n  close() {\n    clearTimeout(this.timer);\n    this.textcontainer.style.maxHeight = this.textcontainer.clientHeight + \"px\";\n    void (this.textcontainer.clientHeight);\n\n    this.textcontainer.style.maxHeight = this.ellipsisy + \"px\";\n\n    this.timer = setTimeout(() => {\n      this.textcontainer.style.maxHeight = \"\";\n      this.node.classList.remove(\"hasellipsis--open\");\n    }, 300);\n  }\n}\n\ndompack.register(\".embeddedobject__specializations__specialization\", node => new ellipsisFoldout(node));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./vacancies.scss\";\nimport * as dompack from 'dompack';\nimport { relayoutWidgets } from '@mod-utwente_base/webfeatures/utwidgets/layout';\nimport service from \"./vacancies.rpc.json?proxy\";\n\nasync function getVacancies(node) {\n  const options = JSON.parse(node.dataset.options);\n  const res = await service.ZoekVacatures(options.vw);\n\n  if (res && res.vacancies.length) {\n    res.vacancies.map((item) => {\n      node.appendChild(<a href={item.link} class=\"widget__listitem widget__listitem--link\">\n        <span class=\"widget__listitem-text\">{item.title}</span>\n        <span class=\"widget__listitem-subtext\">{item.subtext}</span>\n        <i class=\"widget__listitem-icon widget__listitem-icon--small UT-icon-UT_icon_52_arrow-right-round-16px\"></i>\n      </a>);\n    });\n  } else\n    node.classList.add(\"novacancies\");\n\n  //Trigger ut masonry update\n  relayoutWidgets(node);\n}\n\ndompack.register(\".widget-vacancies__list--afas\", node => getVacancies(node));\n","const { createService } = require(\"@mod-system/js/wh/rpc.ts\"); export default createService(\"utwente_jobs:utvacatures\");","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport './vacancies.scss';\nimport './vacanciesoverview-filters.scss';\nimport './vacancywidget/index';\n\nimport * as dompack from 'dompack';\nimport * as filteredoverview from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview\";\n\nclass VacancyOverviewFilter extends filteredoverview.ClientSideFilteredOverview {\n  constructor(options) {\n    super({ ...options, filterpagetype: 'vacancies', itemsselector: \".summary__item\" });\n\n    const vactypenode = this.form.querySelector(\"select[name='offerfamily']\");\n    if (vactypenode) {\n      this.branchenode = this.form.querySelector(\"select[name='offerprofile']\");\n      this.brancheoptions = [];\n      for (const node of this.branchenode.options)\n        this.brancheoptions.push({ value: node.value, title: node.textContent });\n\n      vactypenode.addEventListener(\"change\", ev => this.updateBrancheOptions(ev));\n      this.updateBrancheOptions({ target: vactypenode });\n    }\n\n    // FIXME: updating filters and freshing UI should be part of filteredoverview ?\n    this.updateFilters();\n    this.refreshFilterFeedbackUI();\n  }\n\n  updateBrancheOptions(ev) {\n    const seloption = ev.target.options[ev.target.selectedIndex];\n    const selectedbranchevalue = this.branchenode.value;\n    const branchids = seloption.dataset.branche ? \",\" + seloption.dataset.branche + \",\" : \"\";\n\n    this.branchenode.replaceChildren();\n\n    let selectedidx = -1;\n    for (let i = 0; i < this.brancheoptions.length; ++i) {\n      if (!seloption.dataset.branche || this.brancheoptions[i].value == \"\" || branchids.indexOf(\",\" + this.brancheoptions[i].value + \",\") != -1) {\n        if (selectedbranchevalue == this.brancheoptions[i].value)\n          selectedidx = i;\n        this.branchenode.appendChild(dompack.create(\"option\", {\n          value: this.brancheoptions[i].value,\n          textContent: this.brancheoptions[i].title,\n          selected: this.brancheoptions[i].value == selectedbranchevalue\n        }));\n      }\n    }\n\n    if (selectedidx > -1)\n      this.branchenode.value = selectedbranchevalue;\n  }\n\n  showResults() {\n    this.runFilterByDataTags();\n  }\n\n  isMatch(node) {\n    if (!super.isMatch(node))\n      return false;\n\n    const searchtext = this.form.elements.query.value;\n    if (searchtext\n      && !node.textContent.toUpperCase().includes(searchtext.toUpperCase())\n      && !node.dataset.plaintextsearch.toUpperCase().includes(searchtext.toUpperCase()))\n      return false;\n\n    return true;\n  }\n}\n\nfunction checkTagClick(event) {\n  const tag = event.target.closest(\".ut-vacancies__tag\");\n  if (!tag)\n    return;\n\n  dompack.stop(event);\n  //look for the tag in offerprofile\n  const matchoption = dompack.qSA(\"[name=offerprofile] option\").filter(opt => opt.textContent == tag.textContent)[0];\n  if (matchoption)\n    dompack.changeValue(dompack.qS(\"[name=offerprofile]\"), matchoption.value);\n}\n\ndompack.onDomReady(() => {\n  if (!document.documentElement.classList.contains(\"page--vacanciesoverview\"))\n    return;\n\n  window.addEventListener(\"click\", checkTagClick);\n  window.filteredoverview = new VacancyOverviewFilter(\n    { filterpagetype: \"vacancies\" });\n});\n","import { ClientSideFilteredOverview } from \"@mod-utwente_base/webdesigns/ws2016/src/filteredoverview\";\nimport * as dompack from \"@webhare/dompack\";\nimport \"./projectslist.scss\";\n\nclass ProjectsList extends ClientSideFilteredOverview {\n  listnode: HTMLElement;\n\n  constructor(node: HTMLElement, options: { itemsselector?: string }) {\n    super({ ...options, filterpagetype: \"projectlist\" }); //filterpagetype is used for GTM\n\n    this.listnode = dompack.qS(node, \".filteredoverview__items\")!;\n\n    const listtoggle = dompack.qS(\".filteredoverview__viewmode\");\n    if (listtoggle) {\n      const feedbackbar = listtoggle.closest(\".filteredoverview__feedbackandviewbar\")!;\n      feedbackbar.classList.add(this.listnode.classList.contains(\"filteredoverview__items--listview\") ? \"filteredoverview--listview\" : \"filteredoverview--detailview\");//initial detailview\n\n      dompack.addDocEventListener(listtoggle, \"click\", ev => {\n        const togglenode = ev.target.closest(\"[data-viewmode]\") as HTMLElement | null;\n        if (!togglenode)\n          return;\n\n        if (togglenode.dataset.viewmode === \"detailview\" && feedbackbar.classList.contains(\"filteredoverview--detailview\"))\n          return;//already in detailview\n\n        if (togglenode.dataset.viewmode !== \"detailview\" && !feedbackbar.classList.contains(\"filteredoverview--detailview\"))\n          return;//already in listview\n\n        if (togglenode.dataset.viewmode === \"detailview\") {\n          feedbackbar.classList.remove(\"filteredoverview--listview\");\n          feedbackbar.classList.add(\"filteredoverview--detailview\");\n\n          this.listnode.classList.remove(\"filteredoverview__items--listview\");\n        } else {\n          feedbackbar.classList.add(\"filteredoverview--listview\");\n          feedbackbar.classList.remove(\"filteredoverview--detailview\");\n\n          this.listnode.classList.add(\"filteredoverview__items--listview\");\n        }\n      });\n    }\n  }\n\n  showResults() {\n  }\n}\n\ndompack.register(\".projectslist__results\", node => new ProjectsList(node, { itemsselector: \".filteredoverview__item\" }));\n","//Adds autocomplete for VLS School and our organization database\nimport * as dompack from '@webhare/dompack';\n//@ts-ignore not documented yet\nimport leadsservice from './internal/leads.rpc.json?proxy';\nimport { getMatches } from './shared_search';\nimport { setupValidator, FormBase } from \"@mod-publisher/js/forms\";\n\nimport UTAutoComplete from '@mod-utwente_base/webdesigns/ws2016/src/components/autocompleter2/autocompleter';\nimport { TrigramMatcher } from '@mod-utwente_design';\n\ninterface FoundName {\n  title: string;\n  aliases: string[];\n}\n\nfunction getFlatList(list: FoundName[]) {\n  const names: string[] = [];\n  for (const entry of list)\n    names.push(entry.title, ...entry.aliases);\n  return names;\n}\n\nclass PreppedNameList {\n  prep;\n  //build a reverse alias->name list ... we're supposed to MATCH aliases in the trigram list but not SHOW them\n  aliasunmap = new Map<string, string>;\n\n  constructor(list: FoundName[]) {\n    const flatlist = getFlatList(list);\n    this.prep = new TrigramMatcher(flatlist);\n    for (const entry of list)\n      for (const alias of entry.aliases)\n        this.aliasunmap.set(alias, entry.title);\n  }\n\n  getMatches(searchterm: string): string[] {\n    const finallist: string[] = [];\n\n    /*\n        for (const suggestion of scoreStuff(this.prep, searchterm)\n          .sort((a, b) => (b.score - a.score))//highest score first\n          .map(_ => this.aliasunmap.get(_.str) || _.str)) { //remap to riginal nam\n          //because we remap, we might find the same name multiple times. only keep the first (highest score)\n          if (!finallist.includes(suggestion))\n            finallist.push(suggestion);\n        }\n    */\n    let scoredlist = this.prep.score(searchterm);\n\n    // Only show results which scored at least 66% of max score found\n    const minscore = scoredlist.length ? scoredlist[0].score * 0.66 : 0;\n\n    scoredlist = scoredlist.filter(_ => _.score > minscore);\n\n    for (const suggestion of scoredlist.map(_ => this.aliasunmap.get(_.str) || _.str)) {\n      //because we remap, we might find the same name multiple times. only keep the first (highest score)\n      if (!finallist.includes(suggestion))\n        finallist.push(suggestion);\n    }\n\n    return finallist;\n  }\n}\n\nclass Scope {\n  citylistpromise: Promise<string[]> | null = null;\n  cityprep: TrigramMatcher | null = null;\n  namelistpromises: Record<string, Promise<FoundName[]>> = {};\n  namelistprep: Record<string, PreppedNameList> = {};\n}\n\nconst scopes: Record<string, Scope> = {};\nconst lastsuggestions = new Map<HTMLInputElement, string[]>();\n\nfunction getScope(limittypes: string[]) {\n  let scopename = (limittypes.includes('school') ? 'school' : '');\n  if (!scopename)\n    scopename = 'all';\n\n  if (!scopes[scopename])\n    scopes[scopename] = new Scope;\n\n  return scopes[scopename];\n}\n\nasync function getCities(limittypes: string[], searchterm: string, groupname: string) {\n  const scope = getScope(limittypes);\n  if (searchterm.length <= 0)\n    return;\n\n  if (!scope.citylistpromise) {\n    //@ts-ignore leadsservice missing types\n    scope.citylistpromise = leadsservice.getOrgCities(limittypes);\n  }\n\n  if (searchterm.length <= 1) //we'll wait for you to type 2 chars, but at least we'll have the list!\n    return;\n\n  if (limittypes.length === 1 && limittypes[0] === 'school') {\n    if (!scope.cityprep)\n      scope.cityprep = new TrigramMatcher(await scope.citylistpromise!);\n\n    let scoredlist = scope.cityprep.score(searchterm);\n\n    // Only show results which scored at least 66% of max score found\n    const minscore = scoredlist.length ? scoredlist[0].score * 0.66 : 0;\n    scoredlist = scoredlist.filter(_ => _.score > minscore);\n\n    return scoredlist.map(_ => { return { label: _.str, value: _.str, group: groupname }; });\n  }\n\n  const suggestions = getMatches(await scope.citylistpromise!, searchterm);\n  return suggestions.map(_ => { return { label: _, value: _, group: groupname }; });\n}\n\nasync function getOrgNames(node: HTMLInputElement, limittypes: string[], cityfield: HTMLInputElement, searchterm: string, groupname: string) {\n  const scope = getScope(limittypes);\n  if (searchterm.length < 1 || !cityfield.value)\n    return;\n\n  const key = cityfield.value;\n  if (!scope.namelistpromises[key]) {\n    //@ts-ignore leadsservice missing types\n    scope.namelistpromises[key] = leadsservice.getOrgNames2(limittypes, cityfield.value);\n  }\n\n  if (limittypes.length === 1 && limittypes[0] === 'school') {\n    if (!scope.namelistprep[key])\n      scope.namelistprep[key] = new PreppedNameList(await scope.namelistpromises[key]);\n\n    const suggestions = scope.namelistprep[key].getMatches(searchterm);\n    lastsuggestions.set(node, suggestions);\n\n    return suggestions.map(_ => { return { label: _, value: _, group: groupname }; });\n  }\n\n  const suggestions = getMatches(getFlatList(await scope.namelistpromises[key]), searchterm);\n  return suggestions.map(_ => { return { label: _, value: _, group: groupname }; });\n}\n\nfunction setupSchoolCityField(node: HTMLInputElement) {\n  const limittypes = node.dataset.limittypes ? node.dataset.limittypes.split(' ') : [];\n  const groupname = node.matches(\":lang(nl)\") ? \"Bedoelde je:\" : \"Did you mean:\";\n\n  UTAutoComplete({\n    input: node,\n    className: 'ut-autocomplete',\n    preventSubmit: 1,\n    fetch: async function (text, update) {\n      const suggestions = await getCities(limittypes, text, groupname);\n      update(suggestions || []);\n    },\n    onSelect: function (item) {\n      node.value = item.label ?? \"\";\n    },\n  });\n}\n\nfunction validateSchoolName(field: HTMLInputElement) {\n  const suggestions = lastsuggestions.get(field);\n  ///@ts-ignore we're working around lack of suggestion support in the FormBase\n  field.propWhValidationSuggestion = null;\n\n  if (suggestions?.length && !suggestions.includes(field.value)) {\n    const text = field.matches(\":lang(nl)\") ? \"Bedoelde je\" : \"Did you mean\";\n    ///@ts-ignore we're working around lack of suggestion support in the FormBase\n    field.propWhValidationSuggestion = <span class=\"wh-form__emailcorrection\"> {text} <a href=\"#\" class=\"wh-form__emailcorrected\" on={{\n      pointerdown: (evt: Event) => {\n        field.value = suggestions[0];\n        ///@ts-ignore we're working around lack of suggestion support in the FormBase\n        field.propWhValidationSuggestion = null;\n        dompack.stop(evt);\n        ///@ts-ignore we're working around lack of suggestion support in the FormBase\n        FormBase.getForNode(field.closest(\"form\"))._reportFieldValidity(field);\n      }\n    }} > {suggestions[0]}</a> ? </span>;\n  }\n  return \"\";\n}\n\nfunction setupSchoolNameField(node: HTMLInputElement) {\n  //find our preceding schoolcity field\n  const limittypes = node.dataset.limittypes ? node.dataset.limittypes.split(' ') : [];\n  const relevantfields = dompack.qSA<HTMLInputElement>('.utvoorl--orgselectcity input, .utvoorl--orgselectname input');\n  const mypos = relevantfields.indexOf(node);\n  if (mypos > 0) {\n    const groupname = node.matches(\":lang(nl)\") ? \"Bedoelde je:\" : \"Did you mean:\";\n\n    UTAutoComplete({\n      input: node,\n      className: 'ut-autocomplete',\n      preventSubmit: 1,\n      fetch: async function (text, update) {\n        const suggestions = await getOrgNames(node, limittypes, relevantfields[mypos - 1], text, groupname);\n        update(suggestions || []);\n      },\n      onSelect: function (item) {\n        node.value = item.label ?? \"\";\n      },\n    });\n\n    setupValidator(node, validateSchoolName);\n  }\n}\n\ndompack.register('.utvoorl--orgselectcity input', setupSchoolCityField);\ndompack.register('.utvoorl--orgselectname input', setupSchoolNameField);\n","const { createService } = require(\"@mod-system/js/wh/rpc.ts\"); export default createService(\"utwente_voorlichting:leads\");","export function getMatches(results: string[], searchfor: string): string[] {\n  searchfor = searchfor.toUpperCase();\n  //get matches containing 'searchfor', and their position\n  let matches = results.map(text => ({ text, pos: text.toUpperCase().indexOf(searchfor) }));\n  //filter actual matches\n  matches = matches.filter(item => item.pos >= 0);\n  //sort by distance to start of string\n  matches = matches.sort((lhs, rhs) => lhs.pos < rhs.pos ? -1 : lhs.pos === rhs.pos ? 0 : 1);\n  //and return as text\n  return matches.map(item => item.text);\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n//Adds autocomplete for Institutes\nimport * as dompack from 'dompack';\nimport UTAutoComplete from '@mod-utwente_base/webdesigns/ws2016/src/components/autocompleter2/autocompleter';\n\nimport leadsservice from './internal/leads.rpc.json?proxy';\nimport { getMatches } from './shared_search';\n\nconst citylistpromises = {};\nconst institutelistpromises = {};\n\nasync function getInstitutes(countryfield, searchterm, groupname) {\n  if (searchterm.length <= 0 || !countryfield.value)\n    return;\n\n  const key = countryfield.value;\n  if (!citylistpromises[key])\n    citylistpromises[key] = leadsservice.listInstitutesForCountry(key);\n\n  if (searchterm.length <= 1) //we'll wait for you to type 2 chars, but at least we'll have the list!\n    return;\n\n  return getMatches(await citylistpromises[key], searchterm).slice(0, 5).map(_ => { return { label: _, value: _, group: groupname }; });\n}\n\nasync function getInstituteEducations(countryfield, institutefield, searchterm, groupname) {\n  if (searchterm.length < 1 || !countryfield.value || !institutefield.value)\n    return;\n\n  const key = countryfield.value + '.' + institutefield.value;\n  if (!institutelistpromises[key])\n    institutelistpromises[key] = leadsservice.listEducationsForInstitute(countryfield.value, institutefield.value);\n\n  const results = await institutelistpromises[key];\n\n  return getMatches(results, searchterm).slice(0, 5).map(_ => { return { label: _, value: _, group: groupname }; });\n}\n\nfunction getPrevious(node) {\n  const relevantfields = dompack.qSA('.utvoorl--institutecountry select, .utvoorl--institutename input, .utvoorl--instituteeducation input');\n  const mypos = relevantfields.indexOf(node);\n  if (mypos > 0)\n    return relevantfields[mypos - 1];\n}\n\nfunction setupInstituteNameField(node) {\n  const countryfield = getPrevious(node);\n  if (!countryfield)\n    return console.error(\"Missing countryfield\", node);\n\n  const groupname = node.matches(\":lang(nl)\") ? \"Bedoelde je:\" : \"Did you mean:\";\n  UTAutoComplete({\n    input: node,\n    className: 'ut-autocomplete',\n    preventSubmit: 1,\n    fetch: async function (text, update) {\n      const suggestions = await getInstitutes(countryfield, text, groupname);\n      update(suggestions);\n    },\n    onSelect: function (item) {\n      node.value = item.label ?? \"\";\n    },\n  });\n}\nfunction setupInstituteEducationField(node) {\n  const institutefield = getPrevious(node);\n  if (!institutefield)\n    return console.error(\"Missing institutefield\", node);\n\n  const countryfield = getPrevious(institutefield);\n  if (!countryfield)\n    return console.error(\"Missing countryfield\", institutefield, node);\n\n  const groupname = node.matches(\":lang(nl)\") ? \"Bedoelde je:\" : \"Did you mean:\";\n  UTAutoComplete({\n    input: node,\n    className: 'ut-autocomplete',\n    preventSubmit: 1,\n    fetch: async function (text, update) {\n      const suggestions = await getInstituteEducations(countryfield, institutefield, text, groupname);\n      update(suggestions);\n    },\n    onSelect: function (item) {\n      node.value = item.label ?? \"\";\n    },\n  });\n}\n\ndompack.register('.utvoorl--institutename input', setupInstituteNameField);\ndompack.register('.utvoorl--instituteeducation input', setupInstituteEducationField);\n","import * as dompack from 'dompack';\nimport * as dialogapi from 'dompack/api/dialog';\nimport { qS, qSA } from 'dompack';\n\nimport * as modaldialog from \"@mod-utwente_base/webdesigns/ws2016/src/shared/dialog\";\nimport * as forms from '@mod-publisher/js/forms';\nimport * as whintegration from '@mod-system/js/wh/integration';\n//@ts-ignore need to get rid of JSONRPC and WDS_ calls\nimport JSONRPC from \"@mod-system/js/net/jsonrpc\";\n\nimport './cashpointpage.css';\nimport './cashpointpage.lang.json';\nimport getTid from \"@mod-tollium/js/gettid\";\nimport { UTVoorlichtingRPCForm } from '@mod-utwente_voorlichting/js/shared/forms';\nimport { qR } from '@webhare/dompack';\nimport { setupValidator } from '@mod-publisher/js/forms';\n\ntype VerifyResult = {\n  status: \"ok\";\n  price: string;\n  diff_amount: string;\n  courses: Array<{\n    course: number;\n    coursetitle: string;\n    invoicetitle: string;\n    ordering: number;\n    price: number;\n    pricepertype: unknown[];\n    round: number;\n    roundtitle: string;\n  }>;\n  housing: string;\n  paymentreq: boolean;\n} | {\n  status: \"emailinuse\";\n  contactaddress: string;\n} | {\n  status: \"invalidcode\" | \"usedcode\" | \"expiredcode\" | \"invalidforcourse\";\n};\n\nclass StayoverEventsSignupForm extends UTVoorlichtingRPCForm {\n  constructor(form: HTMLFormElement) {\n    super(form);\n\n    if (this.elements.namedItem(\"wrd_dateofbirth\"))\n      setupValidator(this.elements.namedItem(\"wrd_dateofbirth\") as HTMLElement, date => this.checkBirthdate(date as HTMLInputElement));\n\n    qR('#previouspagebutton').addEventListener(\"click\", () => this.onBackButton());\n    qR('#registerbutton').addEventListener(\"click\", () => this.onRegisterButton());\n    qR('#loginbutton').addEventListener(\"click\", () => this.onLoginButton());\n    qS('#cancellink')?.addEventListener('click', evt => this.doCancel());\n\n    qSA(this.node, \"select[name^=round]\").forEach(node => node.addEventListener(\"change\", () => this.checkRoundPulldowns()));\n    qSA(this.node, \"input[name=signupusertype]\").forEach(node => node.addEventListener(\"change\", () => this.checkSignupType()));\n\n    //Verify the discount code\n    (this.elements.namedItem(\"discountcode\") as HTMLElement | undefined)?.addEventListener(\"input\", () => this.setFieldError(this.elements.namedItem(\"discountcode\")! as HTMLElement, '')); //FIXME should autoclear on input but that seems broken so this is a quickfix\n  }\n\n  checkRoundPulldowns() {\n    //Disable options in the 'lower' pulldowns if they're selected higher up\n    const selected = [];\n    for (const pulldown of qSA<HTMLSelectElement>(this.node, \"select[name^=round]\")) {\n      for (const option of qSA<HTMLOptionElement>(pulldown, 'option')) {\n        if (!option.value || option.value === '-')\n          continue;\n\n        option.disabled = selected.includes(option.value); //already selected above, so disable here\n        if (option.disabled && pulldown.value === option.value)\n          pulldown.value = \"\"; //reset\n      }\n      selected.push(pulldown.value);\n    }\n  }\n\n  shouldLogin() {\n    const selection = this.node.querySelector<HTMLInputElement>(\"input[name=signupusertype]:checked\");\n    return selection && ['student', 'employee'].includes(selection.value);\n  }\n\n  checkSignupType() {\n    const showloginbutton = this.shouldLogin();\n    qR(\"#registerbutton\").style.display = showloginbutton ? \"none\" : \"\";\n    qR(\"#loginbutton\").style.display = showloginbutton ? \"\" : \"none\";\n  }\n\n  mapError(error: string) {\n    if (error === \"__curiousu_maxdate\")\n      return <span>You need to be at least 18 years old to join CuriousU.</span>;\n    return error;\n  }\n\n  checkBirthdate(date: HTMLInputElement) {\n    if (date.dataset.minimumdate && new Date(date.value) < new Date(date.dataset.minimumdate))\n      return this.mapError(date.dataset.mindateerror!);\n    if (date.dataset.maximumdate && new Date(date.value) > new Date(date.dataset.maximumdate))\n      return this.mapError(date.dataset.maxdateerror!);\n  }\n\n  async onBackButton() {\n    await this.gotoPage(0);\n  }\n\n  async onLoginButton() {\n    this.onRPC(Promise.withResolvers<void>().promise); //trigger the modality layer but abuse a promise that will never resolve\n\n    const link = new URL(location.href);\n    link.searchParams.set(\"login\", \"1\");\n    //fix scroll position, weird things happen otherwise... even in the tests.. it jumps down but unknown why, much farther than the scrollpos before redirect...\n    location.href = link.toString() + \"#registerform-personaldetails-anchor\";\n  }\n\n  async onRegisterButton() {\n    const discountcodefield = this.elements.namedItem(\"discountcode\") as HTMLInputElement | null;\n    if (discountcodefield) //Verify the discount code\n      this.setFieldError(discountcodefield, '');\n\n    const validateresult = await this.validate(qR<HTMLElement>('#formpage_naw'));\n    if (!validateresult.valid)\n      return;\n\n    const verifyresult = await this.invokeRPC('verifyFirstPage') as VerifyResult;\n    if (verifyresult.status === 'emailinuse') {\n      await dialogapi.runMessageBox(\n        <p>{getTid('utwente_voorlichting:webfeatures.stayoverevents.frontend.alreadysignedup')} <a href={\"mailto:\" + verifyresult.contactaddress}>{verifyresult.contactaddress}</a></p>,\n        [{ result: \"ok\", title: getTid(\"utwente_voorlichting:webfeatures.stayoverevents.frontend.alreadysignedup-ok\") }], { allowcancel: true });\n      return;\n    }\n    if (verifyresult.status !== 'ok') {\n      const translations: Record<string, string> = {\n        invalidcode: getTid('utwente_voorlichting:webfeatures.stayoverevents.frontend.status-invalidcode'),\n        usedcode: getTid('utwente_voorlichting:webfeatures.stayoverevents.frontend.status-usedcode'),\n        expiredcode: getTid('utwente_voorlichting:webfeatures.stayoverevents.frontend.status-expiredcode'),\n        invalidforcourse: getTid('utwente_voorlichting:webfeatures.stayoverevents.frontend.status-invalidforcourse')\n      };\n\n      if (discountcodefield && translations[verifyresult.status])\n        this.setFieldError(discountcodefield, translations[verifyresult.status], { reportimmediately: true });\n      return;\n    }\n\n    qR('#verifyname').textContent = qR<HTMLInputElement>(\"#registerform-wrd_firstname\").value + \" \" + qR<HTMLInputElement>(\"#registerform-wrd_lastname\").value;\n    qR('#verifyemail').textContent = qR<HTMLInputElement>(\"#registerform-wrd_contact_email\").value;\n    qR('#verifycourses').replaceChildren(...verifyresult.courses.map(\n      (roundcourse: { roundtitle: string; coursetitle: string }) => <div class=\"verifycourses__courserow\">\n        <span class=\"verifycourses__roundtitle\">{roundcourse.roundtitle}</span>{\": \"}\n        <span class=\"verifycourses__coursetitle\">{roundcourse.coursetitle}</span>\n      </div>));\n\n    if (qS('#verifyhousing'))\n      qS('#verifyhousing')!.textContent = verifyresult.housing;\n    qR('#verifyprice').textContent = verifyresult.price;\n\n    const diff_amount = parseFloat(verifyresult.diff_amount.replace(',', '.')); //we may receive it with ',', correct that\n    const need_payment = diff_amount > 0;\n\n    if (diff_amount < 0) { // refund\n      qR('#verifyrefundtext').style.display = '';\n      qR('#verifyadditionalpaymenttext').style.display = 'none';\n      qR('#verifyrefund').textContent = verifyresult.diff_amount.substr(1);\n    } else { // No payment needed, or additional payment needed\n      qR('#verifyrefundtext').style.display = 'none';\n      qR('#verifyadditionalpaymenttext').style.display = '';\n      qR('#verifyadditionalpayment').textContent = verifyresult.diff_amount;\n    }\n\n    this.node.dataset.whFormVarRequirespayment = need_payment ? \"true\" : \"\";\n    await this.refreshConditions();\n\n    //Go to next page. We shouldn't jump before refreshConditions because it'll break scroll positions if controls get hidden\n    await this.gotoPage(1);\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  onSubmitSuccess(result: any) {\n    this.onRPC(Promise.withResolvers<void>().promise); //trigger the modality layer but abuse a promise that will never resolve\n    whintegration.executeSubmitInstruction(result.instr);\n  }\n\n  async doCancel() {\n    const result = await modaldialog.runYesNoMessageBox(getTid('utwente_voorlichting:widgets.openday.confirmcancel'));\n    if (result === 'yes') {\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      (new JSONRPC()).async('cancelRegistration').then((res: any) => {\n        whintegration.executeSubmitInstruction(res.instr);\n      });\n    }\n  }\n}\n\nfunction setupPaymentZone() {\n  for (const button of qSA('.curiousu__paymentzone input[type=submit]'))\n    button.classList.add('wh-form__button');\n}\n\nforms.registerHandler(\"curiousu-signupform\", node => new StayoverEventsSignupForm(node));\ndompack.register(\".curiousu__paymentzone\", () => setupPaymentZone());\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/webfeatures/cashpoint/cashpointpage.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_voorlichting\",\"en\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"nl\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Extra opties registratie\",\"agreementsummary\":[\"U bent ermee akkoord gegaan om te betalen voor \",1,\" \",2,\" plekken voor een totaalbedrag van \",3,\".\"],\"alreadysignedup\":\"Dit e-mailadres is recent al gebruikt voor een registratie, neem contact met ons op via\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Kloppen deze gegevens?\",\"back\":\"Terug\",\"billingaddress_enable\":\"Factuuradres toevoegen\",\"billingaddress_group\":\"Factuuradres\",\"billingaddress_separate\":\"Apart factuuradres\",\"billingorgname\":\"Organisatie\",\"cancelregistration\":\"Ik wil mijn registratie annuleren\",\"choosecourse\":\"Maak een keuze\",\"choosegroup\":\"- Kies je groep -\",\"choosehousing\":\"Kies accomodatie\",\"choosevwoclass\":\"- Kies je klas -\",\"contactice\":\"Contact in geval van nood (ICE)\",\"courseaccomodation\":\"Programma\",\"courselockedbydiscount\":\"Uw kortingscode is gekoppeld aan uw programmakeuze\",\"dinner\":\"Ben je aanwezig bij het netwerkdiner in het avondprogramma?\",\"dinner-no\":\"Nee\",\"dinner-yes\":\"Ja\",\"diploma\":\"Diploma\",\"discountcode\":\"Kortingscode (optioneel)\",\"education\":\"Gegevens school\",\"housing\":\"Accomodatie\",\"invoiceorgname\":\"Uw instituut / organisatie\",\"login\":\"Login\",\"name\":\"Naam\",\"optin-preu_junior-label\":\"Stuur mij de Pre-U Junior nieuwsbrief\",\"optin_photo\":\"Fotogebruik\",\"optin_photo-label\":\"Ik geef toestemming om mijn foto te gebruiken\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Ouder / voogd (contact)\",\"paymentmethod\":\"Betaalmethode\",\"personaldetails\":\"Gegevens deelnemer\",\"personaldetails_child\":\"Gegevens kind\",\"placeorder\":\"Bestelling doorvoeren\",\"preferredlanguage\":\"Voorkeurstaal\",\"programme\":\"Programma\",\"refund\":\"Teruggave\",\"registerbutton\":\"Registreer\",\"registrant_organization\":\"Uw organisatie\",\"registrationstatus\":\"Registratiestatus\",\"remarks\":\"Opmerkingen\",\"school_group\":\"Groep\",\"securepayment\":\"Veilige betaling\",\"signup_login\":\"M/S nummer\",\"signuptype\":\"Type aanmelding\",\"signupusertype\":\"Aanmelden als\",\"signupusertype-employee\":\"UT Medewerker\",\"signupusertype-genootschap\":\"Via Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Via PRIMO\",\"signupusertype-regular_signup\":\"Reguliere aanmelding\",\"signupusertype-sponsor\":\"Via sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"uitverkocht\",\"specialagreement\":\"Speciale overeenkomst\",\"sponsor_name\":\"Naam sponsor\",\"sponsor_yournumber\":\"Lidmaatschaps nummer\",\"sponsor_yournumber-ifknown\":\"(indien bekend)\",\"status-expiredcode\":\"De kortingscode is verlopen\",\"status-invalidcode\":\"De kortingscode is ongeldig\",\"status-invalidforcourse\":\"De kortingscode is niet beschikbaar voor het gekozen programma\",\"status-usedcode\":\"De kortingscode is al gebruikt\",\"step\":\"Stap\",\"termsandconditions\":\"Voorwaarden\",\"topay\":\"Te betalen\",\"totalprice\":\"Totaalprijs\",\"workstudy\":\"Werk/studie\",\"workstudy-choose\":\"Kies werk/studie\",\"workstudy-other\":\"Overig\",\"workstudy-study\":\"Studie\",\"workstudy-work\":\"Werk\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"de\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"choosevwoclass\":\"- Wähle deinen Schuljahrgang -\",\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"ar\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"bg\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"el\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"es\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"id\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"pt\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"ro\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"zh\",{\"webfeatures\":{\"stayoverevents\":{\"frontend\":{\"additionaloptions\":\"Additional options\",\"agreementsummary\":[\"You've agreed to pay for \",1,\" \",2,\" spots with a total amount of \",3,\".\"],\"alreadysignedup\":\"Your email has recently been used for this registration form, please contact us at\",\"alreadysignedup-ok\":\"OK\",\"aredetailscorrect\":\"Are these booking details correct?\",\"back\":\"Back\",\"billingaddress_enable\":\"Add billing address for invoice\",\"billingaddress_group\":\"Billing address\",\"billingaddress_separate\":\"Separate billing address\",\"billingorgname\":\"Organization\",\"cancelregistration\":\"I wish to cancel my registration\",\"choosecourse\":\"Choose a course\",\"choosegroup\":\"- Choose your group -\",\"choosehousing\":\"Choose accomodation\",\"choosevwoclass\":\"- Choose your class -\",\"contactice\":\"Contact in case of emergency (ICE)\",\"courseaccomodation\":\"Course and accommodation\",\"courselockedbydiscount\":\"Your discount code is tied to your course selection\",\"dinner\":\"Will you join the network dinner ?\",\"dinner-no\":\"No\",\"dinner-yes\":\"Yes\",\"diploma\":\"Diploma\",\"discountcode\":\"Discount code (optional)\",\"education\":\"Education\",\"housing\":\"Accommodation\",\"invoiceorgname\":\"Your institution / organization\",\"login\":\"Login\",\"name\":\"Name\",\"optin-preu_junior-label\":\"Send me the Pre-U Junior newsletter\",\"optin_photo\":\"Photo use\",\"optin_photo-label\":\"I give permission to use my photo\",\"optin_preu_junior\":\"Pre-U Junior\",\"parentlegalguardian\":\"Parent / legal guardian\",\"paymentmethod\":\"Payment method\",\"personaldetails\":\"Participant details\",\"personaldetails_child\":\"Child details\",\"placeorder\":\"Place order\",\"preferredlanguage\":\"Preferred language\",\"programme\":\"Programme\",\"refund\":\"Refund\",\"registerbutton\":\"Register\",\"registrant_organization\":\"Your organization\",\"registrationstatus\":\"Registration status\",\"remarks\":\"Remarks\",\"school_group\":\"Group\",\"securepayment\":\"Secure Payment\",\"signup_login\":\"M/S number\",\"signuptype\":\"Signup type\",\"signupusertype\":\"Signup as\",\"signupusertype-employee\":\"UT Employee\",\"signupusertype-genootschap\":\"Through Genootschap voor Risicomangement\",\"signupusertype-primo\":\"Through PRIMO\",\"signupusertype-regular_signup\":\"Regular signup\",\"signupusertype-sponsor\":\"Through sponsor\",\"signupusertype-student\":\"UT Student\",\"soldout\":\"sold out\",\"specialagreement\":\"Special agreement\",\"sponsor_name\":\"Sponsor name\",\"sponsor_yournumber\":\"Membership number\",\"sponsor_yournumber-ifknown\":\"(if known)\",\"status-expiredcode\":\"This code has expired\",\"status-invalidcode\":\"This discount code is invalid\",\"status-invalidforcourse\":\"This discount code is not available for the selected program\",\"status-usedcode\":\"This code has already been used\",\"step\":\"Step\",\"termsandconditions\":\"Terms and conditions\",\"topay\":\"To pay\",\"totalprice\":\"Total price\",\"workstudy\":\"Work/study\",\"workstudy-choose\":\"Choose work/study\",\"workstudy-other\":\"Other\",\"workstudy-study\":\"Study\",\"workstudy-work\":\"Work\"}}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/es.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n","export function getPrefills() {\n  return sessionStorage.utFormPrefill ? JSON.parse(sessionStorage.utFormPrefill) : {};\n}\n\nif (location.href.includes('?save') || location.href.includes('&save')) { //might be a prefill\n  const url = new URL(location.href);\n  const prefills: Record<string, string> = {};\n  Array.from(url.searchParams.keys()).filter(key => key.startsWith(\"save.\")).forEach(key => {\n    prefills[key.substring(5)] = url.searchParams.get(key)!;\n    url.searchParams.delete(key);\n  });\n\n  history.replaceState(null, '', url.toString());\n  try {\n    sessionStorage.utFormPrefill = JSON.stringify(prefills);\n  } catch (ignore) {\n  }\n}\n","import { getPrefills } from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm/prefill';\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as dompack from 'dompack';\nimport { RPCFormBase } from '@mod-publisher/js/forms';\n\nexport class UTVoorlichtingRPCForm extends RPCFormBase {\n  emailfield: HTMLInputElement | null;\n  diplomafield: HTMLSelectElement | null;\n  firstnamefield: HTMLInputElement | null;\n  startingyearfield: HTMLInputElement | null;\n\n  constructor(node: HTMLFormElement) {\n    super(node);\n\n    this.emailfield = node.elements.namedItem(\"wrd_contact_email\") as HTMLInputElement | null;\n    this.diplomafield = node.elements.namedItem(\"diploma.select\") as HTMLSelectElement | null;\n    this.firstnamefield = node.elements.namedItem(\"wrd_firstname\") as HTMLInputElement | null;\n    this.startingyearfield = (node.elements.namedItem(\"expectedstartingyear.year\") || node.elements.namedItem(\"expectedstartingyear.select\")) as HTMLInputElement | null;\n\n\n    if (this.emailfield && (!this.emailfield.value || this.emailfield!.closest(\".ut-prefill-save-vars\"))) { //new or explicitly prefillable\n      const prefills = getPrefills();\n      if (prefills.diploma && this.diplomafield) {\n        const toselect = [...this.diplomafield.options].find(_ => _.dataset.diplomatag === prefills.diploma);\n        if (toselect)\n          dompack.changeValue(this.diplomafield, toselect.value);\n      }\n      if (prefills.firstname && this.firstnamefield)\n        this.firstnamefield.value = prefills.firstname;\n      if (prefills.email && this.emailfield)\n        this.emailfield.value = prefills.email;\n      if (prefills.expectedstartingyear && this.startingyearfield)\n        this.startingyearfield.value = prefills.expectedstartingyear;\n\n\n      if (prefills.hasoptin === \"true\") {\n        this.node.setAttribute(\"data-wh-form-var-skipoptin\", \"true\");\n        this.refreshConditions(); //TODO Forms should instead make refeshConditions() sync\n      }\n    }\n  }\n\n  onSubmitSuccess(response: unknown) {\n    const r = response as { guid?: string; firstname: string };\n    if (r.guid)\n      crm.learnedAboutUser(r.guid, r.firstname);\n  }\n\n\n  getFormExtraSubmitData() {\n    const referralinfo = crm.getReferralInfo();\n    const userbeacon = Object.keys(crm.getUserBeacons()).filter(name => name.startsWith('usertype-'))[0];\n    if (userbeacon)\n      referralinfo.beaconusertype = userbeacon.substr(9);\n\n    return {\n      filledoptin: this.node.getAttribute(\"data-wh-form-var-skipoptin\") === \"false\",\n      referralinfo,\n      targetinterest: document.documentElement.dataset.targetinterest || '',\n      targetlanguage: document.documentElement.lang.substr(0, 2)\n    };\n  }\n}\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./echeck.scss\";\nimport \"./echeck-widget.scss\";\nimport * as dompack from \"dompack\";\nimport { config } from \"@mod-system/js/wh/integration\";\nimport { getReferralInfo } from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as forms from \"@mod-publisher/js/forms\";\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport { SlimSelect } from \"@mod-utwente_design\";\n\nconst maxloops = 1000;\nlet echeckreferral;\n\ndompack.register(\".widget-eligibilityprogrammes__form\", form => {\n\n  let idx = 0; // if in programme section set pulldown option for current programme\n  if (document.documentElement.dataset.programme)\n    idx = form.eligibilitycheck.options.findIndex(_ => _.dataset.hodexcode === document.documentElement.dataset.programme);\n\n  form.eligibilitycheck.selectedIndex = idx;\n  form.addEventListener(\"submit\", ev => {\n    ev.preventDefault();\n    if (form.eligibilitycheck.value.startsWith(\"https://\"))\n      location.href = form.eligibilitycheck.value;\n  });\n\n  new SlimSelect({\n    select: form.eligibilitycheck\n  });\n\n});\n\nfunction getEcheckReferral() {\n  return echeckreferral || window.localStorage[\"ut:echeck-referral\"] || null;\n}\n\nfunction setEcheckReferral(code) {\n  echeckreferral = code;\n  window.localStorage[\"ut:echeck-referral\"] = echeckreferral;\n}\n\nfunction checkEcheckReferral() {\n  //wrapping in try-catch to make sure init doesn't fail because of something here throwing. who knows...\n  try {\n    const url = new URL(location.href);\n    const refrl = url.searchParams.get('echeck-referral');\n    if (refrl) {\n      url.searchParams.delete('echeck-referral');\n      history.replaceState(null, document.title, url.toString());\n      setEcheckReferral(refrl);\n    }\n  } catch (e) {\n    console.error(e);\n  }\n\n  const refrl = getEcheckReferral();\n  if (refrl)\n    window.dataLayer.push({ echeck_referralcode: refrl });\n}\n\nclass EcheckForm extends forms.RPCFormBase {\n  constructor(node) {\n    super(node);\n\n    this.history = [];\n\n    this.termsnode = dompack.qS(node, \".echeck2018__form__terms\");\n\n    this.rewriteDiplomaLayout(); // First rewrite diploma to 2 columns layout\n\n    dompack.qSA(node, \".wh-form__fieldgroup--radiogroup,.wh-form__fieldgroup--checkboxgroup\").forEach(group => {\n      if (!group.classList.contains(\"echeck2018__form__groupcolumns\")) {\n        const groupoptions = dompack.qSA(group, \".wh-form__fieldline\");\n        if (groupoptions.length > 6) {\n\n          group.classList.add(\"echeck2018__form__groupcolumns\");\n          const col1 = <div class=\"echeck2018__form__groupcolumns__column\" />;\n          const col2 = <div class=\"echeck2018__form__groupcolumns__column\" />;\n\n          const splitidx = Math.ceil(groupoptions.length / 2);\n          groupoptions.forEach((fieldline, i) => {\n            if (i === 0)\n              fieldline.before(col1);\n            else if (i === splitidx)\n              fieldline.before(col2);\n\n            if (i < splitidx)\n              col1.append(fieldline);\n            else\n              col2.append(fieldline);\n          });\n        }\n      }\n    });\n\n    this.pages = [];\n    const groupids = [];\n    dompack.qSA(this.node, \".echeck2018__page\").forEach(page => {\n      if (page.dataset.groupid) {\n        if (!groupids.includes(page.dataset.groupid)) {\n          groupids.push(page.dataset.groupid);\n          this.pages.push(page);\n        }\n      } else if (page.dataset.pageid)\n        this.pages.push(page);\n    });\n\n    this.setupProgressIndicator();\n\n    this.registerHandlers();\n    this.selectPage(config.obj.firstpage);\n\n    if (this.node.dataset.referralcode)\n      setEcheckReferral(this.node.dataset.referralcode);\n    else if (window.localStorage[\"ut:echeck-referral\"])\n      setEcheckReferral(window.localStorage[\"ut:echeck-referral\"]);\n  }\n\n  rewriteDiplomaLayout() {\n    const diplomagroup = dompack.qS(this.node, \".echeck2018__form__diploma\");\n    if (!diplomagroup)\n      return;\n\n    diplomagroup.classList.add(\"echeck2018__form__groupcolumns\");\n\n    let eduttypewrapper = <div class=\"echeck2018__form__groupcolumns__column\" />;\n    let colcount = 1;\n    let prevtype = \"\";\n    dompack.qSA(diplomagroup, \".wh-form__fieldline input\").forEach((inp, i) => {\n      const fieldline = inp.closest(\".wh-form__fieldline\");\n      if (i === 0)\n        fieldline.before(eduttypewrapper);\n      else if (inp.dataset.edutype !== \"secondary\" && colcount === 1) {\n        eduttypewrapper = <div class=\"echeck2018__form__groupcolumns__column\" />;\n        fieldline.before(eduttypewrapper);\n        ++colcount;\n      }\n\n      if (prevtype !== inp.dataset.edutype) {\n        if (inp.dataset.edutype === \"secondary\")\n          eduttypewrapper.append(<h4>Secondary education</h4>);\n        else if (inp.dataset.edutype === \"bachelor\")\n          eduttypewrapper.append(<h4>{\"Bachelor's\"}</h4>);\n        else if (inp.dataset.edutype === \"master\")\n          eduttypewrapper.append(<h4>{\"Master's\"}</h4>);\n      }\n\n      prevtype = inp.dataset.edutype;\n\n      eduttypewrapper.append(fieldline);\n    });\n  }\n\n  setupProgressIndicator() {\n    const container = dompack.qS(this.node, \".echeck2018__form__progress\");\n    if (!container)\n      return;\n\n    this.progressindicator = <div class=\"echeck2018__form__progress__indicator\" />;\n    this.progressidx = 0; //Initial first position\n\n    const innernode = <div class=\"echeck2018__form__progress__inner\">{this.progressindicator}</div>;\n    container.append(innernode);\n\n    this.progresssteps = [];\n    this.pages.forEach((page, i) => {\n      // Don't show indicator for 'sentresumptionlink' page\n      if (![\"sentresumptionlink\"].includes(page.dataset.pageid))\n        this.progresssteps.push(this.renderStepNode(page.dataset.pageid, page.dataset.groupid, i));\n    });\n\n    // the finish line\n    this.progresssteps.push(this.renderStepNode(\"finalized\", \"\", 0));\n\n    innernode.append(...this.progresssteps);\n  }\n\n  renderStepNode(pageid, groupid, i) {\n    return <div class={\"echeck2018__form__progress__page \" + (i ? \"echeck2018__form__progress__page--withlabel\" : \"\")} data-pageid={pageid} data-groupid={groupid}>\n      {i > 0 ? <div class=\"echeck2018__form__progress__label\" hidden>\n        <span class=\"echeck2018__form__progress__label__nr\">{i}</span>\n      </div> : null\n      }\n    </div>;\n  }\n\n  updateProgressIndicator(current, status) {\n    if (!this.progressindicator)\n      return;\n\n    if (!status)\n      status = \"\";\n\n    let idx = -1;\n    if (current.dataset.groupid)\n      idx = this.progresssteps.findIndex(_ => _.dataset.groupid === current.dataset.groupid);\n    else\n      idx = this.progresssteps.findIndex(_ => _.dataset.pageid === current.dataset.pageid);\n\n    if (idx < 0)\n      idx = this.progressidx;\n\n    const finalized = this.node.classList.contains(\"echeck2018__form--success\");\n\n    if (status === \"failed\" && !idx)\n      idx = 1;\n\n    this.progresssteps.forEach((step, i) => {\n      if (this.progresssteps[i].children.length)\n        this.progresssteps[i].children[0].hidden = i > idx;\n\n      if (finalized && i < idx)\n        this.progresssteps[i].classList.remove(\"echeck2018__form__progress__page--checked\");\n      else\n        this.progresssteps[i].classList.toggle(\"echeck2018__form__progress__page--checked\", i < idx || (status === \"success\" && i === idx));\n\n      this.progresssteps[i].classList.toggle(\"echeck2018__form__progress__page--failed\", status === \"failed\" && i === idx);\n    });\n\n    if (status === \"failed\") {\n      this.progressindicator.style.width = (idx * 100 / (this.progresssteps.length - 1)) + \"%\";\n    } else {\n      const stepsize = 100 / (this.progresssteps.length - 1);\n      let progress = idx * stepsize;\n      if (current.dataset.groupid) {\n        const subpages = dompack.qSA(\".echeck2018__page[data-groupid='\" + current.dataset.groupid + \"']\");\n        const subcount = subpages.length;\n        if (subcount > 1) {\n          const subidx = subpages.findIndex(_ => _.classList.contains(\"echeck2018__page--selected\"));\n          if (subidx > 0)\n            progress += (stepsize * subidx / subcount);\n        }\n      }\n\n      if (progress === 0)\n        this.progressindicator.style.width = \"Calc(\" + progress + \"% + 30px)\";\n      else\n        this.progressindicator.style.width = progress + \"%\";\n    }\n\n    this.progressidx = idx;\n  }\n\n  registerHandlers() {\n    dompack.register(\".echeck2018__prevbutton\", node => node.addEventListener(\"click\", e => this.prevPage(e)));\n    dompack.register(\".echeck2018__nextbutton\", node => node.addEventListener(\"click\", e => this.nextPageLocked(e)));\n  }\n\n  selectPage(pageid, actiontype) {\n    let current = this.node.querySelector(\".echeck2018__page--selected\");\n    if (current)\n      current.classList.remove(\"echeck2018__page--selected\");\n\n    const pos = this.history.indexOf(pageid);\n    if (pos === -1)\n      this.history.push(pageid);\n    else\n      this.history = this.history.slice(0, pos + 1);\n\n    current = this.getPageById(pageid);\n    current.classList.add(\"echeck2018__page--selected\");\n\n    const progressstatus = actiontype && actiontype === \"sendresumptionlink\" ? \"success\" : \"\";\n    this.updateProgressIndicator(current, progressstatus);\n\n    if (this.termsnode) // Show terms in footer if on diploma page\n      this.termsnode.hidden = current.dataset.pageid !== \"diploma\";\n\n    dompack.qS(\".echeck2018__prevbutton\").style.display = this.history.length <= 1 || actiontype === \"sendresumptionlink\" ? \"none\" : \"\";\n    dompack.qS(\".echeck2018__nextbutton\").disabled = current.dataset.disablenextaction;\n  }\n\n  getPageById(pageid) {\n    const page = this.node.querySelector(\".echeck2018__page[data-pageid=\\\"\" + pageid + \"\\\"]\");\n    if (!page)\n      throw new Error(\"No such page '\" + pageid + \"'\");\n    return page;\n  }\n\n  getPageNextAction(page, ignoreanswers) {\n    let nextaction = page.dataset.nextaction;\n    const selectedoption = dompack.qS(page, \"input[type=radio]:checked,option:checked\");\n\n    if (!ignoreanswers && selectedoption && selectedoption.dataset.nextaction)\n      nextaction = selectedoption.dataset.nextaction;\n\n    if (!nextaction)\n      throw new Error(\"Page \" + page.dataset.pageid + \" does not have a nextaction!\");\n\n    nextaction = JSON.parse(nextaction);\n    return nextaction;\n  }\n\n  getCurrentSkipGroups() {\n    const retval = [];\n    this.history.forEach(pageid => {\n      const page = this.getPageById(pageid);\n      const nextaction = this.getPageNextAction(page);\n      if (nextaction.skipgroups)\n        retval.push(...nextaction.skipgroups);\n    });\n    return retval;\n  }\n\n  prevPage() {\n    // First some resets\n    if (this.donepage) {\n      this.donepage.parentNode.removeChild(this.donepage);\n      this.donepage = null;\n    }\n    this.node.classList.remove(\"echeck2018__form--failed\");\n\n    if (this.history.length <= 1)\n      return;\n    this.selectPage(this.history[this.history.length - 2]);\n    this.node.scrollIntoView();\n  }\n\n  getNodesFromHTMLContent(htmlstring) {\n    const parser = new DOMParser();\n    const contentnode = parser.parseFromString(htmlstring, 'text/html');\n    return dompack.qSA(contentnode, \"body > *\");\n  }\n\n  async nextPageLocked() {\n    const nextpagelock = dompack.flagUIBusy();\n    try {\n      return await this.nextPage();\n    } finally {\n      nextpagelock.release();\n    }\n  }\n\n  async nextPage() {\n    const current = this.node.querySelector(\".echeck2018__page--selected\");\n    if (!(await this.validate(current)).valid) {\n      console.log(\"Validation failed\");\n      return;\n    }\n\n    let counter = 0;\n    let nextaction = this.getPageNextAction(current);\n\n    this.node.scrollIntoView();\n\n    const baseforminfo = {\n      guid: config.obj.formentry_guid,\n      history: this.history,\n      referralcode: getEcheckReferral(),\n      referralinfo: getReferralInfo()\n    };\n\n\n    for (; ;) {\n      if (++counter === maxloops)\n        throw new Error(\"Infinite loop in form pages path\");\n      if (!nextaction)\n        throw new Error(\"Looped without setting next action!\");\n\n      const action = nextaction;\n      nextaction = null;\n\n      switch (action.type) {\n        case \"sendresumptionlink\":\n          {\n            await this.invokeRPC(\"SendEmailWithLink\");\n            this.selectPage(action.pageid, action.type);\n            return;\n          }\n        case \"done\":\n          {\n            const submitdata =\n            {\n              ...baseforminfo,\n              finished: true,\n              resultcode: action.resultcode\n            };\n\n            const submitresult = await this.submit(submitdata);\n            window.dataLayer.push(\n              {\n                event: 'formulier-submit',\n                form: action.resultcode.toUpperCase() !== 'EL' ? 'eligibilitycheck-failed'\n                  : submitresult.result.notyetquestions.length ? 'eligibilitycheck-notyet'\n                    : 'eligibilitycheck-positive',\n                form_programme: document.documentElement.dataset.programme,\n                form_diploma: this.elements.diploma.value,\n                form_intent: this.elements.intent.value,\n                form_resultcode: action.resultcode,\n                echeck_notyetquestions: submitresult.result.notyetquestions\n              });\n\n            const resultstatus = action.resultcode.toUpperCase() === 'EL' ? \"success\" : \"failed\";\n\n            this.donepage = <div class=\"echeck2018__page echeck2018__page--selected\" data-pageid={\"resultpage-\" + resultstatus} />;\n            this.donepage.append(...this.getNodesFromHTMLContent(submitresult.result.contents));\n            this.history.push(\"resultpage-\" + resultstatus);\n            current.after(this.donepage);\n            current.classList.remove(\"echeck2018__page--selected\");\n\n            this.node.classList.add(\"echeck2018__form--\" + resultstatus);\n            this.updateProgressIndicator(current, resultstatus);\n\n            crm.learnedAboutUser(submitresult.result.guid, this.elements.firstname.value);\n            return;\n          }\n        case \"nextpage-nostore\":\n        case \"nextpage\":\n        case \"nextpage-modalrpc\":\n          {\n            if (action.informecheckstart) {\n              window.dataLayer.push(\n                {\n                  event: 'formulier-submit',\n                  form: 'eligibilitycheck-enter',\n                  form_programme: document.documentElement.dataset.programme,\n                  form_diploma: this.elements.diploma.value,\n                  form_intent: this.elements.intent.value\n                });\n            }\n            if (action.type !== \"nextpage-nostore\") {\n              const data =\n              {\n                ...baseforminfo,\n                finished: false\n              };\n\n              if (action.type === \"nextpage-modalrpc\") {\n                const res = await this.invokeRPC(\"storeData\", data);\n                config.obj.formentry_guid = res.guid;\n              } else\n                this.invokeBackgroundRPC(\"storeData\", data).then(res => config.obj.formentry_guid = res.guid);\n            }\n\n            const skipgroups = this.getCurrentSkipGroups();\n            const nextpage = this.getPageById(action.pageid);\n\n            const groupid = parseInt(nextpage.dataset.groupid);\n            if (!skipgroups.includes(groupid)) {\n              this.selectPage(action.pageid);\n              return;\n            }\n\n            nextaction = this.getPageNextAction(nextpage, true);\n            if (counter >= maxloops - 20)\n              console.log(\"skipping to page \" + nextaction.pageid);\n\n          } break;\n        case \"noecheck\":\n          {\n            /* Just fetch page */\n            const gotourl = new URL(location.href);\n            gotourl.searchParams.set('nocheck', action.diploma);\n\n            const res = await this.getNoCheckPage(gotourl.toString());\n            if (res && res.length) {\n              this.donepage = <div class=\"echeck2018__page echeck2018__page--selected\" data-pageid=\"noecheck\" />;\n              this.donepage.append(...res);\n              current.after(this.donepage);\n              current.classList.remove(\"echeck2018__page--selected\");\n\n              this.history.push(\"noecheck\");\n              dompack.qS(\".echeck2018__prevbutton\").style.display = \"\";\n\n              this.node.classList.add(\"echeck2018__form--failed\");\n              this.updateProgressIndicator(current, \"failed\");\n            } else\n              location.href = gotourl.toString();\n            return;\n          }\n        default:\n          {\n            throw new Error(\"unknown action \" + action.type);\n          }\n      }\n    }\n  }\n\n  async getNoCheckPage(url) {\n    let response;\n    try {\n      response = await fetch(url, { cache: 'reload' });\n    } catch (e) { }\n\n    if (!response || response.status !== 200) {\n      console.error(\"Error loading page: \" + url);\n      return null;\n    }\n\n    const content = await response.text();\n    const parser = new DOMParser();\n    const doc = parser.parseFromString(content, 'text/html');\n\n    return dompack.qSA(doc, \"main > *:not(.wh-form__buttongroup)\");\n  }\n}\n\nforms.registerHandler(\"utwente_voorlichting:echeck2018\", node => new EcheckForm(node));\n\ncheckEcheckReferral();\n","import * as dompack from 'dompack';\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as dialogapi from 'dompack/api/dialog';\nimport { qS, qSA, qR } from '@webhare/dompack';\nimport * as forms from \"@mod-publisher/js/forms\";\nimport * as whintegration from \"@mod-system/js/wh/integration\";\n\nimport './opendagen.scss';\nimport './opendagen.lang.json';\nimport \"../ws2016_voorlichting/activities/activityform.scss\";\n\nimport { getTid, getHTMLTid } from \"@mod-tollium/js/gettid\";\nimport type { FormSubmitMessage } from '@mod-publisher/js/forms/formbase';\nimport { UTVoorlichtingRPCForm } from '@mod-utwente_voorlichting/js/shared/forms';\nimport { pushToDataLayer } from '@webhare/frontend';\n\nlet formapitype = '';\n\nasync function runConfirmResignup() {\n  return dialogapi.runMessageBox(\n    <div>\n      <p>{getTid('utwente_voorlichting:widgets.openday.alreadysignedup-1')}</p>\n      <p><b>{getTid('utwente_voorlichting:widgets.openday.alreadysignedup-2')}</b></p>\n    </div>,\n    [\n      { result: \"yes\", title: getTid(\"utwente_voorlichting:widgets.openday.alreadysignedup-yes\") },\n      { result: \"no\", title: getTid(\"utwente_voorlichting:widgets.openday.alreadysignedup-no\") }\n    ]);\n}\n\ntype EventSelection = {\n  diploma: string | null;\n  rounds: Array<{\n    programme: string;\n    special: string;\n    tag: string | null;\n    select: HTMLSelectElement;\n  }>;\n};\n\nclass OpenDagenForm extends UTVoorlichtingRPCForm {\n\n  eventselection: EventSelection = { diploma: null, rounds: [] };\n  diplomaselect: HTMLSelectElement;\n  isedit: boolean;\n  origemail: string;\n  isclusterconflict = false;\n  opendaysettings: {\n    questions: string[];\n    apitype: string;\n  };\n  lastselectedcity = '';\n  shortform;\n\n  constructor(node: HTMLFormElement) {\n    super(node);\n    this.shortform = node.hasAttribute(\"data-shortform\");\n    this.diplomaselect = qR<HTMLSelectElement>(node, `select[name=\"diploma.select\"]`);\n    this.opendaysettings = whintegration.config.obj.opendaysettings as typeof this.opendaysettings;\n\n    dompack.qSA(node, '.foldablecontent').forEach(foldablenode => foldablenode.addEventListener(\"click\", evt => {\n      if (foldablenode.classList.contains(\"foldablecontent--open\")) { //just opened one?\n        dompack.qSA(node, '.foldablecontent--open').forEach(currentlyopen => {\n          if (currentlyopen !== foldablenode) {\n            dompack.dispatchCustomEvent(currentlyopen, \"ws:foldable-toggle\",\n              {\n                bubbles: true,\n                cancelable: false\n              });\n          }\n        });\n      }\n    }));\n\n    this.isedit = this.node.classList.contains(\"openday--isedit\");\n\n    this.origemail = (node.elements.namedItem(\"wrd_contact_email\") as HTMLInputElement).value;\n    if (this.node.dataset.guid)\n      crm.learnedAboutUser(this.node.dataset.guid, (node.elements.namedItem(\"wrd_firstname\") as HTMLInputElement).value);\n\n    this.node.addEventListener('change', evt => this.updateFormOptions(), true);\n    qSA(this.node, '.openday--js-cancel').forEach(el => el.addEventListener('click', () => this.onODCancel()));\n\n    this.prefill();\n    (this.elements.namedItem(\"extrainfo_schoolcity_fromlist\") as HTMLElement | null)?.addEventListener(\"change\", () => this.updateSchoolList());\n\n    const firstpagebutton = qS<HTMLButtonElement>('[data-wh-form-action=\"next\"]');\n    if (firstpagebutton) {\n      firstpagebutton.addEventListener('click', () => {\n        if (!firstpagebutton.disabled) {\n          crm.triggerUserBeacon('opendaysignup-' + formapitype + '-firstpage');\n          crm.clearUserBeacon('opendaysignup-' + formapitype + '-cancelled');\n        }\n      });\n    }\n\n    this.updateFormOptions();\n    formapitype = this.node.dataset.apitype!;\n    document.documentElement.classList.add('openday--type-' + formapitype);\n    crm.triggerUserBeacon('opendaysignup-' + formapitype + '-impression');\n  }\n\n  updateSchoolList() {\n    const selectedcity = (this.elements.namedItem(\"extrainfo_schoolcity_fromlist\") as HTMLSelectElement | null)!.value;\n    const schoolname = this.elements.namedItem(\"extrainfo_schoolname_fromlist\") as HTMLSelectElement;\n    if (selectedcity !== this.lastselectedcity) {\n      this.lastselectedcity = selectedcity;\n      schoolname.value = '';\n    }\n    for (const opt of qSA<HTMLOptionElement>(schoolname, 'option')) {\n      const show = !opt.dataset.city || opt.dataset.city === selectedcity;\n      opt.classList[show ? \"remove\" : \"add\"](\"openday--hide\");\n      opt.disabled = !show;\n    }\n  }\n\n  async gotoPage(idx: number) {\n    if (idx === 1 && this.shortform) {\n      await this.invokeRPC(\"prepShortForm\", crm.getReferralInfo());\n      setTimeout(() => pushToDataLayer({ event: \"onlineopendays-shortform\" }), 1); //send AFTER form content is reported to analytics\n    }\n\n    const result = await super.gotoPage(idx);\n    this.node.scrollIntoView(); //scrollfix\n    return result;\n  }\n\n\n  getDatalayerInfo(): Record<string, string> {\n    const programmes = this.eventselection.rounds.map(val => val.programme).filter(val => Boolean(val));\n    const specials = this.eventselection.rounds.map(val => val.special).filter(val => Boolean(val));\n    const rounds = this.eventselection.rounds.map(val => val.tag).filter(val => Boolean(val));\n    const info: Record<string, string> =\n    {\n      origemail: this.node.dataset.origemail || '',\n      ischange: this.node.dataset.origemail ? 'true' : 'false',\n      //compatibility with currently ill-implemented gtm code\n      form_programme1_code: programmes.length > 0 ? programmes[0] : '',\n      form_programme2_code: programmes.length > 1 ? programmes.slice(1).join(',') : '',\n      form_special1_code: specials.join(','),\n      form_rounds1_code: rounds.join(','),\n\n      form_allprogrammes: programmes.join(','),\n      form_allspecials: specials.join(','),\n      form_allrounds: rounds.join(',')\n    };\n    for (const keyname of this.getFormElementNames()) {\n      let toread = this.elements.namedItem(keyname);\n      if (!toread)\n        continue;\n      if (toread instanceof RadioNodeList && toread.length && ((toread[0] as HTMLInputElement).type === 'radio' || (toread[0] as HTMLInputElement).type === 'checkbox')) // it's a radio/checkbox group\n        toread = (Array.from(toread) as HTMLInputElement[]).filter(node => node.checked)[0];\n\n      if (!toread || !(toread instanceof HTMLElement))\n        continue;\n\n      if (toread instanceof HTMLInputElement && (toread.type === 'radio' || toread.type === 'checkbox') && !toread.checked)\n        continue;\n      if (toread.closest('.openday--hide'))\n        continue;\n\n      if (toread instanceof HTMLSelectElement && toread.options && toread.selectedIndex >= 0)\n        toread = toread.options[toread.selectedIndex];\n\n      const setvalue = (toread instanceof HTMLInputElement && toread.dataset && toread.dataset.tag) ? toread.dataset.tag : (toread as HTMLInputElement).value;\n      if (!setvalue)\n        continue;\n\n      info['form_' + keyname] = setvalue;\n    }\n    return info;\n  }\n\n  formToDatalayer(formadd: string) {\n    if (!window.dataLayer)\n      return;\n\n    const layerobj = this.getDatalayerInfo();\n    layerobj.event = \"formulier-submit\";\n    layerobj.form = formapitype + (formadd || '');\n    window.dataLayer.push(layerobj);\n  }\n\n  prefill() {\n    const url = new URL(location.href);\n\n    if (this.diplomaselect.options.length === 1) {\n      //if there's only one diploma option, just select it (eg HBO)\n      dompack.changeValue(this.diplomaselect, this.diplomaselect.options[0].value);\n    } else {\n      if (this.diplomaselect.value || !url.searchParams.get('diploma'))\n        return; //not a prefill\n\n      const toselect = Array.from(this.diplomaselect.options).filter(opt => opt.dataset.diplomatag === url.searchParams.get('diploma'));\n      if (!toselect.length)\n        return;\n\n      dompack.changeValue(this.diplomaselect, toselect[0].value);\n    }\n\n    const eventday = url.searchParams.get('eventday');\n    if (!eventday)\n      return;\n\n    const selectday = this.getOptions('day').filter(day => day.inputnode.dataset.tag?.toUpperCase() === eventday.toUpperCase());\n    if (!selectday.length)\n      return;\n\n    selectday[0].inputnode.click();\n  }\n\n  updateFormOptions() {\n    this.eventselection = { diploma: null, rounds: [] };\n\n    //reset error messages\n    qSA('.openday__clusterwarning').forEach(node => node.style.display = 'none');\n\n    if (this.diplomaselect.options.length <= 0) //no form\n      return;\n\n    document.documentElement.classList.add('openday--formopen');\n\n    //get diploma and remove days by their diplomafilter. gather available days. clear unavailable days checkbox\n    this.eventselection.diploma = this.diplomaselect.selectedOptions[0]?.dataset.diplomatag || null; //it's important for this to be 'null' during initial set or setupVisibleFields will not run at first rendering\n\n    const availabledays = [];\n    this.getOptions('day').forEach(day => {\n      let enable = JSON.parse(day.inputnode.dataset.diplomas!).includes(this.eventselection.diploma);\n      if (enable) {\n        const dayoptions = this.gatherRoundOptionsForDay();\n        if (!dayoptions.some(opt => !opt.disabled))\n          enable = false; //no space!\n      }\n\n      day.fieldline?.classList[enable ? 'remove' : 'add']('openday--hide');\n      if (!enable)\n        day.inputnode.checked = false;\n      else\n        availabledays.push(day);\n    });\n\n    for (const round of qSA(this.node, '.openday__round'))\n      this.updateRoundOptionsVisibility(round);\n    for (const roundgroup of qSA(this.node, '.openday__roundgroup'))\n      roundgroup.classList.toggle(\"openday--hide\", !roundgroup.querySelector('.openday__round:not(.openday--hide)'));\n\n    const rounds = qSA('.openday__round:not(.openday--hide)');\n    let gotsingleoption = false;\n\n    if (rounds.length === 1) { //if only one round with one real option, just select that (insight day autoselect)\n      const select = qR<HTMLSelectElement>(rounds[0], 'select');\n      const options = qSA<HTMLOptionElement>(select, 'option:not(.openday--hide)').filter(node => Boolean(node.value));\n      if (options.length === 1) {\n        select.value = options[0].value;\n        gotsingleoption = true;\n      }\n    }\n\n    qR('#opendagen-optionstree').classList.toggle(\"openday--hide\", rounds.length === 0 || gotsingleoption);\n\n    /* FIXME IF ONLY ONE OPTION, AUTOSELET THAT\n        roundgroups.forEach(round =>\n        {\n          let checkedoption = this.getSelectedOption('round_' + round.roundid);\n          if(checkedoption && !round.enable)\n            checkedoption.checked = false;\n\n    //console.log(round.roundid, round.checkboxgroup, round.checkboxgroup.checked, checkedoption, round.enable, round.availableoptions);\n          if(!checkedoption && round.checkbox.checked && round.enable && round.availableoptions.length)\n            round.availableoptions[0].checked=true;\n        });\n    */\n    this.eventselection.rounds = [];\n\n    //These are the radio options that match the rounds, if there are alternative options\n    const roundshowupboxes = qSA<HTMLSelectElement>(this.node, 'select').filter(select => select.name.match(/^roundpulldown/) && !dompack.closest(select, '.openday--hide'));\n    roundshowupboxes.forEach(select => {\n      const current = select.options[select.selectedIndex];\n      if (current)\n        this.eventselection.rounds.push({\n          programme: parseInt(current.dataset.programmeid || \"\") ? current.dataset.tag ?? '' : '',\n          special: parseInt(current.dataset.special || \"\") ? current.dataset.tag ?? '' : '',\n          tag: current.dataset.tag || '',\n          select: select\n        });\n    });\n\n    // //For signup, check if the NEXT button should be available\n    // const firstpagebutton = qS<HTMLButtonElement>('[data-wh-form-action=\"next\"]');\n    // this.checkRoundQuestionsClusters(this.eventselection.rounds);\n    // if (firstpagebutton) {\n    //   firstpagebutton.disabled = !this.eventselection.diploma\n    //     || (!this.isAnyRoundSelected() && !this.opendaysettings.questions.includes(\"optionalrounds\"))\n    //     || this.isclusterconflict\n    //     ;\n    // }\n    // console.log('state', this.getDatalayerInfo());\n  }\n\n  updateRoundOptionsVisibility(round: HTMLElement) {\n    const selectnode = qR<HTMLSelectElement>(round, 'select');\n    const enable = true;\n\n    let anyvisitvisible = false; //any 'visit' visible (eg anything but 'not coming')\n\n    for (const opt of selectnode.querySelectorAll('option')) {\n      const show = enable\n        && (!opt.dataset.diplomafilter\n          || JSON.parse(opt.dataset.diplomafilter).includes(this.eventselection.diploma)\n        );\n      if (opt.value && show)\n        anyvisitvisible = true;\n\n      dompack.toggleClasses(opt, { \"openday--hide\": !show });\n      opt.disabled = Boolean(!show || opt.dataset.isfull);\n    }\n\n    for (const optgroup of selectnode.querySelectorAll('optgroup')) {\n      const show = Boolean(optgroup.querySelector('option:not(.openday--hide)'));\n      dompack.toggleClasses(optgroup, { \"openday--hide\": !show });\n    }\n\n    //is current option hidden?\n    if (selectnode.options[selectnode.selectedIndex] && selectnode.options[selectnode.selectedIndex].classList.contains('openday--hide')) {\n      const toselect = selectnode.querySelector<HTMLOptionElement>('option:not(.openday--hide)');\n      if (toselect)\n        selectnode.value = toselect.value;\n    }\n\n    dompack.toggleClasses(round, { \"openday--hide\": !anyvisitvisible });\n  }\n\n  isAnyRoundSelected() {\n    const roundshowupboxes = qSA<HTMLSelectElement>(this.node, 'select').filter(select => select.name.match(/^roundpulldown/) && !dompack.closest(select, '.openday--hide'));\n    return roundshowupboxes.length === 0 || roundshowupboxes.filter(select => select.value).length > 0;\n  }\n\n  gatherRoundOptionsForDay(): HTMLOptionElement[] {\n    const programmeselects = dompack.qSA<HTMLSelectElement>(this.node, \"select[name^='roundpulldown_']\");\n    const alloptions = [];\n    const diploma = this.eventselection.diploma;\n    for (const programmeselect of programmeselects) {\n      alloptions.push(...Array.from(programmeselect.options).filter(option => option.dataset.diplomafilter && JSON.parse(option.dataset.diplomafilter).includes(diploma)));\n    }\n    return alloptions;\n  }\n\n  checkRoundQuestionsClusters(rounds: EventSelection[\"rounds\"]) {\n    const programmes: HTMLOptionElement[] = [];\n\n    rounds.forEach(round => {\n      const selection = round.select.options[round.select.selectedIndex];\n      if (selection && selection.dataset.programmeid)\n        programmes.push(selection);\n    });\n\n    this.verifyClustering(programmes);\n  }\n\n  verifyClustering(programmes: HTMLOptionElement[]) {\n    const checkedprogrammes = [];\n    this.isclusterconflict = false;\n    for (const opt of programmes) {\n      if (opt.dataset.clusteredwith) {\n        const clusteredwith = JSON.parse(opt.dataset.clusteredwith);\n        for (const programme of checkedprogrammes)\n          if (clusteredwith.includes(parseInt(programme.dataset.programmeid || ''))) {\n            const usenode = dompack.closest(opt, '.openday__round')?.querySelector<HTMLElement>('.openday__clusterwarning');\n            if (!usenode)\n              continue;\n\n            if (this.opendaysettings.apitype === 'campusexperience')\n              usenode.textContent = getTid('utwente_voorlichting:widgets.openday.programmeinclusterwith_campusexperience', programme.textContent);\n            else\n              usenode.textContent = getTid('utwente_voorlichting:widgets.openday.programmeinclusterwith', programme.textContent);\n\n            usenode.style.display = 'block';\n            this.isclusterconflict = true;\n            return;\n          }\n      }\n      checkedprogrammes.push(opt);\n    }\n  }\n\n  onSubmitFailed(errors: FormSubmitMessage[], result: unknown) {\n    if (errors.length === 1 && errors[0].name === \"wrd_contact_email\" && (errors[0] as { metadata: { verifyresub: string } }).metadata.verifyresub) {\n      //We're being rejected because the email address is already known\n      runConfirmResignup().then(res => {\n        if (res === \"yes\")\n          this.validateAndSubmit({\n            verifyresub: (errors[0] as { metadata: { verifyresub: string } }).metadata.verifyresub\n          });\n      });\n      return;\n    }\n    super.onSubmitFailed(errors, result);\n  }\n\n  onSubmitSuccess(_result: unknown) {\n    const result = _result as {\n      editlink: string;\n      pdflink: string;\n      firstname: string;\n      guid: string;\n      eventname: string;\n      eventdatetext: string;\n      status: string;\n      schedule: Array<{\n        timerange: string;\n        title: string;\n        scheduleprefix: string;\n      }>;\n    };\n    this.formToDatalayer('-submitregistration');\n    crm.triggerUserBeacon('opendaysignup-' + formapitype + '-signedup');\n    crm.clearUserBeacon('opendaysignup-' + formapitype + '-cancelled');\n\n    //hide pagetabs (if any) ??\n    //this.pagenav.tabs.forEach( node => node.style.display = \"none\");\n\n    document.documentElement.classList.add('openday--signupdone');\n    window.opendaySubmitResult = result; //used by CI\n\n    qSA('.opendag_thankyou').forEach(node => node.innerHTML = getHTMLTid(\"utwente_voorlichting:widgets.openday.thankyou\", result.firstname, result.eventname, result.eventdatetext));\n    qSA('.opendag__programma').forEach(node => {\n      node.innerHTML = '';\n      result.schedule.forEach(scheduleitem => {\n        node.appendChild(dompack.create('div',\n          {\n            className: \"opendag__programmaitem\",\n            childNodes: [\n              dompack.create(\"div\", { className: \"opendag__timerange\", textContent: getTid(\"utwente_voorlichting:widgets.openday.timerange\", scheduleitem.timerange) }),\n              dompack.create(\"div\", { className: \"opendag__schedtitle\", textContent: (scheduleitem.scheduleprefix ? scheduleitem.scheduleprefix + \" \" : \"\") + scheduleitem.title })\n            ]\n          }));\n      });\n    });\n\n    if (result.guid)\n      crm.learnedAboutUser(result.guid, result.firstname);\n\n    if (result.editlink)\n      console.log('edit url', result.editlink);\n    if (result.pdflink)\n      console.log('eticket url', result.pdflink);\n  }\n\n  async onODCancel() {\n    if (await dialogapi.runMessageBox(getTid(\"utwente_voorlichting:widgets.openday.confirmcancel\"),\n      [\n        { result: \"yes\", title: getTid(\"utwente_base:site-common.texts.yes\") },\n        { result: \"no\", title: getTid(\"utwente_base:site-common.texts.no\") }\n      ]) !== 'yes')\n      return;\n\n    const lock = dompack.flagUIBusy({ modal: true });\n    this.formToDatalayer('-cancelregistration');\n    await this.invokeRPC('cancelRegistration');\n\n    crm.triggerUserBeacon('opendaysignup-' + formapitype + '-cancelled');\n    crm.clearUserBeacon('opendaysignup-' + formapitype + '-firstpage');\n    crm.clearUserBeacon('opendaysignup-' + formapitype + '-signedup');\n\n    lock.release();\n    dialogapi.runMessageBox(getTid(\"utwente_voorlichting:widgets.openday.cancelled\"), [], { allowcancel: false });\n  }\n}\n\nforms.registerHandler(\"utwente_voorlichting:opendays\", node => new OpenDagenForm(node));\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/webfeatures/opendagen/opendagen.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_voorlichting\",\"en\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"nl\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"Je bent met dit e-mailadres al aangemeld voor dit evenement. Als je je opnieuw aanmeldt, overschrijven we de bestaande aanmelding.\",\"alreadysignedup-2\":\"Wil je je aanmelding overschrijven?\",\"alreadysignedup-no\":\"Nee, niet overschrijven\",\"alreadysignedup-yes\":\"Ja, overschrijven\",\"btn_confirm\":\"Bevestigen\",\"btn_nextpage\":\"Volgende\",\"btn_previouspage\":\"Vorige\",\"cancelled\":\"Je registratie is verwijderd.\",\"cancellink\":\"Aanmelding verwijderen\",\"chooseaday\":\"Kies een dag\",\"chooseeducation\":\"Kies je opleidingsniveau\",\"choosepresentation\":\"Kies een presentatie\",\"chooseprogrammes\":\"Kies een opleiding\",\"chooseprograms\":\"Van welke opleiding(en) wil je een presentatie volgen?\",\"chooseqasession\":\"Kies een Q&A sessie\",\"choosevwoclass\":\"- Kies je klas -\",\"class\":\"Klas\",\"confirmcancel\":\"Weet je zeker dat je je registratie wil verwijderen?\",\"confirmcancel_no\":\"Nee\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Ja\",\"contactme\":\"Neem contact met mij op voor reisinformatie\",\"dayprogramme\":\"Jouw programma voor deze dag\",\"differentprogramlink\":\"Ik wil iets wijzigen\",\"diploma\":\"Huidige (of recent afgeronde) opleiding\",\"extrainfo_resume\":\"Upload hier je cijferlijst. We hebben dit nodig om je opleidingsachtergrond te beoordelen. Vermeld hierbij duidelijk in welke klas je nu zit, op welke school je zit. Vakken en bijbehorende cijfers horen er uiteraard ook op te staan. Zonder je cijferlijst kunnen we je aanmeldverzoek helaas niet in behandeling nemen.\",\"extrainfo_why\":\"Waarom wil je Technology and Liberal Arts & Sciences (ATLAS) studeren aan het University College Twente? Geef ons een korte motivatie.\",\"extras\":[\"Let op: maximaal \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"persoon\"],\"subselse\":[\"personen\"]},\".\"],\"extras_title\":\"Hoeveel personen neem je mee?\",\"full\":\"vol\",\"group-extra\":\"Extra sessies en activiteiten\",\"group-presentation\":\"Opleidingspresentaties\",\"location\":\"| Enschede\",\"maxtwoprogrames\":\"Je kunt maximaal twee voorlichtingsrondes bezoeken\",\"myprogramme\":\"Mijn programma\",\"nochoiceyet\":\"Ik kies later\",\"personaldata\":\"Mijn gegevens\",\"personaldatatitle\":\"Mijn persoonlijke gegevens\",\"personalinfo\":\"Persoonlijke info\",\"profile\":\"Profiel\",\"program1\":\"Keuze 1\",\"program2\":\"Keuze 2\",\"program_notsureyet\":\"Ik weet het nog niet zeker\",\"programmefull\":\"Door de drukte is het helaas niet mogelijk beide programma's te bezoeken. Wijzig je selectie.\",\"programmeinclusterwith\":[\"De gekozen opleiding heeft een gecombineerde presentatie met \",1,\". Daarom kun je deze opleidingen niet individueel bezoeken.\"],\"programmeinclusterwith_campusexperience\":[\"Deze opleiding heeft een gezamenlijke tour met \",1,\". Kies een andere opleiding.\"],\"register\":\"Aanmelden\",\"registration\":\"Aanmelden\",\"request_visitcampus\":\"Ik wil ook de campus bezoeken.\",\"school\":\"Wat is de naam van je school?\",\"school_city\":\"In welke plaats zit je nu op school?\",\"selectcity\":\"- Kies je stad -\",\"selectpresentation\":\"- Kies presentatie -\",\"selectprogramme\":\"- Kies opleiding -\",\"selectqasession\":\"- Kies een Q&A sessie -\",\"selectroundoption\":\"Maak een keuze (optioneel)\",\"selectroundoption-required\":\"Maak een keuze (verplicht)\",\"selectschool\":\"- Kies je school -\",\"setupday\":\"Stel je dagprogramma samen\",\"thanks1\":\"Leuk dat je komt\",\"thanks2\":\"! Je hebt je aangemeld voor\",\"thankyou\":[\"Je bent aangemeld. Leuk dat je naar onze campus in Enschede komt, \",1,\"!\"],\"timerange\":[1,\" uur\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"de\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"Du bist mit dieser E-Mail Adresse bereits für dieses Event angemeldet. Wenn du dich noch einmal anmeldest, dann wird die erste Registrierung überschrieben.\",\"alreadysignedup-2\":\"Möchtest du deine Registrierung überschreiben?\",\"alreadysignedup-no\":\"Nein, nicht überschreiben\",\"alreadysignedup-yes\":\"Ja, überschreiben\",\"btn_confirm\":\"Bestätigen\",\"btn_nextpage\":\"Weiter\",\"btn_previouspage\":\"Zurück\",\"cancelled\":\"Du hast dich erfolgreich abgemeldet.\",\"cancellink\":\"Abmelden\",\"chooseaday\":\"Wähle einen Tag\",\"chooseeducation\":\"Wähle deine momentane Vorbildung\",\"choosepresentation\":\"Wähle eine Präsentation\",\"chooseprogrammes\":\"Wähle einen Studiengang\",\"chooseprograms\":\"Von welchem/welchen Programm(en) möchten Sie eine Präsentation besuchen?\",\"chooseqasession\":\"Wähle ein Q&A session\",\"choosevwoclass\":\"- Wähle deinen Schuljahrgang -\",\"class\":\"Schuljahrgang\",\"confirmcancel\":\"Möchtest du dich wirklich abmelden?\",\"confirmcancel_no\":\"Nein\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Ja\",\"contactme\":\"Ich wünsche eine Kontaktaufnahme der Uni bezüglich Anreiseinformationen\",\"dayprogramme\":\"Dein Programm für diesen Tag\",\"differentprogramlink\":\"Ja, ich möchte etwas anpassen\",\"diploma\":\"Diploma\",\"extrainfo_resume\":[\"Bitte lade deinen Lebenslauf \",{\"t\":\"tag\",\"tag\":\"b\",\"subs\":\"mit deinen letzten Noten\"},\" hoch (alles in einem Dokument). Wir benötigen diese Daten um deine Vorbildung zu beurteilen. Wenn du keinen Lebenslauf abgibst, können wir deine Anmeldung leider nicht beurteilen.\"],\"extrainfo_why\":\"Warum möchtest du Technology and Liberal Arts & Sciences (ATLAS) am University College Twente studieren? Bitte gebe uns eine kurze Begründung.\",\"extras\":[\"Maximum \",1,\".\"],\"extras_title\":\"Wie viele Besucher/Freunde begleiten dich?\",\"full\":\"voll\",\"group-extra\":\"Extra Sessions und Aktivitäten\",\"group-presentation\":\"Studiengang Präsentationen\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"Du kannst maximal zwei Informationsrunden besuchen\",\"myprogramme\":\"Mein Programm\",\"nochoiceyet\":\"Ich möchte mich später entscheiden\",\"personaldata\":\"Meine Daten\",\"personaldatatitle\":\"Meine persönlichen Daten\",\"personalinfo\":\"Persönlichen Daten\",\"profile\":\"Profil\",\"program1\":\"Option 1\",\"program2\":\"Option 2\",\"program_notsureyet\":\"Ich bin mir noch nicht sicher\",\"programmefull\":\"Aufgrund hoher Anmeldezahlen ist es leider nicht möglich beide Programmteile zu besuchen. Bitte ändere deine Auswahl.\",\"programmeinclusterwith\":[\"Der gewählte Studiengang präsentiert sich zusammen mit \",1,\". Deswegen kannst du diesen Studiengang nur in dieser Kombination besuchen.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Anmelden\",\"registration\":\"Anmelden\",\"request_visitcampus\":\"Ich möchte den Campus in Zukunft besuchen. Schicken Sie mir eine E-Mail, wenn ich mich dafür anmelden kann.\",\"school\":\"Wie heisst deine Schule?\",\"school_city\":\"In welcher Stadt gehst du zur Schule?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Wähle Präsentation -\",\"selectprogramme\":\"- Wähle einen Studiengang -\",\"selectqasession\":\"- Wähle ein Q&A session -\",\"selectroundoption\":\"Auswahl treffen (optional)\",\"selectroundoption-required\":\"Auswahl treffen (erforderlich)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Stelle dein Tagesprogramm zusammen\",\"thanks1\":\"Wir freuen uns auf deinen Besuch\",\"thanks2\":\"! Du hast dich angemeldet für\",\"timerange\":[1,\" hours\"],\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"ar\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"bg\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"el\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"es\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"id\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"pt\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"ro\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\nregisterTexts(\"utwente_voorlichting\",\"zh\",{\"widgets\":{\"openday\":{\"alreadysignedup-1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-2\":\"Would you like to overwrite your registration?\",\"alreadysignedup-no\":\"No, do not overwrite\",\"alreadysignedup-yes\":\"Yes, overwrite\",\"btn_confirm\":\"Confirm\",\"btn_nextpage\":\"Next\",\"btn_previouspage\":\"Previous\",\"cancelled\":\"Your registration has been cancelled.\",\"cancellink\":\"Cancel registration\",\"chooseaday\":\"Choose a day\",\"chooseeducation\":\"Choose your level of education\",\"choosepresentation\":\"Choose a presentation\",\"chooseprogrammes\":\"Choose a programme\",\"chooseprograms\":\"Of which programme(s) would you like to attend a presentation?\",\"chooseqasession\":\"Choose a Q&A session\",\"choosevwoclass\":\"- Choose your class -\",\"class\":\"Class\",\"confirmcancel\":\"Are you sure you want to cancel your registration?\",\"confirmcancel_no\":\"No\",\"confirmcancel_ok\":\"Ok\",\"confirmcancel_yes\":\"Yes\",\"contactme\":\"Please contact me about travel information\",\"dayprogramme\":\"Your schedule for this day\",\"differentprogramlink\":\"I want to change something\",\"diploma\":\"Current (or recently completed) education\",\"extrainfo_resume\":\"Upload your grade list or transcript. We need this document to check your educational background. Your transcript should clearly state what your current year is, high school name, courses being taken and of course grades should also be clearly stated on the transcript. Without sending the grade list you cannot be considered for the In_Sight Day.\",\"extrainfo_why\":\"Why are you interested in University College Twente and BSc. Technology and Liberal Arts & Sciences (ATLAS)? Please give us a short motivation.\",\"extras\":[\"Please note: max \",1,\" \",{\"t\":\"ifparam\",\"p\":1,\"value\":\"1\",\"subs\":[\"person\"],\"subselse\":[\"persons\"]},\".\"],\"extras_title\":\"How many people will accompany you?\",\"full\":\"full\",\"group-extra\":\"Extra sessions and activities\",\"group-presentation\":\"Study presentations\",\"location\":\"| Enschede | The Netherlands\",\"maxtwoprogrames\":\"You can visit a maximum of two programmes.\",\"myprogramme\":\"My programme\",\"nochoiceyet\":\"I want to choose later\",\"personaldata\":\"My information\",\"personaldatatitle\":\"My personal information\",\"personalinfo\":\"Personal info\",\"profile\":\"Profile\",\"program1\":\"First programme\",\"program2\":\"Second programme\",\"program_notsureyet\":\"I'm not sure yet\",\"programmefull\":\"Because of the high number of registrations it's unfortunately not possible to visit both programmes. Please choose another programme.\",\"programmeinclusterwith\":[\"The chosen programme has a combined presentation with \",1,\". Therefore, you cannot visit these programmes seperately.\"],\"programmeinclusterwith_campusexperience\":[\"This programme has a combined tour with \",1,\". Choose another programme.\"],\"register\":\"Register\",\"registration\":\"Register\",\"request_visitcampus\":\"I would like to visit the campus in the future. Send me an email when I can sign up for this.\",\"school\":\"What is the name of your current school?\",\"school_city\":\"In what city or town is your school located?\",\"selectcity\":\"- Select your city -\",\"selectpresentation\":\"- Choose presentation -\",\"selectprogramme\":\"- Choose a programme -\",\"selectqasession\":\"- Choose a Q&A session -\",\"selectroundoption\":\"Make a choice (optional)\",\"selectroundoption-required\":\"Make a choice (required)\",\"selectschool\":\"- Select your school -\",\"setupday\":\"Set up your schedule\",\"thanks1\":\"Great to hear you’ll be coming\",\"thanks2\":\"! You have registered for\",\"thankyou\":[\"You have registered. \",1,\", it's great that you're coming to our campus in Enschede, The Netherlands!\"],\"timerange\":[1,\" hours\"]}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/es.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n","import * as dompack from '@webhare/dompack';\nimport * as dialogapi from 'dompack/api/dialog';\nimport { UTVoorlichtingRPCForm } from '@mod-utwente_voorlichting/js/shared/forms';\nimport * as forms from \"@mod-publisher/js/forms\";\nimport { getTid } from \"@webhare/gettid\";\nimport './opendays_v2.lang.json';\nimport './opendays_v2.scss';\nimport { getReferralInfo } from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport { navigateTo } from '@webhare/env';\nimport { pushToDataLayer } from '@webhare/frontend';\n\nclass OpenDagenFormV2 extends UTVoorlichtingRPCForm {\n  shortform;\n\n  constructor(node: HTMLFormElement) {\n    super(node);\n    this.shortform = node.hasAttribute(\"data-shortform\");\n\n    pushToDataLayer({ onlineopenday_eventtype: this.node.dataset.onlineopenday_eventtype || '' });\n\n    this.diplomafield?.addEventListener(\"change\", () => this._onDiplomaChange());\n    dompack.qS('#cancellink')?.addEventListener('click', evt => this.doCancel(evt));\n\n    if (new URL(location.href).searchParams.get(\"type\") === \"cancel\")\n      this.doCancel();\n  }\n\n  _onDiplomaChange() {\n    const eventoptions = this.node.querySelectorAll<HTMLInputElement>(\"input[name=event]:not([disabled]\");\n    if (eventoptions.length === 1 && !eventoptions[0].checked)\n      eventoptions[0].click(); //autoselect only option\n  }\n\n  async gotoPage(idx: number) {\n    if (idx === 1 && this.shortform) {\n      await this.invokeRPC(\"prepShortForm\", getReferralInfo());\n      setTimeout(() => pushToDataLayer({ event: \"onlineopendays-shortform\" }), 1); //send AFTER form content is reported to analytics\n    }\n\n    const result = await super.gotoPage(idx);\n    this.node.scrollIntoView(); //scrollfix\n    return result;\n  }\n\n  async runConfirmResignup() {\n    return dialogapi.runMessageBox(\n      <div>\n        <p>{getTid('utwente_voorlichting:frontend.opendays_v2.js.alreadysignedup-line1')}</p>\n        <p><b>{getTid('utwente_voorlichting:frontend.opendays_v2.js.alreadysignedup-line2')}</b></p>\n      </div>,\n      [\n        { result: \"yes\", title: getTid(\"utwente_voorlichting:frontend.opendays_v2.js.yes-dontoverwrite\") },\n        { result: \"no\", title: getTid(\"utwente_voorlichting:frontend.opendays_v2.js.no-overwrite\") }\n      ]);\n  }\n\n  onSubmitSuccess(result: unknown) {\n    const r = result as { debughtmlinfo?: string };\n    if (r.debughtmlinfo) {\n      const debuginfoholder = <div class=\"opendaysv2__debuginfo\" />;\n      debuginfoholder.innerHTML = r.debughtmlinfo;\n      dompack.qR(\".opendaysv2__successtext\").after(debuginfoholder);\n    }\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- formbase should give us proper Errors type first\n  onSubmitFailed(errors: any, result: unknown) {\n    if (errors.length === 1 && errors[0].name === \"wrd_contact_email\" && errors[0].metadata && errors[0].metadata.verifyresub) { //We're being rejected because the email address is already known\n      this.runConfirmResignup().then(r => {\n        if (r === \"yes\")\n          this.validateAndSubmit({ verifyresub: errors[0].metadata.verifyresub });\n      });\n      return;\n    }\n\n    super.onSubmitFailed(errors, result);\n  }\n\n  doCancel(evt?: Event) {\n    if (evt)\n      dompack.stop(evt);\n    void dialogapi.runMessageBox(\n      <div>\n        <p>{getTid('utwente_voorlichting:frontend.opendays_v2.js.confirm-cancel')}</p>\n      </div>,\n      [\n        { result: \"yes\", title: getTid(\"utwente_voorlichting:frontend.opendays_v2.js.yes-cancel\") },\n        { result: \"no\", title: getTid(\"utwente_voorlichting:frontend.opendays_v2.js.no-dont-cancel\") }\n      ]).then(result => {\n        if (result === \"yes\") {\n          navigateTo({ type: \"form\", form: { action: location.href, vars: [{ name: \"type\", value: \"cancel\" }], method: \"POST\" } });\n        } else {\n          const url = new URL(location.href);\n          if (url.searchParams.get(\"type\") === \"cancel\") { //remove cancel:1 from url\n            url.searchParams.delete(\"type\");\n            history.replaceState({}, document.title, url.toString());\n          }\n        }\n      });\n  }\n}\n\nforms.registerHandler(\"utwente_voorlichting:opendays_v2\", node => new OpenDagenFormV2(node));\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/webfeatures/opendays_v2/opendays_v2.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_voorlichting\",\"en\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"nl\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"Je bent met dit e-mailadres al aangemeld voor dit evenement. Als je je opnieuw aanmeldt, overschrijven we de bestaande aanmelding.\",\"alreadysignedup-line2\":\"Wil je je aanmelding overschrijven?\",\"confirm-cancel\":\"Weet je zeker dat je je aanmelding wil annuleren?\",\"no-dont-cancel\":\"Nee\",\"no-overwrite\":\"Nee, niet overschrijven\",\"yes-cancel\":\"Ja, annuleren\",\"yes-dontoverwrite\":\"Ja, overschrijven\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"de\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"ar\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"bg\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"el\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"es\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"id\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"pt\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"ro\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"zh\",{\"frontend\":{\"opendays_v2\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/es.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport './leadswidgets.scss';\nimport * as dompack from 'dompack';\nimport * as widgets from '@mod-utwente_base/webfeatures/utwidgets/layout';\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as forms from \"@mod-publisher/js/forms\";\n\nimport \"./brochurerequest/brochurerequest\";\nimport \"./stayuptodate/stayuptodate\";\n\nclass PreRegistrationFormHandler extends forms.RPCFormBase {\n  constructor(node) {\n    super(node);\n    this.widget = dompack.closest(node, '.widget-preregistrationwidget');\n  }\n\n  async onRPC(promise) {\n    if (this.widget.classList.contains(\"rpc--active\"))\n      return;\n\n    this.widget.classList.add(\"rpc--active\");\n    await promise;\n    this.widget.classList.remove(\"rpc--active\");\n  }\n\n  getFormExtraSubmitData() {\n    const targetinterest = document.documentElement.dataset.targetinterest || '';\n    if (!targetinterest)\n      console.warn(\"data-targetinterest isn't specified on this page.\");\n\n    return {\n      \"targetinterest\": targetinterest,\n      \"hoofdniveau\": document.documentElement.dataset.hoofdniveau || '',\n      \"subniveau\": document.documentElement.dataset.subniveau || '',\n      \"programme\": document.documentElement.dataset.programme || '',\n      \"interesttype\": this.node.dataset.interesttype || '',\n      dontaskpermission: this.node.dataset.dontaskpermission === \"true\"\n    };\n  }\n\n  onSubmitSuccess(response) {\n    if (response.success) {\n      this.reset();\n      const gotourl = this.node.dataset.successRedirect;\n      crm.learnedAboutUser(response.guid, this.node.firstname.value);\n\n      if (gotourl) {\n        setTimeout(() => location.href = gotourl, 150); //give GTM time to learn about the userid\n      } else {\n        this.widget.classList.add('rpc--success');\n        widgets.relayoutWidgets(this.widget);\n      }\n    } else {\n      this.widget.classList.add('rpc--fail');\n      widgets.relayoutWidgets(this.widget);\n    }\n  }\n}\n\nforms.registerHandler(\"utwente_voorlichting:preregistration\", node => new PreRegistrationFormHandler(node));\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./brochurerequest.scss\";\nimport * as dompack from 'dompack';\nimport * as widgets from '@mod-utwente_base/webfeatures/utwidgets/layout';\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as forms from \"@mod-publisher/js/forms\";\nimport services from \"../leadswidgets.rpc.json?proxy\";\nimport * as dialogapi from 'dompack/api/dialog';\n\nclass EducationBrochureFormHandler extends forms.RPCFormBase {\n  constructor(node) {\n    super(node);\n\n    const foldnode = this.node.closest(\".foldablecontent\");\n    if (foldnode) { // Show brochure request form if hash links brochure request widget\n      // https://gitlab.webhare.com/utwente/utwente_base/-/issues/2551\n      window.addEventListener(\"hashchange\", () => this.onHashChange(foldnode, location.hash));\n      if (location.hash.length > 1)\n        this.onHashChange(foldnode, location.hash);\n    }\n\n    if (node.dataset.brochurelist)\n      this.brochurelist = JSON.parse(node.dataset.brochurelist);\n    else\n      this.brochurelist = window.brochurelist; //legacy until end of 2022\n\n    this.widget = node.closest('.brochurerequestform-container'); // generic class so both the inline and footer(file)widget version work\n    if (!this.widget) // fallback for not yet republished pages\n      this.widget = node.closest('.widget-brochurerequestform');\n\n    this.downloadform = dompack.qS(this.widget, \".downloadpage form\");\n    this.downloadform.addEventListener(\"submit\", this.doDownloadBrochure.bind(this));\n\n    this.downloadform.querySelector(\".wh-form__button.email\").addEventListener(\"click\", ev => this.doEmailBrochure(ev));\n\n    const htmllinknode = dompack.qS(this.widget, \".brochurerequestform__htmlbrochure__link\");\n    if (htmllinknode) {\n      this.downloadform.programme_dl.addEventListener(\"change\", () => this.updateBrochureHtmlLink(htmllinknode));\n      this.updateBrochureHtmlLink(htmllinknode);\n    }\n\n    dompack.qSA(this.widget, \".imnot\").forEach(\n      link => link.addEventListener(\"click\",\n        evt => {\n          dompack.stop(evt);\n          dompack.dispatchCustomEvent(window, \"ut-brochureform-returntoform\", { bubbles: true, cancelable: false });\n          setTimeout(() => this.node.scrollIntoView({ behavior: \"smooth\" }), 300);\n        }));\n\n    this.txt_afterlanding = dompack.qS(this.widget, \".afterlanding__text\").textContent;\n\n    this.updateBrochureWidget();\n    window.addEventListener(\"ut-brochureform-returntoform\", () => this.doReturnToForm());\n  }\n\n  updateBrochureHtmlLink(htmllinknode) {\n    let htmllink = \"\";\n    if (this.downloadform.programme_dl.value !== \"\") {\n      const selected_brochure = this.downloadform.programme_dl.selectedOptions[0];\n      if (selected_brochure?.dataset?.htmllink)\n        htmllink = selected_brochure.dataset.htmllink;\n    }\n\n    htmllinknode.parentNode.hidden = htmllink === \"\";\n    htmllinknode.href = htmllink ?? \"#\";\n  }\n\n  isBrochureDeeplink(foldnode, hash) {\n    if (!this.deeplinks) {\n      const deeplinkcontainer = foldnode.closest(\".foldabledeeplink\");\n      if (deeplinkcontainer)\n        this.deeplinks = dompack.qSA(deeplinkcontainer, \".wh-anchor[id]\").map(_ => \"#\" + _.id);\n    }\n\n    return this.deeplinks ? this.deeplinks.indexOf(hash) : false;\n  }\n\n  onHashChange(foldnode, hash) {\n    if (!hash || hash === \"#\")\n      return;\n\n    if (!this.isBrochureDeeplink(foldnode, hash))\n      return;\n\n    if (foldnode.classList.contains(\"foldablecontent--open\"))\n      return; // Already open\n\n    /* Check if foldablecontent is initialized (foldablecontent--active)\n       See: utwente_base/webdesigns/ws2016/src/widgets/embeddedobjects/index.es\n       and utwente_base/doc/topics/utwente-random/foldablecontent.md\n    */\n    if (foldnode.classList.contains(\"foldablecontent--active\"))\n      this.showBrochureRequestForm(foldnode);\n    else {\n      new MutationObserver((mutlist, obs) => {\n        if (mutlist.find(_ => _.target.classList.contains(\"foldablecontent--active\"))) {\n          obs.disconnect(); // observe just once\n          this.showBrochureRequestForm(foldnode);\n        }\n      }).observe(foldnode, { subtree: false, attributes: true, attributeFilter: [\"class\"] });\n    }\n  }\n\n  showBrochureRequestForm(foldnode) {\n    dompack.dispatchCustomEvent(foldnode, \"ws:foldable-set\", {\n      bubbles: true,\n      cancelable: false,\n      detail: { open: true }\n    });\n    return true;\n  }\n\n  doEmailBrochure(ev) {\n    ev.preventDefault();\n    this.sendBrochureMail(this.downloadform.programme_dl.value);\n  }\n\n  async sendBrochureMail(programmeid) {\n    if (this.widget.classList.contains(\"rpc--active\"))\n      return;\n\n    const guid = crm.getUserSettings().guid;\n    if (!guid) {\n      dompack.dispatchCustomEvent(window, \"ut-brochureform-returntoform\", { bubbles: true, cancelable: false });\n      return;\n    }\n\n    const data = {\n      programme: programmeid,\n      targetinterest: this.getFormExtraSubmitData().targetinterest,\n      source: document.location.href,\n      targetlanguage: document.documentElement.lang.substr(0, 2)\n    };\n\n    this.widget.classList.add(\"rpc--active\");\n    const res = await services.mailBrochure(guid, data);\n    this.widget.classList.remove(\"rpc--active\");\n\n    if (!res) // when the form fails we return to the first page (... but aren't we still there?)\n      dompack.dispatchCustomEvent(window, \"ut-brochureform-returntoform\", { bubbles: true, cancelable: false });\n    else {\n      const msgnode = this.widget.querySelector(\".emailbrochureform-success\");\n      if (msgnode) {\n        const dialog = dialogapi.createDialog({ allowcancel: true, borrow: msgnode });\n        dialog.runModal();\n      }\n    }\n  }\n\n  doReturnToForm() {\n    this.reset();\n\n    this.setBrochureState(\"form\", true);\n    widgets.relayoutWidgets(this.widget);\n    crm.setUserSettings({ guid: null, firstname: null, \"brochure-lastprogramme\": null });\n  }\n\n  doDownloadBrochure(evt) {\n    evt.preventDefault();\n\n    const selected_brochure = this.downloadform.programme_dl.selectedOptions[0];\n    if (selected_brochure?.dataset?.link)\n      window.open(selected_brochure.dataset.link, \"_blank\");\n    else\n      window.open(this.lookupBrochure(selected_brochure.value).brochure, \"_blank\");\n  }\n\n  lookupBrochure(programme) {\n    return window.brochurelist.find(_ => _.rowkey === programme);\n  }\n\n  async onRPC(promise) {\n    if (this.widget.classList.contains(\"rpc--active\"))\n      return;\n\n    this.widget.classList.add(\"rpc--active\");\n    await promise;\n    this.widget.classList.remove(\"rpc--active\");\n  }\n\n  onSubmitSuccess(result) {\n    // Note: if no marketing permission, we don't have a guid\n    crm.learnedAboutUser(result ? result.guid : null, this.node.firstname.value);\n    crm.setUserSettings({ \"brochure-lastprogramme\": this.node.programme.value });\n\n    //  Replace with download widget\n    this.updateBrochureWidget(true);\n    this.setBrochureState(\"download\", true);\n\n    dompack.changeValue(this.downloadform.programme_dl, this.node.programme.value);\n\n    dompack.qSA(this.widget, \".aftersubmission\").forEach(_ => _.style.display = \"block\");\n    dompack.qSA(this.widget, \".afterlanding\").forEach(_ => _.style.display = \"none\");\n    const node = dompack.qS(this.widget, \".aftersubmission\");\n    this.node.classList.add(\"requestform--aftersubmission\");\n    for (const txtnode of node.querySelectorAll(\".text\"))\n      txtnode.textContent = txtnode.textContent.replace(\"[naam]\", this.node.firstname.value);\n    node.style.display = \"block\";\n  }\n\n  getFormExtraSubmitData() {\n    const targetinterest = document.documentElement.dataset.targetinterest || '';\n    if (!targetinterest)\n      console.warn(\"data-targetinterest isn't specified on this page.\");\n\n    return { \"targetinterest\": targetinterest };\n  }\n\n  setBrochureState(state, also_set_focus) {\n    const page1 = state === \"form\";\n    this.node.style.display = page1 ? \"block\" : \"none\";\n    dompack.qS(this.widget, \".downloadpage\").style.display = page1 ? \"none\" : \"block\";\n    requestAnimationFrame(() => widgets.relayoutWidgets(this.widget));\n\n    if (also_set_focus) {\n      if (state === \"form\")\n        this.widget.querySelector(\".requestform\").focus();\n      else if (state === \"download\")\n        this.widget.querySelector(\".downloadpage\").focus();\n    }\n  }\n\n  updateBrochureWidget(aftersubmit) {\n    if (crm.getUserSettings()[\"brochure-lastprogramme\"]) {\n      // Some someone already used the widget\n      // so move to the second page in which\n      // you can download or email additional brochures.\n\n      // dompack.changeValue(this.downloadform.programme_dl, crm.getUserSettings()[\"brochure-lastprogramme\"]); //dont preselect the last ever brochure, might not match when moving to different sites\n\n      dompack.qS(this.widget, \".firstname\").textContent = crm.getUserSettings().firstname || '';\n      // dompack.qS(this.widget, \".imnot\").style.display = \"block\";\n\n      this.setBrochureState(\"download\", aftersubmit); // if we came here through user-interaction (submit) we set the focus\n\n      dompack.qSA(this.widget, \".aftersubmission\").forEach(_ => _.style.display = \"none\");\n\n      dompack.qSA(this.widget, \".firstname\").forEach(_ => _.textContent = crm.getUserSettings().firstname || '');\n\n      const node = dompack.qS(this.widget, \".afterlanding__text\");\n      node.textContent = this.txt_afterlanding.replace(\"[naam]\", crm.getUserSettings().firstname || '');\n      node.parentNode.style.display = \"block\";\n\n      widgets.relayoutWidgets(this.widget);\n    } else {\n      this.setBrochureState(\"form\");\n    }\n  }\n}\n\nforms.registerHandler(\"utwente_voorlichting:brochurerequest\", node => new EducationBrochureFormHandler(node));\n","const { createService } = require(\"@mod-system/js/wh/rpc.ts\"); export default createService(\"utwente_voorlichting:leads\");","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./stayuptodate.scss\";\nimport * as dompack from 'dompack';\nimport * as forms from \"@mod-publisher/js/forms\";\nimport services from \"../leadswidgets.rpc.json?proxy\";\n\nimport { UTVoorlichtingRPCForm } from '@mod-utwente_voorlichting/js/shared/forms';\n\nclass stayuptodateFormHandler extends UTVoorlichtingRPCForm {\n  constructor(formnode) {\n    super(formnode);\n\n    this.haveprogram = Boolean(this.elements[\"program.select_master\"]?.value || this.elements[\"program.select_bachelor\"]?.value);\n    if (this.haveprogram) //already set?\n    {\n      if (this.elements[\"program.select_master\"])\n        this.elements[\"program.select_master\"].closest(\".wh-form__fieldgroup\").style.display = \"none\";\n      if (this.elements[\"program.select_bachelor\"])\n        this.elements[\"program.select_bachelor\"].closest(\".wh-form__fieldgroup\").style.display = \"none\";\n    }\n\n    this.elements[\"update\"].addEventListener(\"click\", evt => this.onUpdateData(evt));\n  }\n\n  onSubmitSuccess(response) {\n    this.updatetoken = response.updatetoken;\n    super.onSubmitSuccess(response);\n  }\n\n  async onUpdateData() {\n    const lock = dompack.flagUIBusy({ ismodal: true });\n    try {\n      const updatedata = { expectedstartingyear: parseInt(this.elements[\"expectedstartingyear.select\"].value) };\n\n      if (this.elements[\"targetinterest\"]?.value)\n        updatedata.targetinterest = this.elements[\"targetinterest\"].value;\n\n      //check whether either master is explicitly selected or the bachelor select isn't even rendered\n      const ismaster = updatedata.targetinterest == 'MASTER' || !this.elements[\"program_bachelor.select\"];\n      const programnode = this.elements[ismaster ? \"program_master.select\" : \"program_bachelor.select\"];\n      if (programnode?.value)\n        updatedata.program = programnode.value;\n\n      await services.updateProfile(this.updatetoken, updatedata);\n      if (this.getCurrentPageNumber) //WH5.2+ added this\n        this.gotoPage(this.getCurrentPageNumber() + 1); //'next' thank you page\n      else\n        this.gotoPage(2); //for now we know it to be 1, but the above seems clearer in purpose\n    } finally {\n      lock.release();\n    }\n  }\n}\n\nforms.registerHandler(\"utwente_voorlichting:stayuptodate\", node => new stayuptodateFormHandler(node));\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\n// Don't import the entire utwente_base/webdesigns/ws2016/src/shared/utforms\n//  as it overwrites other webdesign css (ws2026), should only be imported within ws2016 webdesign\n//import '@mod-utwente_base/webdesigns/ws2016/src/shared/utforms';\n\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as dompack from 'dompack';\nimport { registerHandler, RPCFormBase } from '@mod-publisher/js/forms';\n\n\nlet formnode;\nlet formextradata;\n\n\nclass ContactForm extends RPCFormBase {\n  constructor(form) {\n    super(form);\n\n    formnode = form;\n    formextradata = JSON.parse(form.getAttribute(\"data-extraformdata\"));\n\n    if (form.programme) {\n      form.programme.addEventListener(\"change\", updateSpecializations);\n      updateSpecializations();\n    }\n  }\n  onSubmitSuccess(data) {\n    window.dataLayer.push(data.todatalayer);\n    if (data.guid)\n      crm.learnedAboutUser(data.guid, data.firstname);\n  }\n}\n\nregisterHandler(\"utwente_voorlichting:mastercontact\", node => new ContactForm(node));\n\nfunction updateSpecializations() {\n  if (!formextradata || !formextradata.tracks_per_programme)\n    return;\n\n  const programmeid = formnode.programme.value;\n  const programme = formextradata.tracks_per_programme.find(programme => programme.programme == programmeid);\n\n  formnode.specialization.innerHTML = \"\";\n\n  const fieldline = dompack.closest(formnode.specialization, \".wh-form__fieldgroup\");\n\n  if (!(programme && programme.programme)) {\n    fieldline.style.display = \"none\";\n  } else {\n    // placeholder\n    var elem = document.createElement(\"option\");\n    elem.value = 0;\n    elem.innerText = formextradata.nospec;\n    elem.setAttribute(\"selected\", \"selected\");\n    formnode.specialization.appendChild(elem);\n\n    for (const track of programme.tracks) {\n      var elem = document.createElement(\"option\");\n      elem.value = track.trackid;\n      elem.innerText = track.title;\n      formnode.specialization.appendChild(elem);\n      //elem.selected == track.trackid == extradata.specialization;\n    }\n\n    fieldline.style.display = \"\";\n  }\n\n  dompack.dispatchCustomEvent(formnode.specialization\n    , \"refresh\", {\n      bubbles: true,\n    cancelable: false\n  });\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport * as dialogapi from \"dompack/api/dialog\";\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport * as forms from \"@mod-publisher/js/forms\";\nimport getTid from \"@mod-tollium/js/gettid\";\nimport { UTVoorlichtingRPCForm } from '@mod-utwente_voorlichting/js/shared/forms';\n\nimport \"./tasterdays.scss\";\nimport \"./tasterdays.lang.json\";\nimport \"../ws2016_voorlichting/activities/activityform.scss\";\n\nclass TasterDaysForm extends UTVoorlichtingRPCForm {\n  constructor(node) {\n    super(node);\n    const cancelregistration = this.node.querySelector(\".wh-form__fieldgroup[data-wh-form-group-for='cancelregistration'] .wh-form__richtext\");\n    if (cancelregistration)\n      cancelregistration.append(<p class=\"normal\"><a href=\"#\" onClick={event => this.doCancel(event)}>{getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.cancelregistration\")}</a><br /><br /></p>);\n\n    dompack.register('.utwente-tasterdays--hide-infotext-if-nl', node => this.hideInfoTextIfNL(node));\n  }\n\n  hideInfoTextIfNL(node) {\n    node.querySelector(\"select\").addEventListener(\"input\", () => this.checkInfoTextNL(node));\n    this.checkInfoTextNL(node);\n  }\n\n  checkInfoTextNL(node) {\n    node.querySelector('.wh-form__infotextwrapper').hidden = node.querySelector(\"select\").value == 'NL';\n  }\n\n  async doCancel(event) {\n    dompack.stop(event);\n    if (await dialogapi.runMessageBox(\n      <div>\n        <p>{getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.confirm-cancel\")}</p>\n      </div>,\n      [\n        { result: \"yes\", title: getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.yes-cancel\") },\n        { result: \"no\", title: getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.no-dont-cancel\") }\n      ]) == \"yes\") {\n      const gotourl = new URL(location.href);\n      gotourl.searchParams.set(\"cancel\", 1);\n      location.href = gotourl.toString();\n    }\n  }\n\n  async doConfirmResignup() {\n    return dialogapi.runMessageBox(\n      <div>\n        <p>{getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.alreadysignedup-line1\")}</p>\n        <p><b>{getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.alreadysignedup-line2\")}</b></p>\n      </div>,\n      [\n        { result: \"yes\", title: getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.yes-dontoverwrite\") },\n        { result: \"no\", title: getTid(\"utwente_voorlichting:webfeatures.tasterdays.js.no-overwrite\") }\n      ]);\n  }\n\n  onSubmitSuccess(result) {\n    // Show debug info if available\n    if (result && result.debughtmlinfo) {\n      const debuginfoholder = <div class=\"tasterdays__debuginfo\" />;\n      debuginfoholder.innerHTML = result.debughtmlinfo;\n      dompack.qS(this.node, \".wh-form__fieldgroup[data-wh-form-group-for='thankyou']\").after(debuginfoholder);\n    }\n  }\n\n  onSubmitFailed(errors, result) {\n    if (errors.length == 1 && errors[0].name == \"wrd_contact_email\" && errors[0].metadata && errors[0].metadata.verifyresub) {\n      //We're being rejected because the email address is already known\n      this.doConfirmResignup().then(result => {\n        if (result == \"yes\") {\n          this.validateAndSubmit({ verifyresub: errors[0].metadata.verifyresub }).then(() => this.gotoPage(1));\n        }\n      });\n      return;\n    }\n\n    super.onSubmitFailed(errors, result);\n  }\n}\n\nforms.registerHandler(\"utwente_voorlichting:tasterdays\", node => new TasterDaysForm(node));\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/webfeatures/tasterdays/tasterdays.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_voorlichting\",\"en\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"nl\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"Je bent met dit e-mailadres al aangemeld voor dit evenement. Als je je opnieuw aanmeldt, overschrijven we de bestaande aanmelding.\",\"alreadysignedup-line2\":\"Wil je je aanmelding overschrijven?\",\"cancelregistration\":\"Ik wil mijn registratie annuleren\",\"confirm-cancel\":\"Weet je zeker dat je je registratie wil verwijderen?\",\"no-dont-cancel\":\"Nee\",\"no-overwrite\":\"Nee, niet overschrijven\",\"yes-cancel\":\"Ja, verwijderen\",\"yes-dontoverwrite\":\"Ja, overschrijven\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"de\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"ar\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"bg\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"el\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"es\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"id\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"pt\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"ro\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\nregisterTexts(\"utwente_voorlichting\",\"zh\",{\"webfeatures\":{\"tasterdays\":{\"js\":{\"alreadysignedup-line1\":\"You're already registered for this event with this email address. If you register again, we will overwrite your existing registration.\",\"alreadysignedup-line2\":\"Would you like to overwrite your registration?\",\"cancelregistration\":\"I wish to cancel my registration\",\"confirm-cancel\":\"Are you sure you want to cancel your registration?\",\"no-dont-cancel\":\"No\",\"no-overwrite\":\"No, do not overwrite\",\"yes-cancel\":\"Yes, cancel\",\"yes-dontoverwrite\":\"Yes, overwrite\"}}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/es.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n","// FIXME Decide whether it's safe to compile this into te UT Bundle or that it should be a separate bundle\nimport { SlimSelect, TrigramMatcher } from \"@mod-utwente_design\";\nimport { getFrontendData } from \"@webhare/frontend\";\nimport \"./sirform.scss\";\nimport { create, dispatchCustomEvent, dispatchDomEvent, flagUIBusy, getLocal, qR, qSA, qS, setLocal } from \"@webhare/dompack\";\nimport { compareProperties, generateRandomId, parseTyped, pick, sleep, wrapSerialized } from \"@webhare/std\";\nimport { LocalFormBase, registerHandler, submitForm, type FormSubmission, type FormSubmitResult } from \"@webhare/forms\";\nimport { rpc } from \"@webhare/rpc\";\nimport type { SirFormConfig, SirFormEvent, SirFormSignup } from \"./sirform.rpc\";\nimport { RPCFormBase, type FormSubmitEmbeddedResult } from \"@mod-publisher/js/forms\";\nimport * as dialogapi from 'dompack/api/dialog';\nimport type { UTDialog } from \"@mod-utwente_base/webdesigns/ws2016/src/shared/dialog\";\nimport * as pwalib from '@mod-publisher/js/pwa';\nimport { getTid, getTidLanguage } from \"@webhare/gettid\";\nimport \"./sirform.lang.json\";\nimport type { UTReferralInfo } from \"@mod-utwente_base/js/types\";\nimport { getHardcodedURLReferralInfo, getReferralInfo } from \"@mod-utwente_base/webdesigns/ws2016/src/shared/crm/referralinfo\";\n\ndeclare module \"@webhare/frontend\" {\n  interface FrontendDataTypes {\n    \"utwente_voorlichting:sirform\": {\n      fairsinfo?: string;\n    };\n  }\n}\n\ntype ExtraSubmitData = {\n  id: string;\n  language: string;\n  date: string;\n  event: string;\n  referralinfo: UTReferralInfo;\n};\n\nlet admin: ConfigFormHandler | null = null;\nlet fairsinfo: SirFormConfig | null = null;\n\nfunction getSirConfig(): SirFormConfig {\n  return fairsinfo || getLocal<SirFormConfig>(\"utwente_voorlichting:sirform.config\") || {\n    fairTypes: [],\n    fairs: [],\n    programs: [],\n    schools: [],\n    now: \"\"\n  };\n}\nfunction getSelectedEventId(): string | null {\n  return fairsinfo ? fairsinfo.fairs[0].wrdGuid : getLocal<string>(\"utwente_voorlichting:sirform.selectedeventguid\");\n}\nfunction getSelectedEvent(): SirFormEvent | null {\n  const eventid = getSelectedEventId();\n  return eventid && getSirConfig().fairs.find(fair => fair.wrdGuid === eventid) || null;\n}\nfunction getUploadQueue(): FormSubmission[] {\n  return getLocal<FormSubmission[]>(\"utwente_voorlichting:sirform.uploadqueue\") || [];\n}\nfunction getNumUploaded(): number {\n  const eventid = getSelectedEventId();\n  return (eventid && getLocal<Record<string, number>>(\"utwente_voorlichting:sirform.uploadcounts\")?.[eventid]) || 0;\n}\nfunction increaseNumUploaded(eventid: string) {\n  const uploadMap = getLocal<Record<string, number>>(\"utwente_voorlichting:sirform.uploadcounts\") || {};\n  uploadMap[eventid] = (uploadMap[eventid] || 0) + 1;\n  setLocal<Record<string, number>>(\"utwente_voorlichting:sirform.uploadcounts\", uploadMap);\n}\n\nfunction updateOptions(select: HTMLSelectElement, newoptions: HTMLOptionElement[], { initialValue = '' } = {}) {\n  const oldvalue = select.value || initialValue;\n  select.replaceChildren(...newoptions);\n\n  if (select.value) {\n    select.value = oldvalue;\n    if (select.selectedIndex === -1) //reset if value not found\n      select.selectedIndex = 0;\n  }\n}\n\nfunction setupTrigramSearch(selnode: HTMLSelectElement) {\n  if (!selnode.utSlimSelect)\n    throw new Error(\"SlimSelect not initialized on select element\");\n\n  const seloptions = Array.from(selnode.options).map(opt => ({\n    value: opt.value,\n    text: opt.textContent || \"\",\n    id: opt.value,\n    selected: opt.selected,\n    parent: opt.dataset.parent || \"\",\n    style: opt.getAttribute(\"style\") || \"\",\n    class: opt.className || \"\"\n  }));\n\n  selnode.utSlimSelect.events.search = (search, currentData) => {\n    const selvalues = currentData.map(d => d.id);\n    seloptions.forEach(opt => opt.selected = selvalues.includes(opt.id)); //keep selection state in sync\n\n    if (search.length < 2)\n      return seloptions; // Just return all options if search is less than 2 characters\n\n    const list = seloptions.filter(_ => !_.selected).map(_ => _.text || \"\").filter(s => s.length > 0);\n\n    const prep = new TrigramMatcher(list);\n    const scorelist = prep.score(search);\n\n    // Only show results which scored at least 66% of max score found\n    const minscore = scorelist.length ? scorelist[0].score * 0.66 : 0;\n    const filteredScoreList = scorelist.filter(_ => _.score > minscore).map(_ => _.str);\n\n    const options = seloptions.filter(_ => filteredScoreList.includes(_.text || \"\"));\n    const insertedParents = options.filter(opt => opt.parent === \"\").map(_ => _.value);\n    options.forEach((opt, i) => {\n      if (opt.parent && !insertedParents.includes(opt.parent)) {\n        insertedParents.push(opt.parent);\n        const parentOpt = seloptions.find(o => o.value === opt.parent);\n        if (parentOpt) {// Insert parent option before the first child\n          options.splice(i, 0, parentOpt);\n          if (parentOpt.class.indexOf(\"suboptionvisible\") === -1)\n            parentOpt.class += \" suboptionvisible\";\n        }\n      }\n    });\n\n    return options;\n  };\n}\n\nclass ConfigFormHandler extends LocalFormBase<{\n  eventtype: string;\n  event: string;\n}> {\n  isAdminVisible = false;\n\n  constructor(formnode: HTMLFormElement) {\n    super(formnode);\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\n    admin = this;\n    (this.getElementByName(\"eventtype\") as HTMLSelectElement).addEventListener(\"change\", () => this.updateEvents());\n    pwalib.onReady(() => void this.continuePWASetup(), { reportusage: true });\n\n    this.setupPageForAdminForm();\n    this.setAdminPageVisible(!getSelectedEvent());\n    this.checkUploadQueue();\n\n    //preset the form\n    this.updateEventTypes();\n    const curevent = getSelectedEvent();\n    if (curevent?.fairtype) {\n      this.data.eventtype = curevent.fairtype;\n    }\n    this.updateEvents();\n    if (curevent) {\n      sleep(50).then(() => this.data.event = curevent.wrdGuid);\n    }\n\n    setInterval(() => this.checkUploadQueue(), 30000);\n  }\n\n  checkUploadQueue() {\n    const queue = getUploadQueue();\n    console.log(\"SIR form upload queue check, entries:\", queue.length);\n    for (const entry of queue) {\n      void this.uploadEntry(entry);\n    }\n  }\n\n  async uploadEntry(entry: FormSubmission): Promise<void> {\n    const result = await submitForm(entry);\n    if (result.success) {\n      const queue = getUploadQueue().filter(e => (e.extrasubmit as ExtraSubmitData).id !== (entry.extrasubmit as ExtraSubmitData).id);\n      setLocal<FormSubmission[]>(\"utwente_voorlichting:sirform.uploadqueue\", queue);\n      increaseNumUploaded((entry.extrasubmit as ExtraSubmitData).event);\n      this.refreshStats();\n    }\n  }\n\n  async continuePWASetup() {\n    void this.checkAppUpdate();\n  }\n\n  setAdminPageVisible(adminVisible: boolean) {\n    qR(\"form[data-wh-form-id=config]\").style.display = adminVisible ? \"\" : \"none\";\n    qR(\"form[data-wh-form-id=signup]\").style.display = adminVisible ? \"none\" : \"\";\n    if (adminVisible)\n      qR(\"h1.contentpart__title\").textContent = 'Admin';\n    this.isAdminVisible = adminVisible;\n    qR(\"#sirform-status\").hidden = !adminVisible;\n    this.refreshStats();\n\n    const lock = getSirConfig().fairTypes.length ? null : flagUIBusy({ modal: true });\n    void this.checkForEventUpdateas().finally(() => {\n      lock?.release();\n    });\n    void this.checkAppUpdate();\n  }\n\n  refreshStats() {\n    qR(\"#sirform-lastupdate\").textContent = getSirConfig().now;\n    qR(\"#sirform-registrationsinqueue\").textContent = String(getUploadQueue().length);\n    qR(\"#sirform-registrationsuploaded\").textContent = String(getNumUploaded());\n  }\n\n  setupPageForAdminForm() {\n    for (const toremove of qSA(\".contentpart__topmenuitem--search\"))\n      toremove.remove();\n\n    const loginitem = create(\"div\", {\n      className: \"contentpart__topmenuitem\",\n      textContent: \"Admin\",\n      on: { click: (evt: Event) => this.openConfig(evt) }\n    });\n\n    qR(\".contentpart__topmenu\").appendChild(loginitem);\n  }\n\n  openConfig(evt: Event) {\n    evt.preventDefault();\n    if (this.isAdminVisible)\n      return;\n\n    const dialog = dialogapi.createDialog({ allowcancel: true }) as UTDialog;\n\n    const form = create('form', { className: 'wh-styledinput sirform__loginform' });\n    form.addEventListener(\"submit\", ev => this.onAdminLogin(ev, form, dialog));\n\n    form.append(\n      create(\"label\", { for: \"adminpassword\", textContent: \"Enter admin password to open configuration\", className: \"wh-form__label\" }),\n      create(\"input\", { type: \"password\", name: \"password\", id: \"adminpassword\" }),\n      create(\"button\", {\n        type: \"submit\", id: \"adminloginbutton\",\n        textContent: \"Login\",\n        className: \"wh-form__button\",\n      })\n    );\n\n    dialog.contentnode!.append(form);\n\n    void dialog.runModal();\n  }\n\n  onAdminLogin(evt: Event, form: HTMLFormElement, dialog: UTDialog) {\n    evt.preventDefault();\n    if (form.password.value === \"aap\")\n      this.setAdminPageVisible(true);\n    dialog.closeDialog();\n  }\n\n  updateEventTypes() {\n    updateOptions(this.getElementByName(\"eventtype\") as HTMLSelectElement, getSirConfig()\n      .fairTypes.toSorted(compareProperties([\"wrdTitle\", \"wrdGuid\"])).\n      map(ft => create(\"option\", { value: ft.wrdGuid, textContent: ft.wrdTitle })));\n  }\n\n  checkForEventUpdateas = wrapSerialized(async () => {\n    setLocal<SirFormConfig>(\"utwente_voorlichting:sirform.config\", await rpc(\"utwente_voorlichting:fairs\").getFairs());\n\n    this.updateEventTypes();\n    this.updateEvents();\n  }, { coalesce: true });\n\n  checkAppUpdate = wrapSerialized(async () => {\n    const updateres = await pwalib.checkForUpdate() as {\n      needsupdate: boolean;\n      forcerefresh: boolean;\n    }; //'as' required, not typed in WH5.8\n    console.log(\"checkAppUpdate result:\", updateres);\n\n    if (updateres.needsupdate) {\n      await pwalib.downloadUpdate();\n      if (!this.isAdminVisible)\n        return; //don't bother users if we've already exited the admin oage\n\n      await dialogapi.runMessageBox(getTid(\"utwente_voorlichting:frontend.sirform.update_downloaded\"), [{ title: \"Restart\" }]);\n      await pwalib.updateApplication();\n    }\n  });\n\n  updateEvents() {\n    const events = getSirConfig().fairs.filter(\n      fair => !this.data.eventtype || fair.fairtype === this.data.eventtype\n    );\n    const eventSelect = this.getElementByName(\"event\") as HTMLSelectElement;\n    updateOptions(eventSelect, events.\n      toSorted(compareProperties([[\"date\", \"desc\"], \"wrdTitle\", \"wrdGuid\"])).\n      map(ft => create(\"option\", { value: ft.wrdGuid, textContent: ft.title })));\n\n    eventSelect.utSlimSelect ||= new SlimSelect({\n      select: eventSelect,\n      settings: {\n        placeholderText: getTid(\"utwente_voorlichting:frontend.sirform.selectvalue\"),\n        closeOnSelect: true,\n        keepSearch: true\n      }\n    });\n    setupTrigramSearch(eventSelect);\n  }\n\n  async submit(): Promise<{ result?: FormSubmitEmbeddedResult }> {\n    //TODO reconfig parent form based one vent\n    const selectedEvent = getSirConfig().fairs.find(fair => fair.wrdGuid === this.data.event) || null;\n    if (selectedEvent) {\n      setLocal<string>(\"utwente_voorlichting:sirform.selectedeventguid\", selectedEvent.wrdGuid);\n      this.setAdminPageVisible(false);\n      dispatchCustomEvent(window, \"utwente:ut-sirform-selectevent\", { bubbles: true, cancelable: true });\n    }\n\n    return { result: {} };\n  }\n}\n\nfunction getTrackTitle(track: SirFormConfig[\"programs\"][number][\"tracks\"][number]): string {\n  return document.documentElement.lang.startsWith(\"nl\") ? track.nameNl : (document.documentElement.lang.startsWith(\"de\") ? track.nameDe : track.nameEn) || track.nameEn || track.nameNl;\n}\n\nfunction getProgramTitle(prog: SirFormConfig[\"programs\"][number]): string {\n  const basename = document.documentElement.lang.startsWith(\"nl\") ? prog.nameNl : (document.documentElement.lang.startsWith(\"de\") ? prog.nameDe : prog.nameEn) || prog.nameEn || prog.nameNl;\n  if (prog.isBachelor)\n    return `${basename} (BSc)`;\n  if (prog.isMaster)\n    return `${basename} (MSc)`;\n  return basename;\n}\n\nclass SignupFormHandler extends RPCFormBase<SirFormSignup> {\n  constructor(formnode: HTMLFormElement) {\n    super(formnode);\n\n    const config_fairsinfo = getFrontendData(\"utwente_voorlichting:sirform\", { allowMissing: true })?.fairsinfo;\n    if (config_fairsinfo) { //user app!\n      fairsinfo = parseTyped(config_fairsinfo);\n    }\n\n    addEventListener(\"utwente:ut-sirform-selectevent\", (evt: Event) => this.onEventSelected());\n    if (getSelectedEvent())\n      this.onEventSelected();\n\n    const thankyoupage = qR(this.node, \"[data-wh-form-pagerole=thankyou]\");\n    const btnwrapper = create(\"div\", { className: \"sirform__centerbtnwrapper\" });\n    thankyoupage.append(btnwrapper);\n    btnwrapper.append(\n      create(\"button\", {\n        type: \"button\",\n        className: \"wh-form__button\",\n        textContent: getTid(\"utwente_voorlichting:frontend.sirform.resetbutton\"),\n        on: {\n          click: () => {\n            this.reset();\n            qSA<HTMLSelectElement>(this.node, \"select\").forEach(_ => dispatchDomEvent(_, \"change\"));\n          }\n        }\n      })\n    );\n\n    for (const phoneInput of qSA<HTMLInputElement>(this.node, \".webform-utwente--phonefield__input\")) {\n      phoneInput.inputMode = \"tel\";\n      phoneInput.addEventListener(\"input\", evt => {\n        const fixedValue = phoneInput.value.replaceAll(/[^0-9+]/g, '');\n        if (fixedValue !== phoneInput.value)\n          phoneInput.value = fixedValue;\n      });\n    }\n  }\n\n  async getFieldValue(field: HTMLElement) { //FIXME formsapi should support select multiple\n    if (field instanceof HTMLSelectElement && field.multiple) {\n      return Array.from(field.selectedOptions).map(opt => opt.value).join(\",\");\n    }\n    return super.getFieldValue(field);\n  }\n\n  //Read selectedEvent and apply to form\n  onEventSelected() {\n    qR(\"h1.contentpart__title\").textContent = getSelectedEvent()?.title || '';\n\n    //Update schools\n    const schools = getSirConfig().schools.filter(school => getSelectedEvent()?.schools.includes(school.wrdId)).toSorted(compareProperties([\"wrdTitle\"]));\n    updateOptions(qR<HTMLSelectElement>(this.node, \"select[name=school]\"), [\n      create(\"option\", { textContent: \"\", value: \"\" }),\n      ...schools.map(school => create(\"option\", { textContent: school.wrdTitle, value: school.wrdGuid }))\n    ]);\n\n    this.node.dataset.whFormVarSelectschool = schools.length > 1 ? \"1\" : \"\";\n    this.node.dataset.whFormVarSelectprogram = getSelectedEvent()?.allownoprogram ? \"\" : \"1\";\n    this.node.dataset.whFormVarShortform = getSelectedEvent()?.shortform ? \"1\" : \"\";\n    void this.refreshConditions(); //TODO can't the form autorespond to data attribute change\n\n    //Update program selector\n    const programOptions = getSirConfig().programs.filter(prog => getSelectedEvent()?.programmes.includes(prog.wrdId));\n    const interestedInSel = qR<HTMLSelectElement>(this.node, \"select[name=interestedin]\");\n\n    const programOptionElements: HTMLOptionElement[] = [];\n    const progopts: Array<{\n      title: string;\n      value: string;\n      isBachelor: boolean;\n      isMaster: boolean;\n      tracks: Array<{ title: string; value: string; style: string; parent: string }>;\n    }> = [];\n\n    // First we build a structured list of programs and tracks, sorted by title. This makes it easier to generate the option elements with correct indentation and sorting.\n    programOptions.forEach(prog => {\n      const tracks: Array<{ title: string; value: string; style: string; parent: string }> = [];\n      if (prog.tracks.length) {\n        tracks.push(...prog.tracks.flatMap(track =>\n          [{ title: getTrackTitle(track), value: track.wrdGuid, parent: prog.wrdGuid, style: \"margin-left:15px;font-size:95%;\" }]\n        ));\n        tracks.sort(compareProperties([\"title\"]));\n      }\n      progopts.push({ title: getProgramTitle(prog), isBachelor: prog.isBachelor, isMaster: prog.isMaster, value: prog.wrdGuid, tracks });\n    });\n    progopts.sort(compareProperties([\"title\"]));\n\n    progopts.forEach((prog) => {\n      programOptionElements.push(create(\"option\", { textContent: prog.title, className: \"mainoption\" + (prog.tracks.length ? \" mainoption--hassuboption suboptionvisible\" : \"\"), value: prog.value, dataset: { parent: \"\" } }));\n      if (prog.tracks.length) {\n        programOptionElements.push(...prog.tracks.flatMap(track =>\n          [create(\"option\", { textContent: track.title, value: track.value, className: \"suboption\", dataset: { parent: track.parent }, style: track.style })]\n        ));\n      }\n    });\n\n    if (programOptions.some(_ => _.isBachelor))\n      programOptionElements.unshift(create(\"option\", { textContent: getTid(\"utwente_voorlichting:frontend.sirform.genericinterest_bsc\"), value: \"BACHELOR\" }));\n    if (programOptions.some(_ => _.isMaster))\n      programOptionElements.unshift(create(\"option\", { textContent: getTid(\"utwente_voorlichting:frontend.sirform.genericinterest_msc\"), value: \"MASTER\" }));\n\n    interestedInSel.replaceChildren(...programOptionElements);\n\n    qSA<HTMLSelectElement>(this.node, \".wh-form__fieldgroup--slimselect select\").forEach(selnode => {\n      selnode.utSlimSelect ||= new SlimSelect({\n        select: selnode,\n        events: { afterChange: () => this.onSelectChange(selnode) },\n        settings: {\n          placeholderText: selnode.name === \"interestedin\" ? getTid(\"utwente_voorlichting:frontend.sirform.selectinterest\") : getTid(\"utwente_voorlichting:frontend.sirform.selectvalue\"),\n          closeOnSelect: selnode.multiple ? false : true,\n          hideSelected: selnode.multiple, //hides already selected options from the dropdown in multiple select\n          allowDeselect: true,\n          keepSearch: true\n        }\n      });\n      setupTrigramSearch(selnode);\n    });\n\n    this.reset();\n  }\n\n  onSelectChange(node: HTMLSelectElement) {\n    if (node.name === \"interestedin\") {\n      qSA(\".ss-content[data-id='\" + node.dataset.id + \"'] .mainoption--hassuboption.ss-selected\").forEach(mainopt => {\n        let hasSubOptions = false;\n        let subopt = mainopt.nextElementSibling;\n        while (subopt && subopt.classList.contains(\"suboption\")) {\n          if (!subopt.classList.contains(\"ss-selected\"))\n            hasSubOptions = true; // Available suboption found, keep main option visible\n          subopt = subopt.nextElementSibling;\n        }\n\n        mainopt.classList.toggle(\"suboptionvisible\", hasSubOptions); // if selected mainoption has available suboptions keep is visible\n      });\n    }\n  }\n\n  async getFormExtraSubmitData(): Promise<ExtraSubmitData> {\n    return {\n      id: generateRandomId(),\n      language: getTidLanguage(),\n      date: (new Date).toISOString(),\n      event: getSelectedEvent()?.wrdGuid || '',\n      referralinfo: admin ? getHardcodedURLReferralInfo(\"https://www.utwente.nl/sir/adminapp\") : getReferralInfo(),\n    };\n  }\n\n  async submitForm(entry: FormSubmission): Promise<FormSubmitResult> {\n    if (!admin)\n      return super.submitForm(entry);\n\n    const queue = getUploadQueue();\n    setLocal<FormSubmission[]>(\"utwente_voorlichting:sirform.uploadqueue\", [...queue, entry]);\n    admin.refreshStats();\n    void admin.uploadEntry(entry);\n    return {\n      success: true,\n      result: {},\n      errors: [],\n      warnings: [],\n      messages: []\n    };\n  }\n\n  reset() {\n    super.reset();\n    if (!getSelectedEvent()?.noNationalityPrefill) {\n      (this.getElementByName(\"nationality.select\") as HTMLSelectElement).utSlimSelect?.setSelected(getSelectedEvent()?.address?.country || '');\n    } else {\n      //TODO or should slimselect process the reset?\n      (this.getElementByName(\"nationality.select\") as HTMLSelectElement).utSlimSelect?.setSelected(\"\");\n    }\n\n    // Prefill phone country if possible\n    const phoneCountryEl = qS(\"select.webform-utwente--phonefield__country[data-prefilled-country]\") as HTMLSelectElement;\n    if (phoneCountryEl && phoneCountryEl.utSlimSelect)\n      phoneCountryEl.utSlimSelect.setSelected(phoneCountryEl.dataset.prefilledCountry || '');\n\n    void this.gotoPage(0); //WH5.8 forgot this\n  }\n}\n\nregisterHandler(\"utwente_voorlichting:sirform.config\", form => new ConfigFormHandler(form));\nregisterHandler(\"utwente_voorlichting:sirform.signup\", form => {\n  //Unfortunately formsapi doesnt support <select multiple so we'll let it render an input and replace it just before we start regsitering the form\n  const interestedIn = form.elements.namedItem(\"interestedin\") as HTMLInputElement;\n  const interestedInSel = create(\"select\", { multiple: true, ...pick(interestedIn, [\"id\", \"name\"]) });\n  interestedIn.replaceWith(interestedInSel);\n\n  const school = form.elements.namedItem(\"school\") as HTMLInputElement;\n  const schoolSel = create(\"select\", { ...pick(school, [\"id\", \"name\"]) });\n  school.replaceWith(schoolSel);\n\n  return new SignupFormHandler(form);\n});\n","/* eslint-disable no-alert */ //TODO avoid the alert()s though. require dompack dialogs?\n\nimport * as pxl from \"@mod-consilio/js/pxl\";\nimport * as dompack from 'dompack';\nimport * as whintegration from '@mod-system/js/wh/integration';\nimport './internal/debugmenu';\nimport * as settings from './internal/settings';\nimport { getAssetPackBase } from \"@mod-platform/js/concepts/frontend\";\nimport { navigateTo } from \"@webhare/env\";\nimport type { PWACheckVersionResponse } from \"@mod-platform/webfeatures/pwaserviceworker/pwaserviceworker\";\n\nconst appbase = location.href.indexOf(\"?\") > -1 ? location.href.split('?')[0] : location.href.split('#')[0];\nlet didinit = false;\n\n//set up a promise we'll use to signal succesful offline mode\nconst offlinedeferred = Promise.withResolvers<void>();\nlet swregistration: ServiceWorkerRegistration | undefined;\n\nfunction getAppName() {\n  //we'll assume the webdesignname is the appname\n  //TODO clean this up. designroot is undocumented, appname should be in PWASSettings\n  const settings2 = (whintegration.config as unknown as { designroot: string }).designroot.match(/^\\/.publisher\\/sd\\/([^/]*)\\/([^/]*)\\/$/)!;\n  const module = settings2[1];\n  const webdesign = settings2[2];\n  return module + ':' + webdesign;\n}\n\nfunction sendSWRequestTo(sw: ServiceWorker, type: string, data?: object) {\n  return new Promise((resolve, reject) => {\n    const msg_chan = new MessageChannel();\n    msg_chan.port1.onmessage = event => {\n      if (event.data && event.data.__throw)\n        reject(new Error(event.data.__throw));\n      else\n        resolve(event.data);\n    };\n    // console.log(navigator.serviceWorker);\n    // console.log(navigator.serviceWorker.controller);\n    // navigator.serviceWorker.controller.postMessage({ swrequest: type, data }, [msg_chan.port2]);\n    sw.postMessage({ swrequest: type, data }, [msg_chan.port2]);\n  });\n}\n\n//TODO type the SWRequest protocol properly\nasync function sendSWRequest(type: string, data?: object) {\n  //wait for SW to be available. (waiting for ready isn't safe, it may pick up an already installed SW but doesn't mean that onReady is done\n  await offlinedeferred.promise;\n  if (!swregistration?.active)\n    throw new Error(\"ServiceWorker registration failed\");\n  return sendSWRequestTo(swregistration.active, type, data);\n}\n\nexport async function checkForUpdate(): Promise<PWACheckVersionResponse> {\n  return await sendSWRequest(\"checkversion\", {\n    pwauid: document.documentElement.dataset.whPwaUid,\n    pwafileid: document.documentElement.dataset.whPwaFileid\n  }) as PWACheckVersionResponse;\n}\nexport async function downloadUpdate() {\n  return await sendSWRequest(\"downloadupdate\");\n}\n//install downloaded update now\nexport async function updateApplication() {\n  console.log(\"Reloading to update application\");\n  navigateTo({ type: \"reload\" });\n  return new Promise((resolve, reject) => setTimeout(() => reject(new Error(\"The update failed\")), 20000)); //timeout 20 sec...\n}\n\n\nexport function onReady(initfunction: () => void, options?: {\n  reportusage?: boolean;\n  onAvailableOffline?: () => void;\n  onOfflineFailed?: (e: Error) => void;\n}): void {\n  if (didinit)\n    throw new Error(\"pwalib.onReady should be invoked only once\");\n\n  didinit = true;\n\n  //figure out the base of the app we have to work with\n  if (!location.href.startsWith(whintegration.config.siteroot)) {\n    alert(\"You cannot access a PWA app using a URL outside its site.\\n\\nThe WebHare 'preview' is not supported by a PWA\");\n    return;\n  }\n  if (!appbase.endsWith('/')) {\n    //we might redirect deeper.. but this shouldn't happen anyway\n    alert(\"The application base URL must end with a /\");\n    return;\n  }\n\n  if (options?.reportusage) {\n    //determinate app name. we should probably get Versioninfo and webhare/other version numbers too\n    pxl.sendPxlEvent(\"publisher:pwastart\", { ds_appname: settings.getAppName() });\n  }\n\n  //wait for dompack to be ready...\n  dompack.onDomReady(async function () {\n    //we can now run initialization which can do some basic UI setup\n    initfunction();\n\n    //bind it to user given clalbacks\n    if (options?.onAvailableOffline)\n      offlinedeferred.promise = offlinedeferred.promise.then(() => options.onAvailableOffline!());\n    if (options?.onOfflineFailed) //we need to chain our catch to the new promise above or we risk a \"unhandled rejection\" - https://stackoverflow.com/questions/52409326/unhandled-promise-rejection-despite-catching-the-promise\n      offlinedeferred.promise = offlinedeferred.promise.catch(e => options.onOfflineFailed!(e));\n\n    //and we can start registration\n    if (!(\"serviceWorker\" in navigator)) {\n      offlinedeferred.reject(new Error(\"This browser does not support serviceWorker\"));\n      return;\n    }\n    if (window.isSecureContext === false) {\n      offlinedeferred.reject(new Error(\"This webpage is not running in a secure context (https or localhost)\"));\n      return;\n    }\n\n    const swurl = `${getAssetPackBase(\"platform:pwaserviceworker\")}ap.mjs?app=${encodeURIComponent(settings.getAppName())}`;\n\n    try {\n      swregistration = await navigator.serviceWorker.register(swurl, { scope: appbase });\n\n      if (swregistration.installing) { //detect an installing worker going straight to redundant\n        swregistration.installing.addEventListener(\"statechange\", () => {\n          if (swregistration?.installing?.state === \"redundant\")\n            offlinedeferred.reject(new Error(\"The serviceWorker failed to install\"));\n        });\n      }\n\n      offlinedeferred.resolve(navigator.serviceWorker.ready.then(() => void undefined));\n    } catch (e) {\n      console.log(\"PWA Registration failed\", (e as Error).message);\n      offlinedeferred.reject(e);\n    }\n  });\n}\n\n//inform any serviceworkers that a pwalib app has connected. gives them a chance to watch for forced version checks\nasync function precheckExistingWorkers() {\n  if (!navigator.serviceWorker)\n    return;\n\n  const registrations = await (navigator.serviceWorker.getRegistrations());\n  for (const sw of registrations)\n    if (sw.active && sw.scope === appbase)\n      await sendSWRequestTo(sw.active, 'loading', {\n        pwasettings: whintegration.config.obj.pwasettings,\n        pwauid: document.documentElement.dataset.whPwaUid,\n        pwafileid: document.documentElement.dataset.whPwaFileid\n      });\n}\n\nfunction onServiceWorkerMessage(event: MessageEvent) {\n  if (event.data.type === 'forceRefresh') {\n    console.log(\"Reloading because forced by the serice worker\");\n    navigateTo({ type: \"reload\" });\n    return;\n  }\n  if (event.data.type === \"log\") {\n    //@ts-ignore TODO ugly, cleanup up\n    console[event.data.loglevel](\"[From ServiceWorker] \" + event.data.message);\n    return;\n  }\n  console.error(\"onServiceWorkerMessage\", event.data);\n}\n\nif (whintegration.config.obj.pwasettings) { //only activate if pwasettings are present - avoid sideeffects\n  settings.setAppName(getAppName());\n\n  navigator.serviceWorker.addEventListener(\"message\", onServiceWorkerMessage);\n  void precheckExistingWorkers();\n}\n","import * as dompack from 'dompack';\nimport \"./debugmenu.scss\";\nimport * as settings from './settings';\nimport * as maintenance from './maintenance';\n\nlet debuglayer: HTMLDivElement | undefined;\n\nasync function clearCache() {\n  await maintenance.clearCache(settings.getAppName());\n}\nasync function restartApp() {\n  location.reload();\n}\nasync function unregisterServiceWorkers() {\n  await maintenance.unregisterServiceWorkers();\n}\n\nexport function runPWADebugMenu() {\n  if (debuglayer)\n    debuglayer.remove();\n\n  debuglayer =\n    <div id=\"pwadebugmenu\">\n      <h1>PWA Debugger</h1>\n      <div>\n        <button type=\"button\" onClick={clearCache}>Clear cache</button><br />\n        <button type=\"button\" onClick={unregisterServiceWorkers}>unregisterServiceWorkers</button><br />\n        <button type=\"button\" onClick={restartApp}>Restart application</button><br />\n      </div>\n    </div>;\n\n  document.body.appendChild(debuglayer!);\n}\n\n\nlet activatetouches: number[] = [];\nlet expectnumtouches = Infinity;\nlet expecttaptime = Infinity;\n\nfunction testMenuTap(event: Event) {\n  activatetouches.push(Date.now());\n  activatetouches = activatetouches.slice(-expectnumtouches);\n\n  const totaltime = (activatetouches.at(-1)! - activatetouches[0]);\n  if (totaltime) { // fast enough\n    if (activatetouches.length > 1)\n      dompack.stop(event);\n\n    if (activatetouches.length === expectnumtouches)\n      runPWADebugMenu();\n  }\n}\n\ndompack.register(\"[data-app-activatedebugmenu]\", node => {\n  const settings2 = node.dataset.appActivatedebugmenu?.split(':');\n  if (!settings2)\n    return;\n\n  expectnumtouches = parseInt(settings2[0]);\n  expecttaptime = parseInt(settings2[1]);\n  if (!expecttaptime || !expectnumtouches)\n    return;\n\n  node.addEventListener(\"touchstart\", testMenuTap);\n  node.addEventListener(\"click\", testMenuTap);\n});\n","let appname: string;\n\nexport function setAppName(newappname: string) {\n  appname = newappname;\n}\n\nexport function getAppName() {\n  return appname;\n}\n","const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n    return (idbProxyableTypes ||\n        (idbProxyableTypes = [\n            IDBDatabase,\n            IDBObjectStore,\n            IDBIndex,\n            IDBCursor,\n            IDBTransaction,\n        ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n    return (cursorAdvanceMethods ||\n        (cursorAdvanceMethods = [\n            IDBCursor.prototype.advance,\n            IDBCursor.prototype.continue,\n            IDBCursor.prototype.continuePrimaryKey,\n        ]));\n}\nconst transactionDoneMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n    const promise = new Promise((resolve, reject) => {\n        const unlisten = () => {\n            request.removeEventListener('success', success);\n            request.removeEventListener('error', error);\n        };\n        const success = () => {\n            resolve(wrap(request.result));\n            unlisten();\n        };\n        const error = () => {\n            reject(request.error);\n            unlisten();\n        };\n        request.addEventListener('success', success);\n        request.addEventListener('error', error);\n    });\n    // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This\n    // is because we create many promises from a single IDBRequest.\n    reverseTransformCache.set(promise, request);\n    return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n    // Early bail if we've already created a done promise for this transaction.\n    if (transactionDoneMap.has(tx))\n        return;\n    const done = new Promise((resolve, reject) => {\n        const unlisten = () => {\n            tx.removeEventListener('complete', complete);\n            tx.removeEventListener('error', error);\n            tx.removeEventListener('abort', error);\n        };\n        const complete = () => {\n            resolve();\n            unlisten();\n        };\n        const error = () => {\n            reject(tx.error || new DOMException('AbortError', 'AbortError'));\n            unlisten();\n        };\n        tx.addEventListener('complete', complete);\n        tx.addEventListener('error', error);\n        tx.addEventListener('abort', error);\n    });\n    // Cache it for later retrieval.\n    transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n    get(target, prop, receiver) {\n        if (target instanceof IDBTransaction) {\n            // Special handling for transaction.done.\n            if (prop === 'done')\n                return transactionDoneMap.get(target);\n            // Make tx.store return the only store in the transaction, or undefined if there are many.\n            if (prop === 'store') {\n                return receiver.objectStoreNames[1]\n                    ? undefined\n                    : receiver.objectStore(receiver.objectStoreNames[0]);\n            }\n        }\n        // Else transform whatever we get back.\n        return wrap(target[prop]);\n    },\n    set(target, prop, value) {\n        target[prop] = value;\n        return true;\n    },\n    has(target, prop) {\n        if (target instanceof IDBTransaction &&\n            (prop === 'done' || prop === 'store')) {\n            return true;\n        }\n        return prop in target;\n    },\n};\nfunction replaceTraps(callback) {\n    idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n    // Due to expected object equality (which is enforced by the caching in `wrap`), we\n    // only create one new func per func.\n    // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n    // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n    // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n    // with real promises, so each advance methods returns a new promise for the cursor object, or\n    // undefined if the end of the cursor has been reached.\n    if (getCursorAdvanceMethods().includes(func)) {\n        return function (...args) {\n            // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n            // the original object.\n            func.apply(unwrap(this), args);\n            return wrap(this.request);\n        };\n    }\n    return function (...args) {\n        // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n        // the original object.\n        return wrap(func.apply(unwrap(this), args));\n    };\n}\nfunction transformCachableValue(value) {\n    if (typeof value === 'function')\n        return wrapFunction(value);\n    // This doesn't return, it just creates a 'done' promise for the transaction,\n    // which is later returned for transaction.done (see idbObjectHandler).\n    if (value instanceof IDBTransaction)\n        cacheDonePromiseForTransaction(value);\n    if (instanceOfAny(value, getIdbProxyableTypes()))\n        return new Proxy(value, idbProxyTraps);\n    // Return the same value back if we're not going to transform it.\n    return value;\n}\nfunction wrap(value) {\n    // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n    // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n    if (value instanceof IDBRequest)\n        return promisifyRequest(value);\n    // If we've already transformed this value before, reuse the transformed value.\n    // This is faster, but it also provides object equality.\n    if (transformCache.has(value))\n        return transformCache.get(value);\n    const newValue = transformCachableValue(value);\n    // Not all types are transformed.\n    // These may be primitive types, so they can't be WeakMap keys.\n    if (newValue !== value) {\n        transformCache.set(value, newValue);\n        reverseTransformCache.set(newValue, value);\n    }\n    return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n    const request = indexedDB.open(name, version);\n    const openPromise = wrap(request);\n    if (upgrade) {\n        request.addEventListener('upgradeneeded', (event) => {\n            upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n        });\n    }\n    if (blocked) {\n        request.addEventListener('blocked', (event) => blocked(\n        // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n        event.oldVersion, event.newVersion, event));\n    }\n    openPromise\n        .then((db) => {\n        if (terminated)\n            db.addEventListener('close', () => terminated());\n        if (blocking) {\n            db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n        }\n    })\n        .catch(() => { });\n    return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n    const request = indexedDB.deleteDatabase(name);\n    if (blocked) {\n        request.addEventListener('blocked', (event) => blocked(\n        // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n        event.oldVersion, event));\n    }\n    return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n    if (!(target instanceof IDBDatabase &&\n        !(prop in target) &&\n        typeof prop === 'string')) {\n        return;\n    }\n    if (cachedMethods.get(prop))\n        return cachedMethods.get(prop);\n    const targetFuncName = prop.replace(/FromIndex$/, '');\n    const useIndex = prop !== targetFuncName;\n    const isWrite = writeMethods.includes(targetFuncName);\n    if (\n    // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n    !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n        !(isWrite || readMethods.includes(targetFuncName))) {\n        return;\n    }\n    const method = async function (storeName, ...args) {\n        // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n        const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n        let target = tx.store;\n        if (useIndex)\n            target = target.index(args.shift());\n        // Must reject if op rejects.\n        // If it's a write operation, must reject if tx.done rejects.\n        // Must reject with op rejection first.\n        // Must resolve with op value.\n        // Must handle both promises (no unhandled rejections)\n        return (await Promise.all([\n            target[targetFuncName](...args),\n            isWrite && tx.done,\n        ]))[0];\n    };\n    cachedMethods.set(prop, method);\n    return method;\n}\nreplaceTraps((oldTraps) => ({\n    ...oldTraps,\n    get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n    has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nconst advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];\nconst methodMap = {};\nconst advanceResults = new WeakMap();\nconst ittrProxiedCursorToOriginalProxy = new WeakMap();\nconst cursorIteratorTraps = {\n    get(target, prop) {\n        if (!advanceMethodProps.includes(prop))\n            return target[prop];\n        let cachedFunc = methodMap[prop];\n        if (!cachedFunc) {\n            cachedFunc = methodMap[prop] = function (...args) {\n                advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));\n            };\n        }\n        return cachedFunc;\n    },\n};\nasync function* iterate(...args) {\n    // tslint:disable-next-line:no-this-assignment\n    let cursor = this;\n    if (!(cursor instanceof IDBCursor)) {\n        cursor = await cursor.openCursor(...args);\n    }\n    if (!cursor)\n        return;\n    cursor = cursor;\n    const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);\n    ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);\n    // Map this double-proxy back to the original, so other cursor methods work.\n    reverseTransformCache.set(proxiedCursor, unwrap(cursor));\n    while (cursor) {\n        yield proxiedCursor;\n        // If one of the advancing methods was not called, call continue().\n        cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());\n        advanceResults.delete(proxiedCursor);\n    }\n}\nfunction isIteratorProp(target, prop) {\n    return ((prop === Symbol.asyncIterator &&\n        instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor])) ||\n        (prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore])));\n}\nreplaceTraps((oldTraps) => ({\n    ...oldTraps,\n    get(target, prop, receiver) {\n        if (isIteratorProp(target, prop))\n            return iterate;\n        return oldTraps.get(target, prop, receiver);\n    },\n    has(target, prop) {\n        return isIteratorProp(target, prop) || oldTraps.has(target, prop);\n    },\n}));\n\nexport { deleteDB, openDB, unwrap, wrap };\n","import * as idb from 'idb';\n\nexport async function deleteDatabase(appname: string) {\n  try {\n    await idb.deleteDB('pwadb-' + appname);\n  } catch (e) {\n    console.log(\"Deletedb failed\", e);\n  }\n}\n\nexport async function clearCache(appname: string) {\n  try {\n    const cache = await window.caches.open(\"pwacache-\" + appname);\n    for (const key of await cache.keys())\n      await cache.delete(key);\n  } catch (e) {\n    console.error(\"Cache cleanup failed\", e);\n    throw e;\n  }\n}\n\nexport async function unregisterServiceWorkers() {\n  const currentregistrations = await navigator.serviceWorker.getRegistrations();\n  for (const reg of currentregistrations)\n    await reg.unregister();\n}\n","// Auto-generated language file from /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/webfeatures/sirform/sirform.lang.json\nvar registerTexts = require(\"@webhare/gettid/src/internal\").registerTexts;\nregisterTexts(\"utwente_voorlichting\",\"en\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"nl\",{\"frontend\":{\"sirform\":{\"askquestion\":\"Vraag stellen\",\"event\":\"Evenement\",\"eventtype\":\"Evenementstype\",\"genericinterest_bsc\":\"BSc opleidingen in het algemeen\",\"genericinterest_msc\":\"MSc opleidingen in het algemeen\",\"interestedin\":\"Ik ben geïnteresseerd in\",\"question\":\"Vragen?\",\"question-placeholder\":\"Laat hier een vraag achter en we reageren via email\",\"resetbutton\":\"Volgende gebruiker\",\"school\":\"School\",\"selectinterest\":\"Selecteer interesse\",\"selectvalue\":\"Kies waarde\",\"thankyou_message\":\"Het formulier is verzonden. Dank je voor je interesse in de University of Twente.\",\"thankyou_optin_message\":\"We houden je op de hoogte! Bedankt voor je interesse in Universiteit Twente.\",\"update_downloaded\":\"Er is een update gedownload van SIR, ververs de pagina (F5 / cmd+r) om de nieuwe versie te gebruiken.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"de\",{\"frontend\":{\"sirform\":{\"askquestion\":\"Frage stellen\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"interestedin\":\"Ich interessiere mich für\",\"question\":\"Fragen?\",\"resetbutton\":\"Nächster Benutzer\",\"school\":\"Schule\",\"selectinterest\":\"Interessen auswählen\",\"thankyou_message\":\"Das Formular wurde erfolgreich versendet\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"selectvalue\":\"Select value\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"ar\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"bg\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"el\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"es\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"id\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"pt\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"ro\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\nregisterTexts(\"utwente_voorlichting\",\"zh\",{\"frontend\":{\"sirform\":{\"askquestion\":\"I want to ask a question\",\"event\":\"Event\",\"eventtype\":\"Event type\",\"genericinterest_bsc\":\"BSc programmes in general\",\"genericinterest_msc\":\"MSc programmes in general\",\"interestedin\":\"My interests\",\"question\":\"Questions?\",\"question-placeholder\":\"Leave your question here and we will reply via email\",\"resetbutton\":\"Next user\",\"school\":\"School\",\"selectinterest\":\"Select interest\",\"selectvalue\":\"Select value\",\"thankyou_message\":\"The registration has been submitted successfully. Thank you for your interest in the University of Twente\",\"thankyou_optin_message\":\"We will keep you informed! Thank you for your interest in the University of Twente.\",\"update_downloaded\":\"An update has been downloaded for SIR. Please restart (F5 / cmd+r) to use the new version.\"}}});\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/nl.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/de.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/es.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n// Adding dependency: /opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/language/default.xml\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\n\n// dompack.register(\".widget--blockswidget\", initBlocksWidget);\n\n// we MUST remove unused blocks from the DOM so the nth-child counting works correct\n// (we need nth child because CSS doesn't have a nth-col/nth-last-col yet)\nlet blocksorder;\nlet bigline;\n\n\nfunction initBlocksPage(switchform) {\n  switchform.addEventListener(\"change\", evt => onSwitchCategory(switchform));\n\n  //  console.log(\"initBlocksWidget\", node);\n\n  const blocks = document.querySelectorAll(\".blockswidget__item\");\n  blocksorder = Array.from(blocks);\n  bigline = document.querySelector(\".blockswidget__bigline\");\n\n}\n\nfunction onSwitchCategory(switchform) {\n  const category = switchform.category.value;\n\n  console.info(\"Switch to category\", category);\n\n  const container = document.querySelector(\".blockswidget__content\");\n  let results = 0;\n\n  if (bigline.parentNode)\n    container.removeChild(bigline);\n\n  const no_filter = category == \"\" || category == \"all\";\n\n  for (const node of blocksorder) {\n    let match = true;\n    if (!no_filter) {\n      const relatedto = node.dataset.relevantto.split(\" \");\n      // node.classList.toggle(\"blockswidget__item--hidden\", relatedto.indexOf(category) == -1);\n      match = relatedto.indexOf(category) > -1;\n    }\n\n\n    if (match) {\n      container.appendChild(node);\n\n      if (results == 0)\n        container.appendChild(bigline);\n\n      results++;\n\n    } else if (node.parentNode) // still in the DOM ?\n    {\n      container.removeChild(node);\n    }\n  }\n}\n\ndompack.register(\".blockswidget__form\", initBlocksPage);\n","import \"./activities.scss\";\nimport \"./my-activities.scss\";\nimport \"./blockspage\";\nimport \"./blockspage.scss\";\n\nimport * as dompack from \"@webhare/dompack\";\n\nimport \"./activitieslist\";\n\n\n// Upon selecting an event we must update\nfunction initActivitiesList(node: HTMLElement) {\n  const form = dompack.qR(node, \"form\");\n  form.addEventListener(\"change\", evt => onChangeEventOption(evt));\n}\n\n\nfunction onChangeEventOption(evt: Event) {\n  const form = (evt.target as HTMLElement).closest<HTMLFormElement>(\"form\")!;\n  const option = (form.elements.namedItem(\"option\") as RadioNodeList)?.value;\n\n  const optionnode = dompack.qR<HTMLInputElement>(form, `input[value=\"${option}\"]`);\n  const signuplink = optionnode.dataset.signuplink!;\n\n  const signupbutton = dompack.qR(form, \".activityitem__signupbutton\");\n  signupbutton.setAttribute(\"href\", signuplink);\n\n  const optionspecificnodes = (evt.target as HTMLElement).closest(\".activityitem\")!.querySelectorAll<HTMLElement>(\"[data-foroption]\");\n  for (const node of optionspecificnodes) {\n    node.classList.toggle(\"activityitem__ischosenoption\", node.dataset.foroption === option);\n  }\n}\n\ndompack.register(\".activityitem--withdayselect\", initActivitiesList);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport \"./activitieslist.scss\";\nimport \"./activitieslist-filter.scss\";\nimport * as deeplinks from \"@mod-utwente_base/webdesigns/ws2016/src/shared/deeplinks\";\nimport * as dialogapi from \"dompack/api/dialog\";\nimport PerfectScrollbar from \"@mod-utwente_design/vendor/perfect-scrollbar-wh\";\nimport * as dompack from \"@webhare/dompack\";\nimport setupToggle from \"../components/toggle\";\nimport { getTidLanguage } from \"@webhare/gettid\";\n\n\nconst defaultshowamount = 5;\nlet showall = false;\nlet items_scroller = null; // PerfectScroll instance\n\n\ndompack.register(\".widget--activitieslist\", initFilters);\ndompack.register(\".blockswidget__item__preregistration\", node => node.addEventListener(\"click\", evt => runPreregistrationWidget(node, evt)));\n\nfunction runPreregistrationWidget(node, event) {\n  dompack.stop(event);\n\n  // TODO this might become a more generic widget popup at some point?\n  const dialogcode = node.querySelector('template');\n  if (!dialogcode)\n    throw new Error(\"<template> with dialog not found\");\n\n  const dialog = dialogapi.createDialog({ allowcancel: true });\n  dialog.contentnode.appendChild(dialogcode.content.cloneNode(true));\n  dompack.registerMissed(dialog.contentnode);\n  dialog.runModal();\n}\n\nfunction initFilters(node) {\n  const tabstrip = node.querySelector(\".whflattabs\");\n  const form = tabstrip.classList.tagName === \"FORM\" ? tabstrip : tabstrip.closest(\"form\");\n  const toggle = node.querySelector(\".whflattabs__filtertoggle\");\n  const panel = node.querySelector(\".whflattabs__filterpanel\");\n  const closebutton = panel.querySelector(\".whflattabs__filterpanel__closebutton\");\n\n  const itemscontainer = node.querySelector(\".activities__filterpanel__items\");\n\n  itemscontainer.classList.add(\"ps-container--customstyling\");\n\n  items_scroller = new PerfectScrollbar(itemscontainer, {\n    swipePropagation: false,\n    wheelPropagation: false,\n    // , suppressScrollX : true\n    wheelSpeed: 2,\n    minScrollbarLength: 20\n  });\n\n  window.addEventListener(\"resize\", ev => {\n    items_scroller.update();\n  });\n\n  window.addEventListener(\"load\", ev => {\n    items_scroller.update(node);\n  });\n\n  // Preselection through URL\n  const program = new URLSearchParams(location.search).get(\"program\");\n  const category = new URLSearchParams(location.search).get(\"category\");\n  if (program) {\n    // Lookup the programme to see under which tab it lives\n    const item = node.querySelector(`.activityitem[data-programid=\"${CSS.escape(program)}\"]`);\n    if (item)\n      form.category.value = item.dataset.relevantto;\n\n    const checkboxnodes = node.querySelectorAll('.activities__filterpanel__items [type=\"checkbox\"]');\n    for (const cnode of checkboxnodes)\n      cnode.checked = cnode.dataset.urlparam === program;\n  } else if (category) {\n    form.category.value = category;\n  }\n\n  const settings = {\n    togglebutton: toggle,\n    closebutton: closebutton,\n\n    // , togglecontainer: tabstrip // element to use class on (instead of <html>)\n    htmlclass: \"whflattabs__filterpanel--open\"\n\n    //, panel:           panel\n    // , visibleonfocus:  true\n    //, title:          \"Header quicklinks\"\n  };\n\n  setupToggle(settings);\n\n  const showmorebutton = node.querySelector(\".activitieslist__showmore\");\n  showmorebutton.addEventListener(\"click\", doShowAll);\n\n\n  document.querySelector(\".whflattabs__filterpanel__showresults\").addEventListener(\"click\", doShowResults);\n\n  doFilter({ target: closebutton }); // FIXME: cleaner api to trigger a filter / update of results count\n  form.addEventListener(\"input\", doFilter);\n\n  // Preselection through URL\n  if (program) {\n    const visibleitems = node.querySelectorAll(\".activityitem:not(.activityitem--hidden)\");\n    if (visibleitems.length > 0)\n      deeplinks.doJumpIntoDeeplink(visibleitems[0]);\n  }\n}\n\nfunction doShowAll(evt: { target: HTMLElement }) {\n  document.querySelector(\".widget--activitieslist\").classList.add(\"widget--activitieslist-showall\");\n  showall = true;\n  doFilter(evt); // FIXME: cleaner api to trigger a filter / update of results count\n}\n\n// called when the button in mobile version of the filters panel is clicked\nfunction doShowResults() {\n  document.documentElement.classList.remove(\"whflattabs__filterpanel--open\");\n}\n\n\nfunction doFilter(evt: { target: HTMLElement }) {\n  const widgetnode = evt.target.closest(\".widget--activitieslist\")!;\n  const form = widgetnode.querySelector(\"form\");\n  const query = form.query.value;\n  const category = form.category.value;\n\n  const items = form.querySelectorAll(\".activities__filterpanel__item\");\n\n  const matching = []; // matches due to tabs and query\n  const selecteditems = []; // matching AND checked\n  const selecteditemstitle = [];\n  for (const itemnode of items) {\n    const match = (query === \"\" || itemnode.dataset.title.toLowerCase().indexOf(query) > -1)\n      &&\n      (category === \"\" || itemnode.dataset.relevantto.split(\",\").indexOf(category) > -1);\n\n    itemnode.classList.toggle(\"hidden\", !match);\n\n    const checkbox = itemnode.querySelector(\"input\");\n    checkbox.toggleAttribute(\"disabled\", !match);\n\n    if (match)\n      matching.push(checkbox.value);\n\n    if (match && checkbox.checked) {\n      selecteditems.push(checkbox.value);\n\n      const lookup = `[for=\"${checkbox.id}\"]`;\n      const labelnodes = document.querySelectorAll(lookup);\n\n      // Get the title from the associated label\n      for (const node of labelnodes) {\n        const itext = node.textContent;\n        if (itext) {\n          selecteditemstitle.push(itext);\n          break;\n        }\n      }\n\n    }\n  }\n\n  let visibleprogrammes = 0;\n  let visibleevents = []; // total amount of events within the visible programmes\n\n  for (const item of evt.target.closest(\".widget--activitieslist\").querySelectorAll(\".activityitem\")) {\n    const match = (selecteditems.length > 0 ? selecteditems.indexOf(item.dataset.studyfilterid) > - 1 : true)\n      &&\n      (category === \"\" || item.dataset.relevantto.split(\",\").indexOf(category) > -1);\n\n    item.classList.toggle(\"activityitem--hidden\", !match || (!showall && visibleprogrammes >= defaultshowamount));\n\n    if (match) {\n      visibleprogrammes++;\n      visibleevents = visibleevents.concat(item.dataset.eventids.split(\",\"));\n    }\n  }\n\n\n  const filterpanel = form.querySelector(\".whflattabs__filterpanel\");\n  filterpanel.classList.toggle(\"activities__filterpanel--noresults\", matching.length === 0);\n  widgetnode.classList.toggle(\"widget--activitieslist--noresults\", visibleprogrammes === 0);\n\n  const manually_checked_items = selecteditems.length > 0;\n\n  const unique_visible_events = new Set(visibleevents).size;\n\n\n  let resultstext = \"\";\n  if (manually_checked_items) {\n    const titles = [];\n    for (const title of selecteditemstitle)\n      titles.push(`“${title}”`);\n\n    if (visibleprogrammes === 1)\n      resultstext = getTidLanguage() === \"nl\" ? `<b>${unique_visible_events} resultaat</b> voor ` + titles.join(\", \")\n        : `<b>${unique_visible_events} result</b> for ` + titles.join(\", \");\n    else\n      resultstext = getTidLanguage() === \"nl\" ? `<b>${unique_visible_events} resultaten</b> voor ` + titles.join(\", \")\n        : `<b>${unique_visible_events} results</b> for ` + titles.join(\", \");\n  } else if (category === \"\") {\n    if (visibleprogrammes === 1)\n      resultstext = getTidLanguage() === \"nl\" ? `<b>${unique_visible_events} resultaat</b>`\n        : `<b>${unique_visible_events} result</b>`;\n    else\n      resultstext = getTidLanguage() === \"nl\" ? `<b>${unique_visible_events} resultaten</b>`\n        : `<b>${unique_visible_events} results</b>`;\n  } else if (category !== \"\") {\n    if (visibleprogrammes === 1)\n      resultstext = getTidLanguage() === \"nl\" ? `<b>${unique_visible_events} resultaat</b> voor “${category}”`\n        : `<b>${unique_visible_events} result</b> for “${category}”`;\n    else\n      resultstext = getTidLanguage() === \"nl\" ? `<b>${unique_visible_events} resultaten</b> voor “${category}”`\n        : `<b>${unique_visible_events} results</b> for “${category}”`;\n  }\n\n\n  widgetnode.querySelector(\".activitieslist__resultscount\").innerHTML = resultstext;\n\n  const showmorebutton = widgetnode.querySelector<HTMLElement>(\".activitieslist__showmore\");\n  if (showmorebutton) {\n    showmorebutton.style.display = (!showall && visibleprogrammes > defaultshowamount) ? \"block\" : \"none\";\n    dompack.qR(showmorebutton, \".activitieslist__showmore__category\").textContent = category;\n  }\n\n\n  let showbuttontext = \"\";\n  if (visibleprogrammes === 0)\n    showbuttontext = getTidLanguage() === \"nl\" ? \"Geen resultaten\" : \"No results\";\n  else if (visibleprogrammes === 1)\n    showbuttontext = getTidLanguage() === \"nl\" ? \"Toon 1 resultaat\" : \"Show 1 result\";\n  else if (visibleprogrammes > 1)\n    showbuttontext = getTidLanguage() === \"nl\" ? `Toon ${visibleprogrammes} resultaten` : `Show ${visibleprogrammes} results`;\n\n  filterpanel.querySelector(\".whflattabs__filterpanel__showresults\").innerHTML = showbuttontext;\n\n  items_scroller.update();\n}\n\ndompack.register(\".js-activityitem\",\n  node => node.addEventListener(\"click\", () => {\n    //studychoice calendar events - https://gitlab.webhare.com/utwente/utwente_base/-/issues/2689\n    const form = dompack.qR<HTMLFormElement>(\"form.js-activityoverview__targetgroup\");\n    const type = node.dataset.tagmanagerType || '';\n    const relevantto = (form.elements.namedItem(\"category\") as RadioNodeList)?.value || '';\n    const position = dompack.qSA(\".js-activityitem\").indexOf(node) + 1;\n    window.dataLayer.push({ event: \"scc-click\", type, relevantto, position });\n  })\n);\n","// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nexport default function setupToggle(options) {\n  options = {\n    togglebutton: null,\n    openbutton: null,\n    closebutton: null,\n\n    togglecontainer: null, // element which should receive the toggle class (defaults to document.documentElement aka <html>)\n    htmlclass: \"\",\n\n    panel: null,\n    visibleonfocus: false, // if true the panel closes when focus isn't within the panel anymore\n    visibleonhover: false, // if true, hovering over the togglebutton or panel keeps the panel open\n\n    title: \"\",\n\n    debug: false,\n\n    ...options\n  };\n\n  if (options.debug)\n    console.log(options);\n\n  if (options.togglebutton) {\n    for (const node of makeArray(options.togglebutton))\n      node.addEventListener(\"click\", evt => doToggle(evt, options));\n  }\n\n  if (options.openbutton) {\n    for (const node of makeArray(options.openbutton))\n      node.addEventListener(\"click\", evt => doOpen(evt, options));\n  }\n\n  if (options.closebutton) {\n    for (const node of makeArray(options.closebutton))\n      node.addEventListener(\"click\", evt => doClose(evt, options));\n  }\n\n  if (options.visibleonfocus)\n    options.panel.addEventListener(\"focusout\", evt => onFocusOut(evt, options));\n\n  if (options.visibleonhover) {\n    for (const node of makeArray(options.togglebutton)) {\n      node.addEventListener(\"mouseenter\", evt => onMouseEnter(evt, options));\n      node.addEventListener(\"mouseleave\", evt => onMouseLeave(evt, options));\n    }\n\n    if (options.panel) /* apparently doesn't always exist ? the setupToggle marked with 'Toggle for themes overview menu' doesnt supply this panel */ {\n      options.panel.addEventListener(\"mouseenter\", evt => onMouseEnter(evt, options));\n      options.panel.addEventListener(\"mouseleave\", evt => onMouseLeave(evt, options));\n    }\n  }\n}\n\nfunction makeArray(input) {\n  if (input instanceof NodeList || input instanceof HTMLCollection) {\n    return Array.from(input);\n  } else if (input instanceof HTMLElement)\n    return [input];\n  else {\n    console.error(\"makeArray cannot handle input:\", input);\n    return [];\n  }\n}\n\nfunction onMouseEnter(evt, options) {\n  doOpen(evt, options);\n}\n\nfunction onMouseLeave(evt, options) {\n  doClose(evt, options);\n}\n\n\nfunction onFocusOut(evt, options) {\n  if (evt.relatedTarget && options.panel.contains(evt.relatedTarget))\n    return;\n\n  doClose(evt, options);\n}\n\nfunction doToggle(evt, options) {\n  const open = !document.documentElement.classList.contains(options.htmlclass);\n\n  if (open)\n    doOpen(evt, options);\n  else\n    doClose(evt, options);\n}\n\n\nfunction doOpen(evt, options) {\n  const node = options.togglecontainer ?? document.documentElement;\n  if (options.htmlclass !== \"\")\n    node.classList.add(options.htmlclass);\n\n  if (options.panel)\n    options.panel.focus();\n}\n\nfunction doClose(evt, options) {\n  const node = options.togglecontainer ?? document.documentElement;\n  if (options.htmlclass !== \"\")\n    node.classList.remove(options.htmlclass);\n}\n","/* eslint-disable */\n// @ts-nocheck -- Bulk rename done by wh devkit:es2ts\n\nimport * as dompack from \"dompack\";\nimport './ctalinks.scss';\nimport * as storage from 'dompack/extra/storage';\n\nfunction setupCTALinksExperiments(node) {\n  const meta = node.previousElementSibling;\n  if (!meta?.matches('meta[name=\"ut-insertactivitiesoverviewwidget-experiment\"'))\n    return; //not running an experiment\n\n  //Lock the experiment for this session\n  const keyname = `ut-ctalinks-${document.documentElement.dataset.id}-experimentgroup`;\n  let abgroup = storage.getLocal(keyname)?.abgroup ?? \"unset\"; //properly differentiate between real 0 and unset\n  if (abgroup === \"unset\") {\n    abgroup = Math.floor(Math.random() * 4); //0-3\n    storage.setLocal(keyname, { abgroup });\n  }\n\n  node.classList.add(\"widget-ctalinks--variant\" + abgroup);\n  document.documentElement.dataset.experimentId = meta.getAttribute(\"content\");\n  document.documentElement.dataset.experimentVariant = abgroup;\n  window.dataLayer.push({\n    experimentId: document.documentElement.dataset.experimentId,\n    experimentVariant: document.documentElement.dataset.experimentVariant\n  });\n\n  dompack.qSA(node, \".widget--ctalinks__item\").forEach(node => node.addEventListener(\"click\", () => {\n    window.dataLayer.push({ event: \"scc_cta_button_click\" });\n  }));\n}\n\ndompack.register(\".widget-ctalinks\", setupCTALinksExperiments);\n\nwindow.__resetCTALinkExperiment = function () {\n  const keyname = `ut-ctalinks-${document.documentElement.dataset.id}-experimentgroup`;\n  storage.setLocal(keyname, null);\n  location.reload();\n};\n","// Our extensions for utwente_base module\nimport * as crm from '@mod-utwente_base/webdesigns/ws2016/src/shared/crm';\nimport '@mod-utwente_voorlichting/js/shared/orgselect';\nimport '@mod-utwente_voorlichting/js/shared/institutes';\nimport '@mod-utwente_voorlichting/webfeatures/cashpoint';\nimport '@mod-utwente_voorlichting/webfeatures/echeck';\nimport '@mod-utwente_voorlichting/webfeatures/opendagen';\nimport '@mod-utwente_voorlichting/webfeatures/opendays_v2';\nimport '@mod-utwente_voorlichting/webfeatures/leadswidgets';\nimport '@mod-utwente_voorlichting/webfeatures/scopemastercontact';\nimport '@mod-utwente_voorlichting/webfeatures/tasterdays';\nimport '@mod-utwente_voorlichting/webfeatures/sirform/sirform';\n\nimport './activities/activities';\nimport \"./tabstrip/tabstrip.scss\";\n\nimport './widgets/applyforprogrammecta/applyforprogrammecta.scss';\n// import './widgets/blockswidget/blockswidget.scss';\nimport './widgets/ctalinks/ctalinks';\n\nvoid crm.requestGeoIP(); //let country check do its thing/RPC first\n","import \"@webhare/frontend/src/init\";import \"/opt/wh/whtree/modules/publisher/js/internal/polyfills/all\";\nimport \"/opt/whdata/installedmodules/utwente_base.20260422T061009.701Z/webdesigns/ws2016/src/site\";\nimport \"/opt/whdata/installedmodules/datacloud.20260310T133612.085Z/webfeatures/datacloud-loader\";\nimport \"/opt/whdata/installedmodules/utwente_courses.20260325T112653.960Z/js/internal/ws2016_courses_hook\";\nimport \"/opt/whdata/installedmodules/utwente_education.20260408T102753.286Z/webfeatures/utwente_base_hooks\";\nimport \"/opt/whdata/installedmodules/utwente_jobs.20251007T194009.901Z/webfeatures/vacanciespage/index\";\nimport \"/opt/whdata/installedmodules/utwente_ppp.20260403T141929.044Z/webdesigns/shared/ws2016_ppp\";\nimport \"/opt/whdata/installedmodules/utwente_voorlichting.20260421T103433.118Z/webfeatures/ws2016_voorlichting/ws2016_voorlichting\";const aps = globalThis.whAssetPacks ||= {}; aps[\"utwente_base:ws2016\"]=\"2026-04-22T08:47:19.341Z\";"],"mappings":"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","names":["require_events","__commonJSMin","exports","module","R","ReflectApply","target","receiver","args","ReflectOwnKeys","ProcessEmitWarning","warning","NumberIsNaN","value","EventEmitter","once","defaultMaxListeners","checkListener","listener","arg","n","_getMaxListeners","that","type","doError","events","er","err","handler","len","listeners","arrayClone","_addListener","prepend","m","existing","w","onceWrapper","_onceWrap","state","wrapped","list","position","i","originalListener","spliceOne","keys","key","_listeners","unwrap","evlistener","unwrapListeners","emitter","listenerCount","arr","copy","index","ret","name","resolve","reject","errorListener","resolver","eventTargetAgnosticAddListener","addErrorHandlerIfEventEmitter","flags","wrapListener","require_requester","__commonJSMin","exports","module","init_dompack","EventEmitter","InternetRequester","options","debugflags","method","url","body","async","key","event","datestr","parseddate","evt","require_jsonrpc","__commonJSMin","exports","module","init_env","InternetRequester","rpcscriptid","JSONRPC","_JSONRPC","options","method","params","deferred","req","errorcode","errormsg","rpcid","promise","result","rejection","onsuccess","onfailure","id","url","timeout","waittimeout","synchronous","errortrace","request","Request","isLive","i","el","event","status","json","trace","line","rec","waiting","nextTimeout","now","waitLength","toGo","parent","require_iscroll_modified","__commonJSMin","exports","module","window","document","Math","rAF","callback","utils","me","_elementStyle","_vendor","vendors","transform","i","l","_prefixStyle","style","target","obj","el","type","fn","capture","pointerEvent","current","start","time","lowerMargin","wrapperSize","deceleration","distance","speed","destination","duration","_transform","appVersion","safariVersion","e","c","re","newclass","left","top","exceptions","k","b","f","eventName","ev","IScroll","options","button","point","pos","deltaX","deltaY","timestamp","newX","newY","absDistX","absDistY","momentumX","momentumY","distanceX","distanceY","easing","snap","that","x","y","touchAction","rf","index","transitionType","offsetX","offsetY","durationProp","self","remove","eventType","matrix","interactive","customStyle","indicators","indicator","createDefaultScrollbar","Indicator","_indicatorsMap","wheelDeltaX","wheelDeltaY","m","n","cx","cy","stepX","stepY","page","posX","posY","keys","now","prevTime","acceleration","destX","destY","easingFn","startX","startY","startTime","destTime","step","direction","scrollbar","scroller","r","val","hold","delay","import_iscroll","tempid","SpellcoderCarrousel","init_src","__esmMin","init_dompack","node","options","domoptions","getJSONAttribute","nodes","initialx","iscrollsettings","IScroll","idx","classname","timestamp","force","dpr","currentpos","scrollleft","newx","animate","offsetx","forward","xfloor","xceil","virtualidx","renderinfo","item","iteminfo","posx","largestheight","fixedslidewidth","width","height","positionwidth","i","j","tmp","msg","width_content","newheight","evt","dispatchCustomEvent","carrouselcell","closest","viewport_rect","clickpos","contentareawidth","middlex","items","pages","left","wanted_left_within_content","idx_neg","pageX","pageY","repeatedcontent","itemidx","val","x","y","iScroll","activation_x","draw","override_scrollleft","absolute_scrollleft","visible_left","visible_right","new_items_onscreen","items_visible","itemcount","draw_itemidx","offsetleft","newactiveslideidx","newactivenode","newactiveslidevirtualidx","newactiveslide_dist","virtualslideidx","outofview","left_in_viewport","use_node","centerwithinheight","offsety","transform","imagecontainer","leftdist","dist","asset","require_fullscreen_slideshow","__commonJSMin","exports","module","init_dompack","init_src","__active_photoviewer","__active_fsslideshow_container","__old_scrolly","__initialized","refreshFullScreenSlideshow","viewer","resizeImagesToFitInViewport","options","getDefaultSlideshowOptions","resizeActivePhotoviewer","doActivateSlideshowByHash","hash","imageid","cell","slideshow","all_items","itemidx","___doActivateSlideshow","doActivateSlideshow","instanceid","containerid","slideshowcontainer","use_carrousel","carrouselcontainer","onActiveSlideChange","doCloseFullscreenSlideshow","carr","SpellcoderCarrousel","detectButtonTaps","slidenodes","node","fsscontainer","headeranim","evt","buttonnode","titlenode","downloadbutton","carrousel","slidenode","urlhash","viewport_width","viewport_height","rect","maximagewidth","maximageheight","dpr","images","idx","image","orig_w","orig_h","max_w_stretch","max_h_stretch","stretch","img_w","img_h","register","require_domtemplate","__commonJSMin","exports","module","init_dompack","setTextWithLinefeeds","node","message","line","idx","create","cloneDeep","appendto","clone","getContent","frag","iterateNode","data","list","copies","item","copy","expandNode","repeatNode","isrepeat","decodeSets","instr","retval","key","subval","expandTemplateContent","clonednode","__originalbasenode","debugflags","next","instructions","getJSONAttribute","toset","deepkey","field","subnode","nextnode","importTemplate","doc","templatenode","content","instantiateTemplate","fragment","expandTemplate","options","el","toinform","range","beforemarker","dispatchCustomEvent","require_ev_emitter","__commonJSMin","exports","module","global","factory","EvEmitter","proto","eventName","listener","events","listeners","onceEvents","onceListeners","index","args","i","isOnce","require_get_size","__commonJSMin","exports","module","window","factory","getStyleSize","value","num","isValid","noop","logError","message","measurements","measurementsLength","getZeroSize","size","i","measurement","getStyle","elem","style","isSetup","isBoxSizeOuter","setup","div","body","getSize","isBorderBox","paddingWidth","paddingHeight","marginWidth","marginHeight","borderWidth","borderHeight","isBorderBoxSizeOuter","styleWidth","styleHeight","require_matches_selector","__commonJSMin","exports","module","window","factory","matchesMethod","ElemProto","prefixes","i","prefix","method","elem","selector","require_utils","__commonJSMin","exports","module","window","factory","matchesSelector","utils","a","b","prop","num","div","arraySlice","obj","isArrayLike","ary","index","elem","selector","event","method","elems","ffElems","childElems","i","_class","methodName","threshold","timeoutName","timeout","args","_this","callback","readyState","str","match","$1","$2","console","WidgetClass","namespace","dashedNamespace","dataAttr","dataAttrElems","jsDashElems","dataOptionsAttr","jQuery","attr","options","error","instance","require_item","__commonJSMin","exports","module","window","factory","EvEmitter","getSize","isEmptyObj","obj","prop","docElemStyle","transitionProperty","transformProperty","transitionEndEvent","vendorProperties","Item","element","layout","proto","event","method","style","elemStyle","supportedProp","isOriginLeft","isOriginTop","xValue","yValue","x","y","layoutSize","xPadding","xProperty","xResetProperty","yPadding","yProperty","yResetProperty","isHorizontal","curX","curY","didNotMove","transX","transY","transitionStyle","args","_transition","h","toDashedAll","str","$1","transitionProps","duration","dashedVendorProperties","propertyName","onTransitionEnd","cleanStyle","cleanTransitionStyle","delay","options","transitionEndProperty","styleProperty","optionStyle","require_outlayer","__commonJSMin","exports","module","window","factory","EvEmitter","getSize","utils","Item","console","jQuery","noop","GUID","instances","Outlayer","element","options","queryElement","id","isInitLayout","proto","opts","option","oldOption","canBindResize","elems","itemElems","items","i","elem","item","layoutInstant","isInstant","measurement","size","queue","position","obj","stagger","getMilliseconds","x","y","isResizingContainer","measure","isWidth","elemSize","eventName","_this","onComplete","count","doneCount","tick","type","event","args","emitArgs","$event","boundingRect","thisRect","offset","hasSizes","previousItems","removeItems","style","namespace","Layout","subclass","Parent","SubClass","msUnits","time","matches","num","unit","mult","require_masonry","__commonJSMin","exports","module","window","factory","Outlayer","getSize","Masonry","proto","i","firstItem","firstItemElem","columnWidth","containerWidth","cols","excess","mathMethod","isFitWidth","container","size","item","remainder","colSpan","colPosMethod","colPosition","position","setHeight","setMax","colGroup","minimumY","groupCount","col","groupColYs","isOver","hasSize","stamp","stampSize","offset","isOriginLeft","firstX","lastX","firstCol","lastCol","isOriginTop","stampMaxY","unusedCols","previousWidth","rpc_exports","__export","createService","RPCClient","getDebugAppend","urldebugvar","name","service","JSONRPCService","JSONRPCServiceProxy","globalseqnr","ControlledCall","init_rpc","__esmMin","init_dompack","client","method","stack","id","options","callurl","fetchoptions","fetchpromise","resolution","response","retryafter","resolve","exception","jsonresponse","url","debugflags","whservicematch","promise","result","error","trace","rec","line","params","args","target","prop","receiver","require_searsia","__commonJSMin","exports","module","searsia","SEARSIAVERSION","globalId","globalApiTemplate","globalMother","searsiaAjax","ajaxObject","url","success","error","dataType","options","response","tries","data","decodeError","message","clearLocalStorage","key","setLocalStorage","field","value","deleteLocalStorage","getLocalStorage","existsLocalStorage","setMother","motherObject","getMother","motherJson","setApiTemplate","template","getApiTemplate","getId","setLocalResource","resource","id","getLocalResource","rid","json","existsLocalResource","deleteLocalResource","fillUrlTemplate","query","page","resourceId","resulttype","start","end","ext","addToHits","hits","hit","i","newIndex","TOP","normalizeText","text","noHTMLattribute","noHTMLelement","scoreText","queryTerms","j","len","textTerms","score","restrictStart","someText","size","prefix","postfix","matchingSnippets","k","description","first","second","scoreAllHits","rerank","queryLen","maxscore","tscore","newHits","nrOfTopHits","printableQuery","a","b","correctUrl","absUrl","relUrl","getHost","match","urlParameters","values","params","paramString","parts","formQuery","encodedQuery","inferMissingData","rank","rhost","typeImages","typeSmall","typeFull","typeTitleOnly","count","prior","maxScore","returnResults","sessionid","olddata","callbackSearch","newscore","oldscore","liveResults","queryResources","pending","checkEmpty","getResults","xhr","err","done","generateUUID","c","r","v","searchFederated","connectToServer","callbackConnect","initClient","originalTemplate","resultType","require_searsiaconfig","__commonJSMin","exports","module","SEARSIA_SOURCES","SEARSIA_DUPLICATE_RESOURCES","QUERY_STOPWORDS","require_search_rpc","__commonJSMin","exports","module","RPCClient","request","promise","result","source","query","options","init_envbackend","getBrowserDebugFlags","varname","flags","urldebugvar","debugcookie","debugcookievalue","flag","config","siteroot","dtapStage","whconfigel","initEnv","flag","getBrowserDebugFlags","debugFlags","frontendConfig","getFrontendData","dataObject","allowMissing","retval","init_polyfills","IteratorPrototype","ArrayIteratorPrototype","OriginalIteratorPrototype","callback","it","value","next_value","real_value","max_count","values","limit","remaining","index","mapper","mapped","reducer","initial_value","acc","count","string","final","first","iterables","others","it_array","e","finished","partition1","partition2","i","max","min","isObject","t","GetIteratorFlattenable","obj","method","iterator","Iterator","WrappedIterator","#iterator","args","returnMethod","Iterator_from","init_dompack","config","forwardPublisherNavigation","event","isHTMLElement","navaction","desturl","origin","configureForCMS","e","init_dompack","init_env","lastSeen","showDataLayerUpdates","debugFlags","entry","pushToDataLayer","vars","options","savecallback","newcallback","resolve","collectFormValues","formnode","donefields","outdata","multifields","qSA","multifield","idx","values","labels","checkboxes","node","cbox","keyname","labelsfornode","labelnode","allkeyname","field","val","opt","didinit","setupGTM","setupFormAnalyticsForGTM","key","form","init_dompack","init_env","init_dompack","init_env","init_envbackend","consentstatus","cookiename","consentoptions","setup","usecookiename","consentrequester","options","debugFlags","getCookie","storeConsent","onDomReady","updateConsent","hasConsent","consentsetting","details","getConsentDetail","setConsent","newsetting","consent_revoked","tag","navigateTo","onConsent","type","callback","evt","updateConsentOverlays","overlays","qSA","consent","getConsentDetail","debugFlags","overlay","parent","updateConsent","details","dispatchCustomEvent","onDomReady","storeConsent","cookiename","setCookie","consentstatus","consentoptions","deleteCookie","navigateTo","gtmsettings","getFrontendData","didinit","processGTMPluginInstruction","node","topush","init","didinit","gtmsettings","resolve","debugFlags","src","loadScript","gtmsrc","register","processGTMPluginInstruction","gtmsettings","init","setupGTM","init_dompack","init_jsonrpc_client","requestbarrier","getIPInfoIntoCache","options","reqoptions","result","createClient","geoinfo","getIPInfo","finaloptions","barrier","curgeoinfotext","e","refetch","retval","init_storage","getLocal","setLocal","getSession","setSession","init_dompack","list","listCookies","read","getCookie","write","setCookie","remove","deleteCookie","init_dompack","init_std","init_dompack","init_jsonrpc_client","init_env","init_dompack","init_env","init_js_api_tools","init_std","isAbsolute","url","getBaseURL","backendBase","ControlledCall","client","method","stack","options","callurl","fetchoptions","fetchpromise","requestStack","response","exception","retryafter","resolve","jsonresponse","parseTyped","logitem","omit","err","prependStackTrace","RPCClient","debugFlags","error","params","stringify","parseTrace","ServiceProxy","target","prop","receiver","newoptions","rpc","args","service","servicematch","rpcclient","PublicCookieSuffix","init_std","getCookieName","getFrontendData","getAuthLocalData","c","parseTyped","getCookie","PublicCookieSuffix","isLoggedIn","getAuthLocalData","getUserInfo","isLoggedIn","getAuthLocalData","startSSOLogin","tag","options","client","createClient","navigateTo","setupWebHareSSOTrigger","getAssetPackBase","assetpack","init_dompack","loadAssetPack","apname","basepath","getAssetPackBase","loadScript","loadCSS","setupAuthorMode","options","getLocal","init_dompack","init_std","init_env","eventname_regex","datakey_regex","max_sessionid_age","globalOptions","pagesession","useAltRecordURL","seqnr","pxlUserId","pxlSessionId","buildOptions","options","pxlFailed","errormessage","params","isLive","makePxlURL","baseurl","eventname","data","options","globalOptions","eventname_regex","pagesession","generateRandomId","url","seqnr","getPxlSessionId","getPxlId","browser","getBrowser","name","value","test","datakey_regex","type","pxlUserId","timestampvar","debugFlags","sessionExpireDays","max_sessionid_age","expiration","pxlSessionId","sendPxlEvent","event","finaloptions","buildOptions","useAltRecordURL","fetchRes","error","init_env","activeListenPrefixes","sendPxl","eventKey","params","data","options","pxldata","k","v","sendPxlEvent","setupFormAnalytics","prefix","registered","dtapStage","e","formeventdata","key","val","getRemoteIPAddress","_","init_env","postRenderChecks","log","logtext","onDomReady","cookiedomain","getLangCode","lang","UtwenteCookies","deleteCookie","setLocal","utwenteCookies","link","cookielink","privacylink","jsxcreate","reject","d","accept","texts","buttons","prefs","getCookie","ischange","vars","pushToDataLayer","evt","e","newsettings","setting","expires","setCookie","newprefs","curprefs","c","setupCookieWidget","form","thirdparty","throwError","ev","setupConsentHandlerForUtwente","syncConsent","consent","setConsent","setup","register","node","onDomReady","__ignored","cookiebar_default","init_dompack","startedload","setupCobrowser","chtbtn","hasConsent","onChatTouchBlur","event","isHTMLElement","acceptnode","cookiebar_default","openCoBrowser","online","loadCobrowser","qS","create","register","onConsent","init_dompack","setupConsentHandlerForUtwente","init_dompack","usersettings","getUserSettings","getUserGuid","setUserSettings","settings","lastguid","write","dispatchCustomEvent","read","init_env","init_dompack","readSessionInfo","getCookie","writeSessionInfo","sessinfo","setCookie","getHardcodedURLReferralInfo","url","browser","getReferralInfo","sessioninfo","usersettings","getUserSettings","referralinfo","cookiebar_default","field","userbeacon","getUserBeacons","name","trackFirstReferrer","referrer","referrerurl","urlparams","varname","sessupdates","debugFlags","urlinfo","grabVar","firstreferage","setUserSettings","init_dompack","auth_exports","__export","WRDAuthenticationProvider","auth_default","getDefaultAuth","init_dompack","init_dompack","init_env","executeSubmitInstruction","instr","options","flagUIBusy","navigateTo","init_keyboard","import_jsonrpc","init_env","init_dompack","defaultauth","getBackVar","backurl","getURLOrigin","url","WRDAuthenticationProvider","options","getUserInfo","JSONRPC","jsstate","read","currentstate","debugflags","logouturl","redirectto","form","KeyboardHandler","evt","event","isHTMLElement","stop","loginfield","passwordfield","persistentfield","persistentlogin","login","password","resolve","reject","opts","response","error","loginproof","type","data","logincontrol","loginlock","flagUIBusy","result","completion","dispatchCustomEvent","navigateTo","code","msg","message","evtdetail","isLoggedIn","sp_tag","defer","getDefaultAuth","frontendConfig","register","node","elname","auth_default","getNetworkForIP","ip","init_env","getLoginLink","prompt","silent","redirect","url","gotourl","getUTUserInfo","auth_exports","register","node","event","stop","dtapStage","userinfo","getNetworkForIP","getRemoteIPAddress","init_envbackend","beacons","geoippromise","onMeeloopdagMessage","event","getGTMTracker","analyticsid","tracker","trackClientId","retry","clientid","getUserSettings","setUserSettings","setSession","setupGTMDataLayer","usersettings","base","getUserGuid","getNetworkForIP","getRemoteIPAddress","requestGeoIP","getIPInfo","geoinfo","getUserCountry","learnedAboutUser","newguid","firstname","opts","setUserSettings","getUserGuid","updateCoBrowser","addReferralInfoToForm","evt","getReferralInfo","userbeacon","beacons","name","getUserBeacons","storeBeacons","dispatchCustomEvent","e","triggerUserBeacon","tag","date","debugFlags","clearUserBeacon","tag","beacons","debugFlags","storeBeacons","pickupGlobalBeacons","list","ck","triggerUserBeacon","remove","userinfo","getUTUserInfo","usertype","cookieusertype","read","setbeacon","name","executeANLEvent","node","updateCoBrowser","usersettings","getUserSettings","visitorid","register","addReferralInfoToForm","setupFormAnalyticsForGTM","evt","pushToDataLayer","setupGTMDataLayer","onMeeloopdagMessage","requestGeoIP","getSession","trackClientId","init_env","samplerate","fetchPredictions","prediction","getFrontendData","logReferrerIfNeeded","alwaysoptin","debugFlags","usesamplerate","requestGeoIP","sendPxl","onDomReady","init_dompack","getActiveElement","doc","getToplevelWindow","toplevelwindow","asIframe","node","getCurrentlyFocusedElement","limitdoc","focused","frame","canFocusTo","ignoreInertAttribute","getFocusableComponents","startnode","options","focusable","currentnode","currentstyle","iframe","subnodes","init_keyboard","dialogstack","keyhandler","dialogconstructor","dialogoptions","onEscape","event","stop","onTab","direction","focusable","getFocusableComponents","el","getCurrentlyFocusedElement","tofocusidx","tofocus","focus","DialogBase","options","borrow","KeyboardHandler","evt","myoffset","response","setupDialogs","newdialogconstructor","createDialog","options","dialogconstructor","dialog","runMessageBox","question","choices","choicebuttons","choice","create","dialogoptions","init_dompack","init_dompack","init_gettid","init_internal","convertElementTids","scope","node","getTid","args","getTidLanguage","setTidLanguage","getHTMLTid","registerTexts","youtubedomain","videonetworks_preload","registerVideoSource","source","options","createMyFrame","inert","ifrm","initYouTube","node","video","playback","args","youtube_url","initVimeo","vimeo_url","t","minutes","seconds","insertVideoPlayer","opts","use_handler","handler","playback_url","initializeVideoElementV1","initializeVideoElementV2","videonodes","qSA","videonode","activateVideo","playbutton","getTid","evt","onConsent","iFrame","registerVideoSource","getYujaPlaybackURL","register","node","initializeVideoElementV1","initializeVideoElementV2","video","playback","args","params","host","videoid","authorizationkey","playback_url","init_dompack","init_env","animDuration","frontendConfig","animSteps","animDelay","colorschemeNode","colorschemeCTANode","colorschemeCTAHoverNode","syncTimeout","curThemeColor","curThemeColorCTA","curThemeColorCTAHover","browser","getBrowser","disableColorAnimation","initializeTheme","node","debugFlags","saveStart","getLocal","setLocal","registered","setAnimation","e","checkThemeColors","randomColor","setThemeColors","names","playState","animationStyle","name","observer","curDelay","syncThemeColors","anyChanges","themeColor","props","register","init_dompack","BasicDialog","DialogBase","classname","options","create","evt","stop","registerMissed","init_dompack","init_gettid","registerTexts","get","element","set","obj","key","let","val","div","className","const","elMatches","matches","query","remove","queryChildren","selector","child","cls","x","scrollingClassTimeout","addScrollingClass","i","classList","removeScrollingClass","setScrollingClassInstantly","EventElement","eventName","handler","target","this","name","prototypeAccessors","EventManager","ee","onceHandler","evt","createEvent","processScrollDiff","axis","diff","useScrollingClass","forceFireReachEvent","fields","ref","y","scrollTop","contentHeight","containerHeight","up","down","toInt","isEditable","el","DOM.matches","outerWidth","styles","CSS.get","env","updateGeometry","roundedScrollTop","rect","DOM.queryChildren","DOM.remove","getThumbSize","updateCss","thumbSize","xRailOffset","CSS.set","yRailOffset","clickRail","e","positionTop","direction","positionLeft","dragThumb","bindMouseScrollHandler","startingScrollTop","startingMousePageY","scrollBy","mouseMoveHandler","pageY","mouseUpHandler","scrollbarYRail","bindMoves","touchMode","railYHeight","scrollbarYHeight","scrollbarY","keyboard","elementHovered","scrollbarFocused","shouldPreventDefault","deltaX","deltaY","scrollLeft","activeElement","wheel","isTop","isBottom","isLeft","isRight","hitsBound","getDeltaFromEvent","shouldBeConsumedByChild","cursor","style","maxScrollTop","maxScrollLeft","mousewheelHandler","shouldPrevent","touch","magnitudeX","magnitudeY","applyTouchMove","differenceX","differenceY","startOffset","startTime","speed","easingLoop","getTouch","shouldHandle","touchStart","touchMove","currentOffset","currentTime","timeGap","touchEnd","defaultSettings","handlers","PerfectScrollbar","userSettings","focus","blur","originalScrollLeft","result","DOM.div","railXStyle","railYStyle","handlerName","runYesNoMessageBox","question","node","jsxcreate","n","runMessageBox","getTid","UTDialog","BasicDialog","options","closebtn","evt","stop","perfect_scrollbar_esm_default","qSA","button","registerMissed","showModalDialog","title","contents","modalnode","hideModalDialog","blurredbg","bg","bodynode","titlenode","contentnode","ev","dialognode","init_dompack","init_browser","register","node","container","jsxcreate","c","getPlatform","perfect_scrollbar_esm_default","init_dompack","onDomReady","init_dompack","init_gettid","registerTexts","formatters","updaters","mergeNode","node","set","data","parts","isNodeFunc","func","exprpath","callparts","funcrest","value","exprpathparts","i","prop","run","mergenode","filter","nodes","sets","init_dompack","init_env","init_dompack","getISOLocalDate","date","init_dompack","init_dompack","init_std","init_env","rfSymbol","init_gettid","init_std","init_dompack","fixupConditionRecursive","node","condition","mapping","anychanges","subcondition","newName","ArrayField","handler","items","name","throwError","qS","event","addDocEventListener","rownode","qSA","form","getFormHandler","newrow","addedrow","registerMissed","setup","stop","delNode","row","rowBaseName","rowFields","getFormElementCandidates","_","RecordFieldHandler","rows","n","rowval","valuePromises","rowPromises","field","values","rowValue","value","idx","rowField","firstnode","valueRows","newvalue","fieldnode","rowid","nodeArray","fieldname","getFieldName","cellname","subname","setFieldName","labelnodes","labelnode","type","conditionnode","parseCondition","minRows","maxRows","numRows","getTid","init_std","unmapFieldName","camelCaseName","nameToSnakeCase","mapFieldName","htmlName","nameToCamelCase","mapValue","type","invalue","unmapValue","fieldDescr","isDate","HTMLFormFieldHandler","form","field","selectedrow","newvalue","setvalue","RadioFormFieldHandler","name","rnodes","group","node","_","myname","CheckboxGroupHandler","cboxes","throwError","toset","missing","cbox","RegisteredFieldHandler","ArrayFieldHandler","items","rfSymbol","ArrayField","getFieldName","FormFieldMap","fieldName","nodes","subpos","groups","fullName","arraygroup","AddressFieldHandler","RecordFieldHandler","options","mapName","match","data","ignoreUnknownFields","key","value","baseName","retval","val","prettyName","omit","FieldMapDataProxy","target","p","prop","init_browser","delayvalidation","validationpendingfor","didGlobalHandlers","lineFeedsToBreaks","text","frag","part","getPageIdx","state","page","idx","getErrorFields","validationresult","field","getFieldName","value","index","self","hasEverFailed","doValidation","iffailedbefore","releasePendingValidations","debugFlags","form","doDelayValidation","tovalidate","lastfocusout","handleFocusOutEvent","event","handleFocusInEvent","handleValidateAfterEvent","FormBase","FormFieldMap","node","getFormElementCandidates","setup","addDocEventListener","evt","#recordLastFocus","pagestate","generateRandomId","#lastFocused","FieldMapDataProxy","name","#onUnload","now","eventdata","dispatchCustomEvent","control","qSA","element","target","ourcondition","parseCondition","searchparams","allvalues","shouldbechecked","tocheck","_","type","getError","fieldgroup","field_with_message","error","potentialgroupnode","contextnode","messageid","messagenode","suggestionholder","create","describedby","describedby_fields","failedfield","getValidationState","stop","extradata","submitter","submitselector","tempbutton","beforeResult","isPromise","el","queryFormFieldLike","startingpoint","lock","flagUIBusy","result","containingpage","pagenum","actionnode","pages","curpage","pagelist","currentpage","scrollto","origscrollto","__isSubmit","pageidx","goingforward","run","direction","pagenode","action","navigateTo","validationstatus","isinit","hiddenPages","mergeNodes","anychanges","formpage","visible","hiddengroups","enabledgroups","requiredgroups","formgroup","groupPage","enabled","required","formline","inputtargets","node_enabled","isFormFieldLike","node_required","isFormControl","option","option_enabled","option_hidden","selectnode","wrapSerialized","nodes","formvalue","mergeNode","conditiontext","fieldname","options","matchfield","isRadioNodeList","currentvalue","conditionfield","fields","attrname","selectedvalue","val","selected","qS","extrafields","condition","subcondition","birthdate","age","matchcase","compareagainst","currentValArray","nextpage","morepages","curpagerole","nextpagerole","richvalues","rawNavigateTo","exitButton","parsedNavTo","redirectdelay","submitButton","submitButtonLabel","registerMissed","isLive","getFieldDisplayName","rfSymbol","deferred","file","fieldnode","saveInteractive","changeValue","foundfields","skiparraymembers","addto","isRadioOrCheckbox","outdata","fieldpromises","receivedvalue","resolve","reject","e","opts","vals","checker","setupValidator","setFieldError","isFieldNativeErrored","updateFieldError","validator","limitset","defer","item","original","group","subnode","tovalidatelist","validationresults","fld","failed","tofocus","canFocusTo","getFocusableComponents","focus","init_env","init_std","init_formservice","lookupcache","verifyHareScriptAddress","address","options","lookupkey","stringify","emplace","getFormService","init_std","SubField","node","pos","throwError","AddressField","qR","prefixLength","fieldpos","field","qSA","event","fieldname","data","firstfield","key","country","ordering","e","prevgroup","idx","item","fieldgroup","setFieldError","value","visiblefields","anyset","allrequiredset","form","FormBase","curstate","result","lock","flagUIBusy","el","verifyHareScriptAddress","debugFlags","err","anychanges","newvalue","changeValue","init_gettid","init_std","formatDate","dateformat","year","month","day","isValidDate","output","c","parseDate","format","newdate","options","parts","dayoffset","monthoffset","yearoffset","daypos","monthpos","yearpos","day","month","year","isValidDate","parseISODate","newdate","options","parseDate","init_std","validateCheckboxGroup","groupnode","nodes","qSA","min","max","anyenabled","node","numChecked","getTid","validateRadioGroup","reformatDate","datestr","parsed","parseISODate","formatDate","validateDate","date","dateparts","year","month","day","isValidDate","normalizeddate","validateTime","time","timeparts","hours","minutes","seconds","setup","form","datecontrol","field","datematch","propname","thedate","getISOLocalDate","setupValidator","timecontrol","propvalue","checkboxgroup","radiogroup","addresscontrol","AddressField","init_gettid","init_dompack","JSFormElement","newname","required","disable","name","oldValue","newValue","init_std","queryFormFieldLike","isInputElement","field","isHTMLElement","isFormFieldLike","control","isFormControl","JSFormElement","isRadioOrCheckbox","isRadioNodeList","el","getFieldName","setFieldName","newname","getFieldDisplayName","downgradeUploadFields","form","uploadfield","qSA","input","attr","getErrorForValidity","validity","getTid","max","reformatDate","min","key","isFieldNativeErrored","getFieldNativeError","parseCondition","conditiontext","getFormElementCandidates","basenode","namePrefix","parentForm","candidates","getFormHandler","node","allowMissing","throwError","setupServerErrorClear","field","group","setFieldError","ComponentValidationState","el","err","getFieldNativeError","validations","getValidationState","state","newstate","error","options","isHTMLElement","debugFlags","getFieldDisplayName","updateFieldError","dispatchCustomEvent","setupValidator","node","checker","init_dompack","init_formservice","init_dompack","init_gettid","init_formservice","init_std","init_env","cache","mayValidateField","field","acceptEmailSuggestion","evt","form","suggestion","stop","validateField","setFieldError","checkvalue","isValidEmail","getTid","key","rpcCall","getFormService","getTidLanguage","sleep","result","e","debugFlags","jsxcreate","init_env","init_std","init_upload","init_jsonrpc_client","init_dompack","init_gettid","registerTexts","captcharegistry","initializeCaptcha","provider","injectInto","settings","finalsettings","getTid","init_dompack","init_gettid","init_dompack","init_upload","init_gettid","registerTexts","isAcceptableType","fileType","masks","basetype","FileEditElement","JSFormElement","csslink","#setValue","evt","error","setFieldError","getTid","value","toset","row","getFieldDisplayName","mimetype","accept","mask","files","_stack","lock","__using","flagUIBusy","file","requestFile","_","_error","_hasError","__callDispose","msg","dispatchCustomEvent","idx","stop","button","init_std","FileUploadFormElement","FileEditElement","#constructFileHolder","fileholder","nodes","idx","file","filename","isFile","filenamefield","jsxcreate","deletebutton","getTid","uploadbutton","UploadField","node","init_dompack","init_std","init_gettid","init_upload","revoker","cachedURLs","createFileURL","file","emplace","newurl","oldurl","getImageDimensions","img","loadImage","getFileAsDataURL","ImgEditElement","_ImgEditElement","FileEditElement","name","_oldValue","newValue","value","textupdate","qSA","node","error","size","setFieldError","getTid","nodes","idx","imgholder","create","deletebutton","contentwrapper","uploadicon","explain","ImgEditField","init_dompack","init_std","formConfiguration","handlers","configuredRegistrations","firstWarningMs","warningIntervalMs","scheduleFormSetup","form","factory","_stack","lock","__using","flagUIBusy","customEls","qSA","_","initPromise","nextWarning","timeoutPromise","sleep","missing","tag","downgradeUploadFields","_error","_hasError","__callDispose","configureForms","setup","dispatchCustomEvent","registerHandlers","addHandlers","defaultHandler","RPCFormBase","handlername","handler","emplace","current","register","registerHandler","getFormConfiguration","init_std","init_dompack","init_keyboard","init_dompack","init_keyboard","init_gettid","init_dompack","recaptchaload","makeRecaptchaLoadPromise","jsxcreate","runRecaptcha","provider","injectInto","settings","lock","flagUIBusy","captchanode","recaptchaid","response","setupGoogleRecaptcha","captcharegistry","init_dompack","script","endpoint","isLoaded","runFriendlyCaptcha","provider","injectInto","settings","captcha","evt","_stack","lock","__using","flagUIBusy","loadScript","_","_error","_hasError","__callDispose","setupFriendlyCaptcha","options","captcharegistry","setupForms","options","registerHandlers","configureForms","omit","init_gettid","CaptchaField","JSFormElement","evt","form","setFieldError","getTid","provider","initializeCaptcha","result","stop","setupCaptchaFieldGroup","captchaControl","create","virtualCaptchaPage","buttonarea","qS","unpackObject","formvalue","_","buildTarget","target","FormSubmitter","cache","offline","file","completed","uploader","SingleFileUploader","uploadinstructions","getTSFormService","uploadedfile","isBlob","result","key","value","buildRPCFormSubmission","target","formValue","options","vals","FormSubmitter","eventdetail","buildTarget","unpackObject","submitRPCForm","submission","createClient","RPCFormBase","FormBase","#hadFocus","#completedUploads","#settingUpCaptcha","formnode","#onFirstFocus","isLive","#getSubmitVals","formvalue","background","methodname","args","waiter","lock","flagUIBusy","rpc","getFormService","result","field","prop","value","matchpage","dataval","fieldnode","promise","messages","msg","extradata","extraSubmitAwaitable","extraSubmit","dispatchCustomEvent","config","getFormConfiguration","captchaConfig","setupCaptchaFieldGroup","parameters","insubmitrpc","submitparameters","debugFlags","didfirstfocus","globalerrors","error","failednode","serverMetadata","focus","setFieldError","run","failedfields","pick","e","errors","create","runMessageBox","navigateTo","getCurrentlyFocusedElement","validation","validateField","init_env","legacyRegisterFormHandler","handlername","handler","registerHandler","form","createdForm","isLive","FormBase","RPCFormBase","setupForms","form","FormBase","setupFormAnalytics","init_dompack","RTDEditElement","JSFormElement","_stack","specifiedopts","structure","hidebuttons","style","rtdoptions","lock","__using","flagUIBusy","richeditor","evt","dispatchCustomEvent","_","_error","_hasError","__callDispose","newvalue","url","formhandler","result","disable","nowenabled","node","RTDField","options","init_dompack","init_formservice","EmbedVideoForm","RPCFormBase","node","dialog","rtd","result","insertVideo","formloadlock","flagUIBusy","formhandler","formdata","getFormService","createDialog","qR","init_dompack","init_dompack","SelectList","options","selection","empty","create","evt","stop","selectitem","pulldowncoords","itemscoords","bottomroom","toproom","bcr","contains","debugflags","init_keyboard","watchingreset","onReset","lock","flagUIBusy","qSA","node","setupMyValueProperty","select","mySelectGetValue","mySelectSetValue","setupMySelectedIndexProperty","mySelectGetSelectedIndex","mySelectSetSelectedIndex","selectedoption","newvalue","origsetter","origgetter","retval","Pulldown","SelectList","options","old_options","evt","create","after","mutations","KeyboardHandler","event","key","registerMissed","direction","stop","selectitem","allitems","selectidx","filter","current","maxiterations","tc","debugflags","focus","anyoptionchange","mutation","dispatchCustomEvent","toggleClass","childnodes","inoptgroup","idx","opt","toselect","option","todisable","toshow","newcurrent","contains","isopen","fireModifiedEvents","init_dompack","CssClasses","classes","join","a","b","name","generateID","hasClassInTree","element","className","hasClass","e","c","parentByClass","debounce","func","wait","immediate","timeout","args","context","later","callNow","isEqual","kebabCase","str","result","match","Option","option","Optgroup","optgroup","o","Store","type","data","dataObj","validationError","dataFinal","optOptions","preserveSelected","newData","selectedOptionsBeforeUpdate","missingSelected","selectedOption","found","newItem","opt","allowEmptySelection","addToStart","selectedType","selectedValues","firstOption","hasSelected","selectedObjects","optionValue","selectedIds","value","id","options","search","searchFilter","filter","includeOptgroup","dataSearch","newOrder","isIn","Render","settings","store","callbacks","classValue","cls","dirClass","selectedOptions","selectedId","animationTiming","cssValue","listboxId","main","highlighted","values","deselect","shouldDelete","before","after","deselectSvg","deselectPath","arrow","arrowPath","eventType","placeholderOption","placeholderText","placeholder","selected","selectedSingle","singleValue","currentNodes","maxValuesMessage","removeNodes","i","node","n","d","shouldAdd","text","deleteDiv","deleteSvg","deletePath","list","input","addable","searchReturn","highlightedEnter","plus","plusPath","inputValue","runFinish","oo","newOption","ids","addableValue","notPlaceholder","notDisabled","notHidden","query","dir","prevOption","prevParent","optgroupLabel","selectOption","selectParent","firstHighlight","listId","error","errorDiv","searchingDiv","po","noResults","fragment","optgroupEl","optgroupLabelText","optgroupActions","selectAll","allSelected","selectAllText","selectAllSvg","selectAllBox","selectAllCheck","currentSelected","newSelected","s","optionIds","optgroupClosable","optgroupClosableSvg","optgroupClosableArrow","optionEl","dataClass","elementID","isCmd","shouldUpdate","isCurrentlySelected","lastIndex","currentIndex","startIndex","endIndex","newSelections","isModifierKey","searchTerm","escapedSearch","tempDiv","highlightTextNodes","regex","wrapper","part","index","mark","child","direction","isAbove","addClass","removeClass","mainHeight","contentHeight","containerRect","top","left","cw","padding","viewportRight","applyOverflowShift","contentRight","overflow","currentLeft","newLeft","container","cTop","cBottom","eTop","eBottom","mainRect","hasSelectedItems","isMultiple","allowDeselect","deselectButton","hideClass","Select","select","listen","ev","mutations","classChanged","disabledChanged","optgroupOptionChanged","selectionChanged","m","currentData","nodes","opts","optgroupOptions","style","pending","info","optionClass","key","labels","selectId","label","parent","labelClickHandler","target","isSlimSelectElement","handler","Settings","SlimSelect","config","debounceEvents","disabled","renderCallbacks","selectAriaLabel","selectAriaLabelledBy","err","dataClean","runAfterChange","searchResults","searchResp","getTrigrams","str","trigrams","i","trigram","TrigramMatcher","strs","s","ut","occ","v","retval","score","t","a","b","init_gettid","PhoneField","input","fieldgroup","wrapper","jsxcreate","countries","country","select","F","setupValidator","inp","matchcountry","c","phoneNumber","selectedCode","countryCode","countryinfo","phonePrefix","digits","getTid","chknumber","match","setValue","changeValue","requestGeoIP","register","node","init_dompack","shouldOpenInNewWindow","link","page","ourtextnode","node","checkNewWindowLink","register","init_env","lang","overlaylayer","qSA","grp","inp","onBusyModal","evt","jsxcreate","UTRPCFormBase","RPCFormBase","getReferralInfo","fixupEmailField","emailfield","register","node","overridelanguage","savelang","getTidLanguage","setTidLanguage","requiredtext","getTid","setupValidator","el","debugFlags","Pulldown","ImgEditField","UploadField","RTDField","insertVideo","init_dompack","colorschemeNode","animDelay","animFirstActivated","animDuration","frontendConfig","onAnimationStart","evt","setAnimationDelay","getExpectedAnimTime","totalDelay","timediff","setAnimation","node","name","style","getAnimationStyle","playState","debugflags","register","saveStart","bg_targets","fg_targets","fgbr_targets","bg_cta_targets","fgbr_cta_targets","buttons","setButtonAnimation","searchhighlights","jsxcreate","registerMissed","init_dompack","handleNewWindow","event","size","register","link","init_dompack","globalRequest","promiseXMLHttpRequest","url","options","resolve","reject","request","header","init_dompack","init_dompack","videoNodeInitialized","vimeoFrameLoaded","default_video_playback","generateVideoNode","video","playback","mergedoptions","playernode","args","youtube_url","__getPlayerFrame","getYouTubePlayer","getStaticVideoPlayer","vimeo_url","t","minutes","seconds","event","getVimeoPlayer","params","host","videoid","authorizationkey","playback_url","getYujaPlayer","getHtml5Player","ifrm","isVideoNodeInitialized","node","initializeVideoNode","options","opts","resolve","reject","player","StaticVideoPlayer","loop","volume","dispatchCustomEvent","YouTubeVideoPlayer","VimeoVideoPlayer","Html5VideoPlayer","YuJaVideoPlayer","playerScripts","waiter","script","deferred","createDeferred","init_dompack","SwipeDetect","node","options","event","ev","dx","dy","abs_x","abs_y","dispatchCustomEvent","SlideShow","nodes","options","node","SwipeDetect","ev","nextSlide","dot","idx","event","nextindex","moveleft","curNode","dispatchCustomEvent","startplay","cookiebar_default","isVideoNodeInitialized","initializeVideoNode","player","show","makeTextFit","container_or_elements","options","sourcetype","elements","idx","container","__makeTextFit","textcontainer","maxwidth","maxheight","node_applystyle","node_measurewidth","node_measureheight","tcontent","textbounds","textwidth","textheight","size_ok","largest_known_fitting_fontsize","smallest_known_too_large_fontsize","optimal_fontsize","bounds_h","bounds_v","steps_used","current_fontsize","fontsize_diff","scaleheadercta","checkWindowSize","scaleHeaderCTA","event","flatcta","ctanode","ctatitle","headercta","hdrheight","hdrtitle","maxheight","hdrtitleheight","makeTextFit","init_dompack","StickyCTAbar","node","e","qS","qSA","btnvisible","btn","sticky","register","template","brochurewidget","form","dialog","createDialog","formwidget","univActive","univElement","svgHeaders","colorschemeNode","syncPathColor","animDuration","frontendConfig","headeranimation_paused","activateHeader","debugflags","loadElement","containerNode","element","elements","el","prevElement","syncPathColor","resolve","tmpSvg","tmpPath","setAnimation","pathColor","svgDoc","promiseXMLHttpRequest","styleNode","pauseHeaderAnimation","svgHeaders","nodes","unPauseHeaderAnimation","onRotate","event","node","syncColor","colorschemeNode","register","univActive","initializing","univElement","svgNode","colorPathNode","SlideShow","init_dompack","SmoothScroll","nodes","options","node","href","target","event","init_dompack","ScrollListener","onDomReady","selnodes","i","treshhold","nodeinfo","scrollvisibleclass","measuremethod","parallax","free","innernode","factor","zoom","info","action","elementheight","containerheight","overflowsize","p","center","ev","scrollpos","visible","rect","node","dispatchCustomEvent","win_height","scrollListener","scrolllistener_default","init_dompack","init_dompack","init_src","whitespace","carrouselwidgets","getContentBlank","widgetnode","measure_element","computed","measureself","fullwidth","rec","doPauseHeaderAnimation","evt","doUnpauseHeaderAnimation","refreshAllCarousels","widget","fixCarrouselWidgetMinHeight","carrclass","remeasureSlides","nextbutton","firstimage","carrouselrect","minheight","doCheckForCarouselVideoTrigger","event","slidecontainer","videocontainer","isVideoNodeInitialized","initializeVideoNode","player","anchor","style","transform","mat","xpos","width","findwidget","carrwidget","viewport","doOnlyAllowSlideImageLinksOnActiveSlides","register","node","idx","carrousel","SpellcoderCarrousel","init_dompack","init_dompack","JustifiedContentGrid","container","options","strip_width","strip_height","img_idx","img_count","current_width","current_width_next","row","ypos","maxiterations","maxrows","column","img_this_strip","item","resized_width","compensatex","grow_if_no_extra_image","shrink_if_extra_image","scale_to_fill_width","scale_to_fill_height","scale_to_fill_both","result_width","result_height","add_each_item","add_last_item","xpos","col_idx","expected_height","items","frag","tel","clip_node","JustifiedImageGrid","imgcount","new_items","img","contentnode","imgwidth","imgheight","imgdesc","item_ref","evt","imgnode","fsslideshow","init_dompack","init_browser","onDomReady","ios","getPlatform","__photoalbum_grids","refreshAllPhotoAlbums","grid","defaultoptions","getDefaultGridOptions","doCheckForImageSelection","evt","item","instanceid","items","itemidx","headeranim","node","dpr","contentWidth","register","idx","gridnode","JustifiedImageGrid","init_dompack","init_dompack","init_src","__observer","checkSlideshowVisibility","onDocumentVisibilityChange","slideshow","entries","observer","visible","invisible","entry","isvisible","CarrouselSlideshow","node","options","domoptions","getJSONAttribute","carrousel_options","SpellcoderCarrousel","dragarea","evt","idx","anchor","viewportheight","slideshowbounds","count","delay","SlideshowWidget","widgetnode","btn_prev","btn_next","CarrouselSlideshow","evt","slidecontainer","slidenode","pass","event","videocontainer","isVideoNodeInitialized","initializeVideoNode","player","register","init_dompack","activestep","register","node","builder","parts","steptag","stepstate","activeoptions_str","activeoptions","allsteps","activestepidx","idx","currentstep","tag","jumpToActiveStep","init_dompack","init_dompack","autocomplete","settings","doc","container","preventSubmit","uid","containerStyle","debounceWaitMs","disableAutoSelect","customContainerParent","items","inputValue","minLen","showOnFocus","selected","fetchCounter","debounceTimer","destroyed","suppressAutocomplete","input","detach","parent","clearDebounceTimer","attach","containerDisplayed","clear","updatePosition","maxHeight","inputRect","calc","docEl","clientTop","clientLeft","scrollTop","scrollLeft","top","left","update","render","item","_","__","itemElement","renderGroup","groupName","groupDiv","fragment","prevGroup","index","div","ev","empty","updateScroll","updateIfDisplayed","resizeEventHandler","scrollEventHandler","e","inputEventHandler","fetch","elements","element","previous","selectBottom","containerBottom","selectPreviousSuggestion","updateSelectedSuggestion","selectNextSuggestion","unselectSuggestion","selectSuggestion","handleArrowAndEscapeKeys","key","containerIsDisplayed","handleEnterKey","keydownEventHandler","focusEventHandler","trigger","startFetch","inputText","cursorPos","savedFetchCounter","keyupEventHandler","clickEventHandler","blurEventHandler","manualFetch","evt","destroy","UTAutoComplete","settings","autocomplete_es_default","init_gettid","import_jsonrpc","init_std","wordRegex","lastWordRegex","SearchIndex","fields","item","key","invalue","value","match","count","term","pos","entry","props","query","results","parsedQuery","baseQuery","suggestQuery","baseResults","#searchInternal","termField","termText","score","#matchesText","suggestion","scores","result","flatscores","#calculateScores","#getSortedItems","searchResult","terms","field","fieldResults","matches","word","queryResult","#executeQuery","text","item_positions","indexEntry","avg","cur","idx","queryWord","termWord","limitDistance","startsWithScore","dist","levenshteinDistance","a","b","_","init_env","filtertags_ignorefields","filter_lastsettings","filter_lastseenkeys","getResultsFeedbackText","totalfound","totalshown","getTid","getResultsTeaserText","FilteredOverviewHeader","debugFlags","options","qR","node","evt","visible","fieldnodes","idx","frontendConfig","expandwhen","pagekey","firstvisitinsession","gettextfunc","contentnode","text","viewportheight","resultsanchor","results_out_of_view","FilteredOverview","pushToDataLayer","qS","filtertagscontainer","qSA","additionalfields","ev","optnode","filters","urlparamsdone","val","inptype","vals","url","name","anchors","anchor","url2","interactivechange","title","labelnode","dlevent","key","keepwords","nrfilters","forcerefresh","filterstr","result","words","JSONRPC","noresults","tagnode","fieldname","fieldvalue","field","tags","tag","rowkey","item","remove","feedbacknode","urlparamstr","allitemscount","ClientSideFilteredOverview","SearchIndex","itemsselector","items","searchnode","UTAutoComplete","update","suggestions","_","filtername","filterval","setvalues","i","itemdata","doesnotmatch","selectedstatus","parts","qmatches","findtext","itemvalue","searchvalue","i2","found","matchvalue","ismatch","init_dompack","DompackMasonry","node","options","domoptions","getJSONAttribute","items","widgetrecs","wnode","widgetcols","item","setitems","widgets","elem","clientwidth","cstyle","padtop","padbottom","padleft","padright","visiblewidgetscount","columnwidth","columncount","singlerow","columns","xcol","columnitems","widget","width","idx","widgetrec","widgetheight","min_ypos","col","itemcount","lastitemincol","ypos","bestcol","maxypos","widgetbottom","styles","maxheight","bookmark_offsety","TimelinePageFilter","FilteredOverview","options","items","node","totalfound","yearsinresults","item","doesnotmatch","key","itemvalue","searchvalue","i","found","matchvalue","ismatch","tlwidget","TimelineWidget","widgetnode","evt","SmoothScroll","year","itemnode","labelnode","viewportrect","topy","event","layout","parts","DompackMasonry","renderinfo","idx","visibleyears","itemrect","bookmarkcontainer","bookmarkcontainer2","bookmark","inview","videocontainer","isVideoNodeInitialized","initializeVideoNode","player","register","onDomReady","init_dompack","currenthovertarget","activatePopupPanels","body","dorelay","togglePopup","onTouchEnd","onEnterPopupTrigger","onLeavePopupTrigger","cssselector","callback_enter","callback_leave","evt","elem","$utPopupActive","_hidePopup","togglePopup","event","node","targetnode","popupid","popupnode","$utPopupActive","_hidePopup","onLeavePopupTrigger","onEnterPopupTrigger","popuptype","getPopupType","cancelPopupClose","posinfo","popupx","popupy","body_pos","anode_pos","anchor_pos","anchor_size","popup_size","marginsize","popupwidth","maxleft","nodelay","schedulePopupClose","typeindex","type","cssclass","settings","activatePopupPanels","TimeTable","container","options","evt","currenttime","time_passed","newx","maxx","scrollx","eventnode","event","rows","prows","firstminute","lastminute","row","events","timestr","parts","pevents","startparts","minutes_start","minutes_end","endparts","ev1","ev2","mergedoptions","parsedrows","timestart_startmins","stmins","timeend_minutes","etmins","timerange_in_minutes","timestep_mins","minwidth_to_fit_timeindicators","scrollviewport_width","contentwidth","rowlabelnodes","idx","rownode","rowlabelnode","rowlabels_width","required_guidelines","timetable_width","guidelines_interspace","guidelines_interperc","timemins","guideline","csstext","str_hours","str_minutes","header_guideline","eventnodes","labelnodes","slots_endx","highestslotidx","event_idx","xstart","xend","slot_idx","slotsettings","slots_needed","slotheight","classes","infonode","popoutnode","contentnode","labelnode","must_use_ellipsis_nodes","cannot_show_label_nodes","label_width","label_height","compstyle","avail_width","avail_height","scaletext","makeTextFit","use_ellipsis","use_icon","header_bcr","viewport_bcr","headerheight","header_would_be_top","page_viewport_height","fixedpos","TimeTableWidget","widget","hash","tab","timetablenodes","ttnode","timetable","TimeTable","firsttabbutton","evt","tabnode","urlhash","tabcontentid","contentnode","qS","tabnodes","tnode","contentnodes","cnode","ttevent","popupnode","showModalDialog","overflow","tabs","register","node","init_dompack","init_dompack","parseManagedCTAConfig","ctaconfig","config","_","regex","idx","r","CTAMatchError","prop","values","params","tryMatchCTAConfig","props","now","debugflags","hitanybeacon","beacon","maxtime","beacondate","matching_regex","only_excludes","cta_regex","e","init_gettid","managedCTASlot","userCountry","userBeacons","ctas","setupManagedCTA","node","getUserCountry","getUserBeacons","debugflags","ctadata","subnode","parseManagedCTAConfig","ctatags","cta","updateManagedCTA","requestGeoIP","country","scrolllistener_default","onManagedCTADisplay","onManagedCTAClick","updateAllManagedCTAs","showManagedCTAPreview","haveCTA","forced","displaycta","tryMatchCTAConfig","e","CTAMatchError","dispatchCustomEvent","params","testprops","any_shown","matcherror","explanations","getTid","beacon","positives","_","negatives","jsxcreate","text","event","eventValues","target","pushToDataLayer","register","init_dompack","getPublicationLinks","container","url","resultinghtml","response","err","setupArticlesAsPlainLinks","node","doc","item","setupArticlesAsDownloadsAndLinks","items","researchlink","jsxcreate","register","init_dompack","BannerSlideshowWidget","widgetnode","CarrouselSlideshow","slide","largestheight","slideheight","refreshBannerSlideshowWidgets","widget","register","init_dompack","offsety","LinksPerCategoryWidget","widget","evt","SmoothScroll","tab","tabs","contentpanels","tabnode","cnode","idx","contentpanelbounds","tabsbounds","bodybounds","scrolltoy","pointCurveFromTo","activetab","curve","startnode","endnode","pointerrect","startnoderect","endnoderect","topy","bottomy","pathwidth","pathheight","abspathheight","curveradiusx","curveradiusy","x0","x1","x2","x3","x4","y0","y1","y2","y3","path","refreshWidgets","register","node","init_dompack","register","node","evt","onSwitchTab","widgetnode","links","idx","ev","stop","init_dompack","initProgressCircles","node","animationsdone","percentage","contoursize","circlenode","percentagenode","ev","timestep","step","t","updateDigits","initProgressBars","initSegmentedCircle","basenode","sel_idx","subnode","selnode","timeout","labelnodes","idx","initChart","chartnr","chartdata","ispreview","rgbcolor","ColorStringToRGB","labels","nrvalues","nrgroups","chartnode","legendanode","chartsize","hintervalwidth","i","labelnode","valuesmax","valuesmin","c","hlinescount","hspacesteps","precisionfactor","hvaluestep","labelwidth","haszeroline","v","yvalue","hnode","vlabelnode","vtitlenode","svgnode","scaley","opacity","svgpath","linenode","colval","x","y","RoundValue","RGBaToColorString","hoverid","legendalabel","pointnode","valuenode","infonode","bulletnode","line","groupoffset","barnodes","left","barheight","stylstr","barnode","number","decimalplaces","multiply1","divide1","divide2","multiply2","colorstr","r","g","b","a","alpha","register","dispatchCustomEvent","initWideImage","checkWideImage","wideimages","imgcount","node","widelink","dragging","dragThreshold","openFoldableContent","className","foldcontainernode","initFoldableContent","titlenode","textnode","setHandler","event","toggleHandler","dispatchCustomEvent","toggleStudyFinderSpecializations","ev","itemnode","spnode","activateStudyfinderWidget","widgetnode","showallnode","evt","expandStudyfinderWidget","dompack_exports","register","prevnode","prevembobjectnode","onDomReady","getCSSVariable","property","options","resolve","reject","data","checkCSSVariable","value","setCSSVariable","ellipsislines","ellipsislinesInitdone","setEllipsisLines","forcerefresh","textsuffix","basenode","nodes","node","innernode","item","dimensions","nodeheight","maxheight","hasfitt","testlength","prevlength","i","fitfontlist","fitfontlistInitDone","fitFonts","h_attr","w_attr","maxwidth","wrappernode","wrapperattr","wrappersize","wrapperheight","wrapperwidth","fontsize","fontunit","fontnum","lineheight","lineunit","linenum","contents","measurenode","measurement","init_gettid","activateSmartLayout","enrichLayoutInfoFor","mainnode","maincontainers","mainchildren","container","children","elemdescr","idx","description","node","classname","footer","windowMode","scrollDuration","initialhash","openFoldableDeepLink","node","container","checkWindowMode","mode","hash","idnode","checkHiglightDeeplink","besthref","bestdeeplink","deeplinklist","qSA","deeplink","href","target","currentvisible","qS","isbefore","combineFloatParagraphs","toCombine","child","nextChild","section","jsxcreate","convertDetailSummaries","summary","details","doChangesToRichtextContent","activateSmartLayout","checkJumpIntoDeeplink","setupDeepLinks","tablenode","headings","h2","formpage","anchor","linkanchor","i","newid","deeplinksNode","getTid","activateDeeplinksMedia","getCSSVariable","breakpoint_deeplinks","event","deeplinks","SmoothScroll","scrolllistener_default","targets","ellipsisDeeplinks","doJumpIntoDeeplink","target2","checkexpand","expandlist","toexpand","openFoldableContent","txt","wrapper_h","txt_h","wrapper_w","onDomReady","init_dompack","setupShowAllLinks","node","containerClass","linkClass","target","event","style","links","windowMode","checkWindowSize","event","section","titlenode","linkscontainer","register","titleNode","target","links","logosNode","SlideShow","setupShowAllLinks","init_dompack","import_domtemplate","observer","resizeListener","entries","onResize","event","onWindowResize","nodes","entry","callback","node","rect","observeNodeResize","unobserveNodeResize","import_jsonrpc","fsslideshow","init_dompack","import_masonry_layout","init_dompack","DompackMasonry","node","options","domoptions","getJSONAttribute","force","clientwidth","cstyle","padtop","padbottom","padleft","padright","widgets","elem","visiblewidgetscount","columnwidth","columncount","singlerow","columns","xcol","widgetrecs","dirty","idx","widget","widgetcols","width","dispatchCustomEvent","widgetrec","widgetheight","bestcol","ypos","col","maxypos","nextypos","styles","maxheight","widgetContainers","relayout_throttle","windowMode","registerWidgetsContainer","widgetContainer","throttledRelayoutWidgets","evt","relayoutWidgetsDueToResize","sendBeforeRelayoutEvent","refreshWidgetBlock","onRelayoutWidgets","event","dispatchCustomEvent","checkWindowSize","mode","refreshDompackWidgetBlock","refreshDesandroWidgetBlock","DesandroMasonry","force","options","layout","parts","DompackMasonry","widgets","widget","register","widgetblock","getCSSVariable","breakpoint_phone","initMasonryMedia","init_dompack","relayoutWidgets","widgetnode","dispatchCustomEvent","forceRelayoutWidgets","init_gettid","init_dompack","setConsentLayers","node","qSA","shieldnode","directlink","network","infocode","qS","info","jsxcreate","getTid","playername","getTwitterConsentlayer","ev","onShieldNodeClick","link","isHTMLElement","cookiebar_default","removeConsentLayers","onDomReady","init_dompack","register","setupCookieWidget","init_dompack","CountDownComponent","node","options","mergedOptions","evt","countdownfrom","parseCountdownToString","specialcontainer","countdownto","digitnode","wrapidx","now_timestamp","now","distance","days","hours","minutes","seconds","digits","idx","leadingzero","initially_visible_digits","digitnr","value","number","amount","digitdesc","position","tracknode","digitcontainer","frag_alldigits","frag_lessdigits","frag_digits_hourstens","digit","frag","nrs","paper","current_nr","str","parts","dayparts","timeparts","register","initCountdownComponent","init_dompack","CountDownEventsWidget","node","now","eventnode","eventdata","parseCountdownToString","firstupcomingevent","addevent_data_container","CountDownComponent","register","initCountDownWidget","init_dompack","renderEvents","node","items","remove","listnode","qS","item","link","jsxcreate","relayoutWidgets","getEventItems","response","register","FeedbackForm","RPCFormBase","node","inpnode","ev","faqnode","res","legacyRegisterFormHandler","init_dompack","block","CarrouselContent","widgetnode","options","itemnode","measurenode","evt","resizeObserver","scrollLeft","idx","animate","bullet","activepage","item","in_view","scrollWidth","containerbounds","pagex","viewportbounds_inner","viewportbounds","nextpage_xpos","pagenr","items_this_page","itemnodes_this_page","itembounds","itemx","itemxend","comp","left","multiplepages","delay","resizeObserver","entries","onResize","resizeAllContentCarrousels","entry","widgetdata","onDomReady","init_dompack","initImagesWithCaptionWidget","widgetnode","carrousel","CarrouselContent","doCreateBullet","onChangeSlide","details","firstnodeinslide","nodeid","activemetanode","metanode","jsxcreate","register","init_dompack","register","node","showModalDialog","jsxcreate","init_dompack","renderNews","node","items","remove","photosnode","qS","listnode","item","i","link","jsxcreate","relayoutWidgets","getNewsItems","response","register","init_dompack","init_dompack","renderPrettyPhoneNumber","node","parts","jsxcreate","showDetails","container","timer","hideDetails","__timer","togglePersonalDetails","node","ev","stop","quoteswidget","widgetnode","foldcontainer","qS","EmbQuoteSlides","wrapper","qSA","jsxcreate","_","idx","register","quotesSlideshow","itemcount","item","i","frontnode","jmpbtns","c","jmpbtn","oldidx","minh","panel","y","relayoutWidgets","renderPrettyPhoneNumber","init_dompack","setupPodcast","node","params","cookiebar_default","startPodcast","ev","qS","podcast_title","startTransistor","startSoundCloud","url","jsxcreate","urlparts","paramnames","name","register","init_dompack","init_dompack","init_events","foldableContent","node","options","ev","stop","open","params","pushToDataLayer","findDetailsHash","hash","openCollapsableContainerFor","target","detailsnode","setDetailsEvents","qS","fireHTMLEvent","register","init","onToggleDetails","evt","isOpen","gtmevent","summaryNode","summaryText","onDomReady","TimelineTableContent","foldableContent","params","table_with_timeline_title","table_with_timeline_main_item","table_with_timeline_sub_item","pushToDataLayer","register","node","init_dompack","register","node","fixVideoPlayButton","playbutton","dir","frontproperty","Tabs","container","event","titles","qSA","page","idx","tab","observeNodeResize","newIdx","pos","firstLeft","titleRect","ListTemplate","node","template","type","url","item","items","data","domtemplate","photosNode","fragment","styleNode","cssText","SlideShow","relayoutWidgets","e","templateString","replaceMatch","match","key","levelKey","cssRules","startIdx","depth","endIdx","rule","cachedNewsEvents","NewsEventsTemplate","options","cached","resolve","reject","deferred","createDeferred","promiseXMLHttpRequest","callbackFormRPC","initializeCallbackForm","JSONRPC","formNode","inputNode","phonenr","formdata","result","initializePhotoslide","widgetphotos","slides","relayoutPhotoslideByEvent","relayoutPhotoslide","evt","infoheight","height","register","widgetinfos","widgettabs","widgetflip","widget","callbackform","newseventstemplate","imagewidget","instanceid","headeranim","initFoldableContent","forceRelayoutWidgets","iOS","preventZoomOnFocus","onTouchStart","onFocusIn","dont_disable_for","evt","tn","setViewport","newvalue","vpnode","init_dompack","createService","pirservice_rpc_default","cPIR","imagekeys","i","key","oldurl","pirservice_rpc_default","url1","url2","node","parts","part","rules","regexp","c","match","cssitem","items","mediarules","onDomReady","init_dompack","register","node","cssPromise","loadCSS","psaPromise","r","onDomReady","loadScript","req","loadApp","resolve","i","psa","e","init_dompack","init_dompack","UniverseAnimation","node","frontendConfig","debugflags","prevelement","elementname","_","elements","url","response","content","svg","jsxcreate","videoSlideTimeout","register","node","jsxcreate","ev","tag","HeaderCTAScaler","getCSSVariable","breakpoint_tablet","flatCTAMedia","event","makeTextFit","SlideShow","VideoSlideShow","videoClass","videoNodes","videoNode","breakpoint_deeplinks","videoPauseMedia","pauseVideo","video","isVideoNodeInitialized","initializeVideoNode","prevVideo","UniverseAnimation","init_dompack","init_browser","init_dompack","init_keyboard","init_env","init_gettid","import_searsia","import_searsiaconfig","init_dompack","init_keyboard","import_requester","import_searsia","SearsiaAutoSuggest","inputNode","resultsNode","options","InternetRequester","event","KeyboardHandler","stop","selectitem","_event","flagUIBusy","value","input","values","dispatchCustomEvent","historyhit","entry","url","searsia","createDeferred","lookupresult","suggestions","match","jsxcreate","selectedvalue","changeValue","init_dompack","init_env","init_std","init_gettid","PHONE_UT_REGEX","PHONE_MOB_REGEX","addDebuggingInfo","hit","source","debugFlags","jsxcreate","createGeneralResult","queryWords","titleprefix","icon","getTid","decodeString","highlightQueryWords","formatURL","createNewsResult","extended","createEventResult","createPeopleResult","getMapRouteLink","formatPhone","createVideoResult","createImageResult","createRelatedResults","hits","_source","createFilteredResult","text","words","className","result","match","url","phone","coord","init_dompack","init_env","init_std","init_gettid","shownWidget","locationRequestId","showSearsiaWidgets","hits","ctaslots","ctaprops","eventsurl","node","result","createLocationWidget","createEventsWidget","tryMatchSearsiaCTA","props","ctaslot","cta","tryMatchCTAConfig","debugFlags","createHighlightCTA","createWidgetCTA","e","CTAMatchError","title","description","widgetNode","jsxcreate","getTid","descriptionHTML","retrieveLocation","name","locreqid","response","data","decodeString","formatPhone","getMapRouteLink","eventNode","alleventsurl","resultScoreProp","resultLangProp","resultSourceProp","searsiaClient","defaultSearchType","isSubArray","master","sub","i","j","SearsiaClient","node","qR","event","KeyboardHandler","_","getUserCountry","debugFlags","requestGeoIP","country","getUserBeacons","tabsNode","perfect_scrollbar_esm_default","tabNode","q","t","searchconfigurl","response","searchconfig","apitemplate","searsia","resolve","SearsiaAutoSuggest","ctaslot","cta","parseManagedCTAConfig","tab","jsxcreate","query","words","terms","phrase","word","phrasestart","__","show","searchType","doshow","dispatchCustomEvent","sendPxlEvent","toshow","sheet","nosearch","style","prop","reset","params","result","filter","term","getHTMLTid","registerMissed","source","relatedHits","createRelatedResults","resourceDuplicateScore","hits","hit","manipulated","dupIdx","resultContainer","refNode","resultNode","createNewsResult","createEventResult","createPeopleResult","createVideoResult","createImageResult","createGeneralResult","gridNode","JustifiedImageGrid","defaultoptions","filteredNode","createFilteredResult","getTid","_source","force","html","isstudent","isemployee","loginmsg","showSearsiaWidgets","peopleResult","relatedResult","suggestion","link","widget","initSearchSheet","searchSheetContentNode","resetSearch","section","setupShowAllLinks","stop","toggle","register","node","initSearchSheet","init_dompack","init_browser","PromiseTimeoutError","timeout","applyTimeoutToPromise","promise","timeoutpromise","_","reject","scrollToOptionsAvailable","calcNavLink","link","nav","navurl","getMenuForPage","getParentForPage","SiteMenu","node","getCSSVariable","duration","event","menuParent","menuItems","e","menuParentId","submenuId","currentId","item","subitem","debugflags","getPlatform","perfect_scrollbar_esm_default","folderId","parentItem","dispatchCustomEvent","error","menuId","menuItem","result","applyTimeoutToPromise","parentId","selectId","toshow","parentlink","menuNode","jsxcreate","itemId","selected","itemNode","scrollRect","itemRect","top","pos","init_dompack","setupLanguageSwitch","event","langlink","setLocal","_hiddenMenuMedia","_hiddenMenuMediaPromise","getHiddenMenuMedia","resolve","getCSSVariable","breakpoint_menuhidden","toggleMenu","state","dispatchCustomEvent","node","toggleMenuTransition","active","register","event","media","SiteMenu","toggle","BreadcrumbList","style","ellipsisNode","jsxcreate","entry","observeNodeResize","width","childNode","styles","shorten","itemsWidth","item","unobserveNodeResize","NAVIGATIONMENU_CLOSE_TIMEOUT","NavigationMenu","force","navbarWidth","menuWidth","closeWidth","_","acc","cur","padding","debugflags","closing","stop","NavBarContainerScroller","breakpoint_deeplinks","visible","hidden","scrollDown","nodeHeight","HeaderResizer","setCSSVariable","navbarHeight","PartnerMenuPositioner","open","getPlatform","ps","perfect_scrollbar_esm_default","setupLanguageSwitch","init_dompack","callback","onDomReady","checkWindowSize","event","fitFonts","dispatchCustomEvent","init_dompack","openedParts","initialLayout","prevAutoFold","evt","updateFoldableContentBlocks","onDomReady","initFoldableContentBlocks","doCheckLostFocus","hash","block","firstBlock","bodyNode","blocks","autoFold","node","summary","processClickDataLayerTags","event","entry","node","attr","key","data","value","setupDataLayerTags","setupFriendlyCaptcha","setupGoogleRecaptcha","setupForms","setupDialogs","options","UTDialog","setupDataLayerTags","init_dompack","import_jsonrpc","init_gettid","init_dompack","filterinputselector","getFormFilters","form","id","filtertitles","filtersettings","extrafilters","frontendConfig","filter","node","inptype","filtertitle","label","labeltxt","val","nodeval","setFormFilters","filters","changeValue","init_dompack","onDomReady","FilteredOverview","EventsFormHandler","UTRPCFormBase","formnode","requesttype","node","ev","showModalDialog","res","dialogcontentnode","getTid","SummaryNavigation","items","btnnode","item","JSONRPC","filtersettings","frontendConfig","urlparamsdone","val","inptype","setFormFilters","moreitems","getFormFilters","filter","id","newfilters","name","urlparamstr","filters","have_more_results","feedbacknode","moreresults","c","urlparams","result","introblocks","t","otherblocks","summarycontainer","noresults","setEllipsisLines","e","fitFonts","enabled","pagenavnodes","summary","register","onDomReady","legacyRegisterFormHandler","registrationform","init_dompack","videos","curVideo","videoActive","windowMode","fallbackTimeout","autoplaySupported","slideTimeout","resumeVideo","nextVideo","nextVideoSlide","pauseVideo","video","isVideoNodeInitialized","playVideo","initializeVideoNode","player","videoStarted","prevVideo","videoFallback","checkWindowSize","event","register","container","node","init_dompack","register","loginbutton","startSSOLogin","form","setupWebHareSSOTrigger","init_gettid","uFondsForm","UTRPCFormBase","formnode","chknode","frontendConfig","ev","val","decsep","parts","cents","full","selval","toggleincassofieldsnames","fieldname","name","urlparamstr","res","executeSubmitInstruction","title","getTid","description","showModalDialog","destination","legacyRegisterFormHandler","node","init_dompack","init_gettid","encodeTextNode","str","cMeetingsForm","UTRPCFormBase","formnode","node","html","participantscount","bhvcount","overviewnode","lines","prevtitle","i","el","title","value","groupnode","separator","prevbhv_nr","bhv_active","bhvnr","create","linecontent","encodeTextNode","res","getTid","description","showModalDialog","legacyRegisterFormHandler","init_dompack","PeopleOverview","FilteredOverview","options","items","frontendConfig","itemmap","item","nodes","node","personid","parsedoptions","getJSONAttribute","itemidx","htmlelem","type","evt","totalfound","seen_catidx","ismatch","catidx","gridheaders","seen","onDomReady","init_dompack","UTMedicalFormHandler","UTRPCFormBase","node","cancelbutton","evt","qSA","currentdate","selection","opt","runMessageBox","result","legacyRegisterFormHandler","init_dompack","init_gettid","MIN_HEADERIMAGE_HEIGHT","MIN_HEADERIMAGE_WIDTH","getImageDimensions","file","resolve","reject","reader","img","error","NEOForm","RPCFormBase","#errorObserver","#publocs","#validatedAuthorizationOnce","node","mutationList","#handleMutations","fieldGroup","qSA","checkbox","qS","imgedit","#updateAltVisibility","#toggleAltEnabled","fields","infotextwrapper","changing","event","input","allChecked","allEmployees","mpAuthorizedField","setupValidator","#checkRequiredAuthorizedPersonTypes","mpPersonTypesField","value","languages","newstype","publocids","publocs","_","publoc","lang","mutation","target","warningNode","errorNode","legacy","hasImage","name","#checkHeaderPhoto","altEN","altNL","size","setFieldError","getTid","warning","jsxcreate","e","enabled","legacyRegisterFormHandler","init_dompack","createService","tablewithfilter_rpc_default","initializedforms","cTableFilter","node","evt","hasinitialvalue","inpnode","val","selnode","FilteredOverviewHeader","w1","w2","idxlist","i","jsxcreate","result","tablewithfilter_rpc_default","filedata","file","link","dataurl","arr","mime","bstr","n","u8arr","count","name","urlparamstr","resultscount","invalid","chkstr","found","c","param","feedbacknode","getResultsFeedbackText","register","init_dompack","init_gettid","FilteredFolder","ClientSideFilteredOverview","node","options","qS","listtoggle","resultsbar","jsxcreate","getTid","listviewheader","ev","col","idx","c","feedbackbar","togglenode","items","qSA","a","b","a_i","b_i","a_c","b_c","e","setupFilteredFolder","register","init_dompack","BTOROverview","FilteredOverview","options","evt","frontendConfig","onDomReady","filterform","init_dompack","setupITCYearControl","node","register","init_dompack","register","node","init_dompack","import_jsonrpc","cConsilioResults","node","ev","JSONRPC","urlparams","name","urlparamstr","val","res","i","itemnode","jsxcreate","descr","register","init_dompack","ProjectsOverviewFilter","ClientSideFilteredOverview","filters","evt","gradcheckbox","tags","newtags","tagref","tag","onDomReady","hecl","init_dompack","init_gettid","init_jsonrpc_client","importHTML","html","node","jsxcreate","showOsirisLink","id","language","osiriscontentnode","getTid","dialog","createDialog","result","createClient","onOsirisLink","event","utcourselink","init_dompack","notificationDelay","notificationNode","notificationId","closedNotifications","onShowNotification","event","_","debugflags","remove","rect","u","c","dispatchCustomEvent","onHideNotification","onNotificationTransitionEnd","register","node","qSA","icon","init_dompack","init_browser","infullscreen","checkFullscreen","el","nowfullscreen","getName","register","node","init_dompack","init_gettid","eventscriptloaded","onAddThisClick","eventnode","getTid","addThisScript","register","event","init_dompack","setupLogin","topmenu","loginoptions","userinfo","getDefaultAuth","menuitems","jsxcreate","item","defineLoginMenu","opts","register","node","init_dompack","deleteRow","recipientsfield","RecipientsField","node","jsxcreate","buttonsholder","evt","rows","row","stop","focus","fieldbasename","newrow","register","init_dompack","tonavbardistance","temporaryfocusednode","temporaryscrolledtonode","onDomReady","init","checkLeavingTemporaryFocusableElement","button","doSkipLinks","evt","main","header","node_headermessagesarea","node_headercta","node_titlecontainerbg","node_titlecontainer","scrolltonode_inheader","focusnode","scrolltonode","navcontainer","navposition","obscuredareaheight","init_dompack","catchServicePortalLoginLink","ev","link","user","getUTUserInfo","getLoginLink","utSilentLogin","why","setSession","getSession","getReasonforSilentLogin","ls","getLocal","beacons","getUserBeacons","isFrame","handleAutoLogin","getDefaultAuth","reason","handleUTGLobalLogin","setLocal","init_dompack","init_env","isTopLevelHomepage","lang","getUTMenuItems","userinfo","getDefaultAuth","dutch","menu","study","defineLoginMenu","getLoginLink","dtapStage","setupAuthorMode","handleUTGLobalLogin","getLocal","requestGeoIP","country","catchServicePortalLoginLink","utSilentLogin","init_dompack","assetPackPromise","register","node","loadAssetPack","init_dompack","init_events","init_dompack","import_jsonrpc","cCalendar","container","options","JSONRPC","jsxcreate","frontendConfig","timetable","firstdate","lastdate","daycontent","prevdate","i","dt","time","timestamp","getRoundedDayTimestamp","getTid","maxdate","today","todaymonths","setmonths","cMonthTable","ev","coursenode","initial","ismobileview","prevview","titlenode","translations","getCalendarTranslations","todaytimestamp","activeym","prevym","monthnode","date","month","year","day","weekday","ym","monthdaynode","h","courseids","filtereditems","monthcount","matchcount","c","id","daynode","curmonthnode","svg","symbol","serieid","title","dialog","createDialog","result","dialogcontent","item","session","itemnode","togglenode","sessionswrapper","closebtn","m","node","morenode","offset","activemonths","language","a","b","agendaitems","mindate","seldate","d","startweekday","orgstartday","startday","monthdaycount","endweekday","enddaycount","rownode","lastagendaitem_idx","celldate","cellday","cellmonth","cellyear","celltimestamp","create","classstr","infonode","datenode","parts","dispatchCustomEvent","dateobj","init_dompack","cCourseDetailsList","node","footernode","itemnode","ev","foldnode","headernode","closenode","fulldescriptionnode","h_inner","shortdescriptionnode","jsxcreate","words","prevcontent","newcontent","h_outer","btnnode","registerTexts","init_dompack","RegistrationForm","RPCFormBase","node","nextbtn","getTid","ev","deeplinklist","jsxcreate","page","selectedserie","description","monthitemswrapper","itemnode","togglenode","sessionswrapper","h","i","titlenode","foldnode","result","retrybutton","legacyRegisterFormHandler","init_dompack","init_dompack","import_jsonrpc","cCancelCourse","data","dialog","createDialog","jsxcreate","getTid","id","hash","ev","e","rpc","JSONRPC","lock","flagUIBusy","cPayCourse","formnode","showPaymentResult","node","btn","cancelCourseDialog","payCourseDialog","import_jsonrpc","register","node","pagecontainer","activetab","ev","tabcountnode","qS","showPaymentResult","cancelCourseDialog","payCourseDialog","updateCourseAlert","categories","unsubscibecourses","rpc","JSONRPC","lock","flagUIBusy","result","token","frontendConfig","coursealertnodes","qSA","removenodes","_","courselinenode","unsubscribeCourseAlert","form","import_search_rpc","FilterCourses","FilteredOverview","pagenode","calendarwrapper","initialdate","year","month","curym","cCalendar","detaillistwrapper","cCourseDetailsList","itemnode","qSA","link","searchnode","catalogtag","UTAutoComplete","text","update","consiliosource","consiliosearch","suggestions","_","item","request","title_regex","term_words","title_matches","dupchecklist","uc_domain","course","uc_course","match","ev","name","newclass","dispatchCustomEvent","coursematchids","freesearchactive","domaincount","i","domainmatch","coursematchcount","courseid","ismatch","f","lohi","lo","hi","credits100","x","countnode","getTid","utwrapper","utcount","sourcewrapper","sourcecount","coursestxt","domainstxt","jsxcreate","domainnode","show","foldnode","obj","key","inpnode","tagnode","fireHTMLEvent","labelnode","register","node","alertoptions","coursetitle","parts","container","qS","overviewline","showCourseAlertForm","options","formnode","dialog","createDialog","showCourseAlertSuccess","CourseAlertForm","RPCFormBase","form","getDefaultAuth","subscribeasoptoins","param","p","categories","subscribeas","loginbtngroup","val","legacyRegisterFormHandler","init_dompack","registerTexts","init_env","FilterStudyFinder","FilteredOverview","jsxcreate","SearchIndex","create","qR","frontendConfig","specializationstotalcount","idx","specid","node","specializations","snode","infonode","rownode","compactnode","i","ev","qSA","dataset","isspecialization","cellnames","navigateTo","currentcellname","cellnode","fieldnode","item","spec","isdetailsview","viewmode","coltitle","getTid","colnode","sortasc","sortedprogrammes","specParent","specNode","prog","isothercolumn","scoresort","qS","s","list","a","b","programmenode","itemnode","spnode","searchnode","UTAutoComplete","text","update","suggestions","_","request","callback","itemNode","activefilters","totalfound","firstnode","matchcount","key","progscore","progtitlescore","specscore","spectitlescore","score","score2","itemdata","tags","attr","itemvalue","searchvalue","matchvalue","words","value","result","terms","regex","descriptionNodes","lastIndex","match","descNode","register","init_dompack","ScholarshipFinderFilter","ClientSideFilteredOverview","options","edutype","qSA","node","filters","onDomReady","init_dompack","createService","services_rpc_default","registerTexts","transferWidget","node","frontendConfig","institute","ev","selnode","programme","busylock","flagUIBusy","opt","result","services_rpc_default","jsxcreate","getHTMLTid","getTid","content","className","routes","c","item","cPIR","initFoldableContent","url","name","register","init_dompack","programmeYearFilter","node","dateitems","closest","ev","val","item","register","init_dompack","register","btn","timer","mediaTwoRows","mediaMobile","itemslist","qR","hidebtn","itemh","dispatchCustomEvent","init_dompack","register","node","ev","btn","sel_action","qSA","toggleClass","basenode","qS","init_dompack","register","node","ev","morebtn","qSA","item","i","remove","init_dompack","studyInNumbers","node","ev","container","qSA","endval","t","el","contoursize","val","register","init_dompack","cssStudiesSorter","node","ev","selcol","closest","hnode","colname","group","groupedlines","previdx","idx","sortval","c","l","row","a","b","register","init_dompack","ellipsisFoldout","node","textcontainer","qS","ev","stop","register","init_dompack","createService","vacancies_rpc_default","getVacancies","node","options","res","vacancies_rpc_default","item","jsxcreate","relayoutWidgets","register","init_dompack","VacancyOverviewFilter","ClientSideFilteredOverview","options","vactypenode","node","ev","seloption","selectedbranchevalue","branchids","selectedidx","i","create","searchtext","checkTagClick","event","tag","stop","matchoption","qSA","opt","changeValue","qS","onDomReady","init_dompack","ProjectsList","ClientSideFilteredOverview","node","options","qS","listtoggle","feedbackbar","addDocEventListener","ev","togglenode","register","init_dompack","createService","leads_rpc_default","getMatches","results","searchfor","matches","text","item","lhs","rhs","getFlatList","list","names","entry","PreppedNameList","flatlist","TrigramMatcher","alias","searchterm","finallist","scoredlist","minscore","_","suggestion","Scope","scopes","lastsuggestions","getScope","limittypes","scopename","getCities","groupname","scope","leads_rpc_default","getMatches","getOrgNames","node","cityfield","key","suggestions","setupSchoolCityField","UTAutoComplete","text","update","item","validateSchoolName","field","jsxcreate","evt","stop","FormBase","setupSchoolNameField","relevantfields","qSA","mypos","setupValidator","register","init_dompack","citylistpromises","institutelistpromises","getInstitutes","countryfield","searchterm","groupname","key","leads_rpc_default","getMatches","_","getInstituteEducations","institutefield","results","getPrevious","node","relevantfields","qSA","mypos","setupInstituteNameField","UTAutoComplete","text","update","suggestions","item","setupInstituteEducationField","register","init_dompack","init_dompack","import_jsonrpc","registerTexts","getPrefills","url","prefills","key","init_dompack","UTVoorlichtingRPCForm","RPCFormBase","node","prefills","getPrefills","toselect","_","changeValue","response","r","learnedAboutUser","referralinfo","getReferralInfo","userbeacon","getUserBeacons","name","init_dompack","StayoverEventsSignupForm","UTVoorlichtingRPCForm","form","setupValidator","date","qR","qS","evt","qSA","node","selected","pulldown","option","selection","showloginbutton","error","jsxcreate","link","discountcodefield","verifyresult","runMessageBox","getTid","translations","roundcourse","diff_amount","need_payment","result","executeSubmitInstruction","runYesNoMessageBox","JSONRPC","res","setupPaymentZone","button","legacyRegisterFormHandler","register","init_dompack","maxloops","echeckreferral","register","form","idx","_","ev","F","getEcheckReferral","setEcheckReferral","code","checkEcheckReferral","url","refrl","EcheckForm","RPCFormBase","node","qS","qSA","group","groupoptions","col1","jsxcreate","col2","splitidx","fieldline","i","groupids","page","frontendConfig","diplomagroup","eduttypewrapper","colcount","prevtype","inp","container","innernode","pageid","groupid","current","status","finalized","step","stepsize","progress","subpages","subcount","subidx","e","actiontype","pos","progressstatus","ignoreanswers","nextaction","selectedoption","retval","htmlstring","contentnode","nextpagelock","flagUIBusy","counter","baseforminfo","getReferralInfo","action","submitdata","submitresult","resultstatus","learnedAboutUser","data","res","skipgroups","nextpage","gotourl","response","content","doc","legacyRegisterFormHandler","init_dompack","init_dompack","registerTexts","formapitype","runConfirmResignup","runMessageBox","jsxcreate","getTid","OpenDagenForm","UTVoorlichtingRPCForm","node","qR","frontendConfig","qSA","foldablenode","evt","currentlyopen","dispatchCustomEvent","learnedAboutUser","el","firstpagebutton","qS","triggerUserBeacon","clearUserBeacon","selectedcity","schoolname","opt","show","idx","getReferralInfo","pushToDataLayer","result","programmes","val","specials","rounds","info","keyname","toread","setvalue","formadd","layerobj","url","changeValue","toselect","eventday","selectday","day","availabledays","enable","round","roundgroup","gotsingleoption","select","options","closest","current","selectnode","anyvisitvisible","toggleClasses","optgroup","roundshowupboxes","programmeselects","alloptions","diploma","programmeselect","option","selection","checkedprogrammes","clusteredwith","programme","usenode","errors","res","_result","getHTMLTid","scheduleitem","create","lock","flagUIBusy","legacyRegisterFormHandler","init_dompack","init_gettid","registerTexts","init_env","OpenDagenFormV2","UTVoorlichtingRPCForm","node","pushToDataLayer","qS","evt","eventoptions","idx","getReferralInfo","result","runMessageBox","jsxcreate","getTid","r","debuginfoholder","qR","errors","stop","navigateTo","url","legacyRegisterFormHandler","init_dompack","init_dompack","createService","leadswidgets_rpc_default","EducationBrochureFormHandler","RPCFormBase","node","foldnode","qS","ev","htmllinknode","qSA","link","evt","stop","dispatchCustomEvent","htmllink","selected_brochure","hash","deeplinkcontainer","_","mutlist","obs","programmeid","guid","getUserSettings","data","res","leadswidgets_rpc_default","msgnode","createDialog","relayoutWidgets","setUserSettings","programme","promise","result","learnedAboutUser","changeValue","txtnode","targetinterest","state","also_set_focus","page1","aftersubmit","legacyRegisterFormHandler","init_dompack","stayuptodateFormHandler","UTVoorlichtingRPCForm","formnode","evt","response","lock","flagUIBusy","updatedata","ismaster","programnode","leadswidgets_rpc_default","legacyRegisterFormHandler","node","PreRegistrationFormHandler","RPCFormBase","node","closest","promise","targetinterest","response","gotourl","learnedAboutUser","relayoutWidgets","legacyRegisterFormHandler","init_dompack","formnode","formextradata","ContactForm","RPCFormBase","form","updateSpecializations","data","learnedAboutUser","legacyRegisterFormHandler","node","programmeid","programme","fieldline","closest","elem","track","dispatchCustomEvent","init_dompack","registerTexts","TasterDaysForm","UTVoorlichtingRPCForm","node","cancelregistration","jsxcreate","event","getTid","register","stop","runMessageBox","gotourl","result","debuginfoholder","qS","errors","legacyRegisterFormHandler","init_dompack","init_std","init_dompack","init_dompack","appname","setAppName","newappname","getAppName","instanceOfAny","object","constructors","c","idbProxyableTypes","cursorAdvanceMethods","getIdbProxyableTypes","getCursorAdvanceMethods","transactionDoneMap","transformCache","reverseTransformCache","promisifyRequest","request","promise","resolve","reject","unlisten","success","error","wrap","cacheDonePromiseForTransaction","tx","done","complete","idbProxyTraps","target","prop","receiver","value","replaceTraps","callback","wrapFunction","func","args","unwrap","transformCachableValue","newValue","readMethods","writeMethods","cachedMethods","getMethod","target","prop","targetFuncName","useIndex","isWrite","method","storeName","args","tx","replaceTraps","oldTraps","receiver","advanceMethodProps","methodMap","advanceResults","ittrProxiedCursorToOriginalProxy","cursorIteratorTraps","cachedFunc","iterate","cursor","proxiedCursor","reverseTransformCache","unwrap","isIteratorProp","instanceOfAny","clearCache","appname","cache","key","unregisterServiceWorkers","currentregistrations","reg","debuglayer","clearCache","getAppName","restartApp","unregisterServiceWorkers","runPWADebugMenu","jsxcreate","activatetouches","expectnumtouches","expecttaptime","testMenuTap","event","stop","register","node","settings2","init_env","appbase","didinit","offlinedeferred","swregistration","getAppName","settings2","frontendConfig","module","webdesign","sendSWRequestTo","sw","type","data","resolve","reject","msg_chan","event","sendSWRequest","checkForUpdate","downloadUpdate","updateApplication","navigateTo","onReady","initfunction","options","sendPxlEvent","onDomReady","e","swurl","getAssetPackBase","precheckExistingWorkers","registrations","onServiceWorkerMessage","setAppName","init_gettid","registerTexts","admin","fairsinfo","getSirConfig","getLocal","getSelectedEventId","getSelectedEvent","eventid","fair","getUploadQueue","getNumUploaded","increaseNumUploaded","uploadMap","setLocal","updateOptions","select","newoptions","initialValue","oldvalue","setupTrigramSearch","selnode","seloptions","opt","search","currentData","selvalues","d","list","_","s","scorelist","TrigramMatcher","minscore","filteredScoreList","options","insertedParents","i","parentOpt","o","ConfigFormHandler","FormBase","formnode","onReady","curevent","sleep","queue","entry","submitRPCForm","e","adminVisible","qR","lock","flagUIBusy","toremove","qSA","loginitem","create","evt","dialog","createDialog","form","ev","compareProperties","ft","wrapSerialized","rpc","updateres","checkForUpdate","downloadUpdate","runMessageBox","getTid","updateApplication","events","eventSelect","F","selectedEvent","dispatchCustomEvent","getTrackTitle","track","getProgramTitle","prog","basename","SignupFormHandler","RPCFormBase","config_fairsinfo","getFrontendData","parseTyped","thankyoupage","btnwrapper","dispatchDomEvent","phoneInput","fixedValue","field","schools","school","programOptions","interestedInSel","programOptionElements","progopts","tracks","node","mainopt","hasSubOptions","subopt","generateRandomId","getTidLanguage","getHardcodedURLReferralInfo","getReferralInfo","phoneCountryEl","qS","registerHandler","interestedIn","pick","schoolSel","init_dompack","blocksorder","bigline","initBlocksPage","switchform","evt","onSwitchCategory","blocks","category","container","results","no_filter","node","match","register","init_dompack","init_dompack","setupToggle","options","node","makeArray","evt","doToggle","doOpen","doClose","onFocusOut","onMouseEnter","onMouseLeave","input","init_gettid","defaultshowamount","showall","items_scroller","register","initFilters","node","evt","runPreregistrationWidget","event","stop","dialogcode","dialog","createDialog","registerMissed","tabstrip","form","toggle","closebutton","itemscontainer","perfect_scrollbar_esm_default","ev","program","category","item","checkboxnodes","cnode","setupToggle","doShowAll","doShowResults","doFilter","visibleitems","doJumpIntoDeeplink","widgetnode","query","items","matching","selecteditems","selecteditemstitle","itemnode","match","checkbox","lookup","labelnodes","itext","visibleprogrammes","visibleevents","filterpanel","manually_checked_items","unique_visible_events","resultstext","titles","title","getTidLanguage","showmorebutton","qR","showbuttontext","type","relevantto","position","qSA","initActivitiesList","node","qR","evt","onChangeEventOption","form","option","signuplink","optionspecificnodes","register","init_dompack","setupCTALinksExperiments","node","meta","keyname","abgroup","getLocal","setLocal","qSA","register","requestGeoIP","aps"]}