PageSourceSearch

https://www.giantec-semi.com/assets/addons/cms/frontend/js/jquery.fullPage.min.js

js giantec-semi.com collected 2026-10-05 07:30:19 UTC 148,200 bytes, 4,084 lines download raw bytes

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

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.