PageSourceSearch

https://lesfranciscaines.fr/themes/custom_theme/js/fullpage.js?tlpthi

js lesfranciscaines.fr collected 2026-10-02 07:07:45 UTC 151,712 bytes, 4,201 lines download raw bytes

1/*!
2 * fullPage 3.0.8
3 * https://github.com/alvarotrigo/fullPage.js
4 *
5 * @license GPLv3 for open source use only
6 * or Fullpage Commercial License for commercial use
7 * http://alvarotrigo.com/fullPage/pricing/
8 *
9 * Copyright (C) 2018 http://alvarotrigo.com/fullPage - A project by Alvaro Trigo
10 */
11(function( root, window, document, factory, undefined) {
12    if( typeof define === 'function' && define.amd ) {
13        // AMD. Register as an anonymous module.
14        define( function() {
15            root.fullpage = factory(window, document);
16            return root.fullpage;
17        } );
18    } else if( typeof exports === 'object' ) {
19        // Node. Does not work with strict CommonJS.
20        module.exports = factory(window, document);
21    } else {
22        // Browser globals.
23        window.fullpage = factory(window, document);
24    }
25}(this, window, document, function(window, document){
26    'use strict';
27
28    // keeping central set of classnames and selectors
29    var WRAPPER =               'fullpage-wrapper';
30    var WRAPPER_SEL =           '.' + WRAPPER;
31
32    // slimscroll
33    var SCROLLABLE =            'fp-scrollable';
34    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
35
36    // util
37    var RESPONSIVE =            'fp-responsive';
38    var NO_TRANSITION =         'fp-notransition';
39    var DESTROYED =             'fp-destroyed';
40    var ENABLED =               'fp-enabled';
41    var VIEWING_PREFIX =        'fp-viewing';
42    var ACTIVE =                'active';
43    var ACTIVE_SEL =            '.' + ACTIVE;
44    var COMPLETELY =            'fp-completely';
45    var COMPLETELY_SEL =        '.' + COMPLETELY;
46
47    // section
48    var SECTION_DEFAULT_SEL =   '.section';
49    var SECTION =               'fp-section';
50    var SECTION_SEL =           '.' + SECTION;
51    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
52    var TABLE_CELL =            'fp-tableCell';
53    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
54    var AUTO_HEIGHT =           'fp-auto-height';
55    var AUTO_HEIGHT_SEL =       '.' + AUTO_HEIGHT;
56    var AUTO_HEIGHT_RESPONSIVE = 'fp-auto-height-responsive';
57    var AUTO_HEIGHT_RESPONSIVE_SEL = '.' + AUTO_HEIGHT_RESPONSIVE;
58    var NORMAL_SCROLL =         'fp-normal-scroll';
59    var NORMAL_SCROLL_SEL =     '.' + NORMAL_SCROLL;
60
61    // section nav
62    var SECTION_NAV =           'fp-nav';
63    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
64    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
65    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
66    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
67
68    // slide
69    var SLIDE_DEFAULT_SEL =     '.slide';
70    var SLIDE =                 'fp-slide';
71    var SLIDE_SEL =             '.' + SLIDE;
72    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
73    var SLIDES_WRAPPER =        'fp-slides';
74    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
75    var SLIDES_CONTAINER =      'fp-slidesContainer';
76    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
77    var TABLE =                 'fp-table';
78
79    // slide nav
80    var SLIDES_NAV =            'fp-slidesNav';
81    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
82    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
83    var SLIDES_ARROW =          'fp-controlArrow';
84    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
85    var SLIDES_PREV =           'fp-prev';
86    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
87    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
88    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
89    var SLIDES_NEXT =           'fp-next';
90    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
91    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
92    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
93
94    function initialise(containerSelector, options) {
95        var isOK = options && new RegExp('([\\d\\w]{8}-){3}[\\d\\w]{8}|^(?=.*?[A-Y])(?=.*?[a-y])(?=.*?[0-8])(?=.*?[#?!@$%^&*-]).{8,}$').test(options['li'+'cen'+'seK' + 'e' + 'y']) || document.domain.indexOf('al'+'varotri' +'go' + '.' + 'com') > -1;
96
97        // cache common elements
98        var $htmlBody = $('html, body');
99        var $html = $('html')[0];
100        var $body = $('body')[0];
101
102        //only once my friend!
103        if(hasClass($html, ENABLED)){ displayWarnings(); return; }
104
105        var FP = {};
106
107        // Creating some defaults, extending them with any options that were provided
108        options = deepExtend({
109            //navigation
110            menu: false,
111            anchors:[],
112            lockAnchors: false,
113            navigation: false,
114            navigationPosition: 'right',
115            navigationTooltips: [],
116            showActiveTooltip: false,
117            slidesNavigation: false,
118            slidesNavPosition: 'bottom',
119            scrollBar: false,
120            hybrid: false,
121
122            //scrolling
123            css3: true,
124            scrollingSpeed: 700,
125            autoScrolling: true,
126            fitToSection: true,
127            fitToSectionDelay: 1000,
128            easing: 'easeInOutCubic',
129            easingcss3: 'ease',
130            loopBottom: false,
131            loopTop: false,
132            loopHorizontal: true,
133            continuousVertical: false,
134            continuousHorizontal: false,
135            scrollHorizontally: false,
136            interlockedSlides: false,
137            dragAndMove: false,
138            offsetSections: false,
139            resetSliders: false,
140            fadingEffect: false,
141            normalScrollElements: null,
142            scrollOverflow: false,
143            scrollOverflowReset: false,
144            scrollOverflowHandler: window.fp_scrolloverflow ? window.fp_scrolloverflow.iscrollHandler : null,
145            scrollOverflowOptions: null,
146            touchSensitivity: 5,
147            touchWrapper: typeof containerSelector === 'string' ? $(containerSelector)[0] : containerSelector,
148            bigSectionsDestination: null,
149
150            //Accessibility
151            keyboardScrolling: true,
152            animateAnchor: true,
153            recordHistory: true,
154
155            //design
156            controlArrows: true,
157            controlArrowColor: '#fff',
158            verticalCentered: true,
159            sectionsColor : [],
160            paddingTop: 0,
161            paddingBottom: 0,
162            fixedElements: null,
163            responsive: 0, //backwards compabitility with responsiveWiddth
164            responsiveWidth: 0,
165            responsiveHeight: 0,
166            responsiveSlides: false,
167            parallax: false,
168            parallaxOptions: {
169                type: 'reveal',
170                percentage: 62,
171                property: 'translate'
172            },
173            cards: false,
174            cardsOptions: {
175                perspective: 100,
176                fadeContent: true,
177                fadeBackground: true
178            },
179
180            //Custom selectors
181            sectionSelector: SECTION_DEFAULT_SEL,
182            slideSelector: SLIDE_DEFAULT_SEL,
183
184            //events
185            v2compatible: false,
186            afterLoad: null,
187            onLeave: null,
188            afterRender: null,
189            afterResize: null,
190            afterReBuild: null,
191            afterSlideLoad: null,
192            onSlideLeave: null,
193            afterResponsive: null,
194
195            lazyLoading: true
196        }, options);
197
198        //flag to avoid very fast sliding for landscape sliders
199        var slideMoving = false;
200
201        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
202        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
203        var container = typeof containerSelector === 'string' ? $(containerSelector)[0] : containerSelector;
204        var windowsHeight = getWindowHeight();
205        var windowsWidth = getWindowWidth();
206        var isResizing = false;
207        var isWindowFocused = true;
208        var lastScrolledDestiny;
209        var lastScrolledSlide;
210        var canScroll = true;
211        var scrollings = [];
212        var controlPressed;
213        var startingSection;
214        var isScrollAllowed = {};
215        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
216        isScrollAllowed.k = deepExtend({}, isScrollAllowed.m);
217        var MSPointer = getMSPointer();
218        var events = {
219            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
220            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
221        };
222        var scrollBarHandler;
223
224        // taken from https://github.com/udacity/ud891/blob/gh-pages/lesson2-focus/07-modals-and-keyboard-traps/solution/modal.js
225        var focusableElementsString = 'a[href], area[href], input
225:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';
226
227        //cheks for passive event support
228        var g_supportsPassive = false;
229        try {
230          var opts = Object.defineProperty({}, 'passive', {
231            get: function() {
232              g_supportsPassive = true;
233            }
234          });
235          window.addEventListener("testPassive", null, opts);
236          window.removeEventListener("testPassive", null, opts);
237        } catch (e) {}
238
239        //timeouts
240        var resizeId;
241        var resizeHandlerId;
242        var afterSectionLoadsId;
243        var afterSlideLoadsId;
244        var scrollId;
245        var scrollId2;
246        var keydownId;
247        var g_doubleCheckHeightId;
248        var originals = deepExtend({}, options); //deep copy
249        var activeAnimation;
250        var g_initialAnchorsInDom = false;
251        var g_canFireMouseEnterNormalScroll = true;
252        var g_mediaLoadedId;
253        var extensions = [
254            'parallax',
255            'scrollOverflowReset',
256            'dragAndMove',
257            'offsetSections',
258            'fadingEffect',
259            'responsiveSlides',
260            'continuousHorizontal',
261            'interlockedSlides',
262            'scrollHorizontally',
263            'resetSliders',
264            'cards'
265        ];
266
267        displayWarnings();
268
269        //easeInOutCubic animation included in the plugin
270        window.fp_easings = deepExtend(window.fp_easings, {
271            easeInOutCubic: function (t, b, c, d) {
272                if ((t/=d/2) < 1) return c/2*t*t*t + b;return c/2*((t-=2)*t*t + 2) + b;
273            }
274        });
275
276        /**
277        * Sets the autoScroll option.
278        * It changes the scroll bar visibility and the history of the site as a result.
279        */
280        function setAutoScrolling(value, type){
281            //removing the transformation
282            if(!value){
283                silentScroll(0);
284            }
285
286            setVariableState('autoScrolling', value, type);
287
288            var element = $(SECTION_ACTIVE_SEL)[0];
289
290            if(options.autoScrolling && !options.scrollBar){
291                css($htmlBody, {
292                    'overflow': 'hidden',
293                    'height': '100%'
294                });
295
296                setRecordHistory(originals.recordHistory, 'internal');
297
298                //for IE touch devices
299                css(container, {
300                    '-ms-touch-action': 'none',
301                    'touch-action': 'none'
302                });
303
304                if(element != null){
305                    //moving the container up
306                    silentScroll(element.offsetTop);
307                }
308            }else{
309                css($htmlBody, {
310                    'overflow' : 'visible',
311                    'height' : 'initial'
312                });
313
314                var recordHistory = !options.autoScrolling ? false : originals.recordHistory;
315                setRecordHistory(recordHistory, 'internal');
316
317                //for IE touch devices
318                css(container, {
319                    '-ms-touch-action': '',
320                    'touch-action': ''
321                });
322
323                //scrolling the page to the section with no animation
324                if (element != null) {
325                    var scrollSettings = getScrollSettings(element.offsetTop);
326                    scrollSettings.element.scrollTo(0, scrollSettings.options);
327                }
328            }
329        }
330
331        /**
332        * Defines wheter to record the history for each hash change in the URL.
333        */
334        function setRecordHistory(value, type){
335            setVariableState('recordHistory', value, type);
336        }
337
338        /**
339        * Defines the scrolling speed
340        */
341        function setScrollingSpeed(value, type){
342            setVariableState('scrollingSpeed', value, type);
343        }
344
345        /**
346        * Sets fitToSection
347        */
348        function setFitToSection(value, type){
349            setVariableState('fitToSection', value, type);
350        }
351
352        /**
353        * Sets lockAnchors
354        */
355        function setLockAnchors(value){
356            options.lockAnchors = value;
357        }
358
359        /**
360        * Adds or remove the possibility of scrolling through sections by using the mouse wheel or the trackpad.
361        */
362        function setMouseWheelScrolling(value){
363            if(value){
364                addMouseWheelHandler();
365                addMiddleWheelHandler();
366            }else{
367                removeMouseWheelHandler();
368                removeMiddleWheelHandler();
369            }
370        }
371
372        /**
373        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
374        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
375        *
376        * @param directions string containing the direction or directions separated by comma.
377        */
378        function setAllowScrolling(value, directions){
379            if(typeof directions !== 'undefined'){
380                directions = directions.replace(/ /g,'').split(',');
381
382                directions.forEach(function (direction){
383                    setIsScrollAllowed(value, direction, 'm');
384                });
385            }
386            else{
387                setIsScrollAllowed(value, 'all', 'm');
388            }
389        }
390
391        /**
392        * Adds or remove the mouse wheel hijacking
393        */
394        function setMouseHijack(value){
395            if(value){
396                setMouseWheelScrolling(true);
397                addTouchHandler();
398            }else{
399                setMouseWheelScrolling(false);
400                removeTouchHandler();
401            }
402        }
403
404        /**
405        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
406        */
407        function setKeyboardScrolling(value, directions){
408            if(typeof directions !== 'undefined'){
409                directions = directions.replace(/ /g,'').split(',');
410
411                directions.forEach(function(direction){
412                    setIsScrollAllowed(value, direction, 'k');
413                });
414            }else{
415                setIsScrollAllowed(value, 'all', 'k');
416                options.keyboardScrolling = value;
417            }
418        }
419
420        /**
421        * Moves the page up one section.
422        */
423        function moveSectionUp(){
424            var prev = prevUntil($(SECTION_ACTIVE_SEL)[0], SECTION_SEL);
425
426            //looping to the bottom if there's no more sections above
427            if (!prev && (options.loopTop || options.continuousVertical)) {
428                prev = last($(SECTION_SEL));
429            }
430
431            if (prev != null) {
432                scrollPage(prev, null, true);
433            }
434        }
435
436        /**
437        * Moves the page down one section.
438        */
439        function moveSectionDown(){
440            var next = nextUntil($(SECTION_ACTIVE_SEL)[0], SECTION_SEL);
441
442            //looping to the top if there's no more sections below
443            if(!next &&
444                (options.loopBottom || options.continuousVertical)){
445                next = $(SECTION_SEL)[0];
446            }
447
448            if(next != null){
449                scrollPage(next, null, false);
450            }
451        }
452
453        /**
454        * Moves the page to the given section and slide with no animation.
455        * Anchors or index positions can be used as params.
456        */
457        function silentMoveTo(sectionAnchor, slideAnchor){
458            setScrollingSpeed (0, 'internal');
459            moveTo(sectionAnchor, slideAnchor);
460            setScrollingSpeed (originals.scrollingSpeed, 'internal');
461        }
462
463        /**
464        * Moves the page to the given section and slide.
465        * Anchors or index positions can be used as params.
466        */
467        function moveTo(sectionAnchor, slideAnchor){
468            var destiny = getSectionByAnchor(sectionAnchor);
469
470            if (typeof slideAnchor !== 'undefined'){
471                scrollPageAndSlide(sectionAnchor, slideAnchor);
472            }else if(destiny != null){
473                scrollPage(destiny);
474            }
475        }
476
477        /**
478        * Slides right the slider of the active section.
479        * Optional `section` param.
480        */
481        function moveSlideRight(section){
482            moveSlide('right', section);
483        }
484
485        /**
486        * Slides left the slider of the active section.
487        * Optional `section` param.
488        */
489        function moveSlideLeft(section){
490            moveSlide('left', section);
491        }
492
493        /**
494         * When resizing is finished, we adjust the slides sizes and positions
495         */
496        function reBuild(resizing){
497            if(hasClass(container, DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
498
499            isResizing = true;
500
501            //updating global vars
502            windowsHeight = getWindowHeight();
503            windowsWidth = getWindowWidth();
504
505            var sections = $(SECTION_SEL);
506            for (var i = 0; i < sections.length; ++i) {
507                var section = sections[i];
508                var slidesWrap = $(SLIDES_WRAPPER_SEL, section)[0];
509                var slides = $(SLIDE_SEL, section);
510
511                //adjusting the height of the table-cell for IE and Firefox
512                if(options.verticalCentered){
513                    css($(TABLE_CELL_SEL, section), {'height': getTableHeight(section) + 'px'});
514                }
515
516                css(section, {'height': windowsHeight + 'px'});
517
518                //adjusting the position fo the FULL WIDTH slides...
519                if (slides.length > 1) {
520                    landscapeScroll(slidesWrap, $(SLIDE_ACTIVE_SEL, slidesWrap)[0]);
521                }
522            }
523
524            if(options.scrollOverflow){
525                scrollBarHandler.createScrollBarForAll();
526            }
527
528            var activeSection = $(SECTION_ACTIVE_SEL)[0];
529            var sectionIndex = index(activeSection, SECTION_SEL);
530
531            //isn't it the first section?
532            if(sectionIndex){
533                //adjusting the position for the current section
534                silentMoveTo(sectionIndex + 1);
535            }
536
537            isResizing = false;
538            if(isFunction( options.afterResize ) && resizing){
539                options.afterResize.call(container, window.innerWidth, window.innerHeight);
540            }
541            if(isFunction( options.afterReBuild ) && !resizing){
542                options.afterReBuild.call(container);
543            }
544        }
545
546        /**
547        * Determines whether fullpage.js is in responsive mode or not.
548        */
549        function isResponsiveMode(){
550           return hasClass($body, RESPONSIVE);
551        }
552
553        /**
554        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
555        * are smaller than the set limit values.
556        */
557        function setResponsive(active){
558            var isResponsive = isResponsiveMode();
559
560            if(active){
561                if(!isResponsive){
562                    setAutoScrolling(false, 'internal');
563                    setFitToSection(false, 'internal');
564                    hide($(SECTION_NAV_SEL));
565                    addClass($body, RESPONSIVE);
566                    if(isFunction( options.afterResponsive )){
567                        options.afterResponsive.call( container, active);
568                    }
569
570                    //when on page load, we will remove scrolloverflow if necessary
571                    if(options.scrollOverflow){
572                        scrollBarHandler.createScrollBarForAll();
573                    }
574                }
575            }
576            else if(isResponsive){
577                setAutoScrolling(originals.autoScrolling, 'internal');
578                setFitToSection(originals.autoScrolling, 'internal');
579                show($(SECTION_NAV_SEL));
580                removeClass($body, RESPONSIVE);
581                if(isFunction( options.afterResponsive )){
582                    options.afterResponsive.call( container, active);
583                }
584            }
585        }
586
587        if(container){
588            //public functions
589            FP.version = '3.0.8';
590            FP.setAutoScrolling = setAutoScrolling;
591            FP.setRecordHistory = setRecordHistory;
592            FP.setScrollingSpeed = setScrollingSpeed;
593            FP.setFitToSection = setFitToSection;
594            FP.setLockAnchors = setLockAnchors;
595            FP.setMouseWheelScrolling = setMouseWheelScrolling;
596            FP.setAllowScrolling = setAllowScrolling;
597            FP.setKeyboardScrolling = setKeyboardScrolling;
598            FP.moveSectionUp = moveSectionUp;
599            FP.moveSectionDown = moveSectionDown;
600            FP.silentMoveTo = silentMoveTo;
601            FP.moveTo = moveTo;
602            FP.moveSlideRight = moveSlideRight;
603            FP.moveSlideLeft = moveSlideLeft;
604            FP.fitToSection = fitToSection;
605            FP.reBuild = reBuild;
606            FP.setResponsive = setResponsive;
607            FP.getFullpageData = function(){ return options; };
608            FP.destroy = destroy;
609            FP.getActiveSection = getActiveSection;
610            FP.getActiveSlide = getActiveSlide;
611
612            FP.test = {
613                top: '0px',
614                translate3d: 'translate3d(0px, 0px, 0px)',
615                translate3dH: (function(){
616                    var a = [];
617                    for(var i = 0; i < $(options.sectionSelector, container).length; i++){
618                        a.push('translate3d(0px, 0px, 0px)');
619                    }
620                    return a;
621                })(),
622                left: (function(){
623                    var a = [];
624                    for(var i = 0; i < $(options.sectionSelector, container).length; i++){
625                        a.push(0);
626                    }
627                    return a;
628                })(),
629                options: options,
630                setAutoScrolling: setAutoScrolling
631            };
632
633            //functions we want to share across files but which are not
634            //mean to be used on their own by developers
635            FP.shared = {
636                afterRenderActions: afterRenderActions,
637                isNormalScrollElement: false
638            };
639
640            window.fullpage_api = FP;
641
642            //using jQuery initialization? Creating the $.fn.fullpage object
643            if(options.$){
644                Object.keys(FP).forEach(function (key) {    
645                    options.$.fn.fullpage[key] = FP[key];   
646                });
647            }
648
649            init();
650
651            bindEvents();
652        }
653
654        function init(){
655            //if css3 is not supported, it will use jQuery animations
656            if(options.css3){
657                options.css3 = support3d();
658            }
659
660            options.scrollBar = options.scrollBar || options.hybrid;
661
662            setOptionsFromDOM();
663            prepareDom();
664            setAllowScrolling(true);
665            setMouseHijack(true);
666            setAutoScrolling(options.autoScrolling, 'internal');
667            responsive();
668
669            //setting the class for the body element
670            setBodyClass();
671
672            if(document.readyState === 'complete'){
673                scrollToAnchor();
674            }
675            window.addEventListener('load', scrollToAnchor);
676
677            //if we use scrollOverflow we'll fire afterRender in the scrolloverflow file
678            if(!options.scrollOverflow){
679                afterRenderActions();
680            }
681
682            doubleCheckHeight();
683        }
684
685        function bindEvents(){
686
687            //when scrolling...
688            window.addEventListener('scroll', scrollHandler);
689
690            //detecting any change on the URL to scroll to the given anchor link
691            //(a way to detect back history button as we play with the hashes on the URL)
692            window.addEventListener('hashchange', hashChangeHandler);
693
694            //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
695            window.addEventListener('blur', blurHandler);
696
697            //when resizing the site, we adjust the heights of the sections, slimScroll...
698            window.addEventListener('resize', resizeHandler);
699
700            //Sliding with arrow keys, both, vertical and horizontal
701            document.addEventListener('keydown', keydownHandler);
702
703            //to prevent scrolling while zooming
704            document.addEventListener('keyup', keyUpHandler);
705
706            //Scrolls to the section when clicking the navigation bullet
707            //simulating the jQuery .on('click') event using delegation
708            ['click', 'touchstart'].forEach(function(eventName){
709                document.addEventListener(eventName, delegatedEvents);
710            });
711
712            /**
713            * Applying normalScroll elements.
714            * Ignoring the scrolls over the specified selectors.
715            */
716            if(options.normalScrollElements){
717                ['mouseenter', 'touchstart'].forEach(function(eventName){
718                    forMouseLeaveOrTouch(eventName, false);
719                });
720
721                ['mouseleave', 'touchend'].forEach(function(eventName){
722                   forMouseLeaveOrTouch(eventName, true);
723                });
724            }
725        }
726
727        function delegatedEvents(e){
728            var target = e.target;
729
730            if(target && closest(target, SECTION_NAV_SEL + ' a')){
731                sectionBulletHandler.call(target, e);
732            }
733            else if(matches(target, SECTION_NAV_TOOLTIP_SEL)){
734                tooltipTextHandler.call(target);
735            }
736            else if(matches(target, SLIDES_ARROW_SEL)){
737                slideArrowHandler.call(target, e);
738            }
739            else if(matches(target, SLIDES_NAV_LINK_SEL) || closest(target, SLIDES_NAV_LINK_SEL) != null){
740                slideBulletHandler.call(target, e);
741            }
742            else if(closest(target, options.menu + ' [data-menuanchor]')){
743                menuItemsHandler.call(target, e);
744            }
745        }
746
747        function forMouseLeaveOrTouch(eventName, allowScrolling){
748            //a way to pass arguments to the onMouseEnterOrLeave function
749            document['fp_' + eventName] = allowScrolling;
750            document.addEventListener(eventName, onMouseEnterOrLeave, true);
750 //capturing phase
751        }
752
753        function onMouseEnterOrLeave(e) {
754            var type = e.type;
755            var isInsideOneNormalScroll = false;
756            var isUsingScrollOverflow = options.scrollOverflow;
757
758            //onMouseLeave will use the destination target, not the one we are moving away from
759            var target = type === 'mouseleave' ? e.toElement || e.relatedTarget : e.target;
760
761            //coming from closing a normalScrollElements modal or moving outside viewport?
762            if(target == document || !target){
763                setMouseHijack(true);
764
765                if(isUsingScrollOverflow){
766                    options.scrollOverflowHandler.setIscroll(target, true);
767                }
768                return;
769            }
770
771            if(type === 'touchend'){
772                g_canFireMouseEnterNormalScroll = false;
773                setTimeout(function(){
774                    g_canFireMouseEnterNormalScroll = true;
775                }, 800);
776            }
777
778            //preventing mouseenter event to do anything when coming from a touchEnd event
779            //fixing issue #3576
780            if(type === 'mouseenter' && !g_canFireMouseEnterNormalScroll){
781                return;
782            }
783
784            var normalSelectors = options.normalScrollElements.split(',');
785
786            normalSelectors.forEach(function(normalSelector){
787                if(!isInsideOneNormalScroll){
788                    var isNormalScrollTarget = matches(target, normalSelector);
789
790                    //leaving a child inside the normalScoll element is not leaving the normalScroll #3661
791                    var isNormalScrollChildFocused = closest(target, normalSelector);
792
793                    if(isNormalScrollTarget || isNormalScrollChildFocused){
794                        if(!FP.shared.isNormalScrollElement){
795                            setMouseHijack(false);
796
797                            if(isUsingScrollOverflow){
798                                options.scrollOverflowHandler.setIscroll(target, false);
799                            }
800                        }
801                        FP.shared.isNormalScrollElement = true;
802                        isInsideOneNormalScroll = true;
803                    }
804                }
805            });
806
807            //not inside a single normal scroll element anymore?
808            if(!isInsideOneNormalScroll && FP.shared.isNormalScrollElement){
809                setMouseHijack(true);
810                
811                if(isUsingScrollOverflow){
812                    options.scrollOverflowHandler.setIscroll(target, true);
813                }
814
815                FP.shared.isNormalScrollElement = false;
816            }
817        }
818
819        /**
820        * Checks the viewport a few times on a define interval of time to 
821        * see if it has changed in any of those. If that's the case, it resizes.
822        */
823        function doubleCheckHeight(){
824            for(var i = 1; i < 4; i++){
825                g_doubleCheckHeightId = setTimeout(adjustToNewViewport, 350 * i);
826            }
827        }
828
829        /**
830        * Adjusts a section to the viewport if it has changed.
831        */
832        function adjustToNewViewport(){
833            var newWindowHeight = getWindowHeight();
834            var newWindowWidth = getWindowWidth();
835
836            if(windowsHeight !== newWindowHeight || windowsWidth !== newWindowWidth){
837                windowsHeight = newWindowHeight;
838                windowsWidth = newWindowWidth;
839                reBuild(true);
840            }
841        }
842
843        /**
844        * Setting options from DOM elements if they are not provided.
845        */
846        function setOptionsFromDOM(){
847
848            //no anchors option? Checking for them in the DOM attributes
849            if(!options.anchors.length){
850                var anchorsAttribute = '[data-anchor]';
851                var anchors = $(options.sectionSelector.split(',').join(anchorsAttribute + ',') + anchorsAttribute, container);
852                if(anchors.length){
853                    g_initialAnchorsInDom = true;
854                    anchors.forEach(function(item){
855                        options.anchors.push(item.getAttribute('data-anchor').toString());
856                    });
857                }
858            }
859
860            //no tooltips option? Checking for them in the DOM attributes
861            if(!options.navigationTooltips.length){
862                var tooltipsAttribute = '[data-tooltip]';
863                var tooltips = $(options.sectionSelector.split(',').join(tooltipsAttribute + ',') + tooltipsAttribute, container);
864                if(tooltips.length){
865                    tooltips.forEach(function(item){
866                        options.navigationTooltips.push(item.getAttribute('data-tooltip').toString());
867                    });
868                }
869            }
870        }
871
872        /**
873        * Works over the DOM structure to set it up for the current fullpage options.
874        */
875        function prepareDom(){
876            css(container, {
877                'height': '100%',
878                'position': 'relative'
879            });
880
881            //adding a class to recognize the container internally in the code
882            addClass(container, WRAPPER);
883            addClass($html, ENABLED);
884
885            //due to https://github.com/alvarotrigo/fullPage.js/issues/1502
886            windowsHeight = getWindowHeight();
887
888            removeClass(container, DESTROYED); //in case it was destroyed before initializing it again
889
890            addInternalSelectors();
891
892            var sections = $(SECTION_SEL);
893
894            //styling the sections / slides / menu
895            for(var i = 0; i<sections.length; i++){
896                var sectionIndex = i;
897                var section = sections[i];
898                var slides = $(SLIDE_SEL, section);
899                var numSlides = slides.length;
900
901                //caching the original styles to add them back on destroy('all')
902                section.setAttribute('data-fp-styles', section.getAttribute('style'));
903
904                styleSection(section, sectionIndex);
905                styleMenu(section, sectionIndex);
906
907                // if there's any slide
908                if (numSlides > 0) {
909                    styleSlides(section, slides, numSlides);
910                }else{
911                    if(options.verticalCentered){
912                        addTableClass(section);
913                    }
914                }
915            }
916
917            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
918            if(options.fixedElements && options.css3){
919                $(options.fixedElements).forEach(function(item){
920                    $body.appendChild(item);
921                });
922            }
923
924            //vertical centered of the navigation + active bullet
925            if(options.navigation){
926                addVerticalNavigation();
927            }
928
929            enableYoutubeAPI();
930
931            if(options.scrollOverflow){
932                scrollBarHandler = options.scrollOverflowHandler.init(options);
933            }
934        }
935
936        /**
937        * Styles the horizontal slides for a section.
938        */
939        function styleSlides(section, slides, numSlides){
940            var sliderWidth = numSlides * 100;
941            var slideWidth = 100 / numSlides;
942
943            var slidesWrapper = document.createElement('div');
944            slidesWrapper.className = SLIDES_WRAPPER; //fp-slides
945            wrapAll(slides, slidesWrapper);
946
947            var slidesContainer = document.createElement('div');
948            slidesContainer.className = SLIDES_CONTAINER; //fp-slidesContainer
949            wrapAll(slides, slidesContainer);
950
951            css($(SLIDES_CONTAINER_SEL, section), {'width': sliderWidth + '%'});
952
953            if(numSlides > 1){
954                if(options.controlArrows){
955                    createSlideArrows(section);
956                }
957
958                if(options.slidesNavigation){
959                    addSlidesNavigation(section, numSlides);
960                }
961            }
962
963            slides.forEach(function(slide) {
964                css(slide, {'width': slideWidth + '%'});
965
966                if(options.verticalCentered){
967                    addTableClass(slide);
968                }
969            });
970
971            var startingSlide = $(SLIDE_ACTIVE_SEL, section)[0];
972
973            //if the slide won't be an starting point, the default will be the first one
974            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/slide by default.
975            if( startingSlide != null && (index($(SECTION_ACTIVE_SEL), SECTION_SEL) !== 0 || (index($(SECTION_ACTIVE_SEL), SECTION_SEL) === 0 && index(startingSlide) !== 0))){
976                silentLandscapeScroll(startingSlide, 'internal');
977            }else{
978                addClass(slides[0], ACTIVE);
979            }
980        }
981
982        /**
983        * Styling vertical sections
984        */
985        function styleSection(section, index){
986            //if no active section is defined, the 1st one will be the default one
987            if(!index && $(SECTION_ACTIVE_SEL)[0] == null) {
988                addClass(section, ACTIVE);
989            }
990            startingSection = $(SECTION_ACTIVE_SEL)[0];
991
992            css(section, {'height': windowsHeight + 'px'});
993
994            if(options.paddingTop){
995                css(section, {'padding-top': options.paddingTop});
996            }
997
998            if(options.paddingBottom){
999                css(section, {'padding-bottom': options.paddingBottom});
1000            }
1001
1002            if (typeof options.sectionsColor[index] !==  'undefined') {
1003                css(section, {'background-color': options.sectionsColor[index]});
1004            }
1005
1006            if (typeof options.anchors[index] !== 'undefined') {
1007                section.setAttribute('data-anchor', options.anchors[index]);
1008            }
1009        }
1010
1011        /**
1012        * Sets the data-anchor attributes to the menu elements and activates the current one.
1013        */
1014        function styleMenu(section, index){
1015            if (typeof options.anchors[index] !== 'undefined') {
1016                //activating the menu / nav element on load
1017                if(hasClass(section, ACTIVE)){
1018                    activateMenuAndNav(options.anchors[index], index);
1019                }
1020            }
1021
1022            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
1023            if(options.menu && options.css3 && closest($(options.menu)[0], WRAPPER_SEL) != null){
1024                $(options.menu).forEach(function(menu) {
1025                    $body.appendChild(menu);
1026                });
1027            }
1028        }
1029
1030        /**
1031        * Adds internal classes to be able to provide customizable selectors
1032        * keeping the link with the style sheet.
1033        */
1034        function addInternalSelectors(){
1035            addClass($(options.sectionSelector, container), SECTION);
1036            addClass($(options.slideSelector, container), SLIDE);
1037        }
1038
1039        /**
1040        * Creates the control arrows for the given section
1041        */
1042        function createSlideArrows(section){
1043            var arrows = [createElementFromHTML('<div class="' + SLIDES_ARROW_PREV + '"></div>'), createElementFromHTML('<div class="' + SLIDES_ARROW_NEXT + '"></div>')];
1044            after($(SLIDES_WRAPPER_SEL, section)[0], arrows);
1045
1046            if(options.controlArrowColor !== '#fff'){
1047                css($(SLIDES_ARROW_NEXT_SEL, section), {'border-color': 'transparent transparent transparent '+options.controlArrowColor});
1048                css($(SLIDES_ARROW_PREV_SEL, section), {'border-color': 'transparent '+ options.controlArrowColor + ' transparent transparent'});
1049            }
1050
1051            if(!options.loopHorizontal){
1052                hide($(SLIDES_ARROW_PREV_SEL, section));
1053            }
1054        }
1055
1056        /**
1057        * Creates a vertical navigation bar.
1058        */
1059        function addVerticalNavigation(){
1060            var navigation = document.createElement('div');
1061            navigation.setAttribute('id', SECTION_NAV);
1062
1063            var divUl = document.createElement('ul');
1064            navigation.appendChild(divUl);
1065
1066            appendTo(navigation, $body);
1067            var nav = $(SECTION_NAV_SEL)[0];
1068
1069            addClass(nav, 'fp-' + options.navigationPosition);
1070
1071            if(options.showActiveTooltip){
1072                addClass(nav, SHOW_ACTIVE_TOOLTIP);
1073            }
1074
1075            var li = '';
1076
1077            for (var i = 0; i < $(SECTION_SEL).length; i++) {
1078                var link = '';
1079                if (options.anchors.length) {
1080                    link = options.anchors[i];
1081                }
1082
1083                li += '<li><a href="#' + link + '"><span class="fp-sr-only">' + getBulletLinkName(i, 'Section') + '</span><span></span></a>';
1084
1085                // Only add tooltip if needed (defined by user)
1086                var tooltip = options.navigationTooltips[i];
1087
1088                if (typeof tooltip !== 'undefined' && tooltip !== '') {
1089                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' fp-' + options.navigationPosition + '">' + tooltip + '</div>';
1090                }
1091
1092                li += '</li>';
1093            }
1094            $('ul', nav)[0].innerHTML = li;
1095
1096            //centering it vertically
1097            css($(SECTION_NAV_SEL), {'margin-top': '-' + ($(SECTION_NAV_SEL)[0].offsetHeight/2) + 'px'});
1098
1099            //activating the current active section
1100
1101            var bullet = $('li', $(SECTION_NAV_SEL)[0])[index($(SECTION_ACTIVE_SEL)[0], SECTION_SEL)];
1102            addClass($('a', bullet), ACTIVE);
1103        }
1104
1105        /**
1106        * Gets the name for screen readers for a section/slide navigation bullet.
1107        */
1108        function getBulletLinkName(i, defaultName){
1109            return options.navigationTooltips[i]
1110                || options.anchors[i]
1111                || defaultName + ' ' + (i+1);
1112        }
1113
1114        /*
1115        * Enables the Youtube videos API so we can control their flow if necessary.
1116        */
1117        function enableYoutubeAPI(){
1118            $('iframe[src*="youtube.com/embed/"]', container).forEach(function(item){
1119                addURLParam(item, 'enablejsapi=1');
1120            });
1121        }
1122
1123        /**
1124        * Adds a new parameter and its value to the `src` of a given element
1125        */
1126        function addURLParam(element, newParam){
1127            var originalSrc = element.getAttribute('src');
1128            element.setAttribute('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
1129        }
1130
1131        /*
1132        * Returns the prefix sign to use for a new parameter in an existen URL.
1133        *
1134        * @return {String}  ? | &
1135        */
1136        function getUrlParamSign(url){
1137            return ( !/\?/.test( url ) ) ? '?' : '&';
1138        }
1139
1140        /**
1141        * Actions and callbacks to fire afterRender
1142        */
1143        function afterRenderActions(){
1144            var section = $(SECTION_ACTIVE_SEL)[0];
1145
1146            addClass(section, COMPLETELY);
1147
1148            lazyLoad(section);
1149            lazyLoadOthers();
1150            playMedia(section);
1151
1152            if(options.scrollOverflow){
1153                options.scrollOverflowHandler.afterLoad();
1154            }
1155
1156            if(isDestinyTheStartingSection() && isFunction(options.afterLoad) ){
1157                fireCallback('afterLoad', {
1158                    activeSection: section,
1159                    element: section,
1160                    direction: null,
1161
1162                    //for backwards compatibility callback (to be removed in a future!)
1163                    anchorLink: section.getAttribute('data-anchor'),
1164                    sectionIndex: index(section, SECTION_SEL)
1165                });
1166            }
1167
1168            if(isFunction(options.afterRender)){
1169                fireCallback('afterRender');
1170            }
1171        }
1172
1173        /**
1174        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
1175        */
1176        function isDestinyTheStartingSection(){
1177            var anchor = getAnchorsURL();
1178            var destinationSection = getSectionByAnchor(anchor.section);
1179            return !anchor.section || !destinationSection || typeof destinationSection !=='undefined' && index(destinationSection) === index(startingSection);
1180        }
1181
1182        var isScrolling = false;
1183        var lastScroll = 0;
1184
1185        //when scrolling...
1186        function scrollHandler(){
1187            var currentSection;
1188
1189            if(!options.autoScrolling || options.scrollBar){
1190                var currentScroll = getScrollTop();
1191                var scrollDirection = getScrollDirection(currentScroll);
1192                var visibleSectionIndex = 0;
1193                var screen_mid = currentScroll + (getWindowHeight() / 2.0);
1194                var isAtBottom = $body.offsetHeight - getWindowHeight() === currentScroll;
1195                var sections =  $(SECTION_SEL);
1196
1197                //when using `auto-height` for a small last section it won't be centered in the viewport
1198                if(isAtBottom){
1199                    visibleSectionIndex = sections.length - 1;
1200                }
1201                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
1202                else if(!currentScroll){
1203                    visibleSectionIndex = 0;
1204                }
1205
1206                //taking the section which is showing more content in the viewport
1207                else{
1208                    for (var i = 0; i < sections.length; ++i) {
1209                        var section = sections[i];
1210
1211                        // Pick the the last section which passes the middle line of the screen.
1212                        if (section.offsetTop <= screen_mid)
1213                        {
1214                            visibleSectionIndex = i;
1215                        }
1216                    }
1217                }
1218
1219                if(isCompletelyInViewPort(scrollDirection)){
1220                    if(!hasClass($(SECTION_ACTIVE_SEL)[0], COMPLETELY)){
1221                        addClass($(SECTION_ACTIVE_SEL)[0], COMPLETELY);
1222                        removeClass(siblings($(SECTION_ACTIVE_SEL)[0]), COMPLETELY);
1223                    }
1224                }
1225
1226                //geting the last one, the current one on the screen
1227                currentSection = sections[visibleSectionIndex];
1228
1229                //setting the visible section as active when manually scrolling
1230                //executing only once the first time we reach the section
1231                if(!hasClass(currentSection, ACTIVE)){
1232                    isScrolling = true;
1233                    var leavingSection = $(SECTION_ACTIVE_SEL)[0];
1234                    var leavingSectionIndex = index(leavingSection, SECTION_SEL) + 1;
1235                    var yMovement = getYmovement(currentSection);
1236                    var anchorLink  = currentSection.getAttribute('data-anchor');
1237                    var sectionIndex = index(currentSection, SECTION_SEL) + 1;
1238                    var activeSlide = $(SLIDE_ACTIVE_SEL, currentSection)[0];
1239                    var slideIndex;
1240                    var slideAnchorLink;
1241                    var callbacksParams = {
1242                        activeSection: leavingSection,
1243                        sectionIndex: sectionIndex -1,
1244                        anchorLink: anchorLink,
1245                        element: currentSection,
1246                        leavingSection: leavingSectionIndex,
1247                        direction: yMovement
1248                    };
1249
1250                    if(activeSlide){
1251                        slideAnchorLink = activeSlide.getAttribute('data-anchor');
1252                        slideIndex = index(activeSlide);
1253                    }
1254
1255                    if(canScroll){
1256                        addClass(currentSection, ACTIVE);
1257                        removeClass(siblings(currentSection), ACTIVE);
1258
1259                        if(isFunction( options.onLeave )){
1260                            fireCallback('onLeave', callbacksParams);
1261                        }
1262                        if(isFunction( options.afterLoad )){
1263                            fireCallback('afterLoad', callbacksParams);
1264                        }
1265
1266                        stopMedia(leavingSection);
1267                        lazyLoad(currentSection);
1268                        playMedia(currentSection);
1269
1270                        activateMenuAndNav(anchorLink, sectionIndex - 1);
1271
1272                        if(options.anchors.length){
1273                            //needed to enter in hashChange event when using the menu with anchor links
1274                            lastScrolledDestiny = anchorLink;
1275                        }
1276                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
1277                    }
1278
1279                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
1280                    clearTimeout(scrollId);
1281                    scrollId = setTimeout(function(){
1282                        isScrolling = false;
1283                    }, 100);
1284                }
1285
1286                if(options.fitToSection){
1287                    //for the auto adjust of the viewport to fit a whole section
1288                    clearTimeout(scrollId2);
1289
1290                    scrollId2 = setTimeout(function(){
1291                        //checking it again in case it changed during the delay
1292                        if(options.fitToSection &&
1293
1294                            //is the destination element bigger than the viewport?
1295                            $(SECTION_ACTIVE_SEL)[0].offsetHeight <= windowsHeight
1296                        ){
1297                            fitToSection();
1298                        }
1299                    }, options.fitToSectionDelay);
1300                }
1301            }
1302        }
1303
1304        /**
1305        * Fits the site to the nearest active section
1306        */
1307        function fitToSection(){
1308            //checking fitToSection again in case it was set to false before the timeout delay
1309            if(canScroll){
1310                //allows to scroll to an active section and
1311                //if the section is already active, we prevent firing callbacks
1312                isResizing = true;
1313
1314                scrollPage($(SECTION_ACTIVE_SEL)[0]);
1315                isResizing = false;
1316            }
1317        }
1318
1319        /**
1320        * Determines whether the active section has seen in its whole or not.
1321        */
1322        function isCompletelyInViewPort(movement){
1323            var top = $(SECTION_ACTIVE_SEL)[0].offsetTop;
1324            var bottom = top + getWindowHeight();
1325
1326            if(movement == 'up'){
1327                return bottom >= (getScrollTop() + getWindowHeight());
1328            }
1329            return top <= getScrollTop();
1330        }
1331
1332        /**
1333        * Determines whether a section is in the viewport or not.
1334        */
1335        function isSectionInViewport (el) {
1336            var rect = el.getBoundingClientRect();
1337            var top = rect.top;
1338            var bottom = rect.bottom;
1339
1340            //sometimes there's a 1px offset on the bottom of the screen even when the 
1341            //section's height is the window.innerHeight one. I guess because pixels won't allow decimals.
1342            //using this prevents from lazyLoading the section that is not yet visible 
1343            //(only 1 pixel offset is)
1344            var pixelOffset = 2;
1345            
1346            var isTopInView = top + pixelOffset < windowsHeight && top > 0;
1347            var isBottomInView = bottom > pixelOffset && bottom < windowsHeight;
1348
1349            return isTopInView || isBottomInView;
1350        }
1351
1352        /**
1353        * Gets the directon of the the scrolling fired by the scroll event.
1354        */
1355        function getScrollDirection(currentScroll){
1356            var direction = currentScroll > lastScroll ? 'down' : 'up';
1357
1358            lastScroll = currentScroll;
1359
1360            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
1361            previousDestTop = currentScroll;
1362
1363            return direction;
1364        }
1365
1366        /**
1367        * Determines the way of scrolling up or down:
1368        * by 'automatically' scrolling a section or by using the default and normal scrolling.
1369        */
1370        function scrolling(type){
1371            if (!isScrollAllowed.m[type]){
1372                return;
1373            }
1374
1375            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
1376
1377            if(options.scrollOverflow){
1378                var scrollable = options.scrollOverflowHandler.scrollable($(SECTION_ACTIVE_SEL)[0]);
1379                var check = (type === 'down') ? 'bottom' : 'top';
1380
1381                if(scrollable != null ){
1382                    //is the scrollbar at the start/end of the scroll?
1383                    if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
1384                        scrollSection();
1385                    }else{
1386                        return true;
1387                    }
1388                }else{
1389                    // moved up/down
1390                    scrollSection();
1391                }
1392            }else{
1393                // moved up/down
1394                scrollSection();
1395            }
1396        }
1397
1398        /*
1399        * Preventing bouncing in iOS #2285
1400        */
1401        function preventBouncing(e){
1402            if(options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
1403                //preventing the easing on iOS devices
1404                preventDefault(e);
1405            }
1406        }
1407
1408        var touchStartY = 0;
1409        var touchStartX = 0;
1410        var touchEndY = 0;
1411        var touchEndX = 0;
1412
1413        /* Detecting touch events
1414
1415        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
1416        * This way, the touchstart and the touch moves shows an small difference between them which is the
1417        * used one to determine the direction.
1418        */
1419        function touchMoveHandler(e){
1420            var activeSection = closest(e.target, SECTION_SEL) || $(SECTION_ACTIVE_SEL)[0];
1421
1422            if (isReallyTouch(e) ) {
1423
1424                if(options.autoScrolling){
1425                    //preventing the easing on iOS devices
1426                    preventDefault(e);
1427                }
1428
1429                var touchEvents = getEventsPage(e);
1430
1431                touchEndY = touchEvents.y;
1432                touchEndX = touchEvents.x;
1433
1434                //if movement in the X axys is greater than in the Y and the currect section has slides...
1435                if ($(SLIDES_WRAPPER_SEL, activeSection).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
1436
1437                    //is the movement greater than the minimum resistance to scroll?
1438                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > (getWindowWidth() / 100 * options.touchSensitivity)) {
1439                        if (touchStartX > touchEndX) {
1440                            if(isScrollAllowed.m.right){
1441                                moveSlideRight(activeSection); //next
1442                            }
1443                        } else {
1444                            if(isScrollAllowed.m.left){
1445                                moveSlideLeft(activeSection); //prev
1446                            }
1447                        }
1448                    }
1449                }
1450
1451                //vertical scrolling (only when autoScrolling is enabled)
1452                else if(options.autoScrolling && canScroll){
1453
1454                    //is the movement greater than the minimum resistance to scroll?
1455                    if (Math.abs(touchStartY - touchEndY) > (window.innerHeight / 100 * options.touchSensitivity)) {
1456                        if (touchStartY > touchEndY) {
1457                            scrolling('down');
1458                        } else if (touchEndY > touchStartY) {
1459                            scrolling('up');
1460                        }
1461                    }
1462                }
1463            }
1464        }
1465
1466        /**
1467        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
1468        * this way we make sure that is really a touch event what IE is detecting.
1469        */
1470        function isReallyTouch(e){
1471            //if is not IE   ||  IE is detecting `touch` or `pen`
1472            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
1473        }
1474
1475        /**
1476        * Handler for the touch start event.
1477        */
1478        function touchStartHandler(e){
1479
1480            //stopping the auto scroll to adjust to a section
1481            if(options.fitToSection){
1482                activeAnimation = false;
1483            }
1484
1485            if(isReallyTouch(e)){
1486                var touchEvents = getEventsPage(e);
1487                touchStartY = touchEvents.y;
1488                touchStartX = touchEvents.x;
1489            }
1490        }
1491
1492        /**
1493        * Gets the average of the last `number` elements of the given array.
1494        */
1495        function getAverage(elements, number){
1496            var sum = 0;
1497
1498            //taking `number` elements from the end to make the average, if there are not enought, 1
1499            var lastElements = elements.slice(Math.max(elements.length - number, 1));
1500
1501            for(var i = 0; i < lastElements.length; i++){
1502                sum = sum + lastElements[i];
1503            }
1504
1505            return Math.ceil(sum/number);
1506        }
1507
1508        /**
1509         * Detecting mousewheel scrolling
1510         *
1511         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
1512         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
1513         */
1514        var prevTime = new Date().getTime();
1515
1516        function MouseWheelHandler(e) {
1517            var curTime = new Date().getTime();
1518            var isNormalScroll = hasClass($(COMPLETELY_SEL)[0], NORMAL_SCROLL);
1519
1520            //is scroll allowed?
1521            if (!isScrollAllowed.m.down && !isScrollAllowed.m.up) {
1522                preventDefault(e);
1523                return false;
1524            }
1525
1526            //autoscrolling and not zooming?
1527            if(options.autoScrolling && !controlPressed && !isNormalScroll){
1528                // cross-browser wheel delta
1529                e = e || window.event;
1530                var value = e.wheelDelta || -e.deltaY || -e.detail;
1531                var delta = Math.max(-1, Math.min(1, value));
1532
1533                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
1534                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
1535
1536                //Limiting the array to 150 (lets not waste memory!)
1537                if(scrollings.length > 149){
1538                    scrollings.shift();
1539                }
1540
1541                //keeping record of the previous scrollings
1542                scrollings.push(Math.abs(value));
1543
1544                //preventing to scroll the site on mouse wheel when scrollbar is present
1545                if(options.scrollBar){
1546                    preventDefault(e);
1547                }
1548
1549                //time difference between the last scroll and the current one
1550                var timeDiff = curTime-prevTime;
1551                prevTime = curTime;
1552
1553                //haven't they scrolled in a while?
1554                //(enough to be consider a different scrolling action to scroll another section)
1555                if(timeDiff > 200){
1556                    //emptying the array, we dont care about old scrollings for our averages
1557                    scrollings = [];
1558                }
1559
1560                if(canScroll){
1561                    var averageEnd = getAverage(scrollings, 10);
1562                    var averageMiddle = getAverage(scrollings, 70);
1563                    var isAccelerating = averageEnd >= averageMiddle;
1564
1565                    //to avoid double swipes...
1566                    if(isAccelerating && isScrollingVertically){
1567                        //scrolling down?
1568                        if (delta < 0) {
1569                            scrolling('down');
1570
1571                        //scrolling up?
1572                        }else {
1573                            scrolling('up');
1574                        }
1575                    }
1576                }
1577
1578                return false;
1579            }
1580
1581            if(options.fitToSection){
1582                //stopping the auto scroll to adjust to a section
1583                activeAnimation = false;
1584            }
1585        }
1586
1587        /**
1588        * Slides a slider to the given direction.
1589        * Optional `section` param.
1590        */
1591        function moveSlide(direction, section){
1592            var activeSection = section == null ? $(SECTION_ACTIVE_SEL)[0] : section;
1593            var slides = $(SLIDES_WRAPPER_SEL, activeSection)[0];
1594
1595            // more than one slide needed and nothing should be sliding
1596            if (slides == null || slideMoving || $(SLIDE_SEL, slides).length < 2) {
1597                return;
1598            }
1599
1600            var currentSlide = $(SLIDE_ACTIVE_SEL, slides)[0];
1601            var destiny = null;
1602
1603            if(direction === 'left'){
1604                destiny = prevUntil(currentSlide, SLIDE_SEL);
1605            }else{
1606                destiny = nextUntil(currentSlide, SLIDE_SEL);
1607            }
1608
1609            //isn't there a next slide in the secuence?
1610            if(destiny == null){
1611                //respect loopHorizontal settin
1612                if (!options.loopHorizontal) return;
1613
1614                var slideSiblings = siblings(currentSlide);
1615                if(direction === 'left'){
1616                    destiny = slideSiblings[slideSiblings.length - 1]; //last
1617                }else{
1618                    destiny = slideSiblings[0]; //first
1619                }
1620            }
1621
1622            slideMoving = true && !FP.test.isTesting;
1623            landscapeScroll(slides, destiny, direction);
1624        }
1625
1626        /**
1627        * Maintains the active slides in the viewport
1628        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
1629        */
1630        function keepSlidesPosition(){
1631            var activeSlides = $(SLIDE_ACTIVE_SEL);
1632            for( var i =0; i<activeSlides.length; i++){
1633                silentLandscapeScroll(activeSlides[i], 'internal');
1634            }
1635        }
1636
1637        var previousDestTop = 0;
1638        /**
1639        * Returns the destination Y position based on the scrolling direction and
1640        * the height of the section.
1641        */
1642        function getDestinationPosition(element){
1643            var elementHeight = element.offsetHeight;
1644            var elementTop = element.offsetTop;
1645
1646            //top of the desination will be at the top of the viewport
1647            var position = elementTop;
1648            var isScrollingDown =  elementTop > previousDestTop;
1649            var sectionBottom = position - windowsHeight + elementHeight;
1650            var bigSectionsDestination = options.bigSectionsDestination;
1651
1652            //is the destination element bigger than the viewport?
1653            if(elementHeight > windowsHeight){
1654                //scrolling up?
1655                if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
1656                    position = sectionBottom;
1657                }
1658            }
1659
1660            //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
1661            else if(isScrollingDown || (isResizing && next(element) == null) ){
1662                //The bottom of the destination will be at the bottom of the viewport
1663                position = sectionBottom;
1664            }
1665
1666            /*
1667            Keeping record of the last scrolled position to determine the scrolling direction.
1668            No conventional methods can be used as the scroll bar might not be present
1669            AND the section might not be active if it is auto-height and didnt reach the middle
1670            of the viewport.
1671            */
1672            previousDestTop = position;
1673            return position;
1674        }
1675
1676        /**
1677        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
1678        */
1679        function scrollPage(element, callback, isMovementUp){
1680            if(element == null){ return; } //there's no element to scroll, leaving the function
1681
1682            var dtop = getDestinationPosition(element);
1683            var slideAnchorLink;
1684            var slideIndex;
1685
1686            //local variables
1687            var v = {
1688                element: element,
1689                callback: callback,
1690                isMovementUp: isMovementUp,
1691                dtop: dtop,
1692                yMovement: getYmovement(element),
1693                anchorLink: element.getAttribute('data-anchor'),
1694                sectionIndex: index(element, SECTION_SEL),
1695                activeSlide: $(SLIDE_ACTIVE_SEL, element)[0],
1696                activeSection: $(SECTION_ACTIVE_SEL)[0],
1697                leavingSection: index($(SECTION_ACTIVE_SEL), SECTION_SEL) + 1,
1698
1699                //caching the value of isResizing at the momment the function is called
1700                //because it will be checked later inside a setTimeout and the value might change
1701                localIsResizing: isResizing
1702            };
1703
1704            //quiting when destination scroll is the same as the current one
1705            if((v.activeSection == element && !isResizing) || (options.scrollBar && getScrollTop() === v.dtop && !hasClass(element, AUTO_HEIGHT) )){ return; }
1706
1707            if(v.activeSlide != null){
1708                slideAnchorLink = v.activeSlide.getAttribute('data-anchor');
1709                slideIndex = index(v.activeSlide);
1710            }
1711
1712            //callback (onLeave) if the site is not just resizing and readjusting the slides
1713            if(!v.localIsResizing){
1714                var direction = v.yMovement;
1715
1716                //required for continousVertical
1717                if(typeof isMovementUp !== 'undefined'){
1718                    direction = isMovementUp ? 'up' : 'down';
1719                }
1720
1721                //for the callback
1722                v.direction = direction;
1723
1724                if(isFunction(options.onLeave)){
1725                    if(fireCallback('onLeave', v) === false){
1726                        return;
1727                    }
1728                }
1729            }
1730
1731            // If continuousVertical && we need to wrap around
1732            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
1733                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
1734                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
1735
1736                v = createInfiniteSections(v);
1737            }
1738
1739            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
1740            if(!v.localIsResizing){
1741                stopMedia(v.activeSection);
1742            }
1743
1744            if(options.scrollOverflow){
1745                options.scrollOverflowHandler.beforeLeave();
1746            }
1747
1748            addClass(element, ACTIVE);
1749            removeClass(siblings(element), ACTIVE);
1750            lazyLoad(element);
1751
1752            if(options.scrollOverflow){
1753                options.scrollOverflowHandler.onLeave();
1754            }
1755
1756            //preventing from activating the MouseWheelHandler event
1757            //more than once if the page is scrolling
1758            canScroll = false || FP.test.isTesting;
1759
1760            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
1761
1762            performMovement(v);
1763
1764            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
1765            lastScrolledDestiny = v.anchorLink;
1766
1767            //avoid firing it twice (as it does also on scroll)
1768            activateMenuAndNav(v.anchorLink, v.sectionIndex);
1769        }
1770
1771        /**
1772        * Dispatch events & callbacks making sure it does it on the right format, depending on
1773        * whether v2compatible is being used or not.
1774        */
1775        function fireCallback(eventName, v){
1776            var eventData = getEventData(eventName, v);
1777
1778            if(!options.v2compatible){
1779                trigger(container, eventName, eventData);
1780
1781                if(options[eventName].apply(eventData[Object.keys(eventData)[0]], toArray(eventData)) === false){
1782                    return false;
1783                }
1784            }
1785            else{
1786                if(options[eventName].apply(eventData[0], eventData.slice(1)) === false){
1787                    return false;
1788                }
1789            }
1790
1791            return true;
1792        }
1793
1794        /**
1795        * Makes sure to only create a Panel object if the element exist
1796        */
1797        function nullOrSection(el){
1798            return el ? new Section(el) : null;
1799        }
1800
1801        function nullOrSlide(el){
1802            return el ? new Slide(el) : null;
1803        }
1804
1805        /**
1806        * Gets the event's data for the given event on the right format. Depending on whether
1807        * v2compatible is being used or not.
1808        */
1809        function getEventData(eventName, v){
1810            var paramsPerEvent;
1811
1812            if(!options.v2compatible){
1813
1814                //using functions to run only the necessary bits within the object
1815                paramsPerEvent = {
1816                    afterRender: function(){
1817                        return {
1818                            section: nullOrSection($(SECTION_ACTIVE_SEL)[0]),
1819                            slide: nullOrSlide($(SLIDE_ACTIVE_SEL, $(SECTION_ACTIVE_SEL)[0])[0])
1820                        };
1821                    },
1822                    onLeave: function(){
1823                        return {
1824                            origin: nullOrSection(v.activeSection),
1825                            destination: nullOrSection(v.element),
1826                            direction: v.direction
1827                        };
1828                    },
1829
1830                    afterLoad: function(){
1831                        return paramsPerEvent.onLeave();
1832                    },
1833
1834                    afterSlideLoad: function(){
1835                        return {
1836                            section: nullOrSection(v.section),
1837                            origin: nullOrSlide(v.prevSlide),
1838                            destination: nullOrSlide(v.destiny),
1839                            direction: v.direction
1840                        };
1841                    },
1842
1843                    onSlideLeave: function(){
1844                        return paramsPerEvent.afterSlideLoad();
1845                    }
1846                };
1847            }
1848            else{
1849                paramsPerEvent = {
1850                    afterRender: function(){ return [container]; },
1851                    onLeave: function(){ return [v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.direction]; },
1852                    afterLoad: function(){ return [v.element, v.anchorLink, (v.sectionIndex + 1)]; },
1853                    afterSlideLoad: function(){ return [v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex]; },
1854                    onSlideLeave: function(){ return [v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.direction, v.slideIndex]; },
1855                };
1856            }
1857
1858            return paramsPerEvent[eventName]();
1859        }
1860
1861        /**
1862        * Performs the vertical movement (by CSS3 or by jQuery)
1863        */
1864        function performMovement(v){
1865            // using CSS3 translate functionality
1866            if (options.css3 && options.autoScrolling && !options.scrollBar) {
1867
1868                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
1869                // that's why we round it to 0.
1870                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
1871                transformContainer(translate3d, true);
1872
1873                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
1874                //scrollingSpeed to change in case of using silentMoveTo();
1875                if(options.scrollingSpeed){
1876                    clearTimeout(afterSectionLoadsId);
1877                    afterSectionLoadsId = setTimeout(function () {
1878                        afterSectionLoads(v);
1879                    }, options.scrollingSpeed);
1880                }else{
1881                    afterSectionLoads(v);
1882                }
1883            }
1884
1885            // using JS to animate
1886            else{
1887                var scrollSettings = getScrollSettings(v.dtop);
1888                FP.test.top = -v.dtop + 'px';
1889
1890                scrollTo(scrollSettings.element, scrollSettings.options, options.scrollingSpeed, function(){
1891                    if(options.scrollBar){
1892
1893                        /* Hack!
1894                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
1895                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
1896
1897                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
1898                        */
1899                        setTimeout(function(){
1900                            afterSectionLoads(v);
1901                        },30);
1902                    }else{
1903                        afterSectionLoads(v);
1904                    }
1905                });
1906            }
1907        }
1908
1909        /**
1910        * Gets the scrolling settings depending on the plugin autoScrolling option
1911        */
1912        function getScrollSettings(top){
1913            var scroll = {};
1914
1915            //top property animation
1916            if(options.autoScrolling && !options.scrollBar){
1917                scroll.options = -top;
1918                scroll.element = $(WRAPPER_SEL)[0];
1919            }
1920
1921            //window real scrolling
1922            else{
1923                scroll.options = top;
1924                scroll.element = window;
1925            }
1926
1927            return scroll;
1928        }
1929
1930        /**
1931        * Adds sections before or after the current one to create the infinite effect.
1932        */
1933        function createInfiniteSections(v){
1934            // Scrolling down
1935            if (!v.isMovementUp) {
1936                // Move all previous sections to after the active section
1937                after($(SECTION_ACTIVE_SEL)[0], prevAll(v.activeSection, SECTION_SEL).reverse());
1938            }
1939            else { // Scrolling up
1940                // Move all next sections to before the active section
1941                before($(SECTION_ACTIVE_SEL)[0], nextAll(v.activeSection, SECTION_SEL));
1942            }
1943
1944            // Maintain the displayed position (now that we changed the element order)
1945            silentScroll($(SECTION_ACTIVE_SEL)[0].offsetTop);
1946
1947            // Maintain the active slides visible in the viewport
1948            keepSlidesPosition();
1949
1950            // save for later the elements that still need to be reordered
1951            v.wrapAroundElements = v.activeSection;
1952
1953            // Recalculate animation variables
1954            v.dtop = v.element.offsetTop;
1955            v.yMovement = getYmovement(v.element);
1956
1957            return v;
1958        }
1959
1960        /**
1961        * Fix section order after continuousVertical changes have been animated
1962        */
1963        function continuousVerticalFixSectionOrder (v) {
1964            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
1965            // finish moving the elements around so the direct navigation will function more simply
1966            if (v.wrapAroundElements == null) {
1967                return;
1968            }
1969
1970            if (v.isMovementUp) {
1971                before($(SECTION_SEL)[0], v.wrapAroundElements);
1972            }
1973            else {
1974                after($(SECTION_SEL)[$(SECTION_SEL).length-1], v.wrapAroundElements);
1975            }
1976
1977            silentScroll($(SECTION_ACTIVE_SEL)[0].offsetTop);
1978
1979            // Maintain the active slides visible in the viewport
1980            keepSlidesPosition();
1981        }
1982
1983        /**
1984        * Actions to do once the section is loaded.
1985        */
1986        function afterSectionLoads (v){
1987            continuousVerticalFixSectionOrder(v);
1988
1989            //callback (afterLoad) if the site is not just resizing and readjusting the slides
1990            if(isFunction(options.afterLoad) && !v.localIsResizing){
1991                fireCallback('afterLoad', v);
1992            }
1993
1994            if(options.scrollOverflow){
1995                options.scrollOverflowHandler.afterLoad();
1996            }
1997
1998            if(!v.localIsResizing){
1999                playMedia(v.element);
2000            }
2001
2002            addClass(v.element, COMPLETELY);
2003            removeClass(siblings(v.element), COMPLETELY);
2004            lazyLoadOthers();
2005
2006            canScroll = true;
2007
2008            if(isFunction(v.callback)){
2009                v.callback();
2010            }
2011        }
2012
2013        /**
2014        * Sets the value for the given attribute from the `data-` attribute with the same suffix
2015        * ie: data-srcset ==> srcset  |  data-src ==> src
2016        */
2017        function setSrc(element, attribute){
2018            element.setAttribute(attribute, element.getAttribute('data-' + attribute));
2019            element.removeAttribute('data-' + attribute);
2020        }
2021
2022        /**
2023        * Makes sure lazyload is done for other sections in the viewport that are not the
2024        * active one. 
2025        */
2026        function lazyLoadOthers(){
2027            var hasAutoHeightSections = $(AUTO_HEIGHT_SEL)[0] || isResponsiveMode() && $(AUTO_HEIGHT_RESPONSIVE_SEL)[0];
2028
2029            //quitting when it doesn't apply
2030            if (!options.lazyLoading || !hasAutoHeightSections){
2031                return;
2032            }
2033
2034            //making sure to lazy load auto-height sections that are in the viewport
2035            $(SECTION_SEL + ':not(' + ACTIVE_SEL + ')').forEach(function(section){
2036                if(isSectionInViewport(section)){
2037                    lazyLoad(section);
2038                }
2039            });
2040        }
2041
2042        /**
2043        * Lazy loads image, video and audio elements.
2044        */
2045        function lazyLoad(destiny){
2046            if (!options.lazyLoading){
2047                return;
2048            }
2049
2050            var panel = getSlideOrSection(destiny);
2051
2052            $('img[data-src], img[data-srcset], source[data-src], source[data-srcset], video[data-src], audio[data-src], iframe[data-src]', panel).forEach(function(element){
2053                ['src', 'srcset'].forEach(function(type){
2054                    var attribute = element.getAttribute('data-' + type);
2055                    if(attribute != null && attribute){
2056                        setSrc(element, type);
2057                        element.addEventListener('load', function(){
2058                            onMediaLoad(destiny);
2059                        });
2060                    }
2061                });
2062
2063                if(matches(element, 'source')){
2064                    var elementToPlay =  closest(element, 'video, audio');
2065                    if(elementToPlay){
2066                        elementToPlay.load();
2067                        elementToPlay.onloadeddata = function(){
2068                            onMediaLoad(destiny);
2069                        };
2070                    }
2071                }
2072            });
2073        }
2074
2075        /**
2076        * Callback firing when a lazy load media element has loaded.
2077        * Making sure it only fires one per section in normal conditions (if load time is not huge)
2078        */
2079        function onMediaLoad(section){
2080            if(options.scrollOverflow){
2081                clearTimeout(g_mediaLoadedId);
2082                g_mediaLoadedId = setTimeout(function(){
2083                    scrollBarHandler.createScrollBar(section);
2084                }, 200);
2085            }
2086        }
2087
2088        /**
2089        * Plays video and audio elements.
2090        */
2091        function playMedia(destiny){
2092            var panel = getSlideOrSection(destiny);
2093
2094            //playing HTML5 media elements
2095            $('video, audio', panel).forEach(function(element){
2096                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
2097                    element.play();
2098                }
2099            });
2100
2101            //youtube videos
2102            $('iframe[src*="youtube.com/embed/"]', panel).forEach(function(element){
2103                if ( element.hasAttribute('data-autoplay') ){
2104                    playYoutube(element);
2105                }
2106
2107                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
2108                element.onload = function() {
2109                    if ( element.hasAttribute('data-autoplay') ){
2110                        playYoutube(element);
2111                    }
2112                };
2113            });
2114        }
2115
2116        /**
2117        * Plays a youtube video
2118        */
2119        function playYoutube(element){
2120            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
2121        }
2122
2123        /**
2124        * Stops video and audio elements.
2125        */
2126        function stopMedia(destiny){
2127            var panel = getSlideOrSection(destiny);
2128
2129            //stopping HTML5 media elements
2130            $('video, audio', panel).forEach(function(element){
2131                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
2132                    element.pause();
2133                }
2134            });
2135
2136            //youtube videos
2137            $('iframe[src*="youtube.com/embed/"]', panel).forEach(function(element){
2138                if( /youtube\.com\/embed\//.test(element.getAttribute('src')) && !element.hasAttribute('data-keepplaying')){
2139                    element.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
2140                }
2141            });
2142        }
2143
2144        /**
2145        * Gets the active slide (or section) for the given section
2146        */
2147        function getSlideOrSection(destiny){
2148            var slide = $(SLIDE_ACTIVE_SEL, destiny);
2149            if( slide.length ) {
2150                destiny = slide[0];
2151            }
2152
2153            return destiny;
2154        }
2155
2156        /**
2157        * Scrolls to the anchor in the URL when loading the site
2158        */
2159        function scrollToAnchor(){
2160            var anchors =  getAnchorsURL();
2161            var sectionAnchor = anchors.section;
2162            var slideAnchor = anchors.slide;
2163
2164            if(sectionAnchor){  //if theres any #
2165                if(options.animateAnchor){
2166                    scrollPageAndSlide(sectionAnchor, slideAnchor);
2167                }else{
2168                    silentMoveTo(sectionAnchor, slideAnchor);
2169                }
2170            }
2171        }
2172
2173        /**
2174        * Detecting any change on the URL to scroll to the given anchor link
2175        * (a way to detect back history button as we play with the hashes on the URL)
2176        */
2177        function hashChangeHandler(){
2178            if(!isScrolling && !options.lockAnchors){
2179                var anchors = getAnchorsURL();
2180                var sectionAnchor = anchors.section;
2181                var slideAnchor = anchors.slide;
2182
2183                //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
2184                var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
2185                var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
2186
2187                if(sectionAnchor && sectionAnchor.length){
2188                    /*in order to call scrollpage() only once for each destination at a time
2189                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
2190                    event is fired on every scroll too.*/
2191                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove
2192                        || isFirstScrollMove
2193                        || (!slideMoving && lastScrolledSlide != slideAnchor )){
2194
2195                        scrollPageAndSlide(sectionAnchor, slideAnchor);
2196                    }
2197                }
2198            }
2199        }
2200
2201        //gets the URL anchors (section and slide)
2202        function getAnchorsURL(){
2203            var section;
2204            var slide;
2205            var hash = window.location.hash;
2206
2207            if(hash.length){
2208                //getting the anchor link in the URL and deleting the `#`
2209                var anchorsParts =  hash.replace('#', '').split('/');
2210
2211                //using / for visual reasons and not as a section/slide separator #2803
2212                var isFunkyAnchor = hash.indexOf('#/') > -1;
2213
2214                section = isFunkyAnchor ? '/' + anchorsParts[1] : decodeURIComponent(anchorsParts[0]);
2215
2216                var slideAnchor = isFunkyAnchor ? anchorsParts[2] : anchorsParts[1];
2217                if(slideAnchor && slideAnchor.length){
2218                    slide = decodeURIComponent(slideAnchor);
2219                }
2220            }
2221
2222            return {
2223                section: section,
2224                slide: slide
2225            };
2226        }
2227
2228        //Sliding with arrow keys, both, vertical and horizontal
2229        function keydownHandler(e) {
2230            clearTimeout(keydownId);
2231
2232            var activeElement = document.activeElement;
2233            var keyCode = e.keyCode;
2234
2235            //tab?
2236            if(keyCode === 9){
2237                onTab(e);
2238            }
2239
2240            else if(!matches(activeElement, 'textarea') && !matches(activeElement, 'input') && !matches(activeElement, 'select') &&
2241                activeElement.getAttribute('contentEditable') !== "true" && activeElement.getAttribute('contentEditable') !== '' &&
2242                options.keyboardScrolling && options.autoScrolling){
2243
2244                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
2245                var keyControls = [40, 38, 32, 33, 34];
2246                if(keyControls.indexOf(keyCode) > -1){
2247                    preventDefault(e);
2248                }
2249
2250                controlPressed = e.ctrlKey;
2251
2252                keydownId = setTimeout(function(){
2253                    onkeydown(e);
2254                },150);
2255            }
2256        }
2257
2258        function tooltipTextHandler(){
2259            /*jshint validthis:true */
2260            trigger(prev(this), 'click');
2261        }
2262
2263        //to prevent scrolling while zooming
2264        function keyUpHandler(e){
2265            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
2266                controlPressed = e.ctrlKey;
2267            }
2268        }
2269
2270        //binding the mousemove when the mouse's middle button is released
2271        function mouseDownHandler(e){
2272            //middle button
2273            if (e.which == 2){
2274                oldPageY = e.pageY;
2275                container.addEventListener('mousemove', mouseMoveHandler);
2276            }
2277        }
2278
2279        //unbinding the mousemove when the mouse's middle button is released
2280        function mouseUpHandler(e){
2281            //middle button
2282            if (e.which == 2){
2283                container.removeEventListener('mousemove', mouseMoveHandler);
2284            }
2285        }
2286
2287        /**
2288        * Makes sure the tab key will only focus elements within the current section/slide
2289        * preventing this way from breaking the page.
2290        * Based on "Modals and keyboard traps"
2291        * from https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex
2292        */
2293        function onTab(e){
2294            var isShiftPressed = e.shiftKey;
2295            var activeElement = document.activeElement;
2296            var focusableElements = getFocusables(getSlideOrSection($(SECTION_ACTIVE_SEL)[0]));
2297
2298            function preventAndFocusFirst(e){
2299                preventDefault(e);
2300                return focusableElements[0] ? focusableElements[0].focus() : null;
2301            }
2302
2303            //outside any section or slide? Let's not hijack the tab!
2304            if(isFocusOutside(e)){
2305                return;
2306            }
2307
2308            //is there an element with focus?
2309            if(activeElement){
2310                if(closest(activeElement, SECTION_ACTIVE_SEL + ',' + SECTION_ACTIVE_SEL + ' ' + SLIDE_ACTIVE_SEL) == null){
2311                    activeElement = preventAndFocusFirst(e);
2312                }
2313            }
2314
2315            //no element if focused? Let's focus the first one of the section/slide
2316            else{
2317                preventAndFocusFirst(e);
2318            }
2319
2320            //when reached the first or last focusable element of the section/slide
2321            //we prevent the tab action to keep it in the last focusable element
2322            if(!isShiftPressed && activeElement == focusableElements[focusableElements.length - 1] ||
2323                isShiftPressed && activeElement == focusableElements[0]
2324            ){
2325                preventDefault(e);
2326            }
2327        }
2328
2329        /**
2330        * Gets all the focusable elements inside the passed element.
2331        */
2332        function getFocusables(el){
2333            return [].slice.call($(focusableElementsString, el)).filter(function(item) {
2334                    return item.getAttribute('tabindex') !== '-1'
2335                    //are also not hidden elements (or with hidden parents)
2336                    && item.offsetParent !== null;
2337            });
2338        }
2339
2340        /**
2341        * Determines whether the focus is outside fullpage.js sections/slides or not.
2342        */
2343        function isFocusOutside(e){
2344            var allFocusables = getFocusables(document);
2345            var currentFocusIndex = allFocusables.indexOf(document.activeElement);
2346            var focusDestinationIndex = e.shiftKey ? currentFocusIndex - 1 : currentFocusIndex + 1;
2347            var focusDestination = allFocusables[focusDestinationIndex];
2348            var destinationItemSlide = nullOrSlide(closest(focusDestination, SLIDE_SEL));
2349            var destinationItemSection = nullOrSection(closest(focusDestination, SECTION_SEL));
2350
2351            return !destinationItemSlide && !destinationItemSection;
2352        }
2353
2354        //Scrolling horizontally when clicking on the slider controls.
2355        function slideArrowHandler(){
2356            /*jshint validthis:true */
2357            var section = closest(this, SECTION_SEL);
2358
2359            /*jshint validthis:true */
2360            if (hasClass(this, SLIDES_PREV)) {
2361                if(isScrollAllowed.m.left){
2362                    moveSlideLeft(section);
2363                }
2364            } else {
2365                if(isScrollAllowed.m.right){
2366                    moveSlideRight(section);
2367                }
2368            }
2369        }
2370
2371        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
2372        function blurHandler(){
2373            isWindowFocused = false;
2374            controlPressed = false;
2375        }
2376
2377        //Scrolls to the section when clicking the navigation bullet
2378        function sectionBulletHandler(e){
2379            preventDefault(e);
2380
2381            /*jshint validthis:true */
2382            var indexBullet = index(closest(this, SECTION_NAV_SEL + ' li'));
2383            scrollPage($(SECTION_SEL)[indexBullet]);
2384        }
2385
2386        //Scrolls the slider to the given slide destination for the given section
2387        function slideBulletHandler(e){
2388            preventDefault(e);
2389
2390            /*jshint validthis:true */
2391            var slides = $(SLIDES_WRAPPER_SEL, closest(this, SECTION_SEL))[0];
2392            var destiny = $(SLIDE_SEL, slides)[index(closest(this, 'li'))];
2393
2394            landscapeScroll(slides, destiny);
2395        }
2396
2397        //Menu item handler when not using anchors or using lockAnchors:true
2398        function menuItemsHandler(e){
2399            if($(options.menu)[0] && (options.lockAnchors || !options.anchors.length)){
2400                preventDefault(e);
2401                /*jshint validthis:true */
2402                moveTo(this.getAttribute('data-menuanchor'));
2403            }
2404        }
2405
2406        /**
2407        * Keydown event
2408        */
2409        function onkeydown(e){
2410            var shiftPressed = e.shiftKey;
2411            var activeElement = document.activeElement;
2412            var isMediaFocused = matches(activeElement, 'video') || matches(activeElement, 'audio');
2413
2414            //do nothing if we can not scroll or we are not using horizotnal key arrows.
2415            if(!canScroll && [37,39].indexOf(e.keyCode) < 0){
2416                return;
2417            }
2418
2419            switch (e.keyCode) {
2420                //up
2421                case 38:
2422                case 33:
2423                    if(isScrollAllowed.k.up){
2424                        moveSectionUp();
2425                    }
2426                    break;
2427
2428                //down
2429                case 32: //spacebar
2430
2431                    if(shiftPressed && isScrollAllowed.k.up && !isMediaFocused){
2432                        moveSectionUp();
2433                        break;
2434                    }
2435                /* falls through */
2436                case 40:
2437                case 34:
2438                    if(isScrollAllowed.k.down){
2439                        // space bar?
2440                        if(e.keyCode !== 32 || !isMediaFocused){
2441                            moveSectionDown();
2442                        }
2443                    }
2444                    break;
2445
2446                //Home
2447                case 36:
2448                    if(isScrollAllowed.k.up){
2449                        moveTo(1);
2450                    }
2451                    break;
2452
2453                //End
2454                case 35:
2455                     if(isScrollAllowed.k.down){
2456                        moveTo( $(SECTION_SEL).length );
2457                    }
2458                    break;
2459
2460                //left
2461                case 37:
2462                    if(isScrollAllowed.k.left){
2463                        moveSlideLeft();
2464                    }
2465                    break;
2466
2467                //right
2468                case 39:
2469                    if(isScrollAllowed.k.right){
2470                        moveSlideRight();
2471                    }
2472                    break;
2473
2474                default:
2475                    return; // exit this handler for other keys
2476            }
2477        }
2478
2479        /**
2480        * Detecting the direction of the mouse movement.
2481        * Used only for the middle button of the mouse.
2482        */
2483        var oldPageY = 0;
2484        function mouseMoveHandler(e){
2485            if(!options.autoScrolling){
2486                return;
2487            }
2488            if(canScroll){
2489                // moving up
2490                if (e.pageY < oldPageY && isScrollAllowed.m.up){
2491                    moveSectionUp();
2492                }
2493
2494                // moving down
2495                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
2496                    moveSectionDown();
2497                }
2498            }
2499            oldPageY = e.pageY;
2500        }
2501
2502        /**
2503        * Scrolls horizontal sliders.
2504        */
2505        function landscapeScroll(slides, destiny, direction){
2506            var section = closest(slides, SECTION_SEL);
2507            var v = {
2508                slides: slides,
2509                destiny: destiny,
2510                direction: direction,
2511                destinyPos: {left: destiny.offsetLeft},
2512                slideIndex: index(destiny),
2513                section: section,
2514                sectionIndex: index(section, SECTION_SEL),
2515                anchorLink: section.getAttribute('data-anchor'),
2516                slidesNav: $(SLIDES_NAV_SEL, section)[0],
2517                slideAnchor: getAnchor(destiny),
2518                prevSlide: $(SLIDE_ACTIVE_SEL, section)[0],
2519                prevSlideIndex: index($(SLIDE_ACTIVE_SEL, section)[0]),
2520
2521                //caching the value of isResizing at the momment the function is called
2522                //because it will be checked later inside a setTimeout and the value might change
2523                localIsResizing: isResizing
2524            };
2525            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
2526            v.direction = v.direction ? v.direction : v.xMovement;
2527
2528            //important!! Only do it when not resizing
2529            if(!v.localIsResizing){
2530                //preventing from scrolling to the next/prev section when using scrollHorizontally
2531                canScroll = false;
2532            }
2533
2534            if(options.onSlideLeave){
2535
2536                //if the site is not just resizing and readjusting the slides
2537                if(!v.localIsResizing && v.xMovement!=='none'){
2538                    if(isFunction( options.onSlideLeave )){
2539                        if( fireCallback('onSlideLeave', v) === false){
2540                            slideMoving = false;
2541                            return;
2542                        }
2543                    }
2544                }
2545            }
2546
2547            addClass(destiny, ACTIVE);
2548            removeClass(siblings(destiny), ACTIVE);
2549
2550            if(!v.localIsResizing){
2551                stopMedia(v.prevSlide);
2552                lazyLoad(destiny);
2553            }
2554
2555            if(!options.loopHorizontal && options.controlArrows){
2556                //hidding it for the fist slide, showing for the rest
2557                toggle($(SLIDES_ARROW_PREV_SEL, section), v.slideIndex!==0);
2558
2559                //hidding it for the last slide, showing for the rest
2560                toggle($(SLIDES_ARROW_NEXT_SEL, section), next(destiny) != null);
2561            }
2562
2563            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
2564            if(hasClass(section, ACTIVE) && !v.localIsResizing){
2565                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
2566            }
2567
2568            performHorizontalMove(slides, v, true);
2569        }
2570
2571
2572        function afterSlideLoads(v){
2573            activeSlidesNavigation(v.slidesNav, v.slideIndex);
2574
2575            //if the site is not just resizing and readjusting the slides
2576            if(!v.localIsResizing){
2577                if(isFunction( options.afterSlideLoad )){
2578                    fireCallback('afterSlideLoad', v);
2579                }
2580
2581                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
2582                //and to prevent double scroll right after a windows resize
2583                canScroll = true;
2584
2585                playMedia(v.destiny);
2586            }
2587
2588            //letting them slide again
2589            slideMoving = false;
2590        }
2591
2592        /**
2593        * Performs the horizontal movement. (CSS3 or jQuery)
2594        *
2595        * @param fireCallback {Bool} - determines whether or not to fire the callback
2596        */
2597        function performHorizontalMove(slides, v, fireCallback){
2598            var destinyPos = v.destinyPos;
2599
2600            if(options.css3){
2601                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
2602
2603                FP.test.translate3dH[v.sectionIndex] = translate3d;
2604                css(addAnimation($(SLIDES_CONTAINER_SEL, slides)), getTransforms(translate3d));
2605
2606                afterSlideLoadsId = setTimeout(function(){
2607                    if(fireCallback){
2608                        afterSlideLoads(v);
2609                    }
2610                }, options.scrollingSpeed);
2611            }else{
2612                FP.test.left[v.sectionIndex] = Math.round(destinyPos.left);
2613
2614                scrollTo(slides, Math.round(destinyPos.left), options.scrollingSpeed, function(){
2615                    if(fireCallback){
2616                        afterSlideLoads(v);
2617                    }
2618                });
2619            }
2620        }
2621
2622        /**
2623        * Sets the state for the horizontal bullet navigations.
2624        */
2625        function activeSlidesNavigation(slidesNav, slideIndex){
2626            if(options.slidesNavigation && slidesNav != null){
2627                removeClass($(ACTIVE_SEL, slidesNav), ACTIVE);
2628                addClass( $('a', $('li', slidesNav)[slideIndex] ), ACTIVE);
2629            }
2630        }
2631
2632        var previousHeight = windowsHeight;
2633
2634        /*
2635        * Resize event handler.
2636        */        
2637        function resizeHandler(){
2638            clearTimeout(resizeId);
2639
2640            //in order to call the functions only when the resize is finished
2641            //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing    
2642            resizeId = setTimeout(function(){
2643
2644                //issue #3336 
2645                //(some apps or browsers, like Chrome/Firefox for Mobile take time to report the real height)
2646                //so we check it 3 times with intervals in that case
2647                for(var i = 0; i< 4; i++){
2648                    resizeHandlerId = setTimeout(resizeActions, 200 * i);
2649                }
2650            }, 200);
2651        }
2652
2653        /**
2654        * When resizing the site, we adjust the heights of the sections, slimScroll...
2655        */
2656        function resizeActions(){
2657
2658            //checking if it needs to get responsive
2659            responsive();
2660
2661            // rebuild immediately on touch devices
2662            if (isTouchDevice) {
2663                var activeElement = document.activeElement;
2664
2665                //if the keyboard is NOT visible
2666                if (!matches(activeElement, 'textarea') && !matches(activeElement, 'input') && !matches(activeElement, 'select')) {
2667                    var currentHeight = getWindowHeight();
2668
2669                    //making sure the change in the viewport size is enough to force a rebuild. (20 % of the window to avoid problems when hidding scroll bars)
2670                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
2671                        reBuild(true);
2672                        previousHeight = currentHeight;
2673                    }
2674                }
2675            }
2676            else{
2677                adjustToNewViewport();
2678            }
2679        }
2680
2681        /**
2682        * Checks if the site needs to get responsive and disables autoScrolling if so.
2683        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
2684        */
2685        function responsive(){
2686            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
2687            var heightLimit = options.responsiveHeight;
2688
2689            //only calculating what we need. Remember its called on the resize event.
2690            var isBreakingPointWidth = widthLimit && window.innerWidth < widthLimit;
2691            var isBreakingPointHeight = heightLimit && window.innerHeight < heightLimit;
2692
2693            if(widthLimit && heightLimit){
2694                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
2695            }
2696            else if(widthLimit){
2697                setResponsive(isBreakingPointWidth);
2698            }
2699            else if(heightLimit){
2700                setResponsive(isBreakingPointHeight);
2701            }
2702        }
2703
2704        /**
2705        * Adds transition animations for the given element
2706        */
2707        function addAnimation(element){
2708            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
2709
2710            removeClass(element, NO_TRANSITION);
2711            return css(element, {
2712                '-webkit-transition': transition,
2713                'transition': transition
2714            });
2715        }
2716
2717        /**
2718        * Remove transition animations for the given element
2719        */
2720        function removeAnimation(element){
2721            return addClass(element, NO_TRANSITION);
2722        }
2723
2724        /**
2725        * Activating the vertical navigation bullets according to the given slide name.
2726        */
2727        function activateNavDots(name, sectionIndex){
2728            if(options.navigation && $(SECTION_NAV_SEL)[0] != null){
2729                    removeClass($(ACTIVE_SEL, $(SECTION_NAV_SEL)[0]), ACTIVE);
2730                if(name){
2731                    addClass( $('a[href="#' + name + '"]', $(SECTION_NAV_SEL)[0]), ACTIVE);
2732                }else{
2733                    addClass($('a', $('li', $(SECTION_NAV_SEL)[0])[sectionIndex]), ACTIVE);
2734                }
2735            }
2736        }
2737
2738        /**
2739        * Activating the website main menu elements according to the given slide name.
2740        */
2741        function activateMenuElement(name){
2742            $(options.menu).forEach(function(menu) {
2743                if(options.menu && menu != null){
2744                    removeClass($(ACTIVE_SEL, menu), ACTIVE);
2745                    addClass($('[data-menuanchor="'+name+'"]', menu), ACTIVE);
2746                }
2747            });
2748        }
2749
2750        /**
2751        * Sets to active the current menu and vertical nav items.
2752        */
2753        function activateMenuAndNav(anchor, index){
2754            activateMenuElement(anchor);
2755            activateNavDots(anchor, index);
2756        }
2757
2758        /**
2759        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
2760        * from the current section.
2761        */
2762        function getYmovement(destiny){
2763            var fromIndex = index($(SECTION_ACTIVE_SEL)[0], SECTION_SEL);
2764            var toIndex = index(destiny, SECTION_SEL);
2765            if( fromIndex == toIndex){
2766                return 'none';
2767            }
2768            if(fromIndex > toIndex){
2769                return 'up';
2770            }
2771            return 'down';
2772        }
2773
2774        /**
2775        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
2776        * from the current slide.
2777        */
2778        function getXmovement(fromIndex, toIndex){
2779            if( fromIndex == toIndex){
2780                return 'none';
2781            }
2782            if(fromIndex > toIndex){
2783                return 'left';
2784            }
2785            return 'right';
2786        }
2787
2788        function addTableClass(element){
2789            //In case we are styling for the 2nd time as in with reponsiveSlides
2790            if(!hasClass(element, TABLE)){
2791                var wrapper = document.createElement('div');
2792                wrapper.className = TABLE_CELL;
2793                wrapper.style.height = getTableHeight(element) + 'px';
2794
2795                addClass(element, TABLE);
2796                wrapInner(element, wrapper);
2797            }
2798        }
2799
2800        function getTableHeight(element){
2801            var sectionHeight = windowsHeight;
2802
2803            if(options.paddingTop || options.paddingBottom){
2804                var section = element;
2805                if(!hasClass(section, SECTION)){
2806                    section = closest(element, SECTION_SEL);
2807                }
2808
2809                var paddings = parseInt(getComputedStyle(section)['padding-top']) + parseInt(getComputedStyle(section)['padding-bottom']);
2810                sectionHeight = (windowsHeight - paddings);
2811            }
2812
2813            return sectionHeight;
2814        }
2815
2816        /**
2817        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
2818        */
2819        function transformContainer(translate3d, animated){
2820            if(animated){
2821                addAnimation(container);
2822            }else{
2823                removeAnimation(container);
2824            }
2825
2826            css(container, getTransforms(translate3d));
2827            FP.test.translate3d = translate3d;
2828
2829            //syncronously removing the class after the animation has been applied.
2830            setTimeout(function(){
2831                removeClass(container, NO_TRANSITION);
2832            },10);
2833        }
2834
2835        /**
2836        * Gets a section by its anchor / index
2837        */
2838        function getSectionByAnchor(sectionAnchor){
2839            var section = $(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]', container)[0];
2840            if(!section){
2841                var sectionIndex = typeof sectionAnchor !== 'undefined' ? sectionAnchor -1 : 0;
2842                section = $(SECTION_SEL)[sectionIndex];
2843            }
2844
2845            return section;
2846        }
2847
2848        /**
2849        * Gets a slide inside a given section by its anchor / index
2850        */
2851        function getSlideByAnchor(slideAnchor, section){
2852            var slide = $(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]', section)[0];
2853            if(slide == null){
2854                slideAnchor = typeof slideAnchor !== 'undefined' ? slideAnchor : 0;
2855                slide = $(SLIDE_SEL, section)[slideAnchor];
2856            }
2857
2858            return slide;
2859        }
2860
2861        /**
2862        * Scrolls to the given section and slide anchors
2863        */
2864        function scrollPageAndSlide(sectionAnchor, slideAnchor){
2865            var section = getSectionByAnchor(sectionAnchor);
2866
2867            //do nothing if there's no section with the given anchor name
2868            if(section == null) return;
2869
2870            var slide = getSlideByAnchor(slideAnchor, section);
2871
2872            //we need to scroll to the section and then to the slide
2873            if (getAnchor(section) !== lastScrolledDestiny && !hasClass(section, ACTIVE)){
2874                scrollPage(section, function(){
2875                    scrollSlider(slide);
2876                });
2877            }
2878            //if we were already in the section
2879            else{
2880                scrollSlider(slide);
2881            }
2882        }
2883
2884        /**
2885        * Scrolls the slider to the given slide destination for the given section
2886        */
2887        function scrollSlider(slide){
2888            if(slide != null){
2889                landscapeScroll(closest(slide, SLIDES_WRAPPER_SEL), slide);
2890            }
2891        }
2892
2893        /**
2894        * Creates a landscape navigation bar with dots for horizontal sliders.
2895        */
2896        function addSlidesNavigation(section, numSlides){
2897            appendTo(createElementFromHTML('<div class="' + SLIDES_NAV + '"><ul></ul></div>'), section);
2898            var nav = $(SLIDES_NAV_SEL, section)[0];
2899
2900            //top or bottom
2901            addClass(nav, 'fp-' + options.slidesNavPosition);
2902
2903            for(var i=0; i< numSlides; i++){
2904                appendTo(createElementFromHTML('<li><a href="#"><span class="fp-sr-only">'+ getBulletLinkName(i, 'Slide') +'</span><span></span></a></li>'), $('ul', nav)[0] );
2905            }
2906
2907            //centering it
2908            css(nav, {'margin-left': '-' + (nav.innerWidth/2) + 'px'});
2909
2910            addClass($('a', $('li', nav)[0] ), ACTIVE);
2911        }
2912
2913
2914        /**
2915        * Sets the state of the website depending on the active section/slide.
2916        * It changes the URL hash when needed and updates the body class.
2917        */
2918        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
2919            var sectionHash = '';
2920
2921            if(options.anchors.length && !options.lockAnchors){
2922
2923                //isn't it the first slide?
2924                if(slideIndex){
2925                    if(anchorLink != null){
2926                        sectionHash = anchorLink;
2927                    }
2928
2929                    //slide without anchor link? We take the index instead.
2930                    if(slideAnchor == null){
2931                        slideAnchor = slideIndex;
2932                    }
2933
2934                    lastScrolledSlide = slideAnchor;
2935                    setUrlHash(sectionHash + '/' + slideAnchor);
2936
2937                //first slide won't have slide anchor, just the section one
2938                }else if(slideIndex != null){
2939                    lastScrolledSlide = slideAnchor;
2940                    setUrlHash(anchorLink);
2941                }
2942
2943                //section without slides
2944                else{
2945                    setUrlHash(anchorLink);
2946                }
2947            }
2948
2949            setBodyClass();
2950        }
2951
2952        /**
2953        * Sets the URL hash.
2954        */
2955        function setUrlHash(url){
2956            if(options.recordHistory){
2957                location.hash = url;
2958            }else{
2959                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
2960                if(isTouchDevice || isTouch){
2961                    window.history.replaceState(undefined, undefined, '#' + url);
2962                }else{
2963                    var baseUrl = window.location.href.split('#')[0];
2964                    window.location.replace( baseUrl + '#' + url );
2965                }
2966            }
2967        }
2968
2969        /**
2970        * Gets the anchor for the given slide / section. Its index will be used if there's none.
2971        */
2972        function getAnchor(element){
2973            if(!element){
2974                return null;
2975            }
2976            var anchor = element.getAttribute('data-anchor');
2977            var elementIndex = index(element);
2978
2979            //Slide without anchor link? We take the index instead.
2980            if(anchor == null){
2981                anchor = elementIndex;
2982            }
2983
2984            return anchor;
2985        }
2986
2987        /**
2988        * Sets a class for the body of the page depending on the active section / slide
2989        */
2990        function setBodyClass(){
2991            var section = $(SECTION_ACTIVE_SEL)[0];
2992            var slide = $(SLIDE_ACTIVE_SEL, section)[0];
2993
2994            var sectionAnchor = getAnchor(section);
2995            var slideAnchor = getAnchor(slide);
2996
2997            var text = String(sectionAnchor);
2998
2999            if(slide){
3000                text = text + '-' + slideAnchor;
3001            }
3002
3003            //changing slash for dash to make it a valid CSS style
3004            text = text.replace('/', '-').replace('#','');
3005
3006            //removing previous anchor classes
3007            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
3008            $body.className = $body.className.replace(classRe, '');
3009
3010            //adding the current anchor
3011            addClass($body, VIEWING_PREFIX + '-' + text);
3012        }
3013
3014        /**
3015        * Checks for translate3d support
3016        * @return boolean
3017        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
3018        */
3019        function support3d() {
3020            var el = document.createElement('p'),
3021                has3d,
3022                transforms = {
3023                    'webkitTransform':'-webkit-transform',
3024                    'OTransform':'-o-transform',
3025                    'msTransform':'-ms-transform',
3026                    'MozTransform':'-moz-transform',
3027                    'transform':'transform'
3028                };
3029
3030            //preventing the style p:empty{display: none;} from returning the wrong result
3031            el.style.display = 'block';
3032
3033            // Add it to the body to get the computed style.
3034            document.body.insertBefore(el, null);
3035
3036            for (var t in transforms) {
3037                if (el.style[t] !== undefined) {
3038                    el.style[t] = 'translate3d(1px,1px,1px)';
3039                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
3040                }
3041            }
3042
3043            document.body.removeChild(el);
3044
3045            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
3046        }
3047
3048        /**
3049        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
3050        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
3051        */
3052        function removeMouseWheelHandler(){
3053            if (document.addEventListener) {
3054                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
3055                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
3056                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
3057            } else {
3058                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
3059            }
3060        }
3061
3062        /**
3063        * Adds the auto scrolling action for the mouse wheel and trackpad.
3064        * After this function is called, the mousewheel and trackpad movements will scroll through sections
3065        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
3066        */
3067        function addMouseWheelHandler(){
3068            var prefix = '';
3069            var _addEventListener;
3070
3071            if (window.addEventListener){
3072                _addEventListener = "addEventListener";
3073            }else{
3074                _addEventListener = "attachEvent";
3075                prefix = 'on';
3076            }
3077
3078            // detect available wheel event
3079            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
3080                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
3081                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
3082            var passiveEvent = g_supportsPassive ? {passive: false }
3082: false;
3083
3084            if(support == 'DOMMouseScroll'){
3085                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
3086            }
3087
3088            //handle MozMousePixelScroll in older Firefox
3089            else{
3090                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
3091            }
3092        }
3093
3094        /**
3095        * Binding the mousemove when the mouse's middle button is pressed
3096        */
3097        function addMiddleWheelHandler(){
3098            container.addEventListener('mousedown', mouseDownHandler);
3099            container.addEventListener('mouseup', mouseUpHandler);
3100        }
3101
3102        /**
3103        * Unbinding the mousemove when the mouse's middle button is released
3104        */
3105        function removeMiddleWheelHandler(){
3106            container.removeEventListener('mousedown', mouseDownHandler);
3107            container.removeEventListener('mouseup', mouseUpHandler);
3108        }
3109
3110        /**
3111        * Adds the possibility to auto scroll through sections on touch devices.
3112        */
3113        function addTouchHandler(){
3114            if(isTouchDevice || isTouch){
3115                if(options.autoScrolling){
3116                    $body.removeEventListener(events.touchmove, preventBouncing, {passive: false});
3117                    $body.addEventListener(events.touchmove, preventBouncing, {passive: false});
3118                }
3119
3120                var touchWrapper = options.touchWrapper;
3121                touchWrapper.removeEventListener(events.touchstart, touchStartHandler);
3122                touchWrapper.removeEventListener(events.touchmove, touchMoveHandler, {passive: false});
3123
3124                touchWrapper.addEventListener(events.touchstart, touchStartHandler);
3125                touchWrapper.addEventListener(events.touchmove, touchMoveHandler, {passive: false});
3126            }
3127        }
3128
3129        /**
3130        * Removes the auto scrolling for touch devices.
3131        */
3132        function removeTouchHandler(){
3133            if(isTouchDevice || isTouch){
3134                // normalScrollElements requires it off #2691
3135                if(options.autoScrolling){
3136                    $body.removeEventListener(events.touchmove, touchMoveHandler, {passive: false});
3137                    $body.removeEventListener(events.touchmove, preventBouncing, {passive: false});
3138                }
3139
3140                var touchWrapper = options.touchWrapper;
3141                touchWrapper.removeEventListener(events.touchstart, touchStartHandler);
3142                touchWrapper.removeEventListener(events.touchmove, touchMoveHandler, {passive: false});
3143            }
3144        }
3145
3146        /*
3147        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
3148        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
3149        */
3150        function getMSPointer(){
3151            var pointer;
3152
3153            //IE >= 11 & rest of browsers
3154            if(window.PointerEvent){
3155                pointer = { down: 'pointerdown', move: 'pointermove'};
3156            }
3157
3158            //IE < 11
3159            else{
3160                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
3161            }
3162
3163            return pointer;
3164        }
3165
3166        /**
3167        * Gets the pageX and pageY properties depending on the browser.
3168        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
3169        */
3170        function getEventsPage(e){
3171            var events = [];
3172
3173            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
3174            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
3175
3176            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
3177            if(isTouch && isReallyTouch(e) && options.scrollBar && typeof e.touches !== 'undefined'){
3178                events.y = e.touches[0].pageY;
3179                events.x = e.touches[0].pageX;
3180            }
3181
3182            return events;
3183        }
3184
3185        /**
3186        * Slides silently (with no animation) the active slider to the given slide.
3187        * @param noCallback {bool} true or defined -> no callbacks
3188        */
3189        function silentLandscapeScroll(activeSlide, noCallbacks){
3190            setScrollingSpeed(0, 'internal');
3191
3192            if(typeof noCallbacks !== 'undefined'){
3193                //preventing firing callbacks afterSlideLoad etc.
3194                isResizing = true;
3195            }
3196
3197            landscapeScroll(closest(activeSlide, SLIDES_WRAPPER_SEL), activeSlide);
3198
3199            if(typeof noCallbacks !== 'undefined'){
3200                isResizing = false;
3201            }
3202
3203            setScrollingSpeed(originals.scrollingSpeed, 'internal');
3204        }
3205
3206        /**
3207        * Scrolls silently (with no animation) the page to the given Y position.
3208        */
3209        function silentScroll(top){
3210            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
3211            // that's why we round it to 0.
3212            var roundedTop = Math.round(top);
3213
3214            if (options.css3 && options.autoScrolling && !options.scrollBar){
3215                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
3216                transformContainer(translate3d, false);
3217            }
3218            else if(options.autoScrolling && !options.scrollBar){
3219                css(container, {'top': -roundedTop + 'px'});
3220                FP.test.top = -roundedTop + 'px';
3221            }
3222            else{
3223                var scrollSettings = getScrollSettings(roundedTop);
3224                setScrolling(scrollSettings.element, scrollSettings.options);
3225            }
3226        }
3227
3228        /**
3229        * Returns the cross-browser transform string.
3230        */
3231        function getTransforms(translate3d){
3232            return {
3233                '-webkit-transform': translate3d,
3234                '-moz-transform': translate3d,
3235                '-ms-transform':translate3d,
3236                'transform': translate3d
3237            };
3238        }
3239
3240        /**
3241        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
3242        * @type  m (mouse) or k (keyboard)
3243        */
3244        function setIsScrollAllowed(value, direction, type){
3245            //up, down, left, right
3246            if(direction !== 'all'){
3247                isScrollAllowed[type][direction] = value;
3248            }
3249
3250            //all directions?
3251            else{
3252                Object.keys(isScrollAllowed[type]).forEach(function(key){
3253                    isScrollAllowed[type][key] = value;
3254                });
3255            }
3256        }
3257
3258        /*
3259        * Destroys fullpage.js plugin events and optinally its html markup and styles
3260        */
3261        function destroy(all){
3262            setAutoScrolling(false, 'internal');
3263            setAllowScrolling(true);
3264            setMouseHijack(false);
3265            setKeyboardScrolling(false);
3266            addClass(container, DESTROYED);
3267
3268            [
3269                afterSlideLoadsId, 
3270                afterSectionLoadsId,
3271                resizeId,
3272                scrollId,
3273                scrollId2,
3274                g_doubleCheckHeightId,
3275                resizeHandlerId
3276            ].forEach(function(timeoutId){
3277                clearTimeout(timeoutId);
3278            });
3279
3280            window.removeEventListener('scroll', scrollHandler);
3281            window.removeEventListener('hashchange', hashChangeHandler);
3282            window.removeEventListener('resize', resizeHandler);
3283
3284            document.removeEventListener('keydown', keydownHandler);
3285            document.removeEventListener('keyup', keyUpHandler);
3286
3287            ['click', 'touchstart'].forEach(function(eventName){
3288                document.removeEventListener(eventName, delegatedEvents);
3289            });
3290
3291            ['mouseenter', 'touchstart', 'mouseleave', 'touchend'].forEach(function(eventName){
3292                document.removeEventListener(eventName, onMouseEnterOrLeave, true); //true is required!
3293            });
3294
3295            //lets make a mess!
3296            if(all){
3297                destroyStructure();
3298            }
3299        }
3300
3301        /*
3302        * Removes inline styles added by fullpage.js
3303        */
3304        function destroyStructure(){
3305            //reseting the `top` or `translate` properties to 0
3306            silentScroll(0);
3307
3308            //loading all the lazy load content
3309            $('img[data-src], source[data-src], audio[data-src], iframe[data-src]', container).forEach(function(item){
3310                setSrc(item, 'src');
3311            });
3312
3313            $('img[data-srcset]').forEach(function(item){
3314                setSrc(item, 'srcset');
3315            });
3316
3317            remove($(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL));
3318
3319            //removing inline styles
3320            css($(SECTION_SEL), {
3321                'height': '',
3322                'background-color' : '',
3323                'padding': ''
3324            });
3325
3326            css($(SLIDE_SEL), {
3327                'width': ''
3328            });
3329
3330            css(container, {
3331                'height': '',
3332                'position': '',
3333                '-ms-touch-action': '',
3334                'touch-action': ''
3335            });
3336
3337            css($htmlBody, {
3338                'overflow': '',
3339                'height': ''
3340            });
3341
3342            // remove .fp-enabled class
3343            removeClass($html, ENABLED);
3344
3345            // remove .fp-responsive class
3346            removeClass($body, RESPONSIVE);
3347
3348            // remove all of the .fp-viewing- classes
3349            $body.className.split(/\s+/).forEach(function (className) {
3350                if (className.indexOf(VIEWING_PREFIX) === 0) {
3351                    removeClass($body, className);
3352                }
3353            });
3354
3355            //removing added classes
3356            $(SECTION_SEL + ', ' + SLIDE_SEL).forEach(function(item){
3357                if(options.scrollOverflowHandler && options.scrollOverflow){
3358                    options.scrollOverflowHandler.remove(item);
3359                }
3360                removeClass(item, TABLE + ' ' + ACTIVE + ' ' + COMPLETELY);
3361                var previousStyles = item.getAttribute('data-fp-styles');
3362                if(previousStyles){
3363                    item.setAttribute('style', item.getAttribute('data-fp-styles'));
3364                }
3365
3366                //removing anchors if they were not set using the HTML markup
3367                if(hasClass(item, SECTION) && !g_initialAnchorsInDom){
3368                    item.removeAttribute('data-anchor');
3369                }
3370            });
3371
3372            //removing the applied transition from the fullpage wrapper
3373            removeAnimation(container);
3374
3375            //Unwrapping content
3376            [TABLE_CELL_SEL, SLIDES_CONTAINER_SEL,SLIDES_WRAPPER_SEL].forEach(function(selector){
3377                $(selector, container).forEach(function(item){
3378                    //unwrap not being use in case there's no child element inside and its just text
3379                    unwrap(item);
3380                });
3381            });
3382
3383            //removing the applied transition from the fullpage wrapper
3384            css(container, {
3385                '-webkit-transition': 'none',
3386                'transition': 'none'
3387            });
3388
3389            //scrolling the page to the top with no animation
3390            window.scrollTo(0, 0);
3391
3392            //removing selectors
3393            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
3394            usedSelectors.forEach(function(item){
3395                removeClass($('.' + item), item);
3396            });
3397        }
3398
3399        /*
3400        * Sets the state for a variable with multiple states (original, and temporal)
3401        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
3402        * This function is used to keep track of both states, the original and the temporal one.
3403        * If type is not 'internal', then we assume the user is globally changing the variable.
3404        */
3405        function setVariableState(variable, value, type){
3406            options[variable] = value;
3407            if(type !== 'internal'){
3408                originals[variable] = value;
3409            }
3410        }
3411
3412        /**
3413        * Displays warnings
3414        */
3415        function displayWarnings(){
3416            var l = options['li' + 'c' + 'enseK' + 'e' + 'y'];
3417            var msgStyle = 'font-size: 15px;background:yellow;';
3418
3419            if(!isOK){
3420                showError('error', 'Fullpage.js version 3 has changed its license to GPLv3 and it requires a `licenseKey` option. Read about it here:');
3421                showError('error', 'https://github.com/alvarotrigo/fullPage.js#options.');
3422            }
3423            else if(l && l.length < 20){
3424                console.warn('%c This website was made using fullPage.js slider. More info on the following website:', msgStyle);
3425                console.warn('%c https://alvarotrigo.com/fullPage/', msgStyle);
3426            }
3427
3428            if(hasClass($html, ENABLED)){
3429                showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
3430                return;
3431            }
3432
3433            // Disable mutually exclusive settings
3434            if (options.continuousVertical &&
3435                (options.loopTop || options.loopBottom)) {
3436                options.continuousVertical = false;
3437                showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
3438            }
3439
3440            if(options.scrollOverflow &&
3441               (options.scrollBar || !options.autoScrolling)){
3442                showError('warn', 'Options scrollBar:true and autoScrolling:false are mutually exclusive with scrollOverflow:true. Sections with scrollOverflow might not work well in Firefox');
3443            }
3444
3445            if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
3446                options.continuousVertical = false;
3447                showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
3448            }
3449
3450            if(options.scrollOverflow && options.scrollOverflowHandler == null){
3451                options.scrollOverflow = false;
3452                showError('error', 'The option `scrollOverflow:true` requires the file `scrolloverflow.min.js`. Please include it before fullPage.js.');
3453            }
3454
3455            //using extensions? Wrong file!
3456            extensions.forEach(function(extension){
3457                //is the option set to true?
3458                if(options[extension]){
3459                    showError('warn', 'fullpage.js extensions require fullpage.extensions.min.js file instead of the usual fullpage.js. Requested: '+ extension);
3460                }
3461            });
3462
3463            //anchors can not have the same value as any element ID or NAME
3464            options.anchors.forEach(function(name){
3465
3466                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
3467                var nameAttr = [].slice.call($('[name]')).filter(function(item) {
3468                    return item.getAttribute('name') && item.getAttribute('name').toLowerCase() == name.toLowerCase();
3469                });
3470
3471                var idAttr = [].slice.call($('[id]')).filter(function(item) {
3472                    return item.getAttribute('id') && item.getAttribute('id').toLowerCase() == name.toLowerCase();
3473                });
3474
3475                if(idAttr.length || nameAttr.length ){
3476                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
3477                    var propertyName = idAttr.length ? 'id' : 'name';
3478
3479                    if(idAttr.length || nameAttr.length){
3480                        showError('error', '"' + name + '" is is being used by another element `'+ propertyName +'` property');
3481                    }
3482                }
3483            });
3484        }
3485
3486        /**
3487        * Getting the position of the element to scroll when using jQuery animations
3488        */
3489        function getScrolledPosition(element){
3490            var position;
3491
3492            //is not the window element and is a slide?
3493            if(element.self != window && hasClass(element, SLIDES_WRAPPER)){
3494                position = element.scrollLeft;
3495            }
3496            else if(!options.autoScrolling  || options.scrollBar){
3497                position = getScrollTop();
3498            }
3499            else{
3500                position = element.offsetTop;
3501            }
3502
3503            //gets the top property of the wrapper
3504            return position;
3505        }
3506
3507        /**
3508        * Simulates the animated scrollTop of jQuery. Used when css3:false or scrollBar:true or autoScrolling:false
3509        * http://stackoverflow.com/a/16136789/1081396
3510        */
3511        function scrollTo(element, to, duration, callback) {
3512            var start = getScrolledPosition(element);
3513            var change = to - start;
3514            var currentTime = 0;
3515            var increment = 20;
3516            activeAnimation = true;
3517
3518            var animateScroll = function(){
3519                if(activeAnimation){ //in order to stope it from other function whenever we want
3520                    var val = to;
3521
3522                    currentTime += increment;
3523
3524                    if(duration){
3525                        val = window.fp_easings[options.easing](currentTime, start, change, duration);
3526                    }
3527
3528                    setScrolling(element, val);
3529
3530                    if(currentTime < duration) {
3531                        setTimeout(animateScroll, increment);
3532                    }else if(typeof callback !== 'undefined'){
3533                        callback();
3534                    }
3535                }else if (currentTime < duration){
3536                    callback();
3537                }
3538            };
3539
3540            animateScroll();
3541        }
3542
3543        /**
3544        * Scrolls the page / slider the given number of pixels.
3545        * It will do it one or another way dependiong on the library's config.
3546        */
3547        function setScrolling(element, val){
3548            if(!options.autoScrolling || options.scrollBar || (element.self != window && hasClass(element, SLIDES_WRAPPER))){
3549
3550                //scrolling horizontally through the slides?
3551                if(element.self != window  && hasClass(element, SLIDES_WRAPPER)){
3552                    element.scrollLeft = val;
3553                }
3554                //vertical scroll
3555                else{
3556                    element.scrollTo(0, val);
3557                }
3558            }else{
3559                 element.style.top = val + 'px';
3560            }
3561        }
3562
3563        /**
3564        * Gets the active slide.
3565        */
3566        function getActiveSlide(){
3567            var activeSlide = $(SLIDE_ACTIVE_SEL, $(SECTION_ACTIVE_SEL)[0])[0];
3568            return nullOrSlide(activeSlide);
3569        }
3570
3571        /**
3572        * Gets the active section.
3573        */
3574        function getActiveSection(){
3575            return new Section($(SECTION_ACTIVE_SEL)[0]);
3576        }
3577
3578        /**
3579        * Item. Slide or Section objects share the same properties.
3580        */
3581        function Item(el, selector){
3582            this.anchor = el.getAttribute('data-anchor');
3583            this.item = el;
3584            this.index = index(el, selector);
3585            this.isLast = this.index === el.parentElement.querySelectorAll(selector).length -1;
3586            this.isFirst = !this.index;
3587        }
3588
3589        /**
3590        * Section object
3591        */
3592        function Section(el){
3593            Item.call(this, el, SECTION_SEL);
3594        }
3595
3596        /**
3597        * Slide object
3598        */
3599        function Slide(el){
3600            Item.call(this, el, SLIDE_SEL);
3601        }
3602
3603        return FP;
3604    } //end of $.fn.fullpage
3605
3606    //utils
3607    /**
3608    * Shows a message in the console of the given type.
3609    */
3610    function showError(type, text){
3611        window.console && window.console[type] && window.console[type]('fullPage: ' + text);
3612    }
3613
3614    /**
3615    * Equivalent or jQuery function $().
3616    */
3617    function $(selector, context){
3618        context = arguments.length > 1 ? context : document;
3619        return context ? context.querySelectorAll(selector) : null;
3620    }
3621
3622    /**
3623    * Extends a given Object properties and its childs.
3624    */
3625    function deepExtend(out) {
3626        out = out || {};
3627        for (var i = 1, len = arguments.length; i < len; ++i){
3628            var obj = arguments[i];
3629
3630            if(!obj){
3631              continue;
3632            }
3633
3634            for(var key in obj){
3635              if (!obj.hasOwnProperty(key)){
3636                continue;
3637              }
3638
3639              // based on https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
3640              if (Object.prototype.toString.call(obj[key]) === '[object Object]'){
3641                out[key] = deepExtend(out[key], obj[key]);
3642                continue;
3643              }
3644
3645              out[key] = obj[key];
3646            }
3647        }
3648        return out;
3649    }
3650
3651    /**
3652    * Checks if the passed element contains the passed class.
3653    */
3654    function hasClass(el, className){
3655        if(el == null){
3656            return false;
3657        }
3658        if (el.classList){
3659            return el.classList.contains(className);
3660        }
3661        return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
3662    }
3663
3664    /**
3665    * Gets the window height. Crossbrowser.
3666    */
3667    function getWindowHeight(){
3668        return 'innerHeight' in window ? window.innerHeight : document.documentElement.offsetHeight;
3669    }
3670
3671    /**
3672    * Gets the window width.
3673    */
3674    function getWindowWidth(){
3675        return window.innerWidth;
3676    }
3677
3678    /**
3679    * Set's the CSS properties for the passed item/s.
3680    * @param {NodeList|HTMLElement} items
3681    * @param {Object} props css properties and values.
3682    */
3683    function css(items, props) {
3684        items = getList(items);
3685
3686        var key;
3687        for (key in props) {
3688            if (props.hasOwnProperty(key)) {
3689                if (key !== null) {
3690                    for (var i = 0; i < items.length; i++) {
3691                        var item = items[i];
3692                        item.style[key] = props[key];
3693                    }
3694                }
3695            }
3696        }
3697
3698        return items;
3699    }
3700
3701    /**
3702    * Generic function to get the previous or next element.
3703    */
3704    function until(item, selector, fn){
3705        var sibling = item[fn];
3706        while(sibling && !matches(sibling, selector)){
3707            sibling = sibling[fn];
3708        }
3709
3710        return sibling;
3711    }
3712
3713    /**
3714    * Gets the previous element to the passed element that matches the passed selector.
3715    */
3716    function prevUntil(item, selector){
3717        return until(item, selector, 'previousElementSibling');
3718    }
3719
3720    /**
3721    * Gets the next element to the passed element that matches the passed selector.
3722    */
3723    function nextUntil(item, selector){
3724        return until(item, selector, 'nextElementSibling');
3725    }
3726
3727    /**
3728    * Gets the previous element to the passed element.
3729    */
3730    function prev(item){
3731        return item.previousElementSibling;
3732    }
3733
3734    /**
3735    * Gets the next element to the passed element.
3736    */
3737    function next(item){
3738        return item.nextElementSibling;
3739    }
3740
3741    /**
3742    * Gets the last element from the passed list of elements.
3743    */
3744    function last(item){
3745        return item[item.length-1];
3746    }
3747
3748    /**
3749    * Gets index from the passed element.
3750    * @param {String} selector is optional.
3751    */
3752    function index(item, selector) {
3753        item = isArrayOrList(item) ? item[0] : item;
3754        var children = selector != null? $(selector, item.parentNode) : item.parentNode.childNodes;
3755        var num = 0;
3756        for (var i=0; i<children.length; i++) {
3757             if (children[i] == item) return num;
3758             if (children[i].nodeType==1) num++;
3759        }
3760        return -1;
3761    }
3762
3763    /**
3764    * Gets an iterable element for the passed element/s
3765    */
3766    function getList(item){
3767        return !isArrayOrList(item) ? [item] : item;
3768    }
3769
3770    /**
3771    * Adds the display=none property for the passed element/s
3772    */
3773    function hide(el){
3774        el = getList(el);
3775
3776        for(var i = 0; i<el.length; i++){
3777            el[i].style.display = 'none';
3778        }
3779        return el;
3780    }
3781
3782    /**
3783    * Adds the display=block property for the passed element/s
3784    */
3785    function show(el){
3786        el = getList(el);
3787
3788        for(var i = 0; i<el.length; i++){
3789            el[i].style.display = 'block';
3790        }
3791        return el;
3792    }
3793
3794    /**
3795    * Checks if the passed element is an iterable element or not
3796    */
3797    function isArrayOrList(el){
3798        return Object.prototype.toString.call( el ) === '[object Array]' ||
3799            Object.prototype.toString.call( el ) === '[object NodeList]';
3800    }
3801
3802    /**
3803    * Adds the passed class to the passed element/s
3804    */
3805    function addClass(el, className) {
3806        el = getList(el);
3807
3808        for(var i = 0; i<el.length; i++){
3809            var item = el[i];
3810            if (item.classList){
3811                item.classList.add(className);
3812            }
3813            else{
3814              item.className += ' ' + className;
3815            }
3816        }
3817        return el;
3818    }
3819
3820    /**
3821    * Removes the passed class to the passed element/s
3822    * @param {String} `className` can be multiple classnames separated by whitespace
3823    */
3824    function removeClass(el, className){
3825        el = getList(el);
3826
3827        var classNames = className.split(' ');
3828
3829        for(var a = 0; a<classNames.length; a++){
3830            className = classNames[a];
3831            for(var i = 0; i<el.length; i++){
3832                var item = el[i];
3833                if (item.classList){
3834                    item.classList.remove(className);
3835                }
3836                else{
3837                    item.className = item.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
3838                }
3839            }
3840        }
3841        return el;
3842    }
3843
3844    /**
3845    * Appends the given element ot the given parent.
3846    */
3847    function appendTo(el, parent){
3848        parent.appendChild(el);
3849    }
3850
3851    /**
3852    Usage:
3853
3854    var wrapper = document.createElement('div');
3855    wrapper.className = 'fp-slides';
3856    wrap($('.slide'), wrapper);
3857
3858    https://jsfiddle.net/qwzc7oy3/15/ (vanilla)
3859    https://jsfiddle.net/oya6ndka/1/ (jquery equivalent)
3860    */
3861    function wrap(toWrap, wrapper, isWrapAll) {
3862        var newParent;
3863        wrapper = wrapper || document.createElement('div');
3864        for(var i = 0; i < toWrap.length; i++){
3865            var item = toWrap[i];
3866            if(isWrapAll && !i || !isWrapAll){
3867                newParent = wrapper.cloneNode(true);
3868                item.parentNode.insertBefore(newParent, item);
3869            }
3870            newParent.appendChild(item);
3871        }
3872        return toWrap;
3873    }
3874
3875    /**
3876    Usage:
3877    var wrapper = document.createElement('div');
3878    wrapper.className = 'fp-slides';
3879    wrap($('.slide'), wrapper);
3880
3881    https://jsfiddle.net/qwzc7oy3/27/ (vanilla)
3882    https://jsfiddle.net/oya6ndka/4/ (jquery equivalent)
3883    */
3884    function wrapAll(toWrap, wrapper) {
3885        wrap(toWrap, wrapper, true);
3886    }
3887
3888    /**
3889    * Usage:
3890    * wrapInner(document.querySelector('#pepe'), '<div class="test">afdas</div>');
3891    * wrapInner(document.querySelector('#pepe'), element);
3892    *
3893    * https://jsfiddle.net/zexxz0tw/6/
3894    *
3895    * https://stackoverflow.com/a/21817590/1081396
3896    */
3897    function wrapInner(parent, wrapper) {
3898        if (typeof wrapper === "string"){
3899            wrapper = createElementFromHTML(wrapper);
3900        }
3901
3902        parent.appendChild(wrapper);
3903
3904        while(parent.firstChild !== wrapper){
3905            wrapper.appendChild(parent.firstChild);
3906       }
3907    }
3908
3909    /**
3910    * Usage:
3911    * unwrap(document.querySelector('#pepe'));
3912    * unwrap(element);
3913    *
3914    * https://jsfiddle.net/szjt0hxq/1/
3915    *
3916    */
3917    function unwrap(wrapper) {
3918        var wrapperContent = document.createDocumentFragment();
3919        while (wrapper.firstChild) {
3920            wrapperContent.appendChild(wrapper.firstChild);
3921        }
3922
3923        wrapper.parentNode.replaceChild(wrapperContent, wrapper);
3924    }
3925
3926    /**
3927    * http://stackoverflow.com/questions/22100853/dom-pure-javascript-solution-to-jquery-closest-implementation
3928    * Returns the element or `false` if there's none
3929    */
3930    function closest(el, selector) {
3931        if(el && el.nodeType === 1){
3932            if(matches(el, selector)){
3933                return el;
3934            }
3935            return closest(el.parentNode, selector);
3936        }
3937        return null;
3938    }
3939
3940    /**
3941    * Places one element (rel) after another one or group of them (reference).
3942    * @param {HTMLElement} reference
3943    * @param {HTMLElement|NodeList|String} el
3944    * https://jsfiddle.net/9s97hhzv/1/
3945    */
3946    function after(reference, el) {
3947        insertBefore(reference, reference.nextSibling, el);
3948    }
3949
3950    /**
3951    * Places one element (rel) before another one or group of them (reference).
3952    * @param {HTMLElement} reference
3953    * @param {HTMLElement|NodeList|String} el
3954    * https://jsfiddle.net/9s97hhzv/1/
3955    */
3956    function before(reference, el) {
3957        insertBefore(reference, reference, el);
3958    }
3959
3960    /**
vendor: 4,223 bytes, lines 3961-4114
3961    * Based in https://stackoverflow.com/a/19316024/1081396
3962    * and https://stackoverflow.com/a/4793630/1081396
3963    */
3964    function insertBefore(reference, beforeElement, el){
3965        if(!isArrayOrList(el)){
3966            if(typeof el == 'string'){
3967                el = createElementFromHTML(el);
3968            }
3969            el = [el];
3970        }
3971
3972        for(var i = 0; i<el.length; i++){
3973            reference.parentNode.insertBefore(el[i], beforeElement);
3974        }
3975    }
3976
3977    //http://stackoverflow.com/questions/3464876/javascript-get-window-x-y-position-for-scroll
3978    function getScrollTop(){
3979        var doc = document.documentElement;
3980        return (window.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0);
3981    }
3982
3983    /**
3984    * Gets the siblings of the passed element
3985    */
3986    function siblings(el){
3987        return Array.prototype.filter.call(el.parentNode.children, function(child){
3988          return child !== el;
3989        });
3990    }
3991
3992    //for IE 9 ?
3993    function preventDefault(event){
3994        if(event.preventDefault){
3995            event.preventDefault();
3996        }
3997        else{
3998            event.returnValue = false;
3999        }
4000    }
4001
4002    /**
4003    * Determines whether the passed item is of function type.
4004    */
4005    function isFunction(item) {
4006      if (typeof item === 'function') {
4007        return true;
4008      }
4009      var type = Object.prototype.toString(item);
4010      return type === '[object Function]' || type === '[object GeneratorFunction]';
4011    }
4012
4013    /**
4014    * Trigger custom events
4015    */
4016    function trigger(el, eventName, data){
4017        var event;
4018        data = typeof data === 'undefined' ? {} : data;
4019
4020        // Native
4021        if(typeof window.CustomEvent === "function" ){
4022            event = new CustomEvent(eventName, {detail: data});
4023        }
4024        else{
4025            event = document.createEvent('CustomEvent');
4026            event.initCustomEvent(eventName, true, true, data);
4027        }
4028
4029        el.dispatchEvent(event);
4030    }
4031
4032    /**
4033    * Polyfill of .matches()
4034    */
4035    function matches(el, selector) {
4036        return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
4037    }
4038
4039    /**
4040    * Toggles the visibility of the passed element el.
4041    */
4042    function toggle(el, value){
4043        if(typeof value === "boolean"){
4044            for(var i = 0; i<el.length; i++){
4045                el[i].style.display = value ? 'block' : 'none';
4046            }
4047        }
4048        //we don't use it in other way, so no else :)
4049
4050        return el;
4051    }
4052
4053    /**
4054    * Creates a HTMLElement from the passed HTML string.
4055    * https://stackoverflow.com/a/494348/1081396
4056    */
4057    function createElementFromHTML(htmlString) {
4058        var div = document.createElement('div');
4059        div.innerHTML = htmlString.trim();
4060
4061        // Change this to div.childNodes to support multiple top-level nodes
4062        return div.firstChild;
4063    }
4064
4065    /**
4066    * Removes the passed item/s from the DOM.
4067    */
4068    function remove(items){
4069        items = getList(items);
4070        for(var i = 0; i<items.length; i++){
4071            var item = items[i];
4072            if(item && item.parentElement) {
4073                item.parentNode.removeChild(item);
4074            }
4075        }
4076    }
4077
4078    /**
4079    * Filters an array by the passed filter funtion.
4080    */
4081    function filter(el, filterFn){
4082        Array.prototype.filter.call(el, filterFn);
4083    }
4084
4085    //https://jsfiddle.net/w1rktecz/
4086    function untilAll(item, selector, fn){
4087        var sibling = item[fn];
4088        var siblings = [];
4089        while(sibling){
4090            if(matches(sibling, selector) || selector == null) {
4091                siblings.push(sibling);
4092            }
4093            sibling = sibling[fn];
4094        }
4095
4096        return siblings;
4097    }
4098
4099    /**
4100    * Gets all next elements matching the passed selector.
4101    */
4102    function nextAll(item, selector){
4103        return untilAll(item, selector, 'nextElementSibling');
4104    }
4105
4106    /**
4107    * Gets all previous elements matching the passed selector.
4108    */
4109    function prevAll(item, selector){
4110        return untilAll(item, selector, 'previousElementSibling');
4111    }
4112
4113    /**
4114    * Converts an object to an array.
4115    */
4116    function toArray(objectData){
4117        return Object.keys(objectData).map(function(key) {
4118           return objectData[key];
4119        });
4120    }
4121
4122    /**
4123    * forEach polyfill for IE
4124    * https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Browser_Compatibility
4125    */
4126    if (window.NodeList && !NodeList.prototype.forEach) {
4127        NodeList.prototype.forEach = function (callback, thisArg) {
4128            thisArg = thisArg || window;
4129            for (var i = 0; i < this.length; i++) {
4130                callback.call(thisArg, this[i], i, this);
4131            }
4132        };
4133    }
4134
4135    //utils are public, so we can use it wherever we want
4136    window.fp_utils = {
4137        $: $,
4138        deepExtend: deepExtend,
4139        hasClass: hasClass,
4140        getWindowHeight: getWindowHeight,
4141        css: css,
4142        until: until,
4143        prevUntil: prevUntil,
4144        nextUntil: nextUntil,
4145        prev: prev,
4146        next: next,
4147        last: last,
4148        index: index,
4149        getList: getList,
4150        hide: hide,
4151        show: show,
4152        isArrayOrList: isArrayOrList,
4153        addClass: addClass,
4154        removeClass: removeClass,
4155        appendTo: appendTo,
4156        wrap: wrap,
4157        wrapAll: wrapAll,
4158        wrapInner: wrapInner,
4159        unwrap: unwrap,
4160        closest: closest,
4161        after: after,
4162        before: before,
4163        insertBefore: insertBefore,
4164        getScrollTop: getScrollTop,
4165        siblings: siblings,
4166        preventDefault: preventDefault,
4167        isFunction: isFunction,
4168        trigger: trigger,
4169        matches: matches,
4170        toggle: toggle,
4171        createElementFromHTML: createElementFromHTML,
4172        remove: remove,
4173        filter: filter,
4174        untilAll: untilAll,
4175        nextAll: nextAll,
4176        prevAll: prevAll,
4177        showError: showError
4178    };
4179
4180    return initialise;
4181}));
4182
4183/**
4184 * jQuery adapter for fullPage.js 3.0.0
4185 */
4186if(window.jQuery && window.fullpage){
4187    (function ($, fullpage) {
4188        'use strict';
4189
4190        // No jQuery No Go
4191        if (!$ || !fullpage) {
4192            window.fp_utils.showError('error', 'jQuery is required to use the jQuery fullpage adapter!');
4193            return;
4194        }
4195
4196        $.fn.fullpage = function(options) {
4197            options = $.extend({}, options, {'$': $});
4198            var instance = new fullpage(this[0], options);
4199        };
4200    })(window.jQuery, window.fullpage);
4201}

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.