PageSourceSearch

https://www.vcommission.com/wp-content/themes/vcommission/js/fullpage.js?ver=7.1.2

js vcommission.com collected 2026-09-25 08:38:52 UTC 157,254 bytes, 4,236 lines download raw bytes

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

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.