1 2class MVElements { 3 4 constructor(parentElement) { 5 this.parentElement = parentElement; 6 this.selectedTags = []; 7 } 8 9 handleHeadlineByType(type) { 10 switch(type) { 11 case 'page': 12 return 'Seiten'; 13 case 'post': 14 return 'Beiträge'; 15 case 'video': 16 return 'Videos'; 17 case 'ewebinar': 18 return 'Webinare'; 19 case 'storylane': 20 return 'Storylanes'; 21 case 'faq-element': 22 return 'FAQs'; 23 case 'manual-element': 24 return 'Anleitungen'; 25 case 'manual': 26 return 'Handbuch'; 27 default: 28 return 'Ergebnisse'; 29 } 30 31 } 32 33 createResultElement(type, givenResults, target) { 34 35 let row = this.createResultRowElement(type); 36 let container = this.createResultContainerElement(); 37 let headline = this.createResultHeadlineElement(this.handleHeadlineByType(type)); 38 let resultlist = this.createResultList(givenResults, target); 39 40 let resultcontainer = this.createResultDiv(resultlist); 41 42 container.appendChild(headline); 43 container.appendChild(resultcontainer); 44 if(givenResults.length > 0) { 45 row.appendChild(container); 46 this.parentElement.appendChild(row); 47 } 48 } 49 createResultRowElement(type) { 50 let row = document.createElement('div'); 51 row.classList.add('row'); 52 row.classList.add(`results-${type}`); 53 row.classList.add('helpcenter-result-row','d-none','show-on-result-content'); 54 55 return row; 56 } 57 58 createResultContainerElement() { 59 let container = document.createElement('div'); 60 container.classList.add('col-12'); 61 container.classList.add('text-center','px-3' ); 62 return container; 63 } 64 65 createResultDiv(resultlist) { 66 let div = document.createElement('div'); 67 div.classList.add('results'); 68 div.innerHTML = resultlist.outerHTML; 69 return div; 70 } 71 72 createResultHeadlineElement(content) { 73 74 let headline = document.createElement('p'); 75 headline.classList.add('ff-cairo','custom','fw600','fs-30','text-start','pb-3', 'mt-4', 'pt-4'); 76 headline.innerHTML = content; 77 return headline; 78 79 } 80 81 createResultList(results, target) { 82 let ul = document.createElement('ul'); 83 ul.classList.add('collapsing-results'); 84 85 results.forEach(result => { 86 ul.appendChild(this.createResultLiElement(result, target)); 87 }) 88 return ul; 89 } 90 91 createResultLiElement(result, target) { 92 93 let li = document.createElement('li'); 94 li.classList.add('collapsing-result','text-start',`helpcenter-result-li-${result.type}-${result.id}`); 95 li.setAttribute('data-cats',`${result.keyword}`); 96 li.setAttribute('data-id',result.id); 97 li.innerHTML = `<a class="hc-result mv-btn-tracker text-start" rel="noopener" target=${target} id="helpcenter-result-li-${result.type}-${result.id}" href="${result.link}"><span>${result.title.rendered}</span></a>`; 98 return li; 99 } 100 101 hideResultRow(type,parentElementForResults) { 102 if(parentElementForResults.querySelector('.results-'+type)) { 103 parentElementForResults.querySelector('.results-' + type).classList.add('d-none'); 104 } 105 } 106 107 showResultRow(type, parentElementForResults) { 108 if(parentElementForResults.querySelector('.results-'+type)) { 109 parentElementForResults.querySelector('.results-' + type).classList.remove('d-none'); 110 } 111 } 112 113 114 115 116} 117 118/* 119* 120#1 in prepareSearch.js wird im Footer der JSON-String aus dem Backend (REST Api Endpunkt all) in die Variable contentJSON geschrieben 121* 122#2 und dann wird die Klasse Helpcenter instanziiert (in prepareSearch.js) 123* 124#3 die ContentJSON wird in der Klasse Helpcenter in die Variable posts geschrieben und im Array results verteilt nach contenttypen. 125 Damit soll die visuelle Darstellung der Suchergebnisse vereinfacht und vorbereitet werden. Diese müssen auch nach Contenttyp sortiert werden 126* 127* 128* 129 */ 130 131 132 133class Helpcenter { 134 135 constructor(closeimg, parentElementForResults, searchinput, singlepagetype, filtered, parentElm, resultCounter, excludeTypes = [], target = "_blank") { 136 137 this.parentElm = document.querySelector('.main-hc-elm[data-parent="'+parentElm+'"]'); //for better encapsulation of multiple HC elements 138 this.resultCounter = resultCounter; 139 this.excludeTypes = excludeTypes; 140 this.searchinput = searchinput; 141 this.singlepage = singlepagetype; 142 this.searchvalue = ""; 143 this.noresults = this.parentElm.querySelector('.no-results'); 144 this.otherresults = this.parentElm.querySelector('.other-results'); 145 this.closeimg = document.querySelector(closeimg); 146 this.posts = contentJSON; 147 this.parentElementForResults = parentElementForResults; 148 this.searchresults = []; 149 this.state = 'default'; 150 this.types = ['page','post','video','ewebinar','storylane','faq-element','manual-element','manual']; 151 this.trackingFormFields = ['#field_keywordhc2','#field_keywordhc']; 152 this.filtered = []; 153 this.tagFiltered = []; 154 this.keyDownFiltered = []; 155 this.tagFiltered = []; //contains all the via tagnav filtered elements to filter any furterh with the search 156 this.selectedTags = []; //contains all the selected tags and is also used for the filter reset fn 157 /*if(!contentJSON) { 158 alert('No contentJSON found, tell Björn about it'); 159 return; 160 } */ 161 this.target = target; 162 this.checkForPrefilledSearch(); 163 164 //if we use the prefiltered singlepage results, we get the filtered posts from prepareSearch.js, which is invoked in the footer and creates the Helpcenter objects 165 if(singlepagetype != '' && filtered != '') { 166 this.posts = filtered; //prefiltered by singlepage, e.g. only videos or faqs 167 this.filtered = filtered; 168 } 169 170 //quasi state der anwendung 171 this.results = { 172 'page' : { 173 results : [], 174 }, 175 'post' : { 176 results : [], 177 }, 178 'video' : { 179 results : [], 180 }, 181 'storylane' : { 182 results : [], 183 },
184 'ewebinar' : { 185 results : [], 186 }, 187 'faq-element' : { 188 results : [], 189 }, 190 'manual-element' : { 191 results : [], 192 }, 193 'manual' : { 194 results : [], 195 } 196 }; 197 198 this.handleTypeExclusion(); 199 200 //class to manage result elements 201 this.elements = new MVElements(this.parentElementForResults); 202 203 //state füllen, einmal am Anfang und dann auf diesem Bestand fltern 204 //sollten ergebnisse vorhanden sein, dann werden sie in die resultcontainer geschrieben und keine distribution gemacht 205 206 this.handleResultsDistribution(); 207 208 209 this.keyword = ""; 210 211 //nur auf helpcenter themen seiten 212 this.checkForKeyword(); 213 214 } 215 216 isHCMainPage() { 217 return this.parentElm.dataset.parent === 'helpcenter' 218 } 219 220 221 checkForPrefilledSearch() { 222 223 if(this.searchinput.value ) { 224 this.searchvalue = this.searchinput.value; 225 226 // Keydown-Event für die Enter-Taste erstellen 227 const enterEvent = new KeyboardEvent('keyup', { 228 key: 'Enter', // Der Name der Taste 229 keyCode: 13, // Alte Methode, aber noch weit verbreitet 230 code: 'Enter', // Standardisierte Taste 231 which: 13, // Veraltete Eigenschaft, für Kompatibilität 232 bubbles: true, // Event propagiert nach oben 233 cancelable: true // Event kann abgebrochen werden 234 }); 235 document.querySelector('.hcpreloader').classList.add('d-none'); 236 237 window.setTimeout(() => { 238 this.searchinput.dispatchEvent(enterEvent); 239 },100) 240 241 this.keyDownEventAction(enterEvent); 242 243 } 244 } 245 246 checkForKeyword(){ 247 if(document.querySelector('#keyword-line') && this.parentElm.dataset.parent === 'helpcenter-themen') { 248 this.keyword = document.querySelector('#keyword-line').dataset.keyword; 249 this.toggleFrontendState('search'); 250 this.updateVisualMatchesCounter(); 251 } 252 } 253 254 handleTypeExclusion() { 255 if(this.excludeTypes.length > 0) { 256 this.types = this.types.filter(type => !this.excludeTypes.includes(type)); 257 this.excludeTypes.forEach(type => { 258 if(type in this.results){ 259 delete this.results[type]; 260 } 261 }); 262 } 263 } 264 265 //used for simple filtering of already fetched elements 266 filterElements(){ 267 const elementsToFilter = document.querySelectorAll('.youtube'); 268 elementsToFilter.forEach( element => { 269 if(element.dataset.title) { 270 if(element.dataset.title.toLowerCase().indexOf(this.searchvalue.toLowerCase()) > -1 || element.dataset.always == "on" ) { 271 272 //workaround ewebinars 273 if(element.classList.contains('webinar')) { 274 element.parentElement.classList.remove('d-none'); 275 } 276 element.classList.remove('d-none'); 277 } else { 278 //workaround ewebinars 279 if(element.classList.contains('webinar')) { 280 element.parentElement.classList.add('d-none'); 281 } 282 element.classList.add('d-none'); 283 } 284 } 285 }); 286 } 287 288 289 handleSearchResults(source, filtered) { 290 if(source === 'keydown') { 291 this.keyDownFiltered = filtered; //prefiltered by textinput 292 } else { 293 this.tagFiltered = filtered; //prefiltered by tags 294 } 295 } 296 297 resetFilteredElements(){ 298 const elementsToFilter = document.querySelectorAll('.youtube'); 299 300 elementsToFilter.forEach( 301 element => { 302 element.classList.remove('d-none'); 303 } 304 ); 305 } 306 307 308 /* 309 * this is used for the singlepage results, which are preloaded and not triggered by a keydown event 310 */ 311 loadResultView() { 312 313 this.loadPostsAction(); 314 this.handleFilterClicksOnTags(); 315 this.handleTagBreadcrumbClicks(); 316 } 317 318 loadPostsAction() { 319 this.filterPosts().then(results => { 320 console.log(results.length) 321 this.handleNoresultsTracking(); 322 this.handleTypesCount(); //hides empty rows 323 this.toggleFrontendState('search'); 324 this.handleNoresults(); 325 this.searchvalue = " "; 326 this.updateVisualMatchesCounter(); 327 this.searchinput.dispatchEvent(new Event('input', { bubbles: true })) 328 }).catch(err => { 329 this.updateVisualMatchesCounter(); 330 }); 331 } 332 333 keyDownEventAction(e) { 334 if(!this.searchinput.value) { 335 this.searchvalue = e.target.value; 336 } else { 337 this.searchvalue = this.searchinput.value; 338 } 339 this.closeimg.classList.remove('d-none'); 340 341 if(this.singlepage === "videos" || this.singlepage === "ewebinar"){ 342 this.filterElements(); 343 } else { 344 this.loadPostsAction(); 345 } 346 } 347 348 hideTagBreadcrumbs() { 349 document.querySelector('#removeTagFilter').classList.add('d-none'); 350 351 this.selectedTags = []; 352 this.tagFiltered = []; 353 354 355 document.querySelectorAll('.selected_tag').forEach(element => { 356 element.classList.add('d-none'); 357 }); 358 } 359 360 361 362 updateSelectedTags(elementData, tagElement) { 363 364 365 return new Promise((resolve,reject) => { 366 let mainTagElement = document.querySelector('.category_filter[data-category="'+elementData.category+'"]'); 367 let tagBreadcrumbElement = document.querySelector('ul.selected-tags li[data-category="'+elementData.category+'"]'); 368 369 if(document.querySelectorAll('ul.selected-tags li.d-none').length) { 370 document.querySelector('#removeTagFilter').classList.remove('d-none'); 371 } 372 373 if (!this.selectedTags.includes(elementData.category)) { 374 this.selectedTags.push(elementData.category); 375 mainTagElement.classList.add('active'); 376 tagBreadcrumbElement.classList.remove('d-none'); 377 } else { 378 this.selectedTags = this.selectedTags.filter(tag => tag != elementData.category); 379 mainTagElement.classList.remove('active'); 380 381 tagBreadcrumbElement.classList.add('d-none'); 382 383 //the last filter is removed, so we hide the tag breadcrumbs 384 if(document.querySelectorAll('ul.selected-tags li.d-none').length == document.querySelectorAll('ul.selected-tags li').length ) { 385 this.hideTagBreadcrumbs(); 386 387 if(this.keyDownFiltered.length > 0) { 388 this.showPosts('keydown'); 389 } 390 } 391 } 392 393 resolve('tag_handling_done'); 394 395 396 }) 397 } 398 399 filterByTags() { 400 401 return new Promise((resolve,reject) => { 402 let filterresults = []; 403 404 if (this.keyDownFiltered.length > 0) { //if we have prefiltered elements e.g.from the text input, we filter on them 405 this.tagFiltered = this.keyDownFiltered; 406 } else { 407 this.tagFiltered = this.posts; 408 } 409 410 this.tagFiltered.forEach(post => {
411 this.selectedTags.forEach(tag => { 412 if (post.keyword.includes(tag)) { 413 filterresults.push(post); 414 } 415 }); 416 }); 417 418 resolve(filterresults); 419 }); 420 } 421 422 handleFilterClicksOnTags () { 423 let counter = 0; 424 let tagcontainer = document.querySelector('.videofilter'); 425 tagcontainer.querySelectorAll('.category_filter').forEach( 426 element => { 427 element.addEventListener('click', e => { 428 counter++; 429 430 431 let elementData = element.dataset; 432 433 this.updateSelectedTags(elementData, element).then(result => { 434 //Tags are selected, now filter the elements 435 this.filterByTags().then(filterresults => { 436 this.handleSearchResults('click', filterresults); 437 if(filterresults.length > 0) { 438 this.showFilteredPosts(filterresults); 439 } 440 441 }); 442 443 }); 444 }); 445 } 446 ); 447 } 448 449 450 handleTagBreadcrumbClicks() { 451 let tagcontainer = document.querySelector('ul.selected-tags'); 452 tagcontainer.querySelectorAll('.selected_tag').forEach( 453 element => { 454 element.addEventListener('click', e => { 455 456 let elementData = element.dataset; 457 this.updateSelectedTags(elementData, element).then(result => { 458 //Tags are selected, now filter the elements 459 this.filterByTags().then(filterresults => { 460 this.handleSearchResults('click', filterresults); 461 if(filterresults.length > 0) { 462 this.showFilteredPosts(filterresults); 463 } 464 465 }); 466 467 }); 468 }); 469 } 470 ); 471 } 472 473 474 475 handleResultsDistribution() { 476 477 /* 478 this is done on startup to distribute the results to the different result-containers 479 */ 480 this.posts.forEach(post => { 481 if(!this.excludeTypes.includes(post.type)) { 482 // verteile resultate auf das array 483 switch (post.type) { 484 case 'page': 485 this.results.page.results.push(post); 486 break; 487 case 'post': 488 this.results.post.results.push(post); 489 break; 490 case 'video': 491 this.results.video.results.push(post); 492 break; 493 case 'storylane': 494 this.results.video.results.push(post); //wird auch in Videos gepushed 495 break; 496 case 'ewebinar': 497 this.results.ewebinar.results.push(post); 498 break; 499 case 'storylane': 500 this.results.storylane.results.push(post); 501 break; 502 case 'faq-element': 503 this.results['faq-element'].results.push(post); 504 break; 505 case 'manual-element': 506 this.results['manual-element'].results.push(post); 507 break; 508 case 'manual': 509 this.results.manual.results.push(post); 510 break; 511 default: 512 console.log('No type found'); 513 } 514 } 515 }); 516 517 this.initialRendering(); 518 519 } 520 521 initialRendering() { 522 523 if(!this.excludeTypes.includes('ewebinar')){ let webinare = this.elements.createResultElement('ewebinar', this.results.ewebinar.results, this.target)}; 524 if(!this.excludeTypes.includes('video')){ let videos = this.elements.createResultElement('video', this.results.video.results, this.target)}; //contains also storylanes 525 if(!this.excludeTypes.includes('manual')){ let handbuch = this.elements.createResultElement('manual', this.results.manual.results, this.target)}; 526 if(!this.excludeTypes.includes('manual-element')){ let anleitungen = this.elements.createResultElement('manual-element', this.results['manual-element'].results, this.target)}; 527 if(!this.excludeTypes.includes('faq-element')){ let faq = this.elements.createResultElement('faq-element', this.results['faq-element'].results, this.target)}; 528 if(!this.excludeTypes.includes('post')){ let posts = this.elements.createResultElement('post', this.results.post.results, this.target)}; 529 if(!this.excludeTypes.includes('page')){ let pages = this.elements.createResultElement('page', this.results.page.results, this.target) }; 530 } 531 532 533 534 535 showFilteredPosts(filtered) { 536 this.posts.forEach(post => { 537 this.parentElementForResults.querySelector(`.helpcenter-result-li-${post.type}-${post.id}`) && this.parentElementForResults.querySelector(`.helpcenter-result-li-${post.type}-${post.id}`).classList.add('d-none'); 538 });
539 filtered.forEach(post => { 540 this.parentElementForResults.querySelector(`.helpcenter-result-li-${post.type}-${post.id}`) && this.parentElementForResults.querySelector(`.helpcenter-result-li-${post.type}-${post.id}`).classList.remove('d-none'); 541 }); 542 if(filtered.length === 0 && this.selectedTags.length <= 0 ) { 543 this.updateVisualMatchesCounter(this.posts.length); 544 } else { 545 this.updateVisualMatchesCounter(filtered.length); 546 } 547 } 548 549 550 showPosts(source) { 551 if(source == "keydown") { 552 553 this.keyDownFiltered.forEach(post => { 554 this.parentElementForResults.querySelector(`.helpcenter-result-li-${post.type}-${post.id}`) && this.parentElementForResults.querySelector(`.helpcenter-result-li-${post.type}-${post.id}`).classList.remove('d-none'); 555 }); 556 557 this.updateVisualMatchesCounter(this.keyDownFiltered.length); 558 } 559 } 560 561 /* 562 the keydown / input live filter 563 filters on all posts or on the prefiltered posts 564 */ 565 filterPosts(){ 566 567 let value = this.searchvalue; 568 569 return new Promise((resolve,reject) => { 570 571 let filtered; 572 573 //gibt es bereits durch die Tags vorgefilterte Elemente 574 if(this.tagFiltered && this.tagFiltered.length > 0) { 575 this.keyDownFiltered = this.tagFiltered; 576 filtered = this.keyDownFiltered.filter(element => ( element.title.rendered.toLowerCase().search(value.toLowerCase()) > -1 || element.content.rendered.toLowerCase().search(value.toLowerCase()) > -1 || ( element.searchwords.toLowerCase().search(value.toLowerCase()) > -1) && element.searchwords != "") && element.acf.verbergen !== true ); 577 this.handleSearchResults('keydown', filtered); 578 579 } else { 580 console.log('filterPosts',value); 581 582 filtered = this.posts.filter(element => ( element.title.rendered.toLowerCase().search(value.toLowerCase()) > -1 || element.content.rendered.toLowerCase().search(value.toLowerCase()) > -1 || ( element.searchwords.toLowerCase().search(value.toLowerCase()) > -1) && element.searchwords != "") && element.acf.verbergen !== true ); 583 this.handleSearchResults('keydown', filtered); 584 585 } 586 587 this.searchresults = filtered; 588 this.showFilteredPosts(filtered); 589 resolve(filtered); 590 }); 591 592 } 593 594 handleTypesCount() { 595 596 this.types.forEach(type => { 597 //do i exist in this.searchresults 598 let filteredType = this.searchresults.filter(element => element.type === type); 599 if(filteredType.length == 0 || filteredType.length == undefined) { 600 this.elements.hideResultRow(type, this.parentElementForResults); 601 } else { 602 this.elements.showResultRow(type, this.parentElementForResults); 603 } 604 }) 605 606 607 } 608 609 610 toggleFrontendState(type="default") { 611 612 613 if(type === 'search' && this.state =="default") { 614 this.parentElm.querySelectorAll('.show-on-result-content').forEach(e => { 615 e.classList.remove('d-none'); 616 }); 617 this.parentElm.querySelectorAll('.hide-on-result-content').forEach(e => { 618 e.classList.add('d-none'); 619 }); 620 621 this.state = 'search'; 622 } 623 624 if(type === 'default' && this.state =="search") { 625 this.parentElm.querySelectorAll('.show-on-result-content').forEach(e => { 626 e.classList.add('d-none'); 627 }); 628 this.parentElm.querySelectorAll('.hide-on-result-content').forEach(e => { 629 e.classList.remove('d-none'); 630 }); 631 this.state = 'default'; 632 } 633 634 } 635 636 setLoadingState(state) { 637 let loading = document.querySelector('#loading'); 638 639 if(loading == null) return; 640 641 if (state === 'on') { 642 loading.classList.remove('d-none'); 643 } else { 644 loading.classList.add('d-none'); 645 } 646 } 647 648 649 handleInputStyle(state) { 650 if(state === 'on') { 651 this.searchinput.classList.add('no-border'); 652 } else { 653 this.searchinput.classList.remove('no-border'); 654 } 655 } 656 657 658 handleExcludedTypes() { 659 this.excludeTypes.forEach(type => { 660 this.searchresults = this.searchresults.filter(element => element.type != type); 661 }) 662 } 663 664 updateVisualMatchesCounter(numbervalue = -1, tagged=false) { 665 666 this.handleExcludedTypes(); 667 668 if(sessionStorage.getItem('liveSearchResultContent')) { 669 670 } 671 672 if(this.parentElm.dataset.parent == "helpcenter-themen") { 673 this.searchresults.length > 0 ? this.resultCounter.querySelector('span').innerHTML = this.searchresults.length : this.resultCounter.querySelector('span').innerHTML = this.posts.length; 674 675 //return; 676 } else { 677 678 if(numbervalue > -1) { 679 680 this.resultCounter.querySelector('span').innerHTML = numbervalue; 681 return; 682 } 683 684 if(this.searchresults.length > 0 && this.searchvalue != "") { 685 this.resultCounter.querySelector('span').innerHTML = this.searchresults.length; 686 } else { 687 this.resultCounter.querySelector('span').innerHTML = 0; 688 } 689 } 690 691 } 692 693 694 695 handleNoresults(keyword=""){ 696 697 698 let formfield = document.querySelector('#field_keywordhc'); 699 700 if(formfield) { 701 formfield.value = keyword; 702 } 703 704 let noresults = document.querySelector('#noresults'); 705 if(noresults) { 706 707 if(this.searchresults.length === 0) { 708 noresults.classList.remove('d-none'); 709 this.setLoadingState('off'); 710 this.updateVisualMatchesCounter(); 711 if(this.noresults) { 712 this.noresults.classList.add('d-none'); //this is the permanent no-resuls-for-you? form 713 } 714 715 } else { 716 noresults.classList.add('d-none'); 717 if(this.noresults) { 718 this.noresults.classList.remove('d-none'); //this is the permanent no-resuls-for-you? form 719 } 720 } 721 722 } 723 } 724 725 726 handleNoresultsTracking() { 727 this.trackingFormFields.forEach(field => { 728 let formfield = document.querySelector(field); 729 if(formfield) { 730 formfield.value = this.searchvalue; 731 } 732 }) 733 } 734 735 log(msg){ 736 console.log(msg); 737 } 738
739 handleCursor() { 740 this.handleInputStyle('on'); 741 } 742 743 pasteListener() { 744 this.searchinput.addEventListener('paste', e => { 745 this.log('paste'); 746 }); 747 } 748 749 keyDownListener (event) { 750 // this.updateVisualMatchesCounter(); 751 752 this.searchinput.addEventListener('keyup',e => { 753 this.keyDownEventAction(e); 754 this.handleCursor(); 755 }); 756 757 document.addEventListener('keydown',e => { 758 if(e.key === 'Escape') { 759 this.closeSearchState(); 760 } 761 762 }); 763 764 } 765 766 767 768 769 trackSearchValue(prefix="Suchergebnis___"){ 770 let trimatch = prefix + this.searchvalue; 771 772 if (window.dataLayer) { 773 window.dataLayer.push({ 774 'event': 'mv2020-btn', 775 'mv-btn': trimatch 776 }) 777 } 778 } 779 780 781 handleSearchInputOnSearchClose() { 782 this.searchinput.value = ''; 783 this.searchinput.blur(); 784 } 785 786 handleResetOnSearchClose() { 787 this.resetFilteredElements(); 788 } 789 790 /* 791 * set the default state, as if the user has not searched anything 792 */ 793 closeSearchState(){ 794 console.log(this.keyDownFiltered) 795 localStorage.removeItem('voting_timestamp'); 796 this.handleSearchInputOnSearchClose(); 797 if(this.isHCMainPage()) this.deleteHistoryState(); 798 this.handleResetOnSearchClose(); 799 this.toggleFrontendState('default'); 800 this.tagFiltered = []; 801 this.keyDownFiltered = []; 802 window.location.hash = ''; 803 if(this.singlepage === "desktop-search"){ 804 document.getElementById('desktop-search').classList.remove('open'); 805 } 806 807 if(this.singlepage != "desktop-search" && this.singlepage != "" && this.singlepage) { 808 location.reload() 809 } 810 811 } 812 813 clickListener(){ 814 if( this.searchinput == null) return; 815 816 817 818 this.closeimg.addEventListener('click',e => { 819 e.preventDefault(); 820 this.closeSearchState(); 821 }); 822 823 824 document.addEventListener('click',e => { 825 if(e.target.classList.contains('hc-result')) { 826 827 localStorage.setItem('voting_timestamp', this.searchinput.value+'_'+window.scrollY+'_'+Date.now()); 828 829 } 830 }); 831 832 833 } 834 835 836 837 838 deleteHistoryState() { 839 // Lösche den aktuellen Eintrag im Verlauf 840 history.replaceState(null, null, window.location.href); 841 // Lösche die gespeicherten Daten im Session Storage 842 sessionStorage.removeItem('liveSearchTerm'); 843 sessionStorage.removeItem('liveSearchResultContent'); 844 sessionStorage.removeItem('liveSearchResults'); 845 846 } 847 historyStateListener(){ 848 let isHCMainPage = this.parentElm.dataset.parent === 'helpcenter'; 849 console.log('historyStateListener',isHCMainPage); 850 if(isHCMainPage) { 851 this.parentElementForResults.querySelectorAll('.hc-result').forEach(element => { 852 element.addEventListener('mousedown', e => { 853 this.historySaveState(); 854 }); 855 }) 856 } 857 858 859 860 } 861 862 historySaveState() { 863 if( this.searchinput == null) return; 864 // Speichere im Session Storage 865 sessionStorage.setItem('liveSearchTerm', this.searchinput.value); 866 sessionStorage.setItem('liveSearchResultContent', document.getElementById('resultcontent').innerHTML); 867 // Setze History State 868 history.pushState({ liveSearch: true }, '', window.location.href); 869 } 870 871 blurListener(){ 872 if( this.searchinput == null) return; 873 this.searchinput.addEventListener('blur',e => { 874 875 this.trackSearchValue(); 876 this.handleInputStyle('off'); 877 }); 878 } 879 880 unloadListener(){ 881 if( this.searchinput == null) return; 882 window.addEventListener('beforeunload', e => { 883 this.trackSearchValue('Suchergebnis_Seite_Verlassen___'); 884 }); 885 } 886 887 pagehideListener(){ 888 if( this.searchinput == null) return; 889 window.addEventListener('pagehide', e => { 890 this.trackSearchValue('Suchergebnis_Zurückbutton___'); 891 }); 892 } 893 894 fireListeners(){ 895 this.keyDownListener(); 896 this.clickListener(); 897 this.blurListener(); 898 this.pagehideListener(); 899 this.unloadListener(); 900 this.pasteListener(); 901 this.historyStateListener(); 902 } 903 904 triggerAutomaticSearch () { 905 906 if( localStorage.getItem('voting_timestamp')){ 907 let voting_timestamp = localStorage.getItem('voting_timestamp').split('_'); 908 909 910 let keyword = voting_timestamp[0]; 911 let scrollAmount = voting_timestamp[1]; 912 913 914 let timestamp = voting_timestamp[2]; 915 916 let dateDiff = Date.now() - timestamp; 917 let timeDiffToAccept = 1000 * 60 * 5; //5 minutes 918 919 if(keyword && scrollAmount && dateDiff < timeDiffToAccept) { 920 // this.searchinput.value = keyword; 921 922 // this.setLoadingState('on'); 923 924 925 } 926 927 } 928 929} 930 931}
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.