PageSourceSearch

https://icm-mhi.org/wp-content/themes/Hamak-starter-theme/assets/js/gsapSlider.js?ver=1.0

js icm-mhi.org collected 2026-10-01 11:51:00 UTC 53,385 bytes, 1,087 lines download raw bytes

1/**
2 * GSAP Slider x Hamak 1.0.0
3 * AUTHORS: Quentin Lequenne & Sounthida Kong
4 * DECLARATION
5 * const slide = new GSapSlider( selector, options)
6 * 
7 * STRUCTURE
8 * .gsap-slider
9 * -- .gsap-wrapper
10 * ---- .gsap-slide
11 * ---- .gsap-slide
12 * ---- ...
13 * 
14 * OPTIONS
15 * option; type; default => fonction
16 * slidesToShow; int; 1 => Slides à afficher
17 * spaceBetweenSlides; int; 0 => Padding horizontal ajouté à chaque slide
18 * sameHeightSlide; bool; false => Ajuste les tailles de slide à la plus haute
19 * speed; float; 0.5 => Vitesse de transition (en secondes)
20 * ease; string; power1.inOut => Type de transition
21 * fade; bool; false => Transition en fondu (une seule slide)
22 * arrows; bool; false => Instancie les flèches
23 * arrowPrev; string; false => Sélecteur de la flèche Précédent (arrows doit être à true)
24 * arrowNext; string; false => Sélecteur de la flèche Suivant (arrows doit être à true)
25 * pauseOnHover; bool; false => Interrompt les animations au hover
26 * swipe; bool; false => Permet de swiper pour passer aux slides précédentes/suivantes
27 * repeat; bool; false => Slider infini si true
28 * center; bool; false => La slide active est centrée
29 * paused; bool; true => Défilement smooth continu si false (Attention: pas un autoplay)
30 * responsive; array; none => Modification d'options aux breakpoints (sauf fade)
31 * autoplay; bool; false => Lecture automatique
32 * duration; int; 4000 => Temps de break en lecture auto (en ms)
33 * locomotiveSpeed; int; 200 => Vitesse de locomotive (en px/s, couplé à paused: false)
34 * delayedContent; bool; false => Applique un délai d'apparition au contenu de la slide ayant la classe "delayed-content"
35 * delayedContentY; int; 0 => Point d'origine du contenu délayé en Y
36 * delayedContentX; int; 0 => Point d'origine du contenu délayé en X
37 * whiteSpace; bool; true => Empêche la mise à la ligne de phrases si false et recalcule leur largeur
38 * 
39 */
40
41
42class GSapSlider {
43
44    ///////////////////////////////////////////////////////////////////////////
45    // VARIABLES
46    ///////////////////////////////////////////////////////////////////////////
47    sliders;
48    sliderConfig;
49    mainConfig;
50    loopConfig;
51    responsiveOptions;
52    responsiveCount;
53    responsiveBreakpoints;
54
55    ///////////////////////////////////////////////////////////////////////////
56    // CONSTRUCTOR
57    ///////////////////////////////////////////////////////////////////////////
58    constructor ( selector, sliderConfig ){
59        this.sliders = $(selector);
60        this.sliderConfig = sliderConfig;
61        this.mainConfig = this.setConfig( 'slide' );
62        this.loopConfig = this.setConfig( 'loop' );
63        this.responsiveOptions = this.sliderConfig.responsive;
64        this.responsiveBreakpoints = [];
65        this.responsiveCount = this.countResponsive( this.responsiveOptions );
66        this.loopTimeline = this.initLoopTimeline();
67        this.init();
68    }
69
70    ///////////////////////////////////////////////////////////////////////////
71    // INIT FUNCTION
72    ///////////////////////////////////////////////////////////////////////////
73    
74    initLoopTimeline(){
75        var loop = false;
76        const self = this;
77        this.sliders.each(function(){
78            const container = $(this);
79            const boxes = gsap.utils.toArray($(this).find('.gsap-slide'));
80            self.updateSliderConfig( container, boxes );
81            if( !self.mainConfig.fade && boxes.length > self.mainConfig.slidesToShow || !self.mainConfig.fade){
82                loop = self.horizontalLoop(boxes, self.loopConfig);
83
84                console.log(self.loopConfig);
85
86                if(self.mainConfig.arrows == true){
87                    if(boxes.length <= self.mainConfig.slidesToShow){
88                        let previous =  document.querySelector(self.mainConfig.arrowPrev);
89                        previous.closest('.arrows').style.display = 'none';
90                    }else{
91                        let previous =  document.querySelector(self.mainConfig.arrowPrev);
92                        previous.closest('.arrows').style.display = 'flex';
93                    }
94                }
95            }
96        })
97        return{
98            loop
99        }
100    }
101    init = () => {
102        const self = this;
103
104        this.sliders.each(function(){
105            const container = $(this);
106            const boxes = gsap.utils.toArray($(this).find('.gsap-slide'));
107
108            self.setEnvironment( container );
109
110            self.updateSliderConfig( container, boxes );
111
112            window.addEventListener("resize", () => {
113                self.updateSliderConfig( container, boxes );
114
115                if ( self.mainConfig.whiteSpace == false && !self.mainConfig.fade ) {
116                    self.noWhiteSpace( boxes );
117                }
118            });
119
120            var loop = false;
121
122            if( !self.mainConfig.fade && boxes.length > self.mainConfig.slidesToShow ){
123                loop = self.loopTimeline.loop;
124                
125                $(this).hover(
126                    function(){
127                        if( self.mainConfig.pauseOnHover && !self.loopConfig.paused && !self.mainConfig.fade ){
128                            loop.pause();
129                        }
130                    },
131                    function(){
132                        if( self.mainConfig.pauseOnHover && !self.loopConfig.paused && !self.mainConfig.fade ){
133                            loop.play();
134                        }
135                    }
136                )
137            }
138
139            if(self.mainConfig.slideToClickedSlide){
140                boxes.forEach((box, i) => box.addEventListener("click", () => loop.toIndex(i, {duration: 0.8, ease: "power1.inOut"})));
141            }
142                
143            if(self.mainConfig.arrows){
144                if( self.mainConfig.arrowPrev ){
145                    document.querySelector(self.mainConfig.arrowPrev).addEventListener("click", () => {
146                        if( self.mainConfig.arrows && self.mainConfig.arrowPrev && !self.mainConfig.fade ){
147                            loop.previous({duration: self.mainConfig.speed, ease: self.mainConfig.ease})
148                        }
149                        else if( self.mainConfig.arrows && self.mainConfig.arrowPrev && self.mainConfig.fade ){
150                            self.fadeSlide(container, 'prev');
151                        }
152                    });
153                }
154                if( self.mainConfig.arrowNext ){
155                    document.querySelector(self.mainConfig.arrowNext).addEventListener("click", () => {
156                        if( self.mainConfig.arrows && self.mainConfig.arrowNext && !self.mainConfig.fade ){
157                            loop.next({duration: self.mainConfig.speed, ease: self.mainConfig.ease})
158                        }
159                        else if( self.mainConfig.arrows && self.mainConfig.arrowNext && self.mainConfig.fade ){
160                            self.fadeSlide(container, 'next');
161                        }
162                    });
163                }
164    
165            }
166
167            if(self.mainConfig.autoplay){
168
169                const autoplay = new IntervalTimer(() => {
170                    if( loop != false & !self.mainConfig.fade ){
171                        loop.next({duration: self.mainConfig.speed, ease: self.mainConfig.ease})
172                    }
173                    else if( self.mainConfig.fade ){
174                        self.fadeSlide(container, 'next');
175                    }
176                }, self.mainConfig.duration);  
177
178                autoplay.start();   
179
180                if(self.mainConfig.arrows){
181                    document.querySelector(self.mainConfig.arrowPrev).addEventListener("click", () => {
182                        autoplay.pause();
183                        setTimeout(() => {
184                            autoplay.start();   
185                        }, self.mainConfig.duration);
186                    })
187    
188                    document.querySelector(self.mainConfig.arrowNext).addEventListener("click", () => {
189                        autoplay.pause();
190                        setTimeout(() => {
191                            autoplay.start();   
192                        }, self.mainConfig.duration);
193                    })
194                    
195                }
196
197                /*
198                if(self.mainConfig.pauseOnHover == true){                    
199                    $(this).hover(
200                        function(){
201                            autoplay.pause();
202                        },
203                        function(){
204                            autoplay.resume();
205                        }
206                    )        
207                }
208                */
209            }
210
211            if( self.mainConfig.swipe ){
212                var startX;
213                var startY;
214                var threshold = 30;
215                
216                this.addEventListener('touchstart', function(event) {
217                    startX = event.touches[0].clientX;
218                    startY = event.touches[0].clientY;
219                });
220                
221                this.addEventListener('touchmove', function(event) {
222                    event.preventDefault();
223                });
224                
225                this.addEventListener('touchend', function(event) {
226                    var endX = event.changedTouches[0].clientX;
227                    var endY = event.changedTouches[0].clientY;
228                
229                    var deltaX = startX - endX;
230                    var deltaY = startY - endY;
231                
232                    if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > threshold) {
233                        if (deltaX > 0) {
234                            if( !self.mainConfig.fade ){
235                                loop.previous({duration: self.mainConfig.speed, ease: self.mainConfig.ease})
236                            }
237                            else if( self.mainConfig.fade ){
238                                self.fadeSlide(container, 'prev');
239                            }
240                        } else {
241                            if( !self.mainConfig.fade ){
242                                loop.next({duration: self.mainConfig.speed, ease: self.mainConfig.ease})
243                            }
244                            else if( self.mainConfig.fade ){
245                                self.fadeSlide(container, 'next');
246                            }
247                        }
248                    }
249                });
250            }
251
252            if( self.mainConfig.adaptiveHeight ) {
253                let startHeight = container.find('.slide-active').innerHeight();
254                container.css('height', startHeight);
255            }
256
257        })
258    }
259
260    ///////////////////////////////////////////////////////////////////////////
261    // SET CONFIG ON FIRST INITIALIZATION
262    ///////////////////////////////////////////////////////////////////////////
263    setConfig = ( target ) => {
264        const self = this;
265        let activeElement;
266
267        if(self.sliderConfig.slidesToShow == 'autoWidth' && self.sliderConfig.draggable == true){
268            // SET DRAGGABLE ONLY IF DIV IS OVERFLOWING
269            let container_width = this.sliders.outerWidth();
270            let width_slides  = this.sliders.find('.gsap-slide:first-child').outerWidth();
271            let total_slides = this.sliders.find('.gsap-slide').length;
272            let container_scroll_width = width_slides * total_slides;
273
274            if(container_scroll_width > container_width){
275                this.sliders.find('.gsap-wrapper').css('justify-content', 'flex-start');
276                self.sliderConfig.draggable = true;
277            }else{
278                this.sliders.find('.gsap-wrapper').css('justify-content', 'center');
279                self.sliderConfig.draggable = false;
280            }
281        }
282
283        if( target == 'slide' ){    
284            return {
285                slidesToShow: self.sliderConfig.slidesToShow != null ? self.sliderConfig.slidesToShow : 1,
286                spaceBetweenSlides: self.sliderConfig.spaceBetweenSlides != null ? self.sliderConfig.spaceBetweenSlides / 2 : 0,
287                sameHeightSlides: self.sliderConfig.sameHeightSlides != null ? self.sliderConfig.sameHeightSlides : false,
288                speed: self.sliderConfig.speed != null ? self.sliderConfig.speed : 0.5,
289                ease: self.sliderConfig.ease != null ? self.sliderConfig.ease : "power1.inOut",
290                fade: self.sliderConfig.fade != null ? self.sliderConfig.fade : false,
291                arrows: self.sliderConfig.arrows != null ? self.sliderConfig.arrows : true,
292                arrowPrev: self.sliderConfig.arrows != null && self.sliderConfig.arrowPrev != null ? self.sliderConfig.arrowPrev : false,
293                arrowNext: self.sliderConfig.arrows != null && self.sliderConfig.arrowNext != null ? self.sliderConfig.arrowNext : false,
294                pauseOnHover: self.sliderConfig.pauseOnHover != null ? self.sliderConfig.pauseOnHover : true,
295                swipe: self.sliderConfig.swipe != null ? self.sliderConfig.swipe : false,
296                autoplay: self.sliderConfig.autoplay != null ? self.sliderConfig.autoplay : false,
297                duration: self.sliderConfig.duration != null ? self.sliderConfig.duration : 4000,
298                delayedContent: self.sliderConfig.delayedContent != null ? self.sliderConfig.delayedContent : false,
299                delayedContentY: self.sliderConfig.delayedContentY != null ? self.sliderConfig.delayedContentY : 0,
300                delayedContentX: self.sliderConfig.delayedContentX != null ? self.sliderConfig.delayedContentX : 0,
301                adaptiveHeight: self.sliderConfig.adaptiveHeight != null ? self.sliderConfig.adaptiveHeight : false,
302                whiteSpace: self.sliderConfig.whiteSpace != null ? self.sliderConfig.whiteSpace : true,
303                slideToClickedSlide: self.sliderConfig.slideToClickedSlide != null ? self.sliderConfig.slideToClickedSlide : true,
304            }
305        }
306        else if ( target == 'loop' ){
307            return {
308                onChange: (element, index) => { // when the active element changes, this function gets called.
309                    activeElement && activeElement.classList.remove("slide-active");
310                    element.classList.add("slide-active");
311                    activeElement = element;
312                },
313                reversed: self.sliderConfig.reversed != null ? self.sliderConfig.reversed : false,
314                draggable: self.sliderConfig.draggable != null ? self.sliderConfig.draggable : false,
315                repeat: self.sliderConfig.repeat != null && self.sliderConfig.repeat == true ? -1 : false,
316                center: self.sliderConfig.center != null ? self.sliderConfig.center : false,
317                paused: self.sliderConfig.paused != null ? self.sliderConfig.paused : true,
318                speed: self.sliderConfig.locomotiveSpeed != null ? self.sliderConfig.locomotiveSpeed : 0.1,
319            }
320        }
321    }
322
323    ///////////////////////////////////////////////////////////////////////////
324    // UPDATE CONFIG (RESIZE, QUERIES)
325    ///////////////////////////////////////////////////////////////////////////
326    updateConfig = ( target, breakpoint = false ) => {
327        const self = this;
328        let activeElement;
329
330        if( target == 'slide' ){
331
332            var backupOptions = this.mainConfig != null ? this.mainConfig : this.sliderConfig;
333
334            
335            if( breakpoint ) {
336                return {
337                    slidesToShow: self.responsiveOptions[breakpoint].slidesToShow != null ? self.responsiveOptions[breakpoint].slidesToShow : backupOptions.slidesToShow,
338                    spaceBetweenSlides: self.responsiveOptions[breakpoint].spaceBetweenSlides != null ? self.responsiveOptions[breakpoint].spaceBetweenSlides / 2 : backupOptions.spaceBetweenSlides,
339                    sameHeightSlides: self.responsiveOptions[breakpoint].sameHeightSlides != null ? self.responsiveOptions[breakpoint].sameHeightSlides : backupOptions.sameHeightSlides,
340                    speed: self.responsiveOptions[breakpoint].speed != null ? self.responsiveOptions[breakpoint].speed : backupOptions.speed,
341                    ease: self.responsiveOptions[breakpoint].ease != null ? self.responsiveOptions[breakpoint].ease : backupOptions.ease,
342                    arrows: self.responsiveOptions[breakpoint].arrows != null ? self.responsiveOptions[breakpoint].arrows : backupOptions.arrows,
343                    arrowPrev: self.responsiveOptions[breakpoint].arrows != null && self.responsiveOptions[breakpoint].arrowPrev != null ? self.responsiveOptions[breakpoint].arrowPrev : backupOptions.arrowPrev,
344                    arrowNext: self.responsiveOptions[breakpoint].arrows != null && self.responsiveOptions[breakpoint].arrowNext != null ? self.responsiveOptions[breakpoint].arrowNext : backupOptions.arrowNext,
345                    pauseOnHover: self.responsiveOptions[breakpoint].pauseOnHover != null ? self.responsiveOptions[breakpoint].pauseOnHover : backupOptions.pauseOnHover,
346                    swipe: self.responsiveOptions[breakpoint].swipe != null ? self.responsiveOptions[breakpoint].swipe : backupOptions.swipe,
347                    autoplay: self.responsiveOptions[breakpoint].autoplay != null ? self.responsiveOptions[breakpoint].autoplay : backupOptions.autoplay,
348                    duration: self.responsiveOptions[breakpoint].duration != null ? self.responsiveOptions[breakpoint].duration : backupOptions.duration,
349                    delayedContent: self.responsiveOptions[breakpoint].delayedContent != null ? self.responsiveOptions[breakpoint].delayedContent : backupOptions.delayedContent,
350                    delayedContentY: self.responsiveOptions[breakpoint].delayedContentY != null ? self.responsiveOptions[breakpoint].delayedContentY : backupOptions.delayedContentY,
351                    delayedContentX: self.responsiveOptions[breakpoint].delayedContentX != null ? self.responsiveOptions[breakpoint].delayedContentX : backupOptions.delayedContentX,
352                    adaptiveHeight: self.responsiveOptions[breakpoint].adaptiveHeight != null ? self.responsiveOptions[breakpoint].adaptiveHeight : backupOptions.adaptiveHeight,
353                    whiteSpace: self.responsiveOptions[breakpoint].whiteSpace != null ? self.responsiveOptions[breakpoint].whiteSpace : backupOptions.whiteSpace,
354                    fade: backupOptions.fade,
355                }
356            }
357            else{
358                return {
359                    slidesToShow: self.sliderConfig.slidesToShow != null ? self.sliderConfig.slidesToShow : 1,
360                    spaceBetweenSlides: self.sliderConfig.spaceBetweenSlides != null ? self.sliderConfig.spaceBetweenSlides / 2 : 0,
361                    sameHeightSlides: self.sliderConfig.sameHeightSlides != null ? self.sliderConfig.sameHeightSlides : false,
362                    speed: self.sliderConfig.speed != null ? self.sliderConfig.speed : 0.5,
363                    ease: self.sliderConfig.ease != null ? self.sliderConfig.ease : "power1.inOut",
364                    arrows: self.sliderConfig.arrows != null ? self.sliderConfig.arrows : true,
365                    arrowPrev: self.sliderConfig.arrows != null && self.sliderConfig.arrowPrev != null ? self.sliderConfig.arrowPrev : false,
366                    arrowNext: self.sliderConfig.arrows != null && self.sliderConfig.arrowNext != null ? self.sliderConfig.arrowNext : false,
367                    pauseOnHover: self.sliderConfig.pauseOnHover != null ? self.sliderConfig.pauseOnHover : true,
368                    swipe: self.sliderConfig.swipe != null ? self.sliderConfig.swipe : false,
369                    fade: self.sliderConfig.fade != null ? self.sliderConfig.fade : false,
370                    autoplay: self.sliderConfig.autoplay != null ? self.sliderConfig.autoplay : false,
371                    duration: self.sliderConfig.duration != null ? self.sliderConfig.duration : 4000,
372                    delayedContent: self.sliderConfig.delayedContent != null ? self.sliderConfig.delayedContent : false,
373                    delayedContentY: self.sliderConfig.delayedContentY != null ? self.sliderConfig.delayedContentY : 0,
374                    delayedContentX: self.sliderConfig.delayedContentX != null ? self.sliderConfig.delayedContentX : 0,
375                    adaptiveHeight: self.sliderConfig.adaptiveHeight != null ? self.sliderConfig.adaptiveHeight : false,
376                    whiteSpace: self.sliderConfig.whiteSpace != null ? self.sliderConfig.whiteSpace : true,
377                }
378            }
379        }
380        else if ( target == 'loop' ){
381            var backupOptions = this.loopConfig != null ? this.loopConfig : this.sliderConfig;
382    
383            if ( breakpoint ) {
384                return {
385                    onChange: (element, index) => { // when the active element changes, this function gets called.
386                        activeElement && activeElement.classList.remove("slide-active");
387                        element.classList.add("slide-active");
388                        activeElement = element;
389                    },
390                    reversed: self.sliderConfig.reversed != null ? self.sliderConfig.reversed : false,
391                    draggable: self.responsiveOptions[breakpoint].draggable != null ? self.responsiveOptions[breakpoint].draggable : backupOptions.draggable,
392                    center: self.responsiveOptions[breakpoint].center != null ? self.responsiveOptions[breakpoint].center : backupOptions.center,
393                    paused: self.responsiveOptions[breakpoint].paused != null ? self.responsiveOptions[breakpoint].paused : backupOptions.paused,
394                    repeat: self.responsiveOptions[breakpoint].repeat != null && self.responsiveOptions[breakpoint].repeat ? -1 : backupOptions.repeat,
395                    speed: self.responsiveOptions[breakpoint].locomotiveSpeed != null ? self.responsiveOptions[breakpoint].locomotiveSpeed : backupOptions.speed,
396                }
397            }
398            else{
399                return {
400                    onChange: (element, index) => { // when the active element changes, this function gets called.
401                        activeElement && activeElement.classList.remove("slide-active");
402                        element.classList.add("slide-active");
403                        activeElement = element;
404                    },
405                    reversed: self.sliderConfig.reversed != null ? self.sliderConfig.reversed : false,
406                    draggable: self.sliderConfig.draggable != null ? self.sliderConfig.draggable : false,
407                    center: self.sliderConfig.center != null ? self.sliderConfig.center : false,
408                    paused: self.sliderConfig.paused != null ? self.sliderConfig.paused : true,
409                    repeat: self.sliderConfig.repeat != null && self.sliderConfig.repeat ? -1 : false,
410                    speed: self.sliderConfig.locomotiveSpeed != null ? self.sliderConfig.locomotiveSpeed : 0.5,
411                }
412            }
413        }
414    }
415
416    ///////////////////////////////////////////////////////////////////////////
417    // SET SLIDER CONFIG (RESIZE, QUERIES)
418    ///////////////////////////////////////////////////////////////////////////
419    updateSliderConfig = ( container, boxes ) => {
420    
421        const self = this;
422
423        const resp = self.responsiveBreakpoints.sort(function(a, b) { return b - a; });
424        
425        if(resp.length > 0){            
426            if( window.matchMedia('(min-width: ' + resp[0] + 'px)').matches ){
427                self.mainConfig = self.updateConfig( 'slide' );
428                self.loopConfig = self.updateConfig( 'loop' );
429            }
430            else if( 
431                window.matchMedia('(max-width: ' + resp[0] + 'px)').matches &&
432                window.matchMedia('(min-width: ' + resp[resp.length - 1] + 'px)').matches
433            ){
434                for(var i = 0; i < resp.length - 1; i++){
435                    if(
436                        window.matchMedia('(max-width: ' + resp[i] + 'px)').matches &&
437                        window.matchMedia('(min-width: ' + resp[i + 1] + 'px)').matches
438                    ){
439                        self.mainConfig = self.updateConfig( 'slide', resp[i] );
440                        self.loopConfig = self.updateConfig( 'loop', resp[i] );
441                    }
442                }
443            }
444            else{
445                self.mainConfig = self.updateConfig( 'slide', resp[resp.length - 1] );
446                self.loopConfig = self.updateConfig( 'loop', resp[resp.length - 1] );
447            }
448 
449            this.sliders.each(function(){
450                const container = $(this);
451                const boxes = gsap.utils.toArray($(this).find('.gsap-slide'));
452                if( !self.mainConfig.fade && boxes.length > self.mainConfig.slidesToShow || !self.mainConfig.fade){
453                    if(self.mainConfig.arrows == true){
454                        if(boxes.length <= self.mainConfig.slidesToShow){
455                            let previous =  document.querySelector(self.mainConfig.arrowPrev);
456                            previous.closest('.arrows').style.display = 'none';
457                        }else{
458                            let previous =  document.querySelector(self.mainConfig.arrowPrev);
459                            previous.closest('.arrows').style.display = 'flex';
460                        }
461                    }
462                }
463            })
464        }
465
466        const config = self.mainConfig;
467
468        const wrapper = container.find('.gsap-wrapper');
469        const wrapperWidth = wrapper.outerWidth();
470        var higherSlide = 0;
471        var indexSlide = 0;
472        var wrapperAlign = config.sameHeightSlides == true ? 'stretch' : 'center';
473        
474        wrapper.css({
475            'display': 'flex',
476            'align-items': wrapperAlign,
477            'position': 'relative'
478        });
479
480        if( config.spaceBetweenSlides != 0 && config.fade == false ){
481         
482            wrapper.css('margin', '0 -' + config.spaceBetweenSlides + 'px');
483        }
484        boxes.forEach((box, i) => {
485            if(config.whiteSpace !== false){
486                $(box).attr('data-gsap-slide-index', indexSlide).css({
487                    'flex-shrink': '0',
488                });
489            }
490
491            if(config.fade == true){
492                let slideHeight = $(box).outerHeight();
493                let opacity = indexSlide == 0 ? 1 : 0;
494                let visibility = indexSlide == 0 ? 'visible' : 'hidden';
495                let active = indexSlide == 0 ? 'slide-active' : '';
496
497                $(box).addClass(active).css({
498                    'width': '100%',
499                    'position': 'absolute',
500                    'top': 0,
501                    'left' : 0,
502                    'opacity': opacity,
503                    'visibility': visibility,
504                })
505
506                higherSlide = slideHeight > higherSlide ? slideHeight : higherSlide;
507            }
508            else{                
509                $(box).css({
510                    'position': 'relative',
511                    'top': 'auto',
512                    'left' : 'auto',
513                    'opacity': 1,
514                    'visibility': 'visible',
515                })
516                if( config.spaceBetweenSlides != 0 && config.whiteSpace !== false ) {
517                    var slideWidth = (wrapperWidth / config.slidesToShow) + ((config.spaceBetweenSlides * 2) / config.slidesToShow);
518
519                    box.style.width = slideWidth + 'px';
520                    box.style.paddingLeft = config.spaceBetweenSlides + 'px';
521                    box.style.paddingRight = config.spaceBetweenSlides + 'px';
522                }
523                else if( config.whiteSpace == false ) {
524                    var boxWidth = $(box).outerWidth();
525                    $(box).find('p').css({'white-space': 'nowrap'});
526                    $(box).css('width', boxWidth + 'px');
527                }
528                else{
529                    var slideWidth = wrapperWidth / config.slidesToShow;
530                    $(box).css('width', slideWidth + 'px')
531                }
532            }
533
534            indexSlide++;
535        })
536
537        if( config.fade == true ) {
538            wrapper.css('height', higherSlide);
539        }
540        else{
541            wrapper.css('height', 'auto');
542        }
543    }
544
545    ///////////////////////////////////////////////////////////////////////////
546    // HORIZONTAL LOOP CODE
547    ///////////////////////////////////////////////////////////////////////////    
548    /*
549    horizontalLoop = (items, config) => {
550        items = gsap.utils.toArray(items);
551        config = config || {};
552        let tl = gsap.timeline({repeat: config.repeat, paused: config.paused, defaults: {ease: "none"}, onReverseComplete: () => tl.totalTime(tl.rawTime() + tl.duration() * 100)}),
553            length = items.length,
554            startX = items[0].offsetLeft,
555            times = [],
556            widths = [],
557            xPercents = [],
558            curIndex = 0,
559            pixelsPerSecond = (config.speed || 1) * 100,
560            snap = config.snap === false ? v => v : gsap.utils.snap(config.snap || 1), // some browsers shift by a pixel to accommodate flex layouts, so for example if width is 20% the first element's width might be 242px, and the next 243px, alternating back and forth. So we snap to 5 percentage points to make things look more natural
561            populateWidths = () => items.forEach((el, i) => {
562          widths[i] = parseFloat(gsap.getProperty(el, "width", "px"));
563          xPercents[i] = snap(parseFloat(gsap.getProperty(el, "x", "px")) / widths[i] * 100 + gsap.getProperty(el, "xPercent"));
564        }),            
565        getTotalWidth = () => items[length-1].offsetLeft + xPercents[length-1] / 100 * widths[length-1] - startX + items[length-1].offsetWidth * gsap.getProperty(items[length-1], "scaleX") + (parseFloat(config.paddingRight) || 0),
566          totalWidth, curX, distanceToStart, distanceToLoop, item, i;
567        populateWidths();
568      gsap.set(items, { // convert "x" to "xPercent" to make things responsive, and populate the widths/xPercents Arrays to make lookups faster.
569            xPercent: i => xPercents[i]
570        }); 
571        gsap.set(items, {x: 0});
572        totalWidth = getTotalWidth();
573        for (i = 0; i < length; i++) {
574            item = items[i];
575            curX = xPercents[i] / 100 * widths[i];
576            distanceToStart = item.offsetLeft + curX - startX;
577            distanceToLoop = distanceToStart + widths[i] * gsap.getProperty(item, "scaleX");
578            tl.to(item, {xPercent: snap((curX - distanceToLoop) / widths[i] * 100), duration: distanceToLoop / pixelsPerSecond}, 0)
579              .fromTo(item, {xPercent: snap((curX - distanceToLoop + totalWidth) / widths[i] * 100)}, {xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false}, distanceToLoop / pixelsPerSecond)
580              .add("label" + i, distanceToStart / pixelsPerSecond);
581            times[i] = distanceToStart / pixelsPerSecond;
582        }
583        function updateActive(index){
584            items.forEach((el, i) => {
585                if($(el).attr('data-gsap-slide-index') == index){
586                    $(el).addClass('slide-active');
587                }else{
588                    $(el).removeClass('slide-active');
589                }
590            });
591        }
592        function toIndex(index, vars) {
593            vars = vars || {};
594            (Math.abs(index - curIndex) > length / 2) && (index += index > curIndex ? -length : length); // always go in the shortest direction
595            let newIndex = gsap.utils.wrap(0, length, index),
596                time = times[newIndex];
597            if (time > tl.time() !== index > curIndex) { // if we're wrapping the timeline's playhead, make the proper adjustments
598                vars.modifiers = {time: gsap.utils.wrap(0, tl.duration())};
599                time += tl.duration() * (index > curIndex ? 1 : -1);
600            }
601            curIndex = newIndex;
602            vars.overwrite = true;
603
604            updateActive(curIndex);
605            return tl.tweenTo(time, vars);
606        }
607        tl.next = vars => toIndex(curIndex+1, vars);
608        tl.previous = vars => toIndex(curIndex-1, vars);
609        tl.current = () => curIndex;
610        tl.toIndex = (index, vars) => toIndex(index, vars);
611      tl.updateIndex = () => curIndex = Math.round(tl.progress() * items.length);
612        tl.times = times;
613      tl.progress(1, true).progress(0, true); // pre-render for performance
614      if (config.reversed) {
615        tl.vars.onReverseComplete();
616        tl.reverse();
617      }
618      if (config.draggable && typeof(Draggable) === "function") {
619        let proxy = document.createElement("div"),
620            wrap = gsap.utils.wrap(0, 1),
621            ratio, startProgress, draggable, dragSnap, roundFactor,
622            align = () => tl.progress(wrap(startProgress + (draggable.startX - draggable.x) * ratio)),
623            syncIndex = () => tl.updateIndex();
624        typeof(InertiaPlugin) === "undefined" && console.warn("InertiaPlugin required for momentum-based scrolling and snapping. https://greensock.com/club");
625        draggable = Draggable.create(proxy, {
626          trigger: items[0].parentNode,
627          type: "x",
628          onPress() {
629            startProgress = tl.progress();
630            tl.progress(0);
631            populateWidths();
632            totalWidth = getTotalWidth();
633            ratio = 1 / totalWidth;
634            dragSnap = totalWidth / items.length;
635            roundFactor = Math.pow(10, ((dragSnap + "").split(".")[1] || "").length);
636            tl.progress(startProgress);
637          },
638          onDrag: align,
639          onThrowUpdate: align,
640          inertia: true,
641          snap: value => {
642            let n = Math.round(parseFloat(value) / dragSnap) * dragSnap * roundFactor;
643            return (n - n % 1) / roundFactor;
644          },
645          onRelease: syncIndex,
646          onThrowComplete: () => gsap.set(proxy, {x: 0}) && syncIndex()
647        })[0];
648        
649        tl.draggable = draggable;
650      }
651      
652      
653        return tl;
654    }
655    */
656    
657    
658    horizontalLoop(items, config) {
659        items = gsap.utils.toArray(items);
660        config = config || {};
661        console.log(config);
662        let onChange = config.onChange,
663            lastIndex = 0,
664            tl = gsap.timeline({repeat: config.repeat, onUpdate: onChange && function() {
665                    let i = tl.closestIndex();
666                    if (lastIndex !== i) {
667                        lastIndex = i;
668                        onChange(items[i], i);
669                    }
670                }, paused: config.paused, defaults: {ease: "none"}, onReverseComplete: () => tl.totalTime(tl.rawTime() + tl.duration() * 100)}),
671            length = items.length,
672            startX = items[0].offsetLeft,
673            times = [],
674            widths = [],
675            spaceBefore = [],
676            xPercents = [],
677            curIndex = 0,
678            indexIsDirty = false,
679            center = config.center,
680            pixelsPerSecond = (config.speed || 1) * 100,
681            snap = config.snap === false ? v => v : gsap.utils.snap(config.snap || 1), // some browsers shift by a pixel to accommodate flex layouts, so for example if width is 20% the first element's width might be 242px, and the next 243px, alternating back and forth. So we snap to 5 percentage points to make things look more natural
682            timeOffset = 0,
683            container = center === true ? items[0].parentNode : gsap.utils.toArray(center)[0] || items[0].parentNode,
684            totalWidth,
685            getTotalWidth = () => items[length-1].offsetLeft + xPercents[length-1] / 100 * widths[length-1] - startX + spaceBefore[0] + items[length-1].offsetWidth * gsap.getProperty(items[length-1], "scaleX") + (parseFloat(config.paddingRight) || 0),
686            populateWidths = () => {
687                let b1 = container.getBoundingClientRect(), b2;
688                items.forEach((el, i) => {
689                    widths[i] = parseFloat(gsap.getProperty(el, "width", "px"));
690                    xPercents[i] = snap(parseFloat(gsap.getProperty(el, "x", "px")) / widths[i] * 100 + gsap.getProperty(el, "xPercent"));
691                    b2 = el.getBoundingClientRect();
692                    spaceBefore[i] = b2.left - (i ? b1.right : b1.left);
693                    b1 = b2;
694                });
695                gsap.set(items, { // convert "x" to "xPercent" to make things responsive, and populate the widths/xPercents Arrays to make lookups faster.
696                    xPercent: i => xPercents[i]
697                });
698                totalWidth = getTotalWidth();
699            },
700            timeWrap,
701            populateOffsets = () => {
702                timeOffset = center ? tl.duration() * (container.offsetWidth / 2) / totalWidth : 0;
703                center && times.forEach((t, i) => {
704                    times[i] = timeWrap(tl.labels["label" + i] + tl.duration() * widths[i] / 2 / totalWidth - timeOffset);
705                });
706            },
707            getClosest = (values, value, wrap) => {
708                let i = values.length,
709                    closest = 1e10,
710                    index = 0, d;
711                while (i--) {
712                    d = Math.abs(values[i] - value);
713                    if (d > wrap / 2) {
714                        d = wrap - d;
715                    }
716                    if (d < closest) {
717                        closest = d;
718                        index = i;
719                    }
720                }
721                return index;
722            },
723            populateTimeline = () => {
724                let i, item, curX, distanceToStart, distanceToLoop;
725                tl.clear();
726                for (i = 0; i < length; i++) {
727                    item = items[i];
728                    curX = xPercents[i] / 100 * widths[i];
729                    distanceToStart = item.offsetLeft + curX - startX + spaceBefore[0];
730                    distanceToLoop = distanceToStart + widths[i] * gsap.getProperty(item, "scaleX");
731                    tl.to(item, {xPercent: snap((curX - distanceToLoop) / widths[i] * 100), duration: distanceToLoop / pixelsPerSecond}, 0)
732                      .fromTo(item, {xPercent: snap((curX - distanceToLoop + totalWidth) / widths[i] * 100)}, {xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false}, distanceToLoop / pixelsPerSecond)
733                      .add("label" + i, distanceToStart / pixelsPerSecond);
734                    times[i] = distanceToStart / pixelsPerSecond;
735                }
736                timeWrap = gsap.utils.wrap(0, tl.duration());
737            },
738            refresh = (deep) => {
739                let progress = tl.progress();
740                tl.progress(0, true);
741                populateWidths();
742                deep && populateTimeline();
743                populateOffsets();
744                deep && tl.draggable ? tl.time(times[curIndex], true) : tl.progress(progress, true);
745            },
746            proxy;
747        gsap.set(items, {x: 0});
748        populateWidths();
749        populateTimeline();
750        populateOffsets();
751        //window.addEventListener("resize", () => refresh(true));
752        function toIndex(index, vars) {
753            vars = vars || {};
754            (Math.abs(index - curIndex) > length / 2) && (index += index > curIndex ? -length : length); // always go in the shortest direction
755            let newIndex = gsap.utils.wrap(0, length, index),
756                time = times[newIndex];
757            if (time > tl.time() !== index > curIndex && index !== curIndex) { // if we're wrapping the timeline's playhead, make the proper adjustments
758                time += tl.duration() * (index > curIndex ? 1 : -1);
759            }
760            if (time < 0 || time > tl.duration()) {
761                vars.modifiers = {time: timeWrap};
762            }
763            curIndex = newIndex;
764            vars.overwrite = true;
765            gsap.killTweensOf(proxy);    
766            return vars.duration === 0 ? tl.time(timeWrap(time)) : tl.tweenTo(time, vars);
767        }
768        tl.toIndex = (index, vars) => toIndex(index, vars);
769        tl.closestIndex = setCurrent => {
770            let index = getClosest(times, tl.time(), tl.duration());
771            if (setCurrent) {
772                curIndex = index;
773                indexIsDirty = false;
774            }
775            return index;
776        };
777        tl.current = () => indexIsDirty ? tl.closestIndex(true) : curIndex;
778        tl.next = vars => toIndex(tl.current()+1, vars);
779        tl.previous = vars => toIndex(tl.current()-1, vars);
780        tl.times = times;
781        tl.progress(1, true).progress(0, true); // pre-render for performance
782        if (config.reversed) {
783            tl.vars.onReverseComplete();
784            tl.reverse();
785        }
786        if (config.draggable && typeof(Draggable) === "function") {
787            proxy = document.createElement("div")
788            let wrap = gsap.utils.wrap(0, 1),
789                ratio, startProgress, draggable, dragSnap, lastSnap, initChangeX,
790                align = () => tl.progress(wrap(startProgress + (draggable.startX - draggable.x) * ratio)),
791                syncIndex = () => tl.closestIndex(true);
792            typeof(InertiaPlugin) === "undefined" && console.warn("InertiaPlugin required for momentum-based scrolling and snapping. https://greensock.com/club");
793            draggable = Draggable.create(proxy, {
794                trigger: items[0].parentNode,
795                type: "x",
796                onPressInit() {
797            let x = this.x;
798                    gsap.killTweensOf(tl);
799                    startProgress = tl.progress();
800                    refresh();
801                    ratio = 1 / totalWidth;
802            initChangeX = (startProgress / -ratio) - x;
803                    gsap.set(proxy, {x: startProgress / -ratio});
804                },
805                onDrag: align,
806                onThrowUpdate: align,
807          overshootTolerance: 0,
808                inertia: true,
809                snap(value) {
810            //note: if the user presses and releases in the middle of a throw, due to the sudden correction of proxy.x in the onPressInit(), the velocity could be very large, throwing off the snap. So sense that condition and adjust for it. We also need to set overshootTolerance to 0 to prevent the inertia from causing it to shoot past and come back
811            if (Math.abs(startProgress / -ratio - this.x) < 10) {
812              return lastSnap + initChangeX
813            }
814                    let time = -(value * ratio) * tl.duration(),
815                        wrappedTime = timeWrap(time),
816                        snapTime = times[getClosest(times, wrappedTime, tl.duration())],
817                        dif = snapTime - wrappedTime;
818                    Math.abs(dif) > tl.duration() / 2 && (dif += dif < 0 ? tl.duration() : -tl.duration());
819            lastSnap = (time + dif) / tl.duration() / -ratio;
820                    return lastSnap;
821                },
822                onRelease() {
823                    syncIndex();
824                    draggable.isThrowing && (indexIsDirty = true);
825                },
826                onThrowComplete: syncIndex
827            })[0];
828            tl.draggable = draggable;
829        }
830        tl.closestIndex(true);
831      lastIndex = curIndex;
832        onChange && onChange(items[curIndex], curIndex);
833        return tl;
834    }
835   
836    
837
838    ///////////////////////////////////////////////////////////////////////////
839    // FADE SLIDES
840    ///////////////////////////////////////////////////////////////////////////    
841    fadeSlide = ( container, direction ) => {
842        const self = this;
843        const parent = container;
844
845        var currentSlide = parent.find('.slide-active');
846        var slideIndex = currentSlide.data('gsap-slide-index');
847        var slideCount = parent.find('.gsap-slide').length;
848        var nextIndex = 0;
849        var prevIndex = 0;
850
851        if( slideIndex + 1 >= slideCount){
852            if( self.sliderConfig.repeat ){
853                nextIndex = 0;
854            }
855            else{
856                nextIndex = slideCount - 1;
857            }
858        }
859        else{
860            nextIndex = slideIndex + 1;
861        }
862
863        if( slideIndex - 1 <= 0){
864            if( self.sliderConfig.repeat ){
865                prevIndex = slideCount - 1;
866            }
867            else{
868                prevIndex = 0;
869            }
870        }
871        else{
872            prevIndex = slideIndex - 1;
873        }
874
875        var nextSlide = parent.find('.gsap-slide[data-gsap-slide-index=' + nextIndex + ']');
876        var prevSlide = parent.find('.gsap-slide[data-gsap-slide-index=' + prevIndex + ']');
877
878        const fadeTimeline = gsap.timeline({
879            defaults: {
880                ease: self.mainConfig.ease,
881                duration: self.mainConfig.speed
882            }
883        })
884
885        if( direction == 'prev' ) {
886            var nextHeight = prevSlide.innerHeight();
887
888            if( self.mainConfig.delayedContent && self.mainConfig.adaptiveHeight ) {
889                fadeTimeline
890                .to( currentSlide.find('.delayed-content'), {autoAlpha: 0, x: self.mainConfig.delayedContentX, y: self.mainConfig.delayedContentY})
891                .to( currentSlide, {autoAlpha: 0})
892                .to( parent, { height: nextHeight }, '<'  )
893                .to( prevSlide, {autoAlpha: 1}, '<')
894                .to( prevSlide.find('.delayed-content'), {autoAlpha: 1, y: 0, x: 0})
895                .add(function(){
896                    currentSlide.removeClass('slide-active');
897                    prevSlide.addClass('slide-active');
898                })
899            }
900            else if( self.mainConfig.delayedContent ) {
901                fadeTimeline
902                .to( currentSlide.find('.delayed-content'), {autoAlpha: 0, x: self.mainConfig.delayedContentX, y: self.mainConfig.delayedContentY})
903                .to( currentSlide, {autoAlpha: 0})
904                .to( prevSlide, {autoAlpha: 1}, '<')
905                .to( prevSlide.find('.delayed-content'), {autoAlpha: 1, y: 0, x: 0})
906                .add(function(){
907                    currentSlide.removeClass('slide-active');
908                    prevSlide.addClass('slide-active');
909                })
910
911            }
912            else if( self.mainConfig.adaptiveHeight ) {
913                fadeTimeline
914                .to( currentSlide, {autoAlpha: 0})
915                .to( parent, { height: nextHeight }, '<'  )
916                .to( prevSlide, {autoAlpha: 1}, '<')
917                .add(function(){
918                    currentSlide.removeClass('slide-active');
919                    prevSlide.addClass('slide-active');
920                })
921
922            }
923            else{
924                fadeTimeline
925                .to( currentSlide, {autoAlpha: 0})
926                .to( prevSlide, {autoAlpha: 1}, '<')
927                .add(function(){
928                    currentSlide.removeClass('slide-active');
929                    prevSlide.addClass('slide-active');
930                })
931            }
932        }
933        else if( direction == 'next' ){
934            var nextHeight = nextSlide.innerHeight();
935
936            if( self.mainConfig.delayedContent && self.mainConfig.adaptiveHeight ) {
937                fadeTimeline
938                .to( currentSlide.find('.delayed-content'), {autoAlpha: 0, x: self.mainConfig.delayedContentX, y: self.mainConfig.delayedContentY})
939                .to( currentSlide, {autoAlpha: 0})
940                .to( parent, { height: nextHeight }, '<'  )
941                .to( nextSlide, {autoAlpha: 1}, '<')
942                .to( nextSlide.find('.delayed-content'), {autoAlpha: 1, y: 0, x: 0})
943                .add(function(){
944                    currentSlide.removeClass('slide-active');
945                    nextSlide.addClass('slide-active');
946                })
947            }
948            else if( self.mainConfig.delayedContent ) {
949                fadeTimeline
950                .to( currentSlide.find('.delayed-content'), {autoAlpha: 0, x: self.mainConfig.delayedContentX, y: self.mainConfig.delayedContentY})
951                .to( currentSlide, {autoAlpha: 0})
952                .to( nextSlide, {autoAlpha: 1}, '<')
953                .to( nextSlide.find('.delayed-content'), {autoAlpha: 1, y: 0, x: 0})
954                .add(function(){
955                    currentSlide.removeClass('slide-active');
956                    nextSlide.addClass('slide-active');
957                })
958
959            }
960            else if( self.mainConfig.adaptiveHeight ) {
961                fadeTimeline
962                .to( currentSlide, {autoAlpha: 0})
963                .to( parent, { height: nextHeight }, '<'  )
964                .to( nextSlide, {autoAlpha: 1}, '<')
965                .add(function(){
966                    currentSlide.removeClass('slide-active');
967                    nextSlide.addClass('slide-active');
968                })
969
970            }
971            else{
972                fadeTimeline
973                .to( currentSlide, {autoAlpha: 0})
974                .to( nextSlide, {autoAlpha: 1}, '<')
975                .add(function(){
976                    currentSlide.removeClass('slide-active');
977                    nextSlide.addClass('slide-active');
978                })
979            }
980        }
981    }
982
983    ///////////////////////////////////////////////////////////////////////////
984    // COUNT RESPONSIVE BREAKPOINTS
985    ///////////////////////////////////////////////////////////////////////////
986    countResponsive = ( obj ) => {
987        let counter = 0;
988        const self = this;
989        
990        for (var prop in obj) {
991          if(obj.hasOwnProperty(prop)){
992            self.responsiveBreakpoints.push( prop );
993            counter++;
994          }
995        }
996        
997        return counter;
998    }
999
1000    ///////////////////////////////////////////////////////////////////////////
1001    // COUNT RESPONSIVE BREAKPOINTS
1002    ///////////////////////////////////////////////////////////////////////////
1003    setEnvironment = ( container ) => {
1004        container.find('.gsap-wrapper').css({
1005            'width': '100%',
1006            'position': 'relative',
1007            'display': 'flex'
1008        })
1009    }
1010
1011    ///////////////////////////////////////////////////////////////////////////
1012    // CALC NO WHITESPACE
1013    ///////////////////////////////////////////////////////////////////////////
1014    noWhiteSpace = ( boxes ) => {
1015        const config = self.mainConfig;
1016
1017        boxes.forEach((box, i) => {
1018            $(box).css('width', 'fit-content');   
1019            var boxWidth = $(box).outerWidth();
1020
1021            $(box).find('p').css({'white-space': 'nowrap'})
1022            $(box).css('width', boxWidth + 'px');                
1023        })
1024    }
1025}
1026
1027class IntervalTimer {
1028    callbackStartTime;
1029    remaining = 0;
1030    paused = false;
1031    timerId = null;
1032    callback;
1033    delay;
1034
1035    constructor(callback, delay) {
1036        this.callback = callback;
1037        this.delay = delay;
1038    }
1039
1040    pause() {
1041        if (!this.paused) {
1042            this.clear();
1043            this.remaining = new Date().getTime() - this.callbackStartTime;
1044            this.paused = true;
1045        }
1046    }
1047
1048    resume() {
1049        if (this.paused) {
1050            if (this.remaining) {
1051                setTimeout(() => {
1052                    this.run();
1053                    this.paused = false;
1054                    this.start();
1055                }, this.remaining);
1056            } else {
1057                this.paused = false;
1058                this.start();
1059            }
1060        }
1061    }
1062
1063    clear() {
1064        clearInterval(this.timerId);
1065    }
1066
1067    start() {
1068        this.clear();
1069        this.timerId = setInterval(() => {
1070            this.run();
1071        }, this.delay);
1072    }
1073
1074    run() {
1075        this.callbackStartTime = new Date().getTime();
1076        this.callback();
1077    }
1078}
1079
1080// HOW TO USE FUNCTION:
1081/*
1082    1.Wrap slider in a variable;
1083    2.Yourslider.slideToIndex(i);
1084*/
1085GSapSlider.prototype.slideToIndex = function(index, duration, ease) {
1086    this.loopTimeline.loop.toIndex(index, {duration: duration ? duration : 0.8, ease: ease ? ease : "power1.inOut"});
1087}

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.