PageSourceSearch

https://ssupl.com/data/skin/front/19-07_C/js/bnn_featured_brands.js?

js ssupl.com collected 2026-10-09 23:37:42 UTC 28,083 bytes, 929 lines download raw bytes

1(function (window, document) {
2    'use strict';
3
4    var ROOT_ID = 'ssupl-featured-brands';
5    var MENU_ROOT_ID = 'ssupl-featured-brands-menu';
6    var STYLE_ID = 'ssupl-featured-brands-style';
7    var MOBILE_BREAKPOINT = 767;
8
9    /* 브랜드 추가·삭제·수정 */
10    var BRANDS = [
11		{
12            name: 'GR',
13            href: '/goods/goods_list.php?brandCd=535',
14            image: 'https://yellowcorn.dothome.co.kr/gr/main_page_intro02.webp',
15            imageAlt: 'GR',
16            logo: 'https://ssupl01.hgodo.com/img_new/goods/editor/260728/3894fcb836fc3fb9c1517d25ec68232f_231043.jpg',
17            logoAlt: 'GR',
18            description: '라이딩을 위한 프리미엄 스마트폰 마운트'
19        },
20        {
21            name: 'R&G RACING',
22            href: '/goods/goods_list.php?cateCd=177',
23            image: 'https://ssupl01.hgodo.com/img/etc/4/a1.jpg',
24            imageAlt: 'R&G Racing',
25            logo: '/data/skin/front/19-07_C/img/etc/e/a_01.jpg',
26            logoAlt: 'R&G',
27            description: '레이스를 통해 증명된 프로텍션 파츠'
28        },
29        {
30            name: 'DAYTONA',
31            href: '/goods/goods_list.php?cateCd=008477002',
32            image: 'https://ssupl01.hgodo.com/img_new/goods/editor/260319/b10baf9148885177a6278625911a9481_022517.jpg',
33            imageAlt: 'DAYTONA',
34            logo: 'https://ssupl01.hgodo.com/img/etc/main/daytona.jpg',
35            logoAlt: 'DAYTONA',
36            description: '라이더를 위한 정밀한 일본 엔지니어링'
37        },
38        {
39            name: 'HENLYBEGINS',
40            href: '/goods/goods_list.php?cateCd=008285',
41            image: 'https://ssupl01.hgodo.com/img_new/goods/editor/250929/5f93b8bc2854aae04aebebb5fe1a569c_224043.jpg',
42            imageAlt: 'HENLYBEGINS',
43            logo: 'https://ssupl01.hgodo.com/img_new/goods/editor/240706/henlybegins_011551.jpg',
44            logoAlt: 'HENLYBEGINS',
45            description: '라이딩을 보다 편리하고 안락하게'
46        },
47        {
48            name: 'SUPERFLY',
49            href: '/goods/goods_list.php?cateCd=008481',
50            image: 'https://ssupl01.hgodo.com/img/etc/4/a4.jpg',
51            imageAlt: 'SUPERFLY',
52            logo: 'https://ssupl01.hgodo.com/img/etc/main/superfly.jpg',
53            logoAlt: 'SUPERFLY',
54            description: '주행의 차이를 만드는 퍼포먼스 서스펜션'
55        },
56        {
57            name: 'OUTPLORER',
58            href: '/goods/goods_list.php?brandCd=523',
59            image: 'https://ssupl01.hgodo.com/img_new/goods/editor/260107/7f024c106a4e4b0a2994446efe34f69e_180903.gif',
60            imageAlt: 'OUTPLORER',
61            logo: 'https://ssupl01.hgodo.com/img_new/goods/editor/260113/693a9fdd4c2fd0700968fba0d07ff3c0_153919.jpg',
62            logoAlt: 'OUTPLORER',
63            description: '진동 테스트를 통과한 프리미엄 거치대'
64        },
65        {
66            name: 'CHIGEE',
67            href: '/goods/goods_list.php?brandCd=522',
68            image: 'https://ssupl01.hgodo.com/img_new/goods/editor/251209/107f7cadaa6f7ee29fd4ec40fa6317ee_151242.jpg',
69            imageAlt: 'CHIGEE',
70            logo: 'https://ssupl01.hgodo.com/img_new/goods/editor/251212/eece516d8f07cee997168194f850a324_043552.jpg',
71            logoAlt: 'CHIGEE',
72            description: '라이딩을 더 스마트하게 만드는 카플레이'
73        }
74    ];
75
76    function pad(number) {
77        return number < 10 ? '0' + number : String(number);
78    }
79
80    function escapeHtml(value) {
81        return String(value)
82            .replace(/&/g, '&amp;')
83            .replace(/</g, '&lt;')
84            .replace(/>/g, '&gt;')
85            .replace(/"/g, '&quot;')
86            .replace(/'/g, '&#039;');
87    }
88
89    function shuffleBrands(items) {
90        var shuffled = items.slice();
91
92        for (var i = shuffled.length - 1; i > 0; i--) {
93            var randomIndex =
94                Math.floor(Math.random() * (i + 1));
95
96            var temporary =
97                shuffled[i];
98
99            shuffled[i] =
100                shuffled[randomIndex];
101
102            shuffled[randomIndex] =
103                temporary;
104        }
105
106        return shuffled;
107    }
108
109    function addStyle() {
110        if (document.getElementById(STYLE_ID)) {
111            return;
112        }
113
114        var style =
115            document.createElement('style');
116
117        style.id =
118            STYLE_ID;
119
120        style.textContent = [
121            '#' + ROOT_ID + ',',
122            '#' + ROOT_ID + ' *{',
123                'box-sizing:border-box;',
124            '}',
125
126            '#' + ROOT_ID + '{',
127                'position:relative;',
128                'width:100%;',
129                'margin:0;',
130                'padding:70px 0 76px;',
131                'overflow:hidden;',
132                'background:#fff;',
133                'color:#111;',
134                'font-family:-apple-system,BlinkMacSystemFont,"Pretendard","Noto Sans KR","Apple SD Gothic Neo",Arial,sans-serif;',
135            '}',
136
137            '#' + ROOT_ID + ' a{',
138                'color:inherit;',
139                'text-decoration:none;',
140            '}',
141
142            '#' + ROOT_ID + ' button{',
143                'font-family:inherit;',
144            '}',
145
146            /* PC 좌우 패딩 없음 */
147            '#' + ROOT_ID + ' .sfb-inner{',
148                'position:relative;',
149                'width:100%;',
150                'max-width:1200px;',
151                'margin:0 auto;',
152                'padding:0;',
153            '}',
154
155            '#' + ROOT_ID + ' .sfb-head{',
156                'display:flex;',
157                'align-items:flex-end;',
158                'justify-content:space-between;',
159                'margin-bottom:24px;',
160            '}',
161
162            '#' + ROOT_ID + ' .sfb-head h2{',
163                'margin:0;',
164                'color:#111;',
165                'font-size:25px;',
166                'font-weight:800;',
167                'line-height:1.2;',
168                'letter-spacing:-.5px;',
169            '}',
170
171            '#' + ROOT_ID + ' .sfb-head p{',
172                'margin:8px 0 0;',
173                'color:#999;',
174                'font-size:13px;',
175                'line-height:1.5;',
176            '}',
177
178            '#' + ROOT_ID + ' .sfb-count{',
179                'flex:none;',
180                'margin:0 2px 2px 20px;',
181                'color:#aaa;',
182                'font-size:12px;',
183                'line-height:1;',
184            '}',
185
186            '#' + ROOT_ID + ' .sfb-current{',
187                'color:#111;',
188                'font-weight:800;',
189            '}',
190
191            '#' + ROOT_ID + ' .sfb-stage{',
192                'position:relative;',
193            '}',
194
195            '#' + ROOT_ID + ' .sfb-viewport{',
196                'width:100%;',
197                'overflow:hidden;',
198                'touch-action:pan-y;',
199            '}',
200
201            '#' + ROOT_ID + ' .sfb-track{',
202                'display:flex;',
203                'align-items:stretch;',
204                'margin:0;',
205                'padding:0;',
206                'transform:translate3d(0,0,0);',
207                'transition:transform .45s cubic-bezier(.22,.61,.36,1);',
208                'will-change:transform;',
209            '}',
210
211            '#' + ROOT_ID + ' .sfb-card{',
212                'display:block;',
213                'position:relative;',
214                'flex:0 0 auto;',
215                'min-width:0;',
216                'aspect-ratio:4/3;',
217                'overflow:hidden;',
218                'border:0;',
219                'background:#111;',
220                'isolation:isolate;',
221            '}',
222
223            '#' + ROOT_ID + ' .sfb-image{',
224                'position:absolute;',
225                'inset:0;',
226                'z-index:-3;',
227                'width:100%;',
228                'height:100%;',
229                'overflow:hidden;',
230                'background:#111;',
231            '}',
232
233            '#' + ROOT_ID + ' .sfb-image img{',
234                'display:block;',
235                'width:100%;',
236                'height:100%;',
237                'object-fit:cover;',
238                'transition:transform .45s ease;',
239            '}',
240
241            '#' + ROOT_ID + ' .sfb-card:hover .sfb-image img{',
242                'transform:scale(1.035);',
243            '}',
244
245            '#' + ROOT_ID + ' .sfb-card:before{',
246                'content:"";',
247                'position:absolute;',
248                'inset:0;',
249                'z-index:-2;',
250                'background:linear-gradient(180deg,rgba(0,0,0,0) 30%,rgba(0,0,0,.12) 48%,rgba(0,0,0,.88) 100%);',
251            '}',
252
253            '#' + ROOT_ID + ' .sfb-card:after{',
254                'content:"";',
255                'position:absolute;',
256                'inset:0;',
257                'z-index:-1;',
258                'background:linear-gradient(90deg,rgba(0,0,0,.25),rgba(0,0,0,0) 65%);',
259            '}',
260
261            '#' + ROOT_ID + ' .sfb-copy{',
262                'position:absolute;',
263                'right:0;',
264                'bottom:0;',
265                'left:0;',
266                'z-index:2;',
267                'width:100%;',
268                'padding:24px;',
269                'color:#fff;',
270            '}',
271
272            '#' + ROOT_ID + ' .sfb-logo{',
273                'display:inline-flex;',
274                'align-items:center;',
275                'width:auto;',
276                'height:30px;',
277                'margin:0 0 13px;',
278                'padding:5px 9px;',
279                'background:#fff;',
280            '}',
281
282            '#' + ROOT_ID + ' .sfb-logo img{',
283                'display:block;',
284                'width:auto;',
285                'max-width:110px;',
286                'height:auto;',
287                'max-height:20px;',
288                'object-fit:contain;',
289            '}',
290
291            '#' + ROOT_ID + ' .sfb-copy h3{',
292                'margin:0;',
293                'color:#fff;',
294                'font-size:18px;',
295                'font-weight:750;',
296                'line-height:1.4;',
297                'letter-spacing:-.45px;',
298                'word-break:keep-all;',
299                'text-shadow:0 2px 8px rgba(0,0,0,.4);',
300            '}',
301
302            '#' + ROOT_ID + ' .sfb-brand-link{',
303                'display:flex;',
304                'align-items:center;',
305                'justify-content:space-between;',
306                'margin-top:14px;',
307                'color:rgba(255,255,255,.78);',
308                'font-size:12px;',
309                'font-weight:600;',
310                'line-height:1;',
311            '}',
312
313            '#' + ROOT_ID + ' .sfb-brand-link b{',
314                'margin-left:auto;',
315                'color:#fff;',
316                'font-size:16px;',
317                'font-weight:400;',
318            '}',
319
320            '#' + ROOT_ID + ' .sfb-arrow{',
321                'display:flex;',
322                'align-items:center;',
323                'justify-content:center;',
324                'position:absolute;',
325                'top:50%;',
326                'z-index:5;',
327                'width:42px;',
328                'height:42px;',
329                'margin:0;',
330                'padding:0;',
331                'border:1px solid #ddd;',
332                'border-radius:50%;',
333                'background:rgba(255,255,255,.96);',
334                'color:#222;',
335                'font-size:24px;',
336                'line-height:1;',
337                'box-shadow:0 4px 14px rgba(0,0,0,.14);',
338                'transform:translateY(-50%);',
339                'cursor:pointer;',
340            '}',
341
342            '#' + ROOT_ID + ' .sfb-prev{',
343                'left:10px;',
344            '}',
345
346            '#' + ROOT_ID + ' .sfb-next{',
347                'right:10px;',
348            '}',
349
350            '#' + ROOT_ID + ' .sfb-arrow:disabled{',
351                'opacity:.3;',
352                'cursor:default;',
353            '}',
354
355            '#' + ROOT_ID + ' .sfb-progress{',
356                'position:relative;',
357                'width:100%;',
358                'height:2px;',
359                'margin-top:26px;',
360                'overflow:hidden;',
361                'background:#e8e8e8;',
362            '}',
363
364            '#' + ROOT_ID + ' .sfb-progress-bar{',
365                'display:block;',
366                'width:0;',
367                'height:100%;',
368                'background:#111;',
369                'transition:width .35s ease;',
370            '}',
371
372            /* 햄버거 메뉴 랜덤 배너 */
373            '#' + MENU_ROOT_ID + ',',
374            '#' + MENU_ROOT_ID + ' *{',
375                'box-sizing:border-box;',
376            '}',
377
378            '#' + MENU_ROOT_ID + '{',
379                'width:100%;',
380                'margin:0;',
381                'font-family:-apple-system,BlinkMacSystemFont,"Pretendard","Noto Sans KR","Apple SD Gothic Neo",Arial,sans-serif;',
382            '}',
383
384            '#' + MENU_ROOT_ID + ' a{',
385                'color:inherit;',
386                'text-decoration:none;',
387            '}',
388
389            '#' + MENU_ROOT_ID + ' .sfb-menu-card{',
390                    'display:block;',
391					'position:relative;',
392					'width:100%;',
393					'height:120px;',
394					'overflow:hidden;',
395					'background:#111;',
396					'isolation:isolate;',
397            '}',
398
399            '#' + MENU_ROOT_ID + ' .sfb-menu-image{',
400                'position:absolute;',
401                'inset:0;',
402                'z-index:-3;',
403                'width:100%;',
404                'height:100%;',
405            '}',
406
407            '#' + MENU_ROOT_ID + ' .sfb-menu-image img{',
408                'display:block;',
409                'width:100%;',
410                'height:100%;',
411                'object-fit:cover;',
412            '}',
413
414            '#' + MENU_ROOT_ID + ' .sfb-menu-card:before{',
415                'content:"";',
416                'position:absolute;',
417                'inset:0;',
418                'z-index:-2;',
419                'background:linear-gradient(180deg,rgba(0,0,0,.05) 15%,rgba(0,0,0,.85) 100%);',
420            '}',
421
422            '#' + MENU_ROOT_ID + ' .sfb-menu-card:after{',
423                'content:"";',
424                'position:absolute;',
425                'inset:0;',
426                'z-index:-1;',
427                'background:linear-gradient(90deg,rgba(0,0,0,.38),rgba(0,0,0,0) 75%);',
428            '}',
429
430            '#' + MENU_ROOT_ID + ' .sfb-menu-copy{',
431                'position:absolute;',
432				'right:0;',
433				'bottom:0;',
434				'left:0;',
435				'z-index:2;',
436				'padding:15px 16px;',
437				'color:#fff;',
438            '}',
439
440            '#' + MENU_ROOT_ID + ' .sfb-menu-label{',
441                'display:block;',
442                'margin-bottom:9px;',
443                'color:#dd3d42;',
444                'font-size:10px;',
445                'font-weight:800;',
446                'line-height:1;',
447                'letter-spacing:1.2px;',
448            '}',
449
450            '#' + MENU_ROOT_ID + ' .sfb-menu-copy h3{',
451                'margin:0;',
452                'color:#fff;',
453                'font-size:18px;',
454                'font-weight:800;',
455                'line-height:1.35;',
456                'letter-spacing:-.5px;',
457                'word-break:keep-all;',
458                'text-shadow:0 2px 8px rgba(0,0,0,.4);',
459            '}',
460
461            '#' + MENU_ROOT_ID + ' .sfb-menu-link{',
462                'display:flex;',
463                'align-items:center;',
464                'justify-content:space-between;',
465                'margin-top:13px;',
466                'color:rgba(255,255,255,.8);',
467                'font-size:11px;',
468                'font-weight:600;',
469                'line-height:1;',
470            '}',
471
472            '#' + MENU_ROOT_ID + ' .sfb-menu-link b{',
473                'color:#fff;',
474                'font-size:17px;',
475                'font-weight:400;',
476            '}',
477
478            /* 모바일 16px */
479            '@media screen and (max-width:767px){',
480
481                '#' + ROOT_ID + '{',
482                    'padding:42px 0 50px;',
483                '}',
484
485                '#' + ROOT_ID + ' .sfb-inner{',
486                    'padding:0 16px;',
487                '}',
488
489                '#' + ROOT_ID + ' .sfb-head{',
490                    'margin-bottom:18px;',
491                '}',
492
493                '#' + ROOT_ID + ' .sfb-head h2{',
494                    'font-size:21px;',
495                '}',
496
497                '#' + ROOT_ID + ' .sfb-head p{',
498                    'margin-top:6px;',
499                    'font-size:12px;',
500                '}',
501
502                '#' + ROOT_ID + ' .sfb-count{',
503                    'font-size:11px;',
504                '}',
505
506                '#' + ROOT_ID + ' .sfb-copy{',
507                    'padding:20px 18px;',
508                '}',
509
510                '#' + ROOT_ID + ' .sfb-logo{',
511                    'height:28px;',
512                    'margin-bottom:11px;',
513                    'padding:4px 8px;',
514                '}',
515
516                '#' + ROOT_ID + ' .sfb-logo img{',
517                    'max-width:100px;',
518                    'max-height:18px;',
519                '}',
520
521                '#' + ROOT_ID + ' .sfb-copy h3{',
522                    'font-size:17px;',
523                '}',
524
525                '#' + ROOT_ID + ' .sfb-brand-link{',
526                    'margin-top:12px;',
527                    'font-size:11px;',
528                '}',
529
530                '#' + ROOT_ID + ' .sfb-arrow{',
531                    'display:none;',
532                '}',
533
534                '#' + ROOT_ID + ' .sfb-progress{',
535                    'margin-top:20px;',
536                '}',
537
538            '}',
539
540            /* 작은 모바일 12px */
541            '@media screen and (max-width:359px){',
542
543                '#' + ROOT_ID + ' .sfb-inner{',
544                    'padding:0 12px;',
545                '}',
546
547                '#' + ROOT_ID + ' .sfb-head h2{',
548                    'font-size:19px;',
549                '}',
550
551                '#' + ROOT_ID + ' .sfb-copy{',
552                    'padding:17px 15px;',
553                '}',
554
555                '#' + ROOT_ID + ' .sfb-copy h3{',
556                    'font-size:16px;',
557                '}',
558
559            '}'
560        ].join('');
561
562        document.head.appendChild(style);
563    }
564
565    function createCard(brand) {
566        return [
567            '<a href="',
568            escapeHtml(brand.href),
569            '" class="sfb-card">',
570
571                '<div class="sfb-image">',
572                    '<img src="',
573                    escapeHtml(brand.image),
574                    '" alt="',
575                    escapeHtml(brand.imageAlt),
576                    '" loading="lazy" draggable="false">',
577                '</div>',
578
579                '<div class="sfb-copy">',
580
581                    '<div class="sfb-logo">',
582                        '<img src="',
583                        escapeHtml(brand.logo),
584                        '" alt="',
585                        escapeHtml(brand.logoAlt),
586                        '" loading="lazy" draggable="false">',
587                    '</div>',
588
589                    '<h3>',
590                        escapeHtml(brand.description),
591                    '</h3>',
592
593                    '<span class="sfb-brand-link">',
594                        escapeHtml(brand.name),
595                        '<b>→</b>',
596                    '</span>',
597
598                '</div>',
599
600            '</a>'
601        ].join('');
602    }
603
604    function renderMenuBanner() {
605        var menuRoot =
606            document.getElementById(MENU_ROOT_ID);
607
608        if (
609            !menuRoot ||
610            menuRoot.getAttribute('data-ready') === 'true'
611        ) {
612            return;
613        }
614
615        var randomIndex =
616            Math.floor(Math.random() * BRANDS.length);
617
618        var brand =
619            BRANDS[randomIndex];
620
621        menuRoot.setAttribute(
622            'data-ready',
623            'true'
624        );
625
626        menuRoot.innerHTML = [
627            '<a href="',
628            escapeHtml(brand.href),
629            '" class="sfb-menu-card">',
630
631                '<div class="sfb-menu-image">',
632                    '<img src="',
633                    escapeHtml(brand.image),
634                    '" alt="',
635                    escapeHtml(brand.imageAlt),
636                    '" loading="lazy" draggable="false">',
637                '</div>',
638
639                '<div class="sfb-menu-copy">',
640
641                   
642
643                    '<h3>',
644                        escapeHtml(brand.description),
645                    '</h3>',
646
647                    '<span class="sfb-menu-link">',
648                        escapeHtml(brand.name),
649                        '<b>→</b>',
650                    '</span>',
651
652                '</div>',
653
654            '</a>'
655        ].join('');
656    }
657
658    function renderMainSlider(root) {
659        var randomizedBrands =
660            shuffleBrands(BRANDS);
661
662        var cards =
663            randomizedBrands
664                .map(createCard)
665                .join('');
666
667        root.innerHTML = [
668            '<div class="sfb-inner">',
669
670                '<div class="sfb-head">',
671
672                    '<div>',
673                        '<h2>FEATURED BRANDS</h2>',
674                        '<p>SSUPL이 엄선한 파츠 브랜드입니다.</p>',
675                    '</div>',
676
677                    '<span class="sfb-count">',
678                        '<b class="sfb-current">01</b>',
679                        ' / ',
680                        '<span class="sfb-total">01</span>',
681                    '</span>',
682
683                '</div>',
684
685                '<div class="sfb-stage">',
686
687                    '<button type="button" class="sfb-arrow sfb-prev" aria-label="이전 브랜드">',
688                        '‹',
689                    '</button>',
690
691                    '<div class="sfb-viewport">',
692                        '<div class="sfb-track">',
693                            cards,
694                        '</div>',
695                    '</div>',
696
697                    '<button type="button" class="sfb-arrow sfb-next" aria-label="다음 브랜드">',
698                        '›',
699                    '</button>',
700
701                '</div>',
702
703                '<div class="sfb-progress" aria-hidden="true">',
704                    '<span class="sfb-progress-bar"></span>',
705                '</div>',
706
707            '</div>'
708        ].join('');
709    }
710
711    function startSlider(root) {
712        var viewport =
713            root.querySelector('.sfb-viewport');
714
715        var track =
716            root.querySelector('.sfb-track');
717
718        var cards =
719            Array.prototype.slice.call(
720                root.querySelectorAll('.sfb-card')
721            );
722
723        var prevButton =
724            root.querySelector('.sfb-prev');
725
726        var nextButton =
727            root.querySelector('.sfb-next');
728
729        var currentText =
730            root.querySelector('.sfb-current');
731
732        var totalText =
733            root.querySelector('.sfb-total');
734
735        var progressBar =
736            root.querySelector('.sfb-progress-bar');
737
738        var currentPage = 0;
739        var perView = 1;
740        var pageCount = 1;
741        var cardWidth = 0;
742        var gap = 14;
743        var resizeTimer = null;
744        var touchStartX = 0;
745        var touchMoveX = 0;
746
747        function update(animated) {
748            var offset =
749                currentPage *
750                perView *
751                (cardWidth + gap);
752
753            track.style.transition =
754                animated === false
755                    ? 'none'
756                    : 'transform .45s cubic-bezier(.22,.61,.36,1)';
757
758            track.style.transform =
759                'translate3d(' + (-offset) + 'px,0,0)';
760
761            currentText.textContent =
762                pad(currentPage + 1);
763
764            totalText.textContent =
765                pad(pageCount);
766
767            progressBar.style.width =
768                (
769                    ((currentPage + 1) / pageCount) *
770                    100
771                ) + '%';
772
773            prevButton.disabled =
774                currentPage === 0;
775
776            nextButton.disabled =
777                currentPage === pageCount - 1;
778        }
779
780        function setup() {
781            perView =
782                window.innerWidth <= MOBILE_BREAKPOINT
783                    ? 1
784                    : 2;
785
786            gap =
787                window.innerWidth <= MOBILE_BREAKPOINT
788                    ? 10
789                    : 14;
790
791            cardWidth =
792                (
793                    viewport.clientWidth -
794                    (gap * (perView - 1))
795                ) / perView;
796
797            pageCount =
798                Math.max(
799                    1,
800                    Math.ceil(cards.length / perView)
801                );
802
803            currentPage =
804                Math.min(
805                    currentPage,
806                    pageCount - 1
807                );
808
809            track.style.gap =
810                gap + 'px';
811
812            cards.forEach(function (card) {
813                card.style.width =
814                    cardWidth + 'px';
815
816                card.style.flexBasis =
817                    cardWidth + 'px';
818            });
819
820            update(false);
821        }
822
823        function goTo(page) {
824            currentPage =
825                Math.max(
826                    0,
827                    Math.min(page, pageCount - 1)
828                );
829
830            update(true);
831        }
832
833        prevButton.onclick = function () {
834            goTo(currentPage - 1);
835        };
836
837        nextButton.onclick = function () {
838            goTo(currentPage + 1);
839        };
840
841        viewport.addEventListener(
842            'touchstart',
843            function (event) {
844                touchStartX =
845                    event.touches[0].clientX;
846
847                touchMoveX =
848                    touchStartX;
849            },
850            {
851                passive: true
852            }
853        );
854
855        viewport.addEventListener(
856            'touchmove',
857            function (event) {
858                touchMoveX =
859                    event.touches[0].clientX;
860            },
861            {
862                passive: true
863            }
864        );
865
866        viewport.addEventListener(
867            'touchend',
868            function () {
869                var distance =
870                    touchMoveX - touchStartX;
871
872                if (distance < -40) {
873                    goTo(currentPage + 1);
874                }
875
876                if (distance > 40) {
877                    goTo(currentPage - 1);
878                }
879            }
880        );
881
882        window.addEventListener(
883            'resize',
884            function () {
885                window.clearTimeout(resizeTimer);
886
887                resizeTimer =
888                    window.setTimeout(
889                        setup,
890                        150
891                    );
892            }
893        );
894
895        setup();
896    }
897
898    function init() {
899        var mainRoot =
900            document.getElementById(ROOT_ID);
901
902        addStyle();
903
904        if (
905            mainRoot &&
906            mainRoot.getAttribute('data-ready') !== 'true'
907        ) {
908            mainRoot.setAttribute(
909                'data-ready',
910                'true'
911            );
912
913            renderMainSlider(mainRoot);
914            startSlider(mainRoot);
915        }
916
917        renderMenuBanner();
918    }
919
920    if (document.readyState === 'loading') {
921        document.addEventListener(
922            'DOMContentLoaded',
923            init
924        );
925    } else {
926        init();
927    }
928
929})(window, document);

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.