PageSourceSearch

https://theyil.co.kr/web/upload/addbase/fullpage.js

js theyil.co.kr collected 2026-10-06 14:04:09 UTC 153,188 bytes, 4,242 lines download raw bytes

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

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.