1 2class FemanagerValidation{constructor(e){this.element=e,this.requestCallback=null,this.submitFormAllowed=!1,0===this.element.querySelectorAll("*[data-validation]").length&&(this.submitFormAllowed=!0),this.init()}init(){this.element.querySelectorAll('*[data-validation]:not([type="file"])').forEach(e=>{e.addEventListener("blur",()=>{this.validateField(e,!1)})});this.element.querySelectorAll('*[data-validation][type="file"]').forEach(e=>{e.addEventListener("change",()=>{this.validateField(e,!1)})}),this.element.addEventListener("submit",e=>{document.body.style.cursor="wait",this.submitFormAllowed||(e.preventDefault(),this.validateAllFields(this.element))})}createRequestsCompleted(e={}){const t=e.numRequest||0;let a=e.requestsCompleted||0;const r=e.element||null,l=[];e.singleCallback&&l.push(e.singleCallback);const i=()=>{document.body.style.cursor="default",this.submitForm(r),l.forEach(e=>e())};return{addCallbackToQueue:(e,r)=>{e&&a++,r&&l.push(r),a===t&&i()},requestComplete:e=>{e&&a++,a===t&&i()},setCallback:e=>{l.push(e)}}}validateAllFields(e){this.requestCallback=this.createRequestsCompleted({numRequest:e.querySelectorAll("*[data-validation]").length,element:e}),e.querySelectorAll("*[data-validation]").forEach(e=>{this.validateField(e,!0)})}validateField(e,t){if(e.disabled)return void(t&&this.requestCallback.addCallbackToQueue(!0));const a=e.closest("form"),r=a.dataset.femanagerPlugin,l="tx_"+a.dataset.femanagerPluginName,i=a.querySelector('div:first-child input[name="'+l+'[user][__identity]"]')?.value,n=a.querySelector('div:first-child input[name="'+l+'[__referrer][@action]"]')?.value,o=Femanager.getBaseUrl()+"?id="+document.getElementById("femanagerPid")?.value+"&type=1548935210",s=document.getElementById("femanagerStoragePid")?.value,d=e.getAttribute("data-validation"),c=this.getValidations(e);let u=e.value;"checkbox"!==e.type||e.checked||(u="");let m="";if(this.indexOfArray(c,"sameAs")){const e=this.indexOfArray(c,"sameAs"),t=this.getStringInBrackets(e),a=document.querySelector('input[name="'+l+"[user]["+t+']"]');a&&(m=a.value,"checkbox"!==a.type||a.checked||(m=""))}const g=new URLSearchParams;g.append("storagePid",s||""),g.append("L",document.getElementById("femanagerLanguage")?.value||""),g.append("id",document.getElementById("femanagerPid")?.value||""),g.append("tx_femanager_validation[validation]",d||""),g.append("tx_femanager_validation[value]",u||""),g.append("tx_femanager_validation[field]",this.getFieldName(e)||""),g.append("tx_femanager_validation[user]",void 0!==i?i:""),g.append("tx_femanager_validation[additionalValue]",m||""),g.append("tx_femanager_validation[plugin]",r||""),g.append("tx_femanager_validation[pluginName]",l||""),g.append("tx_femanager_validation[referrerAction]",n||""),fetch(o,{method:"POST",body:g,headers:{"Content-Type":"application/x-www-form-urlencoded"},cache:"no-cache"}).then(e=>e.json()).then(a=>{if(t&&this.requestCallback.addCallbackToQueue(!0),a)try{a.validate?this.cleanErrorMessage(e):this.writeErrorMessage(e,a.message)}catch(t){e.insertAdjacentHTML("beforebegin",data)}}).catch(()=>{this.logAjaxError()})}getFieldName(e){let t="";const a=e.name.split("[");return t=void 0!==a[2]?a[2].replace("]",""):a[1].replace("]",""),t}writeErrorMessage(e,t){this.cleanErrorMessage(e);const a=document.querySelector(".femanager_validation_container");if(!a)return;const r=a.innerHTML.replace("###messages###",t);e.insertAdjacentHTML("beforebegin",r),e.closest(".form-group").classList.add("has-error"),e.classList.add("error")}cleanErrorMessage(e){e.closest(".form-group").classList.remove("has-error"),e.parentNode.querySelectorAll(".alert").forEach(t=>{t!==e&&t.remove()}),e.classList.remove("error")}submitForm(e){if(0===e.querySelectorAll(".error").length)this.submitFormAllowed=!0,e.submit();else{const t=e.querySelector(".error");if(!t)return;t.scrollIntoView({behavior:"smooth"})}}indexOfArray(e,t){for(let a=0;a<e.length;a++)if(-1!==e[a].indexOf(t))return e[a];return""}getValidations(e){return e.getAttribute("data-validation").split(",")}getStringInBrackets(e){let t="";if(-1!==e.indexOf("(")){const a=e.split("(");t=a[1].substr(0,a[1].length-1)}return t}logAjaxError(){"object"==typeof console&&console.log("Error: The called url is not available - if you use TYPO3 in a subfolder, please use config.baseURL in TypoScript")}}function initFemanagerValidation(){document.querySelectorAll(".feManagerValidation").forEach(e
2=>{new FemanagerValidation(e)})} 3document.addEventListener("DOMContentLoaded",function(){var e;function t(e){return(e+="").charAt(0).toLowerCase()+e.substr(1)}e=null!=document.querySelector(".tx-femanager[data-labels]")?JSON.parse(document.querySelector(".tx-femanager[data-labels]").dataset.labels):[],initFemanagerValidation(),document.querySelectorAll("*[data-confirm]").forEach(function(e){e.addEventListener("click",function(t){var n=e.getAttribute("data-confirm");confirm(n)||t.preventDefault()})}),document.querySelectorAll("[data-data-endpoint]").forEach(function(n){var a=function(a){var o={"tx_femanager_data[action]":n.dataset.dataEndpoint,"tx_femanager_data[controller]":"Data"},arguments=JSON.parse(JSON.stringify(n.dataset));for(var r in arguments)if(arguments.hasOwnProperty(r)&&r.match("arguments")){var i=document.getElementById(arguments[r]);if(i)o["tx_femanager_data["+t(r.substr(9))+"]"]=i.value}var d=document.getElementById("femanagerPid"),l=Femanager.getBaseUrl()+"index.php?id="+(d?d.value:"")+"&type=1594138042",s=n.dataset.selectedValue;fetch(l,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams(o),cache:"no-cache"}).then(function(e){if(!e.ok)throw new Error("Network response was not ok");return e.json()}).then(function(t){for(var a in n.disabled=!0,n.options.length=0,""===s||t.hasOwnProperty(s)||(n.options[n.options.length]=new Option(e.please_choose)),t)if(t.hasOwnProperty(a)){var o=a===s;n.options[n.options.length]=new Option(t[a],a,o,o),n.disabled=!1}}).catch(function(e){console.log("Error: The called url is not available - if you use TYPO3 in a subfolder, please use config.baseURL in TypoScript")}),n.disabled=!0,n.options.length=0,n.options[0]=new Option(e.loading_states)},o=n.dataset.triggerFields;void 0!==o?o.split(",").forEach(function(e){var t=document.getElementById(e);void 0!==t&&t.addEventListener("change",a)}):n.addEventListener("change",a),a()})}),window.Femanager={},window.Femanager.getBaseUrl=function(){var e,t=document.querySelector("base");if(t)e=t.href;else if(-1!==window.location.hostname.indexOf("localhost"))e="";else{var n="";window.location.port.length>0&&(n=":"+window.location.port),e="https:"!==window.location.protocol?"http://"+window.location.hostname+n+"/":"https://"+window.location.hostname+n+"/"}return e}; 4(function() { 5 'use strict'; 6 7 // mobile navigation open submenu 8 let nodeList = document.getElementsByClassName('menu-sub'); 9 if (nodeList) { 10 addEventListener(nodeList, 'click', function (el, id) { 11 this.parentElement.classList.toggle('submenuopen'); 12 }); 13 function addEventListener(nodeList, event, fn) { 14 for (var i = 0, len = nodeList.length; i < len; i++) { 15 nodeList[i].addEventListener(event, fn, false); 16 } 17 } 18 let nodeList1 = document.querySelectorAll('.menu-sub.level-1'); 19 if (nodeList1) { 20 addEventListener(nodeList1, 'click', function (el, id) { 21 this.parentElement.classList.toggle('submenuopen'); 22 }); 23 } 24 let nodeList2 = document.querySelectorAll('.menu-sub.level-2'); 25 if (nodeList2) { 26 addEventListener(nodeList2, 'click', function (el, id) { 27 this.parentElement.classList.toggle('submenuopen'); 28 }); 29 } 30 } 31 32 function addEventListener(nodeList, event, fn) { 33 for (var i = 0, len = nodeList.length; i < len; i++) { 34 nodeList[i].addEventListener(event, fn, false); 35 } 36 } 37 function findParentLi(el) { 38 var dest = null; 39 do { 40 if (el.tagName.toLowerCase() === 'li') return el; 41 el = el.parentElement || el.parentNode; 42 } while (el !== null && el.nodeType === 1); 43 return null; 44 } 45 // accessible main-menu 46 let navEls = document.querySelectorAll('nav.main-menu > ul > li'); 47 for (let i = 0; i < navEls.length; i++) { 48 let subNav = navEls[i].getElementsByTagName('ul'); 49 if (subNav && subNav.length > 0) { 50 let a = subNav[0].getElementsByTagName('a'); 51 for (let o = 0; o < a.length; o++) { 52 // set tabindex to -1 to exclude all subnavigation links from tabindex 53 a[o].setAttribute('tabindex', '-1'); 54 // second level eventlistener support for ArrowDown and ArrowUp 55 a[o].addEventListener('keydown', keydown); 56 function keydown(event) { 57 switch (event.key) { 58 // find next element 59 case 'ArrowDown': 60 let nextLi = event.target.parentNode.nextElementSibling; 61 while (nextLi && (nextLi.offsetParent === null || !nextLi.querySelector('a'))) { 62 nextLi = nextLi.nextElementSibling; 63 } 64 if (nextLi && nextLi.offsetParent !== null) { 65 let a = nextLi.querySelector('a'); 66 if (a) { 67 a.focus(); 68 } 69 } else { 70 let li = findParentLi(event.target.parentNode.parentNode); 71 let a = li.querySelector('a'); 72 if (a) { 73 a.focus(); 74 } 75 } 76 event.preventDefault(); 77 event.stopPropagation(); 78 break; 79 // find previous element 80 case 'ArrowUp': 81 let prevLi = event.target.parentNode.previousElementSibling; 82 while (prevLi && (prevLi.offsetParent === null || !prevLi.querySelector('a'))) { 83 prevLi = prevLi.previousElementSibling 84 } 85 if (prevLi && prevLi.offsetParent !== null) { 86 let a = prevLi.querySelector('a'); 87 if (a) { 88 a.focus(); 89 } 90 } else { 91 let li = findParentLi(event.target.parentNode.parentNode); 92 let a = li.querySelector('a'); 93 if (a) { 94 a.focus(); 95 } 96 } 97 event.preventDefault(); 98 event.stopPropagation(); 99 break; 100 case ' ': 101 let ul = event.target.parentNode.getElementsByTagName('ul'); 102 if (ul && ul.length > 0) { 103 ul[0].style.display = 'block'; 104 let a = ul[0].querySelector('li > a'); 105 if (a) { 106 a.focus(); 107 } 108 ul[0].style.display = ''; 109 } 110 event.preventDefault(); 111 event.stopPropagation(); 112 break; 113 } 114 } 115 } 116 } 117 // first level eventlistener for ArrowLeft, ArrowRight and ArrowDown 118 navEls[i].addEventListener('keydown', keydown); 119 function keydown(event) { 120 switch (event.key) { 121 case 'ArrowLeft': 122 let prevLi = event.target.parentNode.previousElementSibling; 123 while (prevLi && (prevLi.offsetParent === null || !prevLi.querySelector('a'))) { 124 prevLi = prevLi.previousElementSibling 125 } 126 if (prevLi) { 127 let a = prevLi.querySelector('a'); 128 if (a) { 129 a.focus(); 130 } 131 } 132 event.preventDefault(); 133 event.stopPropagation(); 134 break; 135 case 'ArrowRight': 136 let nextLi = event.target.parentNode.nextElementSibling; 137 while (nextLi && (nextLi.offsetParent === null || !nextLi.querySelector('a'))) { 138 nextLi = nextLi.nextElementSibling; 139 } 140 if (nextLi) { 141 let a = nextLi.querySelector('a'); 142 if (a) { 143 a.focus(); 144 } 145 } 146 event.preventDefault(); 147 event.stopPropagation(); 148 break; 149 // find first element 150 case 'ArrowDown': 151 let li = event.target.parentNode.querySelector('ul > li'); 152 while (li && (li.offsetParent === null || !li.querySelector('a'))) { 153 li = li.nextElementSibling; 154 } 155 if (li) { 156 let a = li.querySelector('a'); 157 if (a) { 158 a.focus(); 159 } 160 } 161 event.preventDefault(); 162 event.stopPropagation(); 163 break; 164 } 165 } 166 } 167 168})(); 169 170const togglePassword = document.querySelector('.togglePassword'); 171const password = document.querySelector('.toggle_password'); 172 173console.log(togglePassword) 174 175if (togglePassword && password) { 176 togglePassword.addEventListener('click', function (e) { 177 // toggle the type attribute 178 const type = password.getAttribute('type') === 'password' ? 'text' : 'password'; 179 password.setAttribute('type', type); 180 // toggle the eye slash icon 181 this.classList.toggle('fa-eye-slash'); 182 }); 183} 184 185(function () { 186 let prefix = "Open in new window"; 187 188 let lang = document.documentElement.lang || 'en'; 189 lang = lang.substring(0,2); 190 if (lang === "en") { 191 prefix = "Open in new window"; 192 } else if (lang === "de") { 193 prefix = "Im neuen Fenster"; 194 } 195 196 let refs = document.querySelectorAll("a[href]"); 197 if (refs.length > 0) { 198 let host = window.location.host; 199 for (let i = 0; i < refs.length; i++) { 200 let href = refs[i].getAttribute('href'); 201 let hit = /https?:\/\/(www\.)?([^\/]*)/i.exec(href); 202 if (hit && hit[2]) { 203 let domainPrefix = hit[1] || ""; // Verhindert 'undefined' 204 if (host != (domainPrefix + hit[2])) { 205 refs[i].classList.add('external'); 206 let title = refs[i].getAttribute('title'); 207 if (title) { 208 title = prefix + ': ' + title; 209 } else { 210 title = prefix; 211 } 212 refs[i].setAttribute('title', title); 213 let target = refs[i].getAttribute('target'); 214 if (!target) { 215 refs[i].setAttribute('target', '_blank'); 216 } 217 } 218 } 219 } 220 } 221 222})(); 223 224(function() { 225 'use strict'; 226 let tables = document.querySelectorAll('table'); 227 if (tables.length > 0) { 228 for (let i = 0; i < tables.length; i++) { 229 let toWrap = tables[i]; 230 let wrapper = document.createElement('div'); 231 wrapper.classList.add('table-scrollable'); 232 toWrap.parentNode.insertBefore(wrapper, toWrap); 233 wrapper.appendChild(toWrap); 234 } 235 } 236})(); 237 238/** 239 * Showmore respects viewport (lazy loading) and focus (focus point) 240 * 241 * - 2023-02-10 JV: Enhanced version with integrated paginator 242 */ 243(function() { 244 'use strict'; 245 246 function Showmore (el) { 247 var self = this; 248 this.el = el; // showmore container 249 this.visibleItems = 0; // count visible items 250// data-store="true" 251 // try to find a unique storage identifier 252 this.store = null; 253 let params = new URLSearchParams(window.location.search); 254 function findClosest(el, s) { 255 var dest = null; 256 do { 257 dest = el.querySelector(s); 258 if (dest) return dest; 259 el = el.parentElement || el.parentNode; 260 } while (el !== null && el.nodeType === 1); 261 return null; 262 } 263 264 /** 265 * generate store name to save state of showmore visible item count 266 * @param {string} storeName 267 */ 268 function generateStoreName(storeName) { 269 self.store = storeName; 270 let element = el;
271 let id = element.id; 272 if (!id) { 273 while (element.parentNode) { 274 element = element.parentNode; 275 if (element.hasAttribute('id')) { 276 id = element.getAttribute('id'); 277 break; 278 } 279 } 280 self.store = self.store + '/' + id; 281 } 282 let t, tab = findClosest(self.el, 'ul.tabsheets > li.tabsheet-item > .sheet-header'); 283 if (tab) { 284 t = tab.innerHTML; 285 self.store = self.store + '/#' + t; 286 } 287 let q = params.get("tx_solr[q]"); 288 if (q) { 289 self.store = self.store + '/' + q; 290 } 291 } 292 generateStoreName(window.location.pathname); 293 // get initialization values 294 this.step = parseInt(el.getAttribute('data-step'), 10); // load more step 295 if (isNaN(this.step)) { 296 this.step = 10; // default if no data-step is defined 297 } 298 // pagination buttons Define how many buttons are visible left and right of the current page 299 this.visibleButtons = 3; 300 // Since the button of pages 1 and last page are always visible, the dedicated "<<" and ">>" buttons can be omited 301 this.hideFirstLastButton = false; 302 303 // Check for showmore button and/or pagination 304 this.paginationElement = this.el.querySelector("[data-type='showmore-paginator']"); 305 if (this.paginationElement) { 306 this.btn = this.el.querySelector("[data-type='showmore-trigger']"); 307 } else { 308 // To be backward compatible get the showmore button exactly as before, if there is no pagination: 309 // Assume the lists last element or a child of the last element is the showmore trigger 310 this.btn = this.el.lastElementChild; 311 if (this.btn) { 312 if (this.btn.dataset.type !== 'showmore-trigger') { 313 this.btn = this.btn.querySelector("[data-type='showmore-trigger']"); 314 } 315 } 316 } 317 let searchbox = this.el.querySelector("[data-type='showmore-searchbox']"); 318 319 if (!this.btn && !this.pagination && !searchbox) { 320 // console.warn('Either showmore button nor pagination nor searchbox found but the showmore javascript therefore was initialized.'); 321 return; 322 } 323 324 // Get the lists showmore items, filter out navigation buttons 325 let childs = this.el.children; 326 this.els = [].filter.call(childs, item => { 327 if ( 328 item.dataset.type === 'showmore-trigger' 329 || item.querySelector("[data-type='showmore-trigger']") 330 || item.dataset.type === 'showmore-paginator' 331 || item.querySelector("[data-type='showmore-search']") 332 || item.dataset.type === 'showmore-searchbox' 333 || item.querySelector("[data-type='showmore-searchbox']") 334 ) { 335 return false; 336 } 337 return true; 338 }); 339 this.len = this.els.length; // item counter 340 341 // Initialize showmore-trigger button, add event listener 342 this.exists(); 343 if (this.btn) { 344 if (this.visibleItems > 0) { 345 // activate showmore trigger button 346 this.btn.addEventListener("click", function (event) { 347 document.activeElement.blur(); 348 self.more(); 349 event.preventDefault(); 350 event.stopPropagation(); 351 }); 352 this.btn.classList.remove('hidden'); 353 } else { 354 // hide button if there are no hidden items to show 355 this.btn.classList.add('hidden'); 356 } 357 } 358 359 // Initialize text input filter, add event listener 360 this.input = null; // filter input field 361 // find contentElement div 362 let node = this.el; 363 while (node && (node.id == '' || node.id.charAt(0) != 'c')) { 364 node = node.parentNode; 365 } 366 if (node && node.id != '' && node.id.charAt(0) == 'c') { 367 // search for filter input 368 let searchbox = node.querySelector("[data-type='showmore-searchbox']"); 369 // add test input 370 if (!searchbox && this.el.dataset && this.el.dataset.options && this.el.dataset.options.indexOf('searchbox') !== -1) { 371 searchbox = document.createElement('div'); 372 searchbox.dataset.type = 'showmore-searchbox'; 373 searchbox.className = 'searchbox list-search-live'; 374 node.insertBefore(searchbox, node.firstChild); 375 } 376 if (searchbox) { 377 let searchinputbox = document.createElement('span'); 378 this.input = document.createElement('input'); 379 this.input.className = 'searchinput'; 380 this.input.type = 'text'; 381 searchinputbox.appendChild(this.input); 382 searchbox.appendChild(searchinputbox); 383 } 384 if (this.input) { 385 this.input.addEventListener('keyup', function (event) { 386 self.filter(); 387 }); 388 this.input.addEventListener('input', function (event) { 389 self.filter(); 390 }); 391 this.input.value = sessionStorage.getItem('filter-' + this.store); 392 this.filter(); 393 } 394 } 395 396 // Initialize pagination buttons, add event listener 397 if (this.paginationElement) { 398 // build pagination buttons 399 this.updatePaginatorButtons(this.paginationElement, 1); 400 // activate button to items by page 401 this.paginationElement.addEventListener("click", function (event) { 402 document.activeElement.blur(); 403 if (!event.targetElement) { 404 // ignore clicks on the parent-node and on the '...'-placeholder node(s) 405 return; 406 } 407 self.pagination(); 408 event.preventDefault(); 409 event.stopPropagation(); 410 }); 411 if (this.btn) { 412 this.btn.classList.remove('hidden'); 413 } 414 } 415 } 416 417 Showmore.prototype = { 418 // check if hidden items exists 419 exists: function () { 420 let c = sessionStorage.getItem('showmore-' + this.store) || 0; // load showmore storage value 421 for (let i = 0; i < this.len; i++) { 422 if (i < c) { 423 // restore showmore storage state 424 this.els[i].classList.remove('hidden'); 425 } else if (this.els[i].classList.contains('hidden')) { 426 // found first hidden item 427 this.visibleItems = i; 428 sessionStorage.setItem('showmore-' + this.store, this.visibleItems); // init showmore storage value 429 return true; 430 } 431 } 432 return false;
433 }, 434 // show more items 435 more: function () { 436 let c = 0; 437 this.btn.classList.add('hidden'); 438 for (let i = 0; i < this.len; i++) { 439 // show more hidden items until counter has size of step 440 if (this.els[i].classList.contains('hidden') && (this.els[i].style.display != 'none')) { 441 if (c < this.step) { 442 this.els[i].classList.remove('hidden'); 443 // Set focus to first newly displayed list item. BAEK- 444 if (c === 0) { 445 let anchor = this.els[i].querySelector('a'); 446 if (anchor) { 447 anchor.focus(); 448 } 449 } 450 c++; 451 } else { 452 this.btn.classList.remove('hidden'); 453 break; 454 } 455 } 456 } 457 this.visibleItems = this.visibleItems + this.step; 458 this.updatePaginatorButtons(this.paginationElement, 1); 459 sessionStorage.setItem('showmore-' + this.store, this.visibleItems); // set showmore storage value 460 }, 461 462 /** 463 * show more items by pagination 464 * 465 * @param {number} page 466 */ 467 pagination: function (page = 1) { 468 let startIndex = page > 1 ? this.visibleItems * (page - 1) : 0; 469 let endIndex = this.visibleItems * page; 470 let count = endIndex - startIndex; 471 // reset showmore-session storage content. 472 if (page > 1) { 473 // sessionStorage.setItem('showmore-' + this.store, this.visibleItems); // init showmore storage value 474 } 475 // console.log ('pageCount: ' + this.pageCount + ', page: ' + page + ', startIndex: ' + startIndex + ', endIndex: ' + endIndex); 476 // Build pagination buttons 477 this.updatePaginatorButtons(this.paginationElement, page); 478 // show items by page 479 let first = 0; 480 let visibleItemsCount = 0; 481 let itemCounter = 0; 482 for (let i = 0; i < this.len; i++) { 483 if (this.els[i].style.display !== 'none') { 484 if (visibleItemsCount + itemCounter >= startIndex && visibleItemsCount < count) { 485 visibleItemsCount++; 486 this.els[i].classList.remove('hidden'); 487 // Set focus to first newly displayed list item. 488 if (first === 0) { 489 first = i; 490 let anchor = this.els[i].querySelector('a'); 491 if (anchor) { 492 anchor.focus(); 493 } 494 } 495 } else { 496 this.els[i].classList.add('hidden'); 497 } 498 itemCounter++; 499 } else { 500 this.els[i].classList.add('hidden'); 501 } 502 } 503 let anchor = this.els[first].querySelector('a'); 504 if (anchor) { 505 anchor.focus(); 506 } 507 // show the showmore-button if applicable 508 if (this.btn && this.len > this.step) { 509 this.btn.classList.remove('hidden'); 510 } 511 // @todo: save and restore pagination state if paginationElement.data-store is set 512 // sessionStorage.setItem('showmore-' + this.store, this.visibleItems); // set showmore storage value 513 this.el.scrollIntoView(); 514 }, 515 516 /** 517 * 518 * @param {Element} element 519 * @param {number} currentPage 520 */ 521 updatePaginatorButtons: function(element, currentPage) { 522 // count list items filtered and unfiltered by textsearch-input 523 let len = this.els.length; 524 if (this.filteredElements) { 525 len = this.filteredElements.length; 526 } 527 // take showmore into account to calculate the number of items of each page 528 let currentlyVisibleCount = this.visibleItems > 0 ? this.visibleItems : this.step; 529 let pageCount = len > currentlyVisibleCount ? Math.ceil(len / currentlyVisibleCount) : 1; 530 // Build page buttons... 531 // ...container ul... 532 let navi = document.createElement("ul"); 533 navi.classList.add('paginator'); 534 // check if first- and back-buttons must be displayed disabled 535 let className = ''; 536 if (currentPage === 1) { 537 className = 'disabled '; 538 } 539 // ...first page button... 540 if (!this.hideFirstLastButton) { 541 navi.appendChild(this.createPageNaviButton(1, className + 'first', '')); 542 } 543 // ...previous page button... 544 navi.appendChild(this.createPageNaviButton( 545 currentPage < 2 ? 1 : currentPage - 1, 546 className + 'previous', 547 '' 548 )); 549 // ...page numbered buttons... 550 className = ''; 551 let lastPage = pageCount; 552 let c = this.visibleButtons; 553 // for counter starts at 1 (one) 554 for (let i = 1; i <= pageCount; i++) { 555 let className = ''; 556 if (i === currentPage) { 557 className = 'active'; 558 } 559 if (pageCount > 3 + (c * 2)) { 560 // replace some page ranges with placeholder 561 if (i <= currentPage) { 562 // Render paginator buttons from first to current page 563 if (i === 2 && currentPage > c + 3) { 564 navi.appendChild(this.createPageNaviButton(0, 'placeholder', '')); 565 } else if (i === 2) { 566 navi.appendChild(this.createPageNaviButton(i, className)); 567 } else if (i === 1 || i >= currentPage - c) { 568 navi.appendChild(this.createPageNaviButton(i, className)); 569 } 570 } else if (i > currentPage) { 571 // Render paginator buttons from current+1 through last page 572 if (i === lastPage - 1 && currentPage <= lastPage - c - 3) { 573 navi.appendChild(this.createPageNaviButton(0, 'placeholder', '')); 574 } else if (i === lastPage - 1) { 575 navi.appendChild(this.createPageNaviButton(i, className)); 576 } else if (i === lastPage || i <= currentPage + c) { 577 navi.appendChild(this.createPageNaviButton(i, className)); 578 } 579 } 580 } else { 581 navi.appendChild(this.createPageNaviButton(i, className)); 582 } 583 } 584 585 // check if last page and next button must be displed disabled 586 if (currentPage === pageCount) { 587 className = 'disabled '; 588 } 589 // ...next page button... 590 navi.appendChild(this.createPageNaviButton( 591 currentPage === pageCount ? pageCount : currentPage + 1, 592 className+ 'next', 593 '' 594 )); 595 // ...last page button... 596 if (!this.hideFirstLastButton) { 597 navi.appendChild(this.createPageNaviButton(pageCount, className + 'last', '')); 598 } 599 // Insert the build paginator into the desired DOM container 600 this.paginationElement.innerHTML = ''; 601 this.paginationElement.appendChild(navi); 602 }, 603 604 // filter items by text search 605 filter: function () { 606 let searchString = this.input.value.toLowerCase(); 607 sessionStorage.setItem('filter-' + this.store, searchString); 608 let c = 0; 609 if (this.btn) { 610 this.btn.classList.add('hidden'); 611 } 612 for (let i = 0; i < this.len; i++) { 613 if (this.els[i].textContent.toLowerCase().indexOf(searchString) > -1) { 614 c++; 615 this.els[i].style.display = ''; 616 } else { 617 this.els[i].style.display = 'none'; 618 } 619 if (c <= this.visibleItems) { 620 this.els[i].classList.remove('hidden'); 621 } else { 622 this.els[i].classList.add('hidden'); 623 if (this.btn) { 624 this.btn.classList.remove('hidden'); 625 } 626 } 627 } 628 if (this.paginationElement) { 629 // get only nodes which are not filtered by textsearch 630 this.filteredElements = this.els.filter(item => item.style.display !== 'none'); 631 this.updatePaginatorButtons(this.paginationElement, 1); 632 this.paginationElement.classList.remove('hidden'); 633 } 634 }, 635 636 /** 637 * create pagination li element with event listener attached 638 * 639 * @param {number} pageNumber 640 * @param {string} className 641 * @param {string} textContent 642 * 643 * @return {HTMLElement} 644 */ 645 createPageNaviButton: function (pageNumber = 0, className = '', textContent= '-#pageNumber#-') { 646 let item = document.createElement("li"); 647 let ariaLabel = 'Page ' + pageNumber; 648 if (textContent === '-#pageNumber#-' && pageNumber !== 0) { 649 item.appendChild(document.createTextNode(pageNumber)); 650 } else if (textContent !== '') { 651 item.appendChild(document.createTextNode(textContent)); 652 ariaLabel = 'Page ' + textContent; 653 } 654 if (className !== '') { 655 let classList = className.split(' '); 656 item.classList.add(...classList); 657 if (className === 'active') { 658 ariaLabel += ', current Page' 659 item.setAttribute('aria-current', 'true'); 660 } 661 } 662 if (pageNumber !== 0) { 663 item.dataset.page = pageNumber; 664 item.addEventListener('click', (event) => { 665 this.pagination(pageNumber); 666 }); 667 } 668 item.setAttribute('aria-label', ariaLabel); 669 return item; 670 } 671 }; 672 673 // get all showmore container 674 var containers = document.querySelectorAll("[data-type='showmore']"), len = containers.length; 675 for (let i = 0; i < len; i++) { 676 // add an onclick eventlistener to loadmore button 677 // that handles the remove of hidden class of load more items 678 // this doesn't break viewport (lazy loading) and focus (focus point) 679 new Showmore(containers[i]); 680 } 681 682 // expose constructor globally 683 window.Showmore = Showmore; 684 685})(); 686 687(function() { 688 'use strict'; 689 690 function ScrollSpyNavigation(sections, options = {}) { 691 this.sections = sections; 692 this.options = { 693 targetNavigation: options.targetNavigation || '', 694 navItemSelector: options.navItemSelector || 'a.scrollspy-nav__item', 695 activeClass: options.activeClass || 'is-active', 696 buildNavigation: options.buildNavigation || false, 697 offset: options.offset || 225, 698 outputFormat: options.outputFormat || 'html', 699 }; 700 } 701 ScrollSpyNavigation.prototype = { 702 init: function () { 703 this.setEvents(); 704 705 const renderedNavigation = this.createNavigation(); 706 707 if (true === this.options.buildNavigation) { 708 this.appendNavigationToTarget(renderedNavigation); 709 } 710 return renderedNavigation; 711 }, 712 setEvents() { 713 const scrollHandler = this.scrollHandler.bind(this); 714 const activeSectionHandler = this.activeSectionHandler.bind(this); 715 716 this.options.targetNavigation.addEventListener('spyNavigationBuildFinished', activeSectionHandler); 717 window.addEventListener('scroll', scrollHandler); 718 }, 719 activeSectionHandler() { 720 const currentSection = this.getCurrentSection(); 721 const currentMenuItem = this.getCurrentMenuItem(currentSection); 722 723 if (currentMenuItem) { 724 this.setActive(currentMenuItem, currentSection); 725 } 726 }, 727 scrollHandler() { 728 const currentSection = this.getCurrentSection(); 729 const currentMenuItem = this.getCurrentMenuItem(currentSection); 730 if (currentMenuItem) { 731 this.removeCurrentActive({ ignoreElement: currentMenuItem }); 732 this.setActive(currentMenuItem); 733 } 734 }, 735 setActive(menuItem) { 736 const isActive = menuItem.classList.contains(this.options.activeClass); 737 if (false === isActive) { 738 menuItem.classList.add(this.options.activeClass); 739 } 740 }, 741 removeCurrentActive(options = { ignoreElement: null }) { 742 const menuItems = this.options.targetNavigation.querySelectorAll( 743 `${this.options.navItemSelector}:not([href="${options.ignoreElement.getAttribute('href')}"])` 744 ); 745
746 menuItems.forEach((item) => { 747 item.classList.remove(this.options.activeClass); 748 }); 749 }, 750 getCurrentSection() { 751 for (const section of this.sections) { 752 const currentPosition = (document.documentElement.scrollTop || document.body.scrollTop) + this.options.offset; 753 const startOfElement = this.getElementOffsetTop(section); 754 const endOfElement = startOfElement + section.offsetHeight; 755 const isInView = currentPosition >= startOfElement && currentPosition < endOfElement; 756 757 if (true === isInView) { 758 return section; 759 } 760 } 761 }, 762 getCurrentMenuItem(section) { 763 if (!section) { 764 return; 765 } 766 767 const sectionId = section.dataset.scollAnchor ?? this.getFirstAnchorInSection(section); 768 return this.options.targetNavigation.querySelector( 769 `[href="#${sectionId}"]` 770 ); 771 }, 772 getElementOffsetTop(element) { 773 let offsetTop = 0; 774 while(element) { 775 offsetTop += element.offsetTop; 776 element = element.offsetParent; 777 } 778 return offsetTop; 779 }, 780 appendNavigationToTarget(navigation) { 781 if (null === this.options.targetNavigation) { 782 return null; 783 } 784 785 if (typeof this.options.targetNavigation !== 'object') { 786 throw new TypeError('Target element is not of type "Object"'); 787 } 788 789 this.options.targetNavigation.insertAdjacentHTML('beforeend', navigation); 790 791 if (this.options.targetNavigation.children instanceof HTMLCollection) { 792 const spyNavigationBuildFinished = new Event('spyNavigationBuildFinished'); 793 this.options.targetNavigation.dispatchEvent(spyNavigationBuildFinished); 794 } 795 }, 796 createNavigation() { 797 const outputFormat = this.capitalizeString(this.options.outputFormat); 798 const renderMethod = 'render' + outputFormat; 799 800 if (typeof this[renderMethod] !== 'function') { 801 throw new TypeError('Render method "' + this.options.outputFormat + '" not supported.'); 802 } 803 804 return this[renderMethod](); 805 }, 806 capitalizeString([first, ...rest], lowerRest = true) { 807 return first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); 808 }, 809 getFirstAnchorInSection(section) { 810 const firstElementWithId = section.querySelector('[id]'); 811 812 return firstElementWithId?.id; 813 }, 814 renderHtml() { 815 const sectionList = Array.from(this.sections); 816 817 if (0 === sectionList.length) { 818 return '' 819 } 820 821 return ` 822 <nav class="scrollspy-nav"> 823 <ul> 824 ${sectionList.map(section => { 825 const sectionId = section.dataset.scollAnchor ?? this.getFirstAnchorInSection(section); 826 const sectionName = section.dataset.name ?? null; 827 828 if (!sectionId) { 829 console.error( 830 'Cant find any element with id attribute to build default anchor for navigation within section "' 831 + section.dataset.name + '".' 832 ) 833 return; 834 } 835 836 if (!sectionName) { 837 console.error( 838 'Section name could not be determined for section with anchor id "' 839 + sectionId + '". Please add a name with the data attribute "data-name" to this section.' 840 ) 841 return; 842 } 843 844 return ` 845 <li> 846 <a href="#${sectionId}" title="Scrolle zum Bereich ${sectionName}" class="scrollspy-nav__item"> 847 <div class="scrollspy-nav__icon"></div> 848 <div class="scrollspy-nav__title">${sectionName}</div> 849 </a> 850 </li> 851 ` 852 }).join('')} 853 </ul> 854 </nav> 855 `; 856 } 857 } 858 859 const sections = document.querySelectorAll('[data-type="scrollspy"]'); 860 const navigationWrapper = document.querySelector('#scollspy-nav-wrapper') 861 if (sections && navigationWrapper) { 862 const scrollSpyNavigation = new ScrollSpyNavigation( 863 sections, 864 { 865 targetNavigation: navigationWrapper, 866 buildNavigation: true 867 } 868 ); 869 scrollSpyNavigation.init(); 870 } 871})(); 872 873(function() { 874 'use strict'; 875 876 window.addEventListener('load',function() { 877 let animationStatus = window.sessionStorage.getItem('preload-animation'); 878 879 if ('finished' === animationStatus) { 880 document.querySelector('body').classList.add('loaded') 881 return; 882 } 883 884 window.sessionStorage.setItem('preload-animation', 'finished'); 885 }); 886})(); 887 888(function() { 889 'use strict'; 890 891 function EventsSearchResults(formElement, responseContainer) { 892 this.formElement = formElement; 893 this.responseContainer = responseContainer; 894 this.keyupDelay = 600; 895 this.init(); 896 } 897 EventsSearchResults.prototype = { 898 899 init: async function () { 900 this.insertLoadingSpinner(); 901 902 let fetchHtmlResponse = await this.fetchSearchForm(this.formElement); 903 await this.replaceResponseInContainer(fetchHtmlResponse); 904 905 this.formElement.addEventListener( 906 'submit', 907 (event) => this.formSubmit(event), 908 false 909 ); 910 911 const resetButton = this.formElement.querySelector('input[type="reset"]'); 912 913 resetButton.addEventListener( 914 'click', 915 (event) => this.formReset(event), 916 false 917 ); 918 919 const searchField = this.formElement.querySelector('#searchEvent'); 920 searchField.addEventListener( 921 'keyup', 922 (event) => this.submitAfterChanges(event), 923 false 924 ) 925 926 const catCheckboxen = [ 927 this.formElement.querySelector('#cat_training'), 928 this.formElement.querySelector('#cat_mediaDesign'), 929 this.formElement.querySelector('#cat_printProduction'), 930 this.formElement.querySelector('#cat_businessManagement'), 931 this.formElement.querySelector('#cat_distribution'), 932 this.formElement.querySelector('#cat_personal') 933 ]; 934 for (let i = 0; i < catCheckboxen.length; i++){ 935 catCheckboxen[i].addEventListener( 936 'change', 937 (event) => this.submitAfterChanges(event), 938 false 939 ) 940 } 941 942 const eventBeginInput = this.formElement.querySelector('#searchEventBegin') 943 eventBeginInput.addEventListener(
944 'focusout', 945 (event) => this.submitAfterChanges(event), 946 false 947 ) 948 949 const eventEndInput = this.formElement.querySelector('#searchEventEnd'); 950 eventEndInput.addEventListener( 951 'focusout', 952 (event) => this.submitAfterChanges(event), 953 false 954 ) 955 956 const eventLocationInput = this.formElement.querySelector('#searchLocation'); 957 eventLocationInput.addEventListener( 958 'change', 959 (event) => this.submitAfterChanges(event), 960 false 961 ) 962 963 const categoryButtons = document.querySelectorAll('.categorymenu button'); 964 965 categoryButtons.forEach((button) => this.bindCategoryButton(button)) 966 }, 967 async fetchSearchForm(formElement, appendValues = Array()) { 968 const formAction = formElement.action; 969 const formData = new FormData(formElement); 970 971 appendValues.forEach(function (appendValue) { 972 formData.append(appendValue.name, appendValue.value) 973 }); 974 975 try { 976 return await fetch(formAction, { 977 method: 'post', 978 body: formData 979 }) 980 .then(function (response) { 981 if (!response.ok) { 982 throw Error(response.statusText); 983 } 984 return response; 985 }) 986 .then(function (response) { 987 return response.text(); 988 }) 989 } catch (error) { 990 console.error(error); 991 this.showErrorMessage('The current Events could not be shown. Please try again.') 992 throw Error('Could not fetch events from form action argument.'); 993 } 994 }, 995 async replaceResponseInContainer(htmlResponse) { 996 setTimeout(() => { 997 this.responseContainer.innerHTML = htmlResponse; 998 }, 300); 999 const replaceResponseInContainerEvent = new Event("replaceResponseInContainerEvent"); 1000 dispatchEvent(replaceResponseInContainerEvent); 1001 }, 1002 async formSubmit(event) { 1003 event.preventDefault(); 1004 this.insertLoadingSpinner(); 1005 1006 const clickTarget = event.target; 1007 let appendValues = Array(); 1008 1009 if ('BUTTON' === clickTarget.tagName) { 1010 appendValues.push({ 1011 name: clickTarget.name, 1012 value: clickTarget.value 1013 }) 1014 } 1015 1016 let fetchHtmlResponse = await this.fetchSearchForm(this.formElement, appendValues); 1017 await this.replaceResponseInContainer(fetchHtmlResponse); 1018 }, 1019 async formReset(event) { 1020 event.preventDefault(); 1021 this.insertLoadingSpinner(); 1022 1023 this.formElement.reset(); 1024 const categoryButtonsList = document.querySelectorAll('.categorymenu li'); 1025 categoryButtonsList.forEach(function (listElement) { 1026 listElement.classList.remove('active'); 1027 }) 1028 1029 let fetchHtmlResponse = await this.fetchSearchForm(this.formElement); 1030 await this.replaceResponseInContainer(fetchHtmlResponse); 1031 }, 1032 bindCategoryButton(button) { 1033 button.addEventListener( 1034 'click', 1035 (event) => this.formSubmit(event), 1036 false 1037 ); 1038 button.addEventListener( 1039 'click', 1040 function () { 1041 const categoryButtonsList = document.querySelectorAll('.categorymenu li'); 1042 const parentListItem = this.closest('li'); 1043 1044 categoryButtonsList.forEach(function (listElement) { 1045 listElement.classList.remove('active'); 1046 }) 1047 parentListItem.classList.add('active') 1048 }, 1049 false 1050 ); 1051 }, 1052 insertLoadingSpinner() { 1053 const loadingSpinnerElement = document.createElement('div'); 1054 loadingSpinnerElement.classList.add('lns-dual-ring'); 1055 loadingSpinnerElement.setAttribute('role', 'status'); 1056 loadingSpinnerElement.innerHTML = '<span class="hidden">Loading...</span>'; 1057 1058 this.responseContainer.replaceChildren(loadingSpinnerElement); 1059 }, 1060 showErrorMessage(message) { 1061 const errorMessageElement = document.createElement('div'); 1062 errorMessageElement.classList.add('alert'); 1063 errorMessageElement.classList.add('alert-danger'); 1064 errorMessageElement.setAttribute('role', 'alert'); 1065 errorMessageElement.innerHTML = message; 1066 1067 this.responseContainer.replaceChildren(errorMessageElement); 1068 }, 1069 1070 awaitTimeout(miliSeconds) { 1071 return new Promise(resolve => setTimeout(resolve, miliSeconds)) 1072 }, 1073 1074 async submitAfterChanges(event) { 1075 await this.awaitTimeout(this.keyupDelay).then( 1076 response => this.formSubmit(event) 1077 ); 1078 } 1079 } 1080 1081 const formElement = document.getElementById('events2SearchForm'); 1082 const responseContainer = document.getElementById('searchResponseContainer'); 1083 if (formElement && responseContainer) { 1084 new EventsSearchResults(formElement, responseContainer); 1085 } 1086})(); 1087 1088(function() { 1089 'use strict'; 1090 function CardListLayoutSwitch(layoutswitch){ 1091 this.SeminarlistLayout = 'card'; 1092 this.layoutswitch = layoutswitch; 1093 this.seminarList = document.querySelector('.seminar-list'); 1094 this.cardstyle = this.layoutswitch.querySelector('.card'); 1095 this.liststyle = this.layoutswitch.querySelector('.list'); 1096 this.listClass = 'list-design'; 1097 this.cardClass = 'card-design'; 1098 this.init(); 1099 } 1100 CardListLayoutSwitch.prototype = { 1101 1102 init: async function () { 1103 if (window.localStorage.getItem('SeminarlistLayout') === 'list'){ 1104 this.SeminarlistLayout = 'list'; 1105 } 1106 1107 await this.switchLayout(this.SeminarlistLayout); 1108 1109 const layoutOptions = this.layoutswitch.querySelectorAll('button'); 1110 1111 layoutOptions.forEach((listElement) => 1112 listElement.addEventListener( 1113 'click', 1114 (event) => this.setClickEventLayoutSwitch(event, listElement), 1115 false 1116 )); 1117 }, 1118 1119 async setClickEventLayoutSwitch(event, listElement){ 1120 event.preventDefault(); 1121 if (listElement.classList.contains('list')){ 1122 this.SeminarlistLayout = 'list'; 1123 } 1124 if (listElement.classList.contains('card')){ 1125 this.SeminarlistLayout = 'card'; 1126 } 1127 await this.switchLayout(this.SeminarlistLayout); 1128 window.localStorage.setItem('SeminarlistLayout', this.SeminarlistLayout); 1129 }, 1130 1131 async switchLayout(layout){ 1132 if (layout === 'list'){ 1133 if (this.seminarList.classList.contains(this.cardClass)){ 1134 this.seminarList.classList.remove(this.cardClass); 1135 this.cardstyle.classList.remove('active'); 1136 this.cardstyle.setAttribute('aria-checked', 'false'); 1137 } 1138 if (!this.seminarList.classList.contains(this.listClass)){ 1139 this.seminarList.classList.add(this.listClass); 1140 this.liststyle.classList.add('active'); 1141 this.liststyle.setAttribute('aria-checked', 'true'); 1142 } 1143 } else { 1144 if (this.seminarList.classList.contains(this.listClass)){ 1145 this.seminarList.classList.remove(this.listClass); 1146 this.liststyle.classList.remove('active'); 1147 this.liststyle.setAttribute('aria-checked', 'false'); 1148 } 1149 if (!this.seminarList.classList.contains(this.cardClass)){ 1150 this.seminarList.classList.add(this.cardClass); 1151 this.cardstyle.classList.add('active'); 1152 this.cardstyle.setAttribute('aria-checked', 'true'); 1153 } 1154 } 1155 }, 1156 } 1157 const isElementLoaded = async selector => { 1158 while ( document.querySelector(selector) === null) { 1159 await new Promise( resolve => requestAnimationFrame(resolve) ) 1160 } 1161 return document.querySelector(selector); 1162 }; 1163 addEventListener( 1164 'replaceResponseInContainerEvent', 1165 (event)=> 1166 isElementLoaded('#layoutswitch').then((selector) => { 1167 new CardListLayoutSwitch(selector); 1168 // get all showmore container 1169 var i, els = document.querySelectorAll("[data-type='showmore']"), len = els.length; 1170 for (i = 0; i < len; i++) { 1171 // add an onclick eventlistener to loadmore button 1172 // that handles the remove of hidden class of load more items 1173 // this doesn't break viewport (lazy loading) and focus (focus point) 1174 new Showmore(els[i]); 1175 } 1176 // expose constructor globally 1177 window.Showmore = Showmore; 1178 }), 1179 false 1180 ); 1181})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.