PageSourceSearch

http://05m-kp.com/cn/js/jquery.fullPage.3.0.4.js

js 05m-kp.com collected 2026-10-09 04:32:43 UTC 147,262 bytes, 3,975 lines download raw bytes

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

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.