1import mwCore from "/js/mw-core/mw-core.js"; 2import "/js/mw-core/mw-core-teaser.js"; 3import "/js/mw-core/mw-core-button.js"; 4 5class mwCoreTeasergroup extends mwCore { 6 // livecycle methods 7 8 beforeFirstRender() { 9 // load swiper async if necessary 10 11 if (this.variant === "slider" || this.variant === "compact" || this.variant === "slider-textbox") { 12 import("/js/mw-core/swiper.js").then((_) => { 13 // load css 14 15 let styles = document.createElement("link"); 16 styles.setAttribute("href", "/css/swiper.css"); 17 styles.setAttribute("rel", "stylesheet"); 18 19 this.shadowRoot.appendChild(styles); 20 21 // set swiper flag 22 23 this._swiperLoaded = true; 24 this._swiperInit = false; 25 26 // rerender layout 27 28 this.reRender(); 29 }); 30 } 31 32 let template; 33 34 // render data 35 36 try { 37 template = this.querySelector(`template[is="component-data"]`); 38 39 if (template) { 40 this._data = JSON.parse(template.content.textContent); 41 42 // remove template from DOM 43 44 template.remove(); 45 } 46 } catch (error) {} 47 48 // render sub component (constants) 49 50 let constants = this.querySelector(`template[is="subcomponent-constants"]`); 51 52 if (constants) { 53 this._CONSTANTS = JSON.parse(constants.content.textContent); 54 55 // remove template from DOM 56 57 constants.remove(); 58 } 59 60 // render sub component style 61 62 let style = this.querySelector(`template[is="subcomponent-style"]`); 63 64 if (style) { 65 this._teaserStyles = style.content.textContent; 66 67 // remove template from DOM 68 69 style.remove(); 70 } 71 } 72 73 updated() { 74 if ( 75 (this.variant === "slider" || this.variant === "compact" || this.variant === "slider-textbox") && 76 this._swiperLoaded && 77 !this._swiperInit 78 ) { 79 let breakpoints = {}; 80 81 if (this.variant === "compact") { 82 breakpoints = { 83 0: { 84 slidesPerView: 1, 85 spaceBetween: 8 86 }, 87 500: { 88 slidesPerView: 2, 89 spaceBetween: 8 90 }, 91 769: { 92 slidesPerView: 3, 93 spaceBetween: 24 94 }, 95 980: { 96 slidesPerView: 4, 97 spaceBetween: 24 98 }, 99 1024: { 100 slidesPerView: 5, 101 spaceBetween: 24 102 } 103 }; 104 } else if (this.variant === "slider-textbox") { 105 breakpoints = { 106 0: { 107 slidesPerView: 1.2, 108 spaceBetween: 16 109 }, 110 769: { 111 slidesPerView: 1.4, 112 spaceBetween: 32 113 }, 114 980: { 115 slidesPerView: 1.2, 116 spaceBetween: 32 117 }, 118 1200: { 119 slidesPerView: 2.2, 120 spaceBetween: 32 121 } 122 }; 123 } else { 124 breakpoints = { 125 0: { 126 slidesPerView: 1.1, 127 spaceBetween: 8 128 }, 129 550: { 130 slidesPerView: 1.8, 131 spaceBetween: 8 132 }, 133 769: { 134 slidesPerView: 2.3, 135 spaceBetween: 32 136 }, 137 980: { 138 slidesPerView: 2.6, 139 spaceBetween: 32 140 }, 141 1024: { 142 slidesPerView: 3.2, 143 spaceBetween: 32 144 } 145 }; 146 } 147 148 if (this.sliderbreakpoints) { 149 // get custom breakpoints (attribute or property) 150 // format px:slidesPerView 151 // example: 768:4 152 153 let customBreakpoints = this.sliderbreakpoints.split("|"); 154 155 breakpoints = {}; 156 157 for (let breakpoint of customBreakpoints) { 158 let pxWidth = parseFloat(breakpoint.split(":")[0]); 159 let spaceBetween = pxWidth >= 769 ? 32 : 8; 160 161 breakpoints[pxWidth] = { 162 slidesPerView: breakpoint.split(":")[1], 163 spaceBetween: spaceBetween 164 }; 165 } 166 } 167 168 this._swiperInstance = new Swiper(this.shadowRoot.querySelector(".swiper-container"), { 169 pagination: { 170 el: this.shadowRoot.querySelector(".swiper-pagination"), 171 clickable: true 172 }, 173 watchOverflow: true, 174 navigation: { 175 nextEl: this.shadowRoot.querySelector(".swiper-button-next"), 176 prevEl: this.shadowRoot.querySelector(".swiper-button-prev") 177 }, 178 breakpoints: breakpoints 179 }); 180 } 181 182 // cache DOM 183 184 this.cacheDOM(); 185 186 // register eventListener 187 188 this.registerEventListener(); 189 } 190 191 static get observedAttributes() { 192 return [ 193 "teaserattributes", 194 "variant", 195 "sliderbreakpoints", 196 "entries", 197 "labelmore", 198 "button", 199 "grouptitle", 200 "grouptext", 201 "noentriesmessage" 202 ]; 203 } 204 205 // css 206 207 styles() { 208 return [ 209 `<link href="/css/styleguide.css" rel="stylesheet">`, 210 ` 211 /*** Global ***/ 212 *:focus-visible { 213 outline: 2px solid black !important; 214 outline-offset: -2px !important; 215 transition: none !important; 216 } 217 * { 218 user-select: none; 219 } 220 a { 221 color: var(--mw-core-color-action-primary); 222 text-decoration: none; 223 } 224 a:hover { 225 text-decoration: underline; 226 } 227 .entry.invisible, 228 mw-core-teaser.invisible { 229 display: none; 230 } 231 .more-button { 232 display: flex; 233 justify-content: center; 234 margin: 20px 0 0 0; 235 } 236 .no-entries-message { 237 color: var(--mw-core-color-state-error); 238 display: table; 239 margin: 0 auto; 240 position: relative; 241 } 242 .no-entries-message p:before { 243 background: var(--mw-core-color-state-error); 244 bottom: 0; 245 content: ""; 246 display: block; 247 left: 0; 248 opacity: 0.1; 249 position: absolute; 250 right: 0; 251 top: 0; 252 z-index: -1; 253 } 254 .no-entries-message p { 255 margin: 0; 256 padding: 8px 16px; 257 text-align: center; 258 } 259 260 /*** Default ***/ 261 262 :host([variant="default"]) .container { 263 display: grid; 264 grid-gap: 16px; 265 grid-template-columns: repeat(1, 1fr); 266 } 267 268 /*** Swiper ***/ 269 270 .container .swiper-container .swiper-slide { 271 height: auto; 272 } 273 .container .swiper-container .swiper-pagination {
274 align-items: flex-end; 275 bottom: auto; 276 display: flex; 277 height: 34px; 278 position: relative; 279 } 280 .container .swiper-container .swiper-pagination.swiper-pagination-lock { 281 display: none; 282 } 283 .container .swiper-container .swiper-pagination-bullet { 284 display: block; 285 height: 10px; 286 margin: 0 10px 0 0 !important; 287 outline: none; 288 width: 10px; 289 } 290 .container .swiper-container .swiper-pagination-bullet-active { 291 background: var(--mw-core-color-action-primary); 292 } 293 .container .swiper-button-disabled { 294 display: none !important; 295 } 296 .container .swiper-button-prev { 297 background: var(--mw-core-color-action-primary); 298 border-top-left-radius: 0; 299 border-bottom-left-radius: 0; 300 color: var(--mw-core-color-body-text-bright); 301 display: none; 302 height: 48px; 303 left: 0; 304 margin-top: -41px; 305 outline: none; 306 transition: 100ms ease background, 100ms ease color; 307 width: 48px; 308 } 309 .container .swiper-button-prev:hover { 310 background: var(--mw-core-color-action-primary-variant); 311 } 312 .container .swiper-button-prev:after { 313 content: ""; 314 } 315 .container .swiper-button-next { 316 background: var(--mw-core-color-action-primary); 317 border-top-right-radius: 0; 318 border-bottom-right-radius: 0; 319 color: var(--mw-core-color-body-text-bright); 320 display: none; 321 height: 48px; 322 margin-top: -41px; 323 outline: none; 324 right: 0; 325 transition: 100ms ease background, 100ms ease color; 326 width: 48px; 327 } 328 .container .swiper-button-next:hover { 329 background: var(--mw-core-color-action-primary-variant); 330 } 331 .container .swiper-button-next:after { 332 content: ""; 333 } 334 335 /*** Slider mit Textbox ***/ 336 337 :host([variant="slider-textbox"]) .groupTitle { 338 margin: 0 0 16px; 339 } 340 :host([variant="slider-textbox"]) .groupText { 341 margin: 25px 0; 342 } 343 :host([variant="slider-textbox"]) .groupButton { 344 margin: 25px 0; 345 } 346 :host([variant="slider-textbox"]) .teaser-container { 347 position: relative; 348 } 349 350 /*** Grid ***/ 351 352 :host([variant="grid"]) .grid-container { 353 margin: 5px 0; 354 } 355 :host([variant="grid"]) .grid-container mw-core-teaser { 356 margin: 5px 0; 357 overflow: hidden; 358 } 359 360 /*** Masonry ***/ 361 362 :host([variant="masonry"]) .entry { 363 margin: 0 0 12px; 364 position: relative; 365 } 366 :host([variant="masonry"]) .entry mw-core-teaser { 367 bottom: 0; 368 left: 0; 369 right: 0; 370 position: absolute; 371 top: 0; 372 } 373 :host([variant="masonry"]) .column1 .entry:nth-child(3n + 1) { 374 padding: 100% 0 0 0; 375 } 376 :host([variant="masonry"]) .column1 .entry:nth-child(3n + 2) { 377 padding: 72% 0 0 0; 378 } 379 :host([variant="masonry"]) .column1 .entry:nth-child(3n + 3) { 380 padding: 137% 0 0 0; 381 } 382 383 :host([variant="masonry"]) .column2 .entry:nth-child(3n + 1) { 384 padding: 137% 0 0 0; 385 } 386 :host([variant="masonry"]) .column2 .entry:nth-child(3n + 2) { 387 padding: 100% 0 0 0; 388 } 389 :host([variant="masonry"]) .column2 .entry:nth-child(3n + 3) { 390 padding: 72% 0 0 0; 391 } 392 393 :host([variant="masonry"]) .column3 .entry:nth-child(3n + 1) { 394 padding: 72% 0 0 0; 395 } 396 :host([variant="masonry"]) .column3 .entry:nth-child(3n + 2) { 397 padding: 137% 0 0 0; 398 } 399 :host([variant="masonry"]) .column3 .entry:nth-child(3n + 3) { 400 padding: 100% 0 0 0; 401 } 402 403 /*** Singleteaser ***/ 404 405 :host([variant="singleteaser"]) mw-core-teaser { 406 margin-bottom: 16px; 407 } 408 409 @media all and (min-width: 500px) { 410 411 /*** Default ***/ 412 413 :host([variant="default"]) .container { 414 grid-template-columns: repeat(2, 1fr); 415 } 416 417 /*** Swiper ***/ 418 419 .container .swiper-button-prev, 420 .container .swiper-button-next { 421 display: flex; 422 } 423 424 /*** Grid ***/ 425 426 :host([variant="grid"]) .grid-container { 427 display: grid; 428 grid-gap: 12px; 429 grid-template-columns: repeat(3, 1fr); 430 grid-template-rows: auto; 431 margin: 12px 0; 432 } 433 :host([variant="grid"]) .grid-container mw-core-teaser { 434 margin: 0; 435 } 436 :host([variant="grid"]) .grid-container mw-core-teaser:nth-child(6n+1) { 437 grid-column: 1 / span 2; 438 grid-row: 1 / span 2; 439 } 440 :host([variant="grid"]) .grid-container mw-core-teaser:nth-child(6n+5) { 441 grid-row: 4 / span 1; 442 } 443 :host([variant="grid"]) .grid-container mw-core-teaser:nth-child(6n) { 444 grid-column: 2 / span 2; 445 grid-row: 3 / span 2; 446 } 447 448 /*** Masonry ***/ 449 450 :host([variant="masonry"]) .masonry { 451 display: grid; 452 grid-gap: 32px; 453 grid-template-columns: repeat(3, 1fr); 454 grid-template-rows: auto; 455 } 456 :host([variant="masonry"]) .entry { 457 margin: 0 0 32px; 458 } 459 460 } 461 462 @media all and (min-width: 769px) { 463 464 /*** Default ***/ 465 466 :host([variant="default"]) .container { 467 grid-gap: 32px; 468 } 469 470 } 471 472 @media all and (min-width: 980px) { 473 474 /*** Default ***/ 475 476 :host([variant="default"]) .container { 477 grid-gap: 16px; 478 grid-template-columns: repeat(3, 1fr); 479 } 480 481 :host([variant="slider-textbox"]) .container { 482 display: flex; 483 } 484 :host([variant="slider-textbox"]) .container .textbox { 485 display: flex; 486 flex: 2; 487 flex-direction: column; 488 margin: 0 32px 0 0; 489 max-width: 368px; 490 } 491 :host([variant="slider-textbox"]) .groupButton { 492 margin: auto 0 34px 0; 493 } 494 :host([variant="slider-textbox"]) .teaser-container { 495 flex: 3; 496 overflow: hidden; 497 position: relative; 498 } 499 500 /*** Singleteaser ***/ 501 502 :host([variant="singleteaser"]) mw-core-teaser { 503 margin-bottom: 32px; 504 } 505 506 @media all and (min-width: 1180px) { 507 508 /*** Default ***/ 509 510 :host([variant="default"]) .container { 511 grid-gap: 32px; 512 } 513 514 } 515 516 } 517 518 ` 519 ]; 520 } 521 522 // render template 523 524 render() { 525 // check data 526 527 if (!this._data && !this.noentriesmessage) { 528 console.error("no valid data"); 529 return ""; 530 } else if (!this._data && this.noentriesmessage) { 531 return `<div class="no-entries-message normal-text"><p>${this.noentriesmessage}</p></div>`; 532 } 533 534 if (!this.variant) { 535 this.variant = "default"; 536 } 537 538 // detect layout 539 540 switch (this.variant) { 541 case "slider": 542 return this.layoutSlider(); 543 544 case "slider-textbox": 545 return this.layoutSliderTextbox(); 546 547 case "grid": 548 return this.layoutGrid(); 549 550 case "masonry": 551 return this.layoutMasonry(); 552 553 case "compact": 554 return this.layoutCompact(); 555 556 default: 557 return this.layoutDefault(); 558 } 559 } 560 561 // getter and setter 562 563 get teaserattributes() { 564 return this._getAttribute("teaserattributes"); 565 } 566 567 set teaserattributes(val) { 568 this._setAttribute("teaserattributes", val); 569 } 570 571 get variant() { 572 return this._getAttribute("variant"); 573 } 574 575 set variant(val) { 576 this._setAttribute("variant", val); 577 } 578 579 get sliderbreakpoints() { 580 return this._getAttribute("sliderbreakpoints"); 581 } 582 583 set sliderbreakpoints(val) { 584 this._setAttribute("sliderbreakpoints", val); 585 } 586 587 get entries() { 588 return this._getAttribute("entries"); 589 } 590 591 set entries(val) { 592 this._setAttribute("entries", val); 593 } 594 595 get labelmore() { 596 return this._getAttribute("labelmore"); 597 } 598 599 set labelmore(val) { 600 this._setAttribute("labelmore", val); 601 } 602 603 get button() { 604 return this._getAttribute("button"); 605 } 606 607 set button(val) { 608 this._setAttribute("button", val); 609 } 610 611 get grouptitle() { 612 return this._getAttribute("grouptitle"); 613 } 614 615 set grouptitle(val) { 616 this._setAttribute("grouptitle", val); 617 } 618 619 get grouptext() { 620 return this._getAttribute("grouptext"); 621 } 622 623 set grouptext(val) { 624 this._setAttribute("grouptext", val); 625 } 626 627 get noentriesmessage() { 628 return this._getAttribute("noentriesmessage"); 629 } 630 631 set noentriesmessage(val) { 632 this._setAttribute("noentriesmessage", val); 633 } 634 635 // custom methods 636 637 cacheDOM() { 638 // cache dom elements for faster access 639 640 this._dom = { 641 morebutton: this.shadowRoot.querySelector("mw-core-button.more"), 642 teaser: this.shadowRoot.querySelectorAll("mw-core-teaser") 643 }; 644 } 645 646 registerEventListener() { 647 // load further teaser 648 649 if (this._dom.morebutton) { 650 this._dom.morebutton.addEventListener("click", () => { 651 this.showMoreEntries(); 652 }); 653 } 654 655 } 656 657 htmlItem(data, css) { 658 // returns single teaser 659 660 return ` 661 <mw-core-teaser ${this.teaserattributes ? this.teaserattributes : ``} ${css ? `class="${css}"` : ``}> 662 <template is="component-data"> 663 <script type="application/json"> 664 ${JSON.stringify(data)} 665 </script> 666 </template> 667 ${ 668 this._CONSTANTS 669 ? ` 670 <template is="component-constants"> 671 <script type="application/json"> 672 ${JSON.stringify(this._CONSTANTS)} 673 </script> 674 </template> 675 ` 676 : "" 677 } 678 ${ 679 this._teaserStyles 680 ? ` 681 <template is="component-style"> 682 <style> 683 ${this._teaserStyles} 684 </style> 685 </template> 686 ` 687 : "" 688 } 689 </mw-core-teaser> 690 `; 691 } 692 693 layoutDefault() { 694 let teaserEntries = ``; 695 696 // items 697 698 this._itemCounter = 0; 699 700 let counter = 0; 701 702 for (let item of this._data.items) { 703 // check counter 704 705 if (this.entries && this._itemCounter >= parseInt(this.entries)) { 706 teaserEntries += this.htmlItem(item, `invisible item${counter + 1}`); 707 } else { 708 teaserEntries += this.htmlItem(item, `item${counter + 1}`); 709 this._itemCounter++; 710 } 711 712 counter++; 713 } 714 715 return ` 716 717 <div class="container"> 718 ${teaserEntries} 719 </div> 720 721 ${ 722 this.entries && parseInt(this.entries) && this._data.items.length > this._itemCounter 723 ? ` 724 <div class="more-button "> 725 <mw-core-button class="more" secondary label="${this.labelmore}"></mw-core-button> 726 </div> 727 ` 728 : "" 729 } 730 731 `; 732 } 733 734 layoutSlider() { 735 // if swiper not loaded -> return placeholder 736 737 if (!this._swiperLoaded) { 738 return; 739 } 740 741 let teaserEntries = ``; 742 743 // items 744 745 this._itemCounter = 0; 746 747 for (let item of this._data.items) { 748 teaserEntries += this.htmlItem(item, `swiper-slide item${this._itemCounter + 1}`); 749 750 this._itemCounter++; 751 } 752 753 // swiper layout 754 755 return ` 756 <div class="container"> 757 <div class="teaser-container"> 758 <div class="swiper-container"> 759 <div class="swiper-wrapper"> 760 ${teaserEntries} 761 </div> 762 <div class="swiper-pagination"></div> 763 </div> 764 <div class="swiper-button-prev effect-border-radius"> 765 <mw-core-icon size="m" name="2"></mw-core-icon> 766 </div> 767 <div class="swiper-button-next effect-border-radius"> 768 <mw-core-icon size="m" name="3"></mw-core-icon> 769 </div>
770 </div> 771 </div> 772 `; 773 } 774 775 layoutSliderTextbox() { 776 // if swiper not loaded -> return placeholder 777 778 if (!this._swiperLoaded) { 779 return; 780 } 781 782 let teaserEntries = ``; 783 784 // items 785 786 this._itemCounter = 0; 787 788 for (let item of this._data.items) { 789 teaserEntries += this.htmlItem(item, `swiper-slide item${this._itemCounter + 1}`); 790 791 this._itemCounter++; 792 } 793 794 // button 795 796 let button = ``; 797 798 if (this.button) { 799 try { 800 let label = this.button.split(",")[0]; 801 let link = this.button.split(",")[1]; 802 let target = this.button.split(",")[2]; 803 804 if (!link) { 805 link = `#`; 806 } 807 808 if (!target) { 809 target = ``; 810 } else { 811 target = `target="${target}"`; 812 } 813 814 button = ` 815 <div class="groupButton"> 816 <a href="${link}" ${target}> 817 <mw-core-button secondary label="${label}"></mw-core-button> 818 </a> 819 </div> 820 `; 821 } catch (error) {} 822 } 823 824 // set text 825 826 let textContent = ``; 827 828 if ((this.grouptitle && this.grouptitle !== true) || (this.grouptext && this.grouptext !== true)) { 829 textContent = ` 830 <div class="textbox"> 831 ${this.grouptitle && this.grouptitle !== true ? `<p class="groupTitle headline3">${this.grouptitle}</p>` : ``} 832 ${this.grouptext && this.grouptext !== true ? `<div class="groupText normal-text">${this.grouptext}</div>` : ``} 833 ${button} 834 </div> 835 `; 836 } 837 838 // swiper layout 839 840 return ` 841 <div class="container"> 842 ${textContent} 843 <div class="teaser-container"> 844 <div class="swiper-container"> 845 <div class="swiper-wrapper"> 846 ${teaserEntries} 847 </div> 848 <div class="swiper-pagination"></div> 849 </div> 850 <div class="swiper-button-prev effect-border-radius"> 851 <mw-core-icon size="m" name="2"></mw-core-icon> 852 </div> 853 <div class="swiper-button-next effect-border-radius"> 854 <mw-core-icon size="m" name="3"></mw-core-icon> 855 </div> 856 </div> 857 </div> 858 `; 859 } 860 861 layoutGrid() { 862 let gridRowArr = []; 863 let teaserEntries = ``; 864 865 // items 866 867 this._itemCounter = 0; 868 let counter = 0; 869 870 for (let item of this._data.items) { 871 // insert teaser in grid 872 // create arr every 6 entries 873 874 // create arr if arr not exists 875 876 if (!gridRowArr[Math.floor(counter / 6)]) { 877 gridRowArr[Math.floor(counter / 6)] = []; 878 } 879 880 // append json to arr 881 882 gridRowArr[Math.floor(counter / 6)][counter % 6] = item; 883 884 counter++; 885 } 886 887 // create grid and its entries 888 889 counter = 0; 890 891 for (let row of gridRowArr) { 892 teaserEntries += `<div class="grid-container">`; 893 894 for (let item of row) { 895 if (this.entries && this._itemCounter >= parseInt(this.entries)) { 896 teaserEntries += this.htmlItem(item, `invisible item${counter + 1}`); 897 } else { 898 teaserEntries += this.htmlItem(item, `item${counter + 1}`); 899 this._itemCounter++; 900 } 901 902 counter++; 903 } 904 905 teaserEntries += `</div>`; 906 } 907 908 return ` 909 910 <div class="container"> 911 ${teaserEntries} 912 </div> 913 914 ${ 915 this.entries && parseInt(this.entries) && this._data.items.length > this._itemCounter 916 ? ` 917 <div class="more-button "> 918 <mw-core-button class="more" secondary label="${this.labelmore}"></mw-core-button> 919 </div> 920 ` 921 : "" 922 } 923 924 `; 925 } 926 927 layoutMasonry() { 928 let teaserColumn1 = []; 929 let teaserColumn2 = []; 930 let teaserColumn3 = []; 931 932 // items 933 934 this._itemCounter = 0; 935 let counter = 0; 936 937 for (let item of this._data.items) { 938 // insert teaser in masonry 939 940 switch (counter % 3) { 941 case 0: 942 teaserColumn1.push({ content: item, counter: counter }); 943 break; 944 945 case 1: 946 teaserColumn2.push({ content: item, counter: counter }); 947 break; 948 949 case 2: 950 teaserColumn3.push({ content: item, counter: counter }); 951 break; 952 } 953 954 counter++; 955 } 956 957 // create masonry and its entries 958 959 let teaserColumn1HTML = ``; 960 961 for (let item of teaserColumn1) { 962 if (this.entries && item.counter >= parseInt(this.entries)) { 963 teaserColumn1HTML += ` 964 <div class="entry invisible item${item.counter + 1}">${this.htmlItem(item.content)}</div> 965 `; 966 } else { 967 teaserColumn1HTML += ` 968 <div class="entry item${item.counter + 1}">${this.htmlItem(item.content)}</div> 969 `; 970 this._itemCounter++; 971 } 972 } 973
974 let teaserColumn2HTML = ``; 975 976 for (let item of teaserColumn2) { 977 if (this.entries && item.counter >= parseInt(this.entries)) { 978 teaserColumn2HTML += ` 979 <div class="entry invisible item${item.counter + 1}">${this.htmlItem(item.content)}</div> 980 `; 981 } else { 982 teaserColumn2HTML += ` 983 <div class="entry item${item.counter + 1}">${this.htmlItem(item.content)}</div> 984 `; 985 this._itemCounter++; 986 } 987 } 988 989 let teaserColumn3HTML = ``; 990 991 for (let item of teaserColumn3) { 992 if (this.entries && item.counter >= parseInt(this.entries)) { 993 teaserColumn3HTML += ` 994 <div class="entry invisible item${item.counter + 1}">${this.htmlItem(item.content)}</div> 995 `; 996 } else { 997 teaserColumn3HTML += ` 998 <div class="entry item${item.counter + 1}">${this.htmlItem(item.content)}</div> 999 `; 1000 this._itemCounter++; 1001 } 1002 } 1003 1004 // masonry layout 1005 1006 return ` 1007 <div class="container"> 1008 1009 <div class="masonry"> 1010 <div class="column1">${teaserColumn1HTML}</div> 1011 <div class="column2">${teaserColumn2HTML}</div> 1012 <div class="column3">${teaserColumn3HTML}</div> 1013 </div> 1014 1015 </div> 1016 1017 ${ 1018 this.entries && parseInt(this.entries) && this._data.items.length > this._itemCounter 1019 ? ` 1020 <div class="more-button "> 1021 <mw-core-button class="more" secondary label="${this.labelmore}"></mw-core-button> 1022 </div> 1023 ` 1024 : "" 1025 } 1026 1027 `; 1028 } 1029 1030 layoutCompact() { 1031 // if swiper not loaded -> return placeholder 1032 1033 if (!this._swiperLoaded) { 1034 return; 1035 } 1036 1037 let teaserEntries = ``; 1038 1039 // items 1040 1041 this._itemCounter = 0; 1042 1043 for (let item of this._data.items) { 1044 teaserEntries += this.htmlItem(item, `swiper-slide item${this._itemCounter + 1}`); 1045 1046 this._itemCounter++; 1047 } 1048 1049 // swiper layout 1050 1051 return ` 1052 <div class="container"> 1053 <div class="teaser-container"> 1054 <div class="swiper-container"> 1055 <div class="swiper-wrapper"> 1056 ${teaserEntries} 1057 </div> 1058 <div class="swiper-pagination"></div> 1059 </div> 1060 <div class="swiper-button-prev effect-border-radius"> 1061 <mw-core-icon size="m" name="2"></mw-core-icon> 1062 </div> 1063 <div class="swiper-button-next effect-border-radius"> 1064 <mw-core-icon size="m" name="3"></mw-core-icon> 1065 </div> 1066 </div> 1067 </div> 1068 `; 1069 } 1070 1071 showMoreEntries() { 1072 // show more entries 1073 1074 let start = this._itemCounter + 1; 1075 1076 for (let i = start; i < start + parseInt(this.entries); i++) { 1077 // in masonry use div.entry 1078 // else use mw-core-teaser 1079 1080 let $nextTeaser; 1081 1082 if (this.variant === "masonry") { 1083 $nextTeaser = this.shadowRoot.querySelectorAll(`.entry.item${i}`); 1084 } else { 1085 $nextTeaser = this.shadowRoot.querySelectorAll(`mw-core-teaser.item${i}`); 1086 } 1087 1088 if ($nextTeaser.length === 1) { 1089 $nextTeaser[0].classList.remove("invisible"); 1090 this._itemCounter++; 1091 } else { 1092 break; 1093 } 1094 } 1095 1096 if (this._itemCounter >= this._data.items.length) { 1097 this._dom.morebutton.remove(); 1098 } 1099 } 1100} 1101 1102customElements.define("mw-core-teasergroup", mwCoreTeasergroup);
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.