PageSourceSearch

https://www.kaipuyun.cn/kp/libs/jquery.fullPage.js

js kaipuyun.cn collected 2026-10-03 23:27:50 UTC 155,237 bytes, 4,188 lines download raw bytes

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

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.