PageSourceSearch

https://drdeitrickg.com/wp-content/themes/webcore/assets/js/jquery.fullPage.js?ver=1791446160

js drdeitrickg.com collected 2026-10-08 07:56:32 UTC 120,622 bytes, 3,125 lines download raw bytes

1/*!
2 * fullPage 2.9.4
3 * https://github.com/alvarotrigo/fullPage.js
4 * @license MIT licensed
5 *
6 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
7 */
8(function(global, factory) {
9    'use strict';
10    if (typeof define === 'function' && define.amd) {
11        define(['jquery'], function($) {
12          return factory($, global, global.document, global.Math);
13        });
14    } else if (typeof exports === "object" && exports) {
15        module.exports = factory(require('jquery'), global, global.document, global.Math);
16    } else {
17        factory(jQuery, global, global.document, global.Math);
18    }
19})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
20    'use strict';
21
22    // keeping central set of classnames and selectors
23    var WRAPPER =               'fullpage-wrapper';
24    var WRAPPER_SEL =           '.' + WRAPPER;
25
26    // slimscroll
27    var SCROLLABLE =            'fp-scrollable';
28    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
29
30    // util
31    var RESPONSIVE =            'fp-responsive';
32    var NO_TRANSITION =         'fp-notransition';
33    var DESTROYED =             'fp-destroyed';
34    var ENABLED =               'fp-enabled';
35    var VIEWING_PREFIX =        'fp-viewing';
36    var ACTIVE =                'active';
37    var ACTIVE_SEL =            '.' + ACTIVE;
38    var COMPLETELY =            'fp-completely';
39    var COMPLETELY_SEL =        '.' + COMPLETELY;
40
41    // section
42    var SECTION_DEFAULT_SEL =   '.section';
43    var SECTION =               'fp-section';
44    var SECTION_SEL =           '.' + SECTION;
45    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
46    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
47    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
48    var TABLE_CELL =            'fp-tableCell';
49    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
50    var AUTO_HEIGHT =           'fp-auto-height';
51    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
52    var NORMAL_SCROLL =         'fp-normal-scroll';
53    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
54
55    // section nav
56    var SECTION_NAV =           'fp-nav';
57    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
58    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
59    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
60    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
61
62    // slide
63    var SLIDE_DEFAULT_SEL =     '.slide';
64    var SLIDE =                 'fp-slide';
65    var SLIDE_SEL =             '.' + SLIDE;
66    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
67    var SLIDES_WRAPPER =        'fp-slides';
68    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
69    var SLIDES_CONTAINER =      'fp-slidesContainer';
70    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
71    var TABLE =                 'fp-table';
72
73    // slide nav
74    var SLIDES_NAV =            'fp-slidesNav';
75    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
76    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
77    var SLIDES_ARROW =          'fp-controlArrow';
78    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
79    var SLIDES_PREV =           'fp-prev';
80    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
81    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
82    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
83    var SLIDES_NEXT =           'fp-next';
84    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
85    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
86    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
87
88    var $window = $(window);
89    var $document = $(document);
90
91    // Default options for iScroll.js used when using scrollOverflow
92    var iscrollOptions = {
93        scrollbars: true,
94        mouseWheel: true,
95        hideScrollbars: false,
96        fadeScrollbars: false,
97        disableMouse: true,
98        interactiveScrollbars: true
99    };
100
101    $.fn.fullpage = function(options) {
102        //only once my friend!
103        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
104
105        // common jQuery objects
106        var $htmlBody = $('html, body');
107        var $body = $('body');
108
109        var FP = $.fn.fullpage;
110
111        // Creating some defaults, extending them with any options that were provided
112        options = $.extend({
113            //navigation
114            menu: false,
115            anchors:[],
116            lockAnchors: false,
117            navigation: false,
118            navigationPosition: 'right',
119            navigationTooltips: [],
120            showActiveTooltip: false,
121            slidesNavigation: false,
122            slidesNavPosition: 'bottom',
123            scrollBar: false,
124            hybrid: false,
125
126            //scrolling
127            css3: true,
128            scrollingSpeed: 700,
129            autoScrolling: true,
130            fitToSection: true,
131            fitToSectionDelay: 1000,
132            easing: 'easeInOutCubic',
133            easingcss3: 'ease',
134            loopBottom: false,
135            loopTop: false,
136            loopHorizontal: true,
137            continuousVertical: false,
138            continuousHorizontal: false,
139            scrollHorizontally: false,
140            interlockedSlides: false,
141            dragAndMove: false,
142            offsetSections: false,
143            resetSliders: false,
144            fadingEffect: false,
145            normalScrollElements: null,
146            scrollOverflow: false,
147            scrollOverflowReset: false,
148            scrollOverflowHandler: iscrollHandler,
149            scrollOverflowOptions: null,
150            touchSensitivity: 5,
151            normalScrollElementTouchThreshold: 5,
152            bigSectionsDestination: null,
153
154            //Accessibility
155            keyboardScrolling: true,
156            animateAnchor: true,
157            recordHistory: true,
158
159            //design
160            controlArrows: true,
161            controlArrowColor: '#fff',
162            verticalCentered: true,
163            sectionsColor : [],
164            paddingTop: 0,
165            paddingBottom: 0,
166            fixedElements: null,
167            responsive: 0, //backwards compabitility with responsiveWiddth
168            responsiveWidth: 0,
169            responsiveHeight: 0,
170            responsiveSlides: false,
171            parallax: false,
172            parallaxOptions: {
173                type: 'reveal',
174                percentage: 62,
175                property: 'translate'
176            },
177
178            //Custom selectors
179            sectionSelector: SECTION_DEFAULT_SEL,
180            slideSelector: SLIDE_DEFAULT_SEL,
181
182            //events
183            afterLoad: null,
184            onLeave: null,
185            afterRender: null,
186            afterResize: null,
187            afterReBuild: null,
188            afterSlideLoad: null,
189            onSlideLeave: null,
190            afterResponsive: null,
191
192            lazyLoading: true
193        }, options);
194
195        //flag to avoid very fast sliding for landscape sliders
196        var slideMoving = false;
197
198        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
199        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
200        var container = $(this);
201        var windowsHeight = $window.height();
202        var isResizing = false;
203        var isWindowFocused = true;
204        var lastScrolledDestiny;
205        var lastScrolledSlide;
206        var canScroll = true;
207        var scrollings = [];
208        var controlPressed;
209        var startingSection;
210        var isScrollAllowed = {};
211        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
212        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
213        var MSPointer = getMSPointer();
214        var events = {
215            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
216            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
217        };
218
219        //timeouts
220        var resizeId;
221        var afterSectionLoadsId;
222        var afterSlideLoadsId;
223        var scrollId;
224        var scrollId2;
225        var keydownId;
226        var originals = $.extend(true, {}, options); //deep copy
227
228        displayWarnings();
229
230        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
231        iscrollOptions.click = isTouch; // see #2035
232
233        //extending iScroll options with the user custom ones
234        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
235
236        //easeInOutCubic animation included in the plugin
237        $.extend($.easing,{ easeInOutCubic: function (x, t, b, c, d) {if ((t/=d/2) < 1) return c/2*t*t*t + b;return c/2*((t-=2)*t*t + 2) + b;}});
238
239        /**
240        * Sets the autoScroll option.
241        * It changes the scroll bar visibility and the history of the site as a result.
242        */
243        function setAutoScrolling(value, type){
244            //removing the transformation
245            if(!value){
246                silentScroll(0);
247            }
248
249            setVariableState('autoScrolling', value, type);
250
251            var element = $(SECTION_ACTIVE_SEL);
252
253            if(options.autoScrolling && !options.scrollBar){
254                $htmlBody.css({
255                    'overflow' : 'hidden',
256                    'height' : '100%'
257                });
258
259                setRecordHistory(originals.recordHistory, 'internal');
260
261                //for IE touch devices
262                container.css({
263                    '-ms-touch-action': 'none',
264                    'touch-action': 'none'
265                });
266
267                if(element.length){
268                    //moving the container up
269                    silentScroll(element.position().top);
270                }
271
272            }else{
273                $htmlBody.css({
274                    'overflow' : 'visible',
275                    'height' : 'initial'
276                });
277
278                setRecordHistory(false, 'internal');
279
280                //for IE touch devices
281                container.css({
282                    '-ms-touch-action': '',
283                    'touch-action': ''
284                });
285
286                //scrolling the page to the section with no animation
287                if (element.length) {
288                    $htmlBody.scrollTop(element.position().top);
289                }
290            }
291        }
292
293        /**
294        * Defines wheter to record the history for each hash change in the URL.
295        */
296        function setRecordHistory(value, type){
297            setVariableState('recordHistory', value, type);
298        }
299
300        /**
301        * Defines the scrolling speed
302        */
303        function setScrollingSpeed(value, type){
304            setVariableState('scrollingSpeed', value, type);
305        }
306
307        /**
308        * Sets fitToSection
309        */
310        function setFitToSection(value, type){
311            setVariableState('fitToSection', value, type);
312        }
313
314        /**
315        * Sets lockAnchors
316        */
317        function setLockAnchors(value){
318            options.lockAnchors = value;
319        }
320
321        /**
322        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
323        */
324        function setMouseWheelScrolling(value){
325            if(value){
326                addMouseWheelHandler();
327                addMiddleWheelHandler();
328            }else{
329                removeMouseWheelHandler();
330                removeMiddleWheelHandler();
331            }
332        }
333
334        /**
335        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
336        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
337        *
338        * @param directions string containing the direction or directions separated by comma.
339        */
340        function setAllowScrolling(value, directions){
341            if(typeof directions !== 'undefined'){
342                directions = directions.replace(/ /g,'').split(',');
343
344                $.each(directions, function (index, direction){
345                    setIsScrollAllowed(value, direction, 'm');
346                });
347            }
348            else if(value){
349                setMouseWheelScrolling(true);
350                addTouchHandler();
351            }else{
352                setMouseWheelScrolling(false);
353                removeTouchHandler();
354            }
355        }
356
357        /**
358        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
359        */
360        function setKeyboardScrolling(value, directions){
361            if(typeof directions !== 'undefined'){
362                directions = directions.replace(/ /g,'').split(',');
363
364                $.each(directions, function (index, direction){
365                    setIsScrollAllowed(value, direction, 'k');
366                });
367            }else{
368                options.keyboardScrolling = value;
369            }
370        }
371
372        /**
373        * Moves the page up one section.
374        */
375        function moveSectionUp(){
376            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
377
378            //looping to the bottom if there's no more sections above
379            if (!prev.length && (options.loopTop || options.continuousVertical)) {
380                prev = $(SECTION_SEL).last();
381            }
382
383            if (prev.length) {
384                scrollPage(prev, null, true);
385            }
386        }
387
388        /**
389        * Moves the page down one section.
390        */
391        function moveSectionDown(){
392            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
393
394            //looping to the top if there's no more sections below
395            if(!next.length &&
396                (options.loopBottom || options.continuousVertical)){
397                next = $(SECTION_SEL).first();
398            }
399
400            if(next.length){
401                scrollPage(next, null, false);
402            }
403        }
404
405        /**
406        * Moves the page to the given section and slide with no animation.
407        * Anchors or index positions can be used as params.
408        */
409        function silentMoveTo(sectionAnchor, slideAnchor){
410            setScrollingSpeed (0, 'internal');
411            moveTo(sectionAnchor, slideAnchor);
412            setScrollingSpeed (originals.scrollingSpeed, 'internal');
413        }
414
415        /**
416        * Moves the page to the given section and slide.
417        * Anchors or index positions can be used as params.
418        */
419        function moveTo(sectionAnchor, slideAnchor){
420            var destiny = getSectionByAnchor(sectionAnchor);
421
422            if (typeof slideAnchor !== 'undefined'){
423                scrollPageAndSlide(sectionAnchor, slideAnchor);
424            }else if(destiny.length > 0){
425                scrollPage(destiny);
426            }
427        }
428
429        /**
430        * Slides right the slider of the active section.
431        * Optional `section` param.
432        */
433        function moveSlideRight(section){
434            moveSlide('right', section);
435        }
436
437        /**
438        * Slides left the slider of the active section.
439        * Optional `section` param.
440        */
441        function moveSlideLeft(section){
442            moveSlide('left', section);
443        }
444
445        /**
446         * When resizing is finished, we adjust the slides sizes and positions
447         */
448        function reBuild(resizing){
449            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
450
451            isResizing = true;
452
453            windowsHeight = $window.height();  //updating global var
454
455            $(SECTION_SEL).each(function(){
456                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
457                var slides = $(this).find(SLIDE_SEL);
458
459                //adjusting the height of the table-cell for IE and Firefox
460                if(options.verticalCentered){
461                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
462                }
463
464                $(this).css('height', windowsHeight + 'px');
465
466                //resizing the scrolling divs
467                if(options.scrollOverflow){
468                    if(slides.length){
469                        slides.each(function(){
470                            createScrollBar($(this));
471                        });
472                    }else{
473                        createScrollBar($(this));
474                    }
475                }
476
477                //adjusting the position fo the FULL WIDTH slides...
478                if (slides.length > 1) {
479                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
480                }
481            });
482
483            var activeSection = $(SECTION_ACTIVE_SEL);
484            var sectionIndex = activeSection.index(SECTION_SEL);
485
486            //isn't it the first section?
487            if(sectionIndex){
488                //adjusting the position for the current section
489                silentMoveTo(sectionIndex + 1);
490            }
491
492            isResizing = false;
493            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
494            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
495        }
496
497        /**
498        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
499        * are smaller than the set limit values.
500        */
501        function setResponsive(active){
502            var isResponsive = $body.hasClass(RESPONSIVE);
503
504            if(active){
505                if(!isResponsive){
506                    setAutoScrolling(false, 'internal');
507                    setFitToSection(false, 'internal');
508                    $(SECTION_NAV_SEL).hide();
509                    $body.addClass(RESPONSIVE);
510                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
511                }
512            }
513            else if(isResponsive){
514                setAutoScrolling(originals.autoScrolling, 'internal');
515                setFitToSection(originals.autoScrolling, 'internal');
516                $(SECTION_NAV_SEL).show();
517                $body.removeClass(RESPONSIVE);
518                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
519            }
520        }
521
522        if($(this).length){
523            //public functions
524            FP.setAutoScrolling = setAutoScrolling;
525            FP.setRecordHistory = setRecordHistory;
526            FP.setScrollingSpeed = setScrollingSpeed;
527            FP.setFitToSection = setFitToSection;
528            FP.setLockAnchors = setLockAnchors;
529            FP.setMouseWheelScrolling = setMouseWheelScrolling;
530            FP.setAllowScrolling = setAllowScrolling;
531            FP.setKeyboardScrolling = setKeyboardScrolling;
532            FP.moveSectionUp = moveSectionUp;
533            FP.moveSectionDown = moveSectionDown;
534            FP.silentMoveTo = silentMoveTo;
535            FP.moveTo = moveTo;
536            FP.moveSlideRight = moveSlideRight;
537            FP.moveSlideLeft = moveSlideLeft;
538            FP.fitToSection = fitToSection;
539            FP.reBuild = reBuild;
540            FP.setResponsive = setResponsive;
541            FP.destroy = destroy;
542
543            init();
544
545            bindEvents();
546        }
547
548        function init(){
549            //if css3 is not supported, it will use jQuery animations
550            if(options.css3){
551                options.css3 = support3d();
552            }
553
554            options.scrollBar = options.scrollBar || options.hybrid;
555
556            setOptionsFromDOM();
557            prepareDom();
558            setAllowScrolling(true);
559            setAutoScrolling(options.autoScrolling, 'internal');
560            responsive();
561
562            //setting the class for the body element
563            setBodyClass();
564
565            if(document.readyState === 'complete'){
566                scrollToAnchor();
567            }
568            $window.on('load', scrollToAnchor);
569        }
570
571        function bindEvents(){
572            $window
573                //when scrolling...
574                .on('scroll', scrollHandler)
575
576                //detecting any change on the URL to scroll to the given anchor link
577                //(a way to detect back history button as we play with the hashes on the URL)
578                .on('hashchange', hashChangeHandler)
579
580                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
581                .blur(blurHandler)
582
583                //when resizing the site, we adjust the heights of the sections, slimScroll...
584                .resize(resizeHandler);
585
586            $document
587                //Sliding with arrow keys, both, vertical and horizontal
588                .keydown(keydownHandler)
589
590                //to prevent scrolling while zooming
591                .keyup(keyUpHandler)
592
593                //Scrolls to the section when clicking the navigation bullet
594                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
595
596                //Scrolls the slider to the given slide destination for the given section
597                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
598
599                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
600
601            //Scrolling horizontally when clicking on the slider controls.
602            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
603
604            /**
605            * Applying normalScroll elements.
606            * Ignoring the scrolls over the specified selectors.
607            */
608            if(options.normalScrollElements){
609                $document.on('mouseenter', options.normalScrollElements, function () {
610                    setMouseWheelScrolling(false);
611                });
612
613                $document.on('mouseleave', options.normalScrollElements, function(){
614                    setMouseWheelScrolling(true);
615                });
616            }
617        }
618
619        /**
620        * Setting options from DOM elements if they are not provided.
621        */
622        function setOptionsFromDOM(){
623            var sections = container.find(options.sectionSelector);
624
625            //no anchors option? Checking for them in the DOM attributes
626            if(!options.anchors.length){
627                options.anchors = sections.filter('[data-anchor]').map(function(){
628                    return $(this).data('anchor').toString();
629                }).get();
630            }
631
632            //no tooltips option? Checking for them in the DOM attributes
633            if(!options.navigationTooltips.length){
634                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
635                    return $(this).data('tooltip').toString();
636                }).get();
637            }
638        }
639
640        /**
641        * Works over the DOM structure to set it up for the current fullpage options.
642        */
643        function prepareDom(){
644            container.css({
645                'height': '100%',
646                'position': 'relative'
647            });
648
649            //adding a class to recognize the container internally in the code
650            container.addClass(WRAPPER);
651            $('html').addClass(ENABLED);
652
653            //due to https://github.com/alvarotrigo/fullPage.js/issues/1502
654            windowsHeight = $window.height();
655
656            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
657
658            addInternalSelectors();
659
660             //styling the sections / slides / menu
661            $(SECTION_SEL).each(function(index){
662                var section = $(this);
663                var slides = section.find(SLIDE_SEL);
664                var numSlides = slides.length;
665
666                styleSection(section, index);
667                styleMenu(section, index);
668
669                // if there's any slide
670                if (numSlides > 0) {
671                    styleSlides(section, slides, numSlides);
672                }else{
673                    if(options.verticalCentered){
674                        addTableClass(section);
675                    }
676                }
677            });
678
679            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
680            if(options.fixedElements && options.css3){
681                $(options.fixedElements).appendTo($body);
682            }
683
684            //vertical centered of the navigation + active bullet
685            if(options.navigation){
686                addVerticalNavigation();
687            }
688
689            enableYoutubeAPI();
690
691            if(options.scrollOverflow){
692                if(document.readyState === 'complete'){
693                    createScrollBarHandler();
694                }
695                //after DOM and images are loaded
696                $window.on('load', createScrollBarHandler);
697            }else{
698                afterRenderActions();
699            }
700        }
701
702        /**
703        * Styles the horizontal slides for a section.
704        */
705        function styleSlides(section, slides, numSlides){
706            var sliderWidth = numSlides * 100;
707            var slideWidth = 100 / numSlides;
708
709            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
710            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
711
712            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
713
714            if(numSlides > 1){
715                if(options.controlArrows){
716                    createSlideArrows(section);
717                }
718
719                if(options.slidesNavigation){
720                    addSlidesNavigation(section, numSlides);
721                }
722            }
723
724            slides.each(function(index) {
725                $(this).css('width', slideWidth + '%');
726
727                if(options.verticalCentered){
728                    addTableClass($(this));
729                }
730            });
731
732            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
733
734            //if the slide won't be an starting point, the default will be the first one
735            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
735ide by default.
736            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
737                silentLandscapeScroll(startingSlide, 'internal');
738            }else{
739                slides.eq(0).addClass(ACTIVE);
740            }
741        }
742
743        /**
744        * Styling vertical sections
745        */
746        function styleSection(section, index){
747            //if no active section is defined, the 1st one will be the default one
748            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
749                section.addClass(ACTIVE);
750            }
751            startingSection = $(SECTION_ACTIVE_SEL);
752
753            section.css('height', windowsHeight + 'px');
754
755            if(options.paddingTop){
756                section.css('padding-top', options.paddingTop);
757            }
758
759            if(options.paddingBottom){
760                section.css('padding-bottom', options.paddingBottom);
761            }
762
763            if (typeof options.sectionsColor[index] !==  'undefined') {
764                section.css('background-color', options.sectionsColor[index]);
765            }
766
767            if (typeof options.anchors[index] !== 'undefined') {
768                section.attr('data-anchor', options.anchors[index]);
769            }
770        }
771
772        /**
773        * Sets the data-anchor attributes to the menu elements and activates the current one.
774        */
775        function styleMenu(section, index){
776            if (typeof options.anchors[index] !== 'undefined') {
777                //activating the menu / nav element on load
778                if(section.hasClass(ACTIVE)){
779                    activateMenuAndNav(options.anchors[index], index);
780                }
781            }
782
783            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
784            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
785                $(options.menu).appendTo($body);
786            }
787        }
788
789        /**
790        * Adds internal classes to be able to provide customizable selectors
791        * keeping the link with the style sheet.
792        */
793        function addInternalSelectors(){
794            container.find(options.sectionSelector).addClass(SECTION);
795            container.find(options.slideSelector).addClass(SLIDE);
796        }
797
798        /**
799        * Creates the control arrows for the given section
800        */
801        function createSlideArrows(section){
802            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
803
804            if(options.controlArrowColor!='#fff'){
805                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
806                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
807            }
808
809            if(!options.loopHorizontal){
810                section.find(SLIDES_ARROW_PREV_SEL).hide();
811            }
812        }
813
814        /**
815        * Creates a vertical navigation bar.
816        */
817        function addVerticalNavigation(){
818            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
819            var nav = $(SECTION_NAV_SEL);
820
821            nav.addClass(function() {
822                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
823            });
824
825            for (var i = 0; i < $(SECTION_SEL).length; i++) {
826                var link = '';
827                if (options.anchors.length) {
828                    link = options.anchors[i];
829                }
830
831                var li = '<li><a href="#' + link + '"><span></span></a>';
832
833                // Only add tooltip if needed (defined by user)
834                var tooltip = options.navigationTooltips[i];
835
836                if (typeof tooltip !== 'undefined' && tooltip !== '') {
837                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
838                }
839
840                li += '</li>';
841
842                nav.find('ul').append(li);
843            }
844
845            //centering it vertically
846            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
847
848            //activating the current active section
849            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
850        }
851
852        /**
853        * Creates the slim scroll scrollbar for the sections and slides inside them.
854        */
855        function createScrollBarHandler(){
856            $(SECTION_SEL).each(function(){
857                var slides = $(this).find(SLIDE_SEL);
858
859                if(slides.length){
860                    slides.each(function(){
861                        createScrollBar($(this));
862                    });
863                }else{
864                    createScrollBar($(this));
865                }
866
867            });
868            afterRenderActions();
869        }
870
871        /*
872        * Enables the Youtube videos API so we can control their flow if necessary.
873        */
874        function enableYoutubeAPI(){
875            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
876                addURLParam($(this), 'enablejsapi=1');
877            });
878        }
879
880        /**
881        * Adds a new parameter and its value to the `src` of a given element
882        */
883        function addURLParam(element, newParam){
884            var originalSrc = element.attr('src');
885            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
886        }
887
888        /*
889        * Returns the prefix sign to use for a new parameter in an existen URL.
890        *
891        * @return {String}  ? | &
892        */
893        function getUrlParamSign(url){
894            return ( !/\?/.test( url ) ) ? '?' : '&';
895        }
896
897        /**
898        * Actions and callbacks to fire afterRender
899        */
900        function afterRenderActions(){
901            var section = $(SECTION_ACTIVE_SEL);
902
903            section.addClass(COMPLETELY);
904
905            if(options.scrollOverflowHandler.afterRender){
906                options.scrollOverflowHandler.afterRender(section);
907            }
908            lazyLoad(section);
909            playMedia(section);
910            options.scrollOverflowHandler.afterLoad();
911            
912            if(isDestinyTheStartingSection()){
913                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
914            }
915
916            $.isFunction( options.afterRender ) && options.afterRender.call(container);
917        }
918
919        /**
920        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
921        */
922        function isDestinyTheStartingSection(){
923            var anchors =  window.location.hash.replace('#', '').split('/');
924            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
925    
926            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
927        }
928
929
930        var isScrolling = false;
931        var lastScroll = 0;
932
933        //when scrolling...
934        function scrollHandler(){
935            var currentSection;
936
937            if(!options.autoScrolling || options.scrollBar){
938                var currentScroll = $window.scrollTop();
939                var scrollDirection = getScrollDirection(currentScroll);
940                var visibleSectionIndex = 0;
941                var screen_mid = currentScroll + ($window.height() / 2.0);
942                var isAtBottom = $body.height() - $window.height() === currentScroll;
943                var sections =  document.querySelectorAll(SECTION_SEL);
944
945                //when using `auto-height` for a small last section it won't be centered in the viewport
946                if(isAtBottom){
947                    visibleSectionIndex = sections.length - 1;
948                }
949                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
950                else if(!currentScroll){
951                    visibleSectionIndex = 0;
952                }
953
954                //taking the section which is showing more content in the viewport
955                else{
956                    for (var i = 0; i < sections.length; ++i) {
957                        var section = sections[i];
958
959                        // Pick the the last section which passes the middle line of the screen.
960                        if (section.offsetTop <= screen_mid)
961                        {
962                            visibleSectionIndex = i;
963                        }
964                    }
965                }
966
967                if(isCompletelyInViewPort(scrollDirection)){
968                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
969                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
970                    }
971                }
972
973                //geting the last one, the current one on the screen
974                currentSection = $(sections).eq(visibleSectionIndex);
975
976                //setting the visible section as active when manually scrolling
977                //executing only once the first time we reach the section
978                if(!currentSection.hasClass(ACTIVE)){
979                    isScrolling = true;
980                    var leavingSection = $(SECTION_ACTIVE_SEL);
981                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
982                    var yMovement = getYmovement(currentSection);
983                    var anchorLink  = currentSection.data('anchor');
984                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
985                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
986                    var slideIndex;
987                    var slideAnchorLink;
988
989                    if(activeSlide.length){
990                        slideAnchorLink = activeSlide.data('anchor');
991                        slideIndex = activeSlide.index();
992                    }
993
994                    if(canScroll){
995                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
996
997                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
998                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
999
1000                        stopMedia(leavingSection);
1001                        lazyLoad(currentSection);
1002                        playMedia(currentSection);
1003
1004                        activateMenuAndNav(anchorLink, sectionIndex - 1);
1005
1006                        if(options.anchors.length){
1007                            //needed to enter in hashChange event when using the menu with anchor links
1008                            lastScrolledDestiny = anchorLink;
1009                        }
1010                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
1011                    }
1012
1013                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
1014                    clearTimeout(scrollId);
1015                    scrollId = setTimeout(function(){
1016                        isScrolling = false;
1017                    }, 100);
1018                }
1019
1020                if(options.fitToSection){
1021                    //for the auto adjust of the viewport to fit a whole section
1022                    clearTimeout(scrollId2);
1023
1024                    scrollId2 = setTimeout(function(){
1025                        //checking it again in case it changed during the delay
1026                        if(options.fitToSection){
1027                            fitToSection();
1028                        }
1029                    }, options.fitToSectionDelay);
1030                }
1031            }
1032        }
1033
1034        /**
1035        * Fits the site to the nearest active section
1036        */
1037        function fitToSection(){
1038            //checking fitToSection again in case it was set to false before the timeout delay
1039            if(canScroll){
1040                //allows to scroll to an active section and
1041                //if the section is already active, we prevent firing callbacks
1042                isResizing = true;
1043
1044                scrollPage($(SECTION_ACTIVE_SEL));
1045                isResizing = false;
1046            }
1047        }
1048
1049        /**
1050        * Determines whether the active section has seen in its whole or not.
1051        */
1052        function isCompletelyInViewPort(movement){
1053            var top = $(SECTION_ACTIVE_SEL).position().top;
1054            var bottom = top + $window.height();
1055
1056            if(movement == 'up'){
1057                return bottom >= ($window.scrollTop() + $window.height());
1058            }
1059            return top <= $window.scrollTop();
1060        }
1061
1062        /**
1063        * Gets the directon of the the scrolling fired by the scroll event.
1064        */
1065        function getScrollDirection(currentScroll){
1066            var direction = currentScroll > lastScroll ? 'down' : 'up';
1067
1068            lastScroll = currentScroll;
1069
1070            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
1071            previousDestTop = currentScroll;
1072
1073            return direction;
1074        }
1075
1076        /**
1077        * Determines the way of scrolling up or down:
1078        * by 'automatically' scrolling a section or by using the default and n
1078ormal scrolling.
1079        */
1080        function scrolling(type, scrollable){
1081            if (!isScrollAllowed.m[type]){
1082                return;
1083            }
1084            var check = (type === 'down') ? 'bottom' : 'top';
1085            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
1086
1087            if(scrollable.length > 0 ){
1088                //is the scrollbar at the start/end of the scroll?
1089                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
1090                    scrollSection();
1091                }else{
1092                    return true;
1093                }
1094            }else{
1095                // moved up/down
1096                scrollSection();
1097            }
1098        }
1099
1100        /*
1101        * Preventing bouncing in iOS #2285
1102        */
1103        function preventBouncing(event){
1104            var e = event.originalEvent;
1105            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e)){
1106                //preventing the easing on iOS devices
1107                event.preventDefault();
1108            }
1109        }
1110
1111        var touchStartY = 0;
1112        var touchStartX = 0;
1113        var touchEndY = 0;
1114        var touchEndX = 0;
1115
1116        /* Detecting touch events
1117
1118        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
1119        * This way, the touchstart and the touch moves shows an small difference between them which is the
1120        * used one to determine the direction.
1121        */
1122        function touchMoveHandler(event){
1123            var e = event.originalEvent;
1124            var activeSection = $(e.target).closest(SECTION_SEL);
1125
1126            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
1127            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
1128
1129                if(options.autoScrolling){
1130                    //preventing the easing on iOS devices
1131                    event.preventDefault();
1132                }
1133
1134                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
1135                var touchEvents = getEventsPage(e);
1136
1137                touchEndY = touchEvents.y;
1138                touchEndX = touchEvents.x;
1139
1140                //if movement in the X axys is greater than in the Y and the currect section has slides...
1141                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
1142
1143                    //is the movement greater than the minimum resistance to scroll?
1144                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
1145                        if (touchStartX > touchEndX) {
1146                            if(isScrollAllowed.m.right){
1147                                moveSlideRight(activeSection); //next
1148                            }
1149                        } else {
1150                            if(isScrollAllowed.m.left){
1151                                moveSlideLeft(activeSection); //prev
1152                            }
1153                        }
1154                    }
1155                }
1156
1157                //vertical scrolling (only when autoScrolling is enabled)
1158                else if(options.autoScrolling && canScroll){
1159
1160                    //is the movement greater than the minimum resistance to scroll?
1161                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
1162                        if (touchStartY > touchEndY) {
1163                            scrolling('down', scrollable);
1164                        } else if (touchEndY > touchStartY) {
1165                            scrolling('up', scrollable);
1166                        }
1167                    }
1168                }
1169            }
1170        }
1171
1172        /**
1173         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
1174         * Currently works well for iOS - Android might need some testing
1175         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
1176         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
1177         * @return {boolean} true if there is a match to options.normalScrollElements
1178         */
1179        function checkParentForNormalScrollElement (el, hop) {
1180            hop = hop || 0;
1181            var parent = $(el).parent();
1182
1183            if (hop < options.normalScrollElementTouchThreshold &&
1184                parent.is(options.normalScrollElements) ) {
1185                return true;
1186            } else if (hop == options.normalScrollElementTouchThreshold) {
1187                return false;
1188            } else {
1189                return checkParentForNormalScrollElement(parent, ++hop);
1190            }
1191        }
1192
1193        /**
1194        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
1195        * this way we make sure that is really a touch event what IE is detecting.
1196        */
1197        function isReallyTouch(e){
1198            //if is not IE   ||  IE is detecting `touch` or `pen`
1199            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
1200        }
1201
1202        /**
1203        * Handler for the touch start event.
1204        */
1205        function touchStartHandler(event){
1206            var e = event.originalEvent;
1207
1208            //stopping the auto scroll to adjust to a section
1209            if(options.fitToSection){
1210                $htmlBody.stop();
1211            }
1212
1213            if(isReallyTouch(e)){
1214                var touchEvents = getEventsPage(e);
1215                touchStartY = touchEvents.y;
1216                touchStartX = touchEvents.x;
1217            }
1218        }
1219
1220        /**
1221        * Gets the average of the last `number` elements of the given array.
1222        */
1223        function getAverage(elements, number){
1224            var sum = 0;
1225
1226            //taking `number` elements from the end to make the average, if there are not enought, 1
1227            var lastElements = elements.slice(Math.max(elements.length - number, 1));
1228
1229            for(var i = 0; i < lastElements.length; i++){
1230                sum = sum + lastElements[i];
1231            }
1232
1233            return Math.ceil(sum/number);
1234        }
1235
1236        /**
1237         * Detecting mousewheel scrolling
1238         *
1239         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
1240         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
1241         */
1242        var prevTime = new Date().getTime();
1243
1244        function MouseWheelHandler(e) {
1245            var curTime = new Date().getTime();
1246            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
1247
1248            //autoscrolling and not zooming?
1249            if(options.autoScrolling && !controlPressed && !isNormalScroll){
1250                // cross-browser wheel delta
1251                e = e || window.event;
1252                var value = e.wheelDelta || -e.deltaY || -e.detail;
1253                var delta = Math.max(-1, Math.min(1, value));
1254
1255                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
1256                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
1257
1258                //Limiting the array to 150 (lets not waste memory!)
1259                if(scrollings.length > 149){
1260                    scrollings.shift();
1261                }
1262
1263                //keeping record of the previous scrollings
1264                scrollings.push(Math.abs(value));
1265
1266                //preventing to scroll the site on mouse wheel when scrollbar is present
1267                if(options.scrollBar){
1268                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
1269                }
1270
1271                var activeSection = $(SECTION_ACTIVE_SEL);
1272                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
1273
1274                //time difference between the last scroll and the current one
1275                var timeDiff = curTime-prevTime;
1276                prevTime = curTime;
1277
1278                //haven't they scrolled in a while?
1279                //(enough to be consider a different scrolling action to scroll another section)
1280                if(timeDiff > 200){
1281                    //emptying the array, we dont care about old scrollings for our averages
1282                    scrollings = [];
1283                }
1284
1285                if(canScroll){
1286                    var averageEnd = getAverage(scrollings, 10);
1287                    var averageMiddle = getAverage(scrollings, 70);
1288                    var isAccelerating = averageEnd >= averageMiddle;
1289
1290                    //to avoid double swipes...
1291                    if(isAccelerating && isScrollingVertically){
1292                        //scrolling down?
1293                        if (delta < 0) {
1294                            scrolling('down', scrollable);
1295
1296                        //scrolling up?
1297                        }else {
1298                            scrolling('up', scrollable);
1299                        }
1300                    }
1301                }
1302
1303                return false;
1304            }
1305
1306            if(options.fitToSection){
1307                //stopping the auto scroll to adjust to a section
1308                $htmlBody.stop();
1309            }
1310        }
1311
1312        /**
1313        * Slides a slider to the given direction.
1314        * Optional `section` param.
1315        */
1316        function moveSlide(direction, section){
1317            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
1318            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
1319            var numSlides = slides.find(SLIDE_SEL).length;
1320
1321            // more than one slide needed and nothing should be sliding
1322            if (!slides.length || slideMoving || numSlides < 2) {
1323                return;
1324            }
1325
1326            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
1327            var destiny = null;
1328
1329            if(direction === 'left'){
1330                destiny = currentSlide.prev(SLIDE_SEL);
1331            }else{
1332                destiny = currentSlide.next(SLIDE_SEL);
1333            }
1334
1335            //isn't there a next slide in the secuence?
1336            if(!destiny.length){
1337                //respect loopHorizontal settin
1338                if (!options.loopHorizontal) return;
1339
1340                if(direction === 'left'){
1341                    destiny = currentSlide.siblings(':last');
1342                }else{
1343                    destiny = currentSlide.siblings(':first');
1344                }
1345            }
1346
1347            slideMoving = true;
1348
1349            landscapeScroll(slides, destiny, direction);
1350        }
1351
1352        /**
1353        * Maintains the active slides in the viewport
1354        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
1355        */
1356        function keepSlidesPosition(){
1357            $(SLIDE_ACTIVE_SEL).each(function(){
1358                silentLandscapeScroll($(this), 'internal');
1359            });
1360        }
1361
1362        var previousDestTop = 0;
1363        /**
1364        * Returns the destination Y position based on the scrolling direction and
1365        * the height of the section.
1366        */
1367        function getDestinationPosition(element){
1368            var elemPosition = element.position();
1369
1370            //top of the desination will be at the top of the viewport
1371            var position = elemPosition.top;
1372            var isScrollingDown =  elemPosition.top > previousDestTop;
1373            var sectionBottom = position - windowsHeight + element.outerHeight();
1374            var bigSectionsDestination = options.bigSectionsDestination;
1375
1376            //is the destination element bigger than the viewport?
1377            if(element.outerHeight() > windowsHeight){
1378                //scrolling up?
1379                if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
1380                    position = sectionBottom;
1381                }
1382            }
1383
1384            //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
1385            else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
1386                //The bottom of the destination will be at the bottom of the viewport
1387                position = sectionBottom;
1388            }
1389
1390            /*
1391            Keeping record of the last scrolled position to determine the scrolling direction.
1392            No conventional methods can be used as the scroll bar might not be present
1393            AND the section might not be active if it is auto-height and didnt reach the middle
1394            of the viewport.
1395            */
1396            previousDestTop = position;
1397            return position;
1398        }
1399
1400        /**
1401        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
1402        */
1403        function scrollPage(element, callback, isMovementUp){
1404            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
1405
1406            var dtop = getDestinationPosition(element);
1407            var slideAnchorLink;
1408            var slideIndex;
1409
1410            //local variables
1411            var v = {
1412                element: element,
1413                callback: callback,
1414                isMovementUp: isMovementUp,
1415                dtop: dtop,
1416                yMovement: getYmovement(element),
1417                anchorLink: element.data('anchor'),
1418                sectionIndex: element.index(SECTION_SEL),
1419                activeSlide: element.find(SLIDE_ACTIVE_SEL),
1420                activeSection: $(SECTION_ACTIVE_SEL),
1421                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
1422
1423                //caching the value of isResizing at the momment the function is called
1424                //because it will be checked later inside a setTimeout and the value might change
1425                localIsResizing: isResizing
1426            };
1427
1428            //quiting when destination scroll is the same as the current one
1429            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
1430
1431            if(v.activeSlide.length){
1432                slideAnchorLink = v.activeSlide.data('anchor');
1433                slideIndex = v.activeSlide.index();
1434            }
1435
1436            // If continuousVertical && we need to wrap around
1437            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
1438                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
1439                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
1440
1441                v = createInfiniteSections(v);
1442            }
1443
1444            //callback (onLeave) if the site is not just resizing and readjusting the slides
1445            if($.isFunction(options.onLeave) && !v.localIsResizing){
1446                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
1447                    return;
1448                }
1449            }
1450
1451            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
1452            if(!v.localIsResizing){
1453                stopMedia(v.activeSection);
1454            }
1455
1456            options.scrollOverflowHandler.beforeLeave();
1457            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
1458            lazyLoad(element);
1459            options.scrollOverflowHandler.onLeave();
1460
1461
1462            //preventing from activating the MouseWheelHandler event
1463            //more than once if the page is scrolling
1464            canScroll = false;
1465
1466            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
1467
1468            performMovement(v);
1469
1470            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
1471            lastScrolledDestiny = v.anchorLink;
1472
1473            //avoid firing it twice (as it does also on scroll)
1474            activateMenuAndNav(v.anchorLink, v.sectionIndex);
1475        }
1476
1477        /**
1478        * Performs the vertical movement (by CSS3 or by jQuery)
1479        */
1480        function performMovement(v){
1481            // using CSS3 translate functionality
1482            if (options.css3 && options.autoScrolling && !options.scrollBar) {
1483
1484                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
1485                // that's why we round it to 0.
1486                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
1487                transformContainer(translate3d, true);
1488
1489                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
1490                //scrollingSpeed to change in case of using silentMoveTo();
1491                if(options.scrollingSpeed){
1492                    clearTimeout(afterSectionLoadsId);
1493                    afterSectionLoadsId = setTimeout(function () {
1494                        afterSectionLoads(v);
1495                    }, options.scrollingSpeed);
1496                }else{
1497                    afterSectionLoads(v);
1498                }
1499            }
1500
1501            // using jQuery animate
1502            else{
1503                var scrollSettings = getScrollSettings(v);
1504
1505                $(scrollSettings.element).animate(
1506                    scrollSettings.options,
1507                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
1508                    if(options.scrollBar){
1509
1510                        /* Hack!
1511                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
1512                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
1513
1514                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
1515                        */
1516                        setTimeout(function(){
1517                            afterSectionLoads(v);
1518                        },30);
1519                    }else{
1520                        afterSectionLoads(v);
1521                    }
1522                });
1523            }
1524        }
1525
1526        /**
1527        * Gets the scrolling settings depending on the plugin autoScrolling option
1528        */
1529        function getScrollSettings(v){
1530            var scroll = {};
1531
1532            if(options.autoScrolling && !options.scrollBar){
1533                scroll.options = { 'top': -v.dtop};
1534                scroll.element = WRAPPER_SEL;
1535            }else{
1536                scroll.options = { 'scrollTop': v.dtop};
1537                scroll.element = 'html, body';
1538            }
1539
1540            return scroll;
1541        }
1542
1543        /**
1544        * Adds sections before or after the current one to create the infinite effect.
1545        */
1546        function createInfiniteSections(v){
1547            // Scrolling down
1548            if (!v.isMovementUp) {
1549                // Move all previous sections to after the active section
1550                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
1551            }
1552            else { // Scrolling up
1553                // Move all next sections to before the active section
1554                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
1555            }
1556
1557            // Maintain the displayed position (now that we changed the element order)
1558            silentScroll($(SECTION_ACTIVE_SEL).position().top);
1559
1560            // Maintain the active slides visible in the viewport
1561            keepSlidesPosition();
1562
1563            // save for later the elements that still need to be reordered
1564            v.wrapAroundElements = v.activeSection;
1565
1566            // Recalculate animation variables
1567            v.dtop = v.element.position().top;
1568            v.yMovement = getYmovement(v.element);
1569
1570            return v;
1571        }
1572
1573        /**
1574        * Fix section order after continuousVertical changes have been animated
1575        */
1576        function continuousVerticalFixSectionOrder (v) {
1577            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
1578            // finish moving the elements around so the direct navigation will function more simply
1579            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
1580                return;
1581            }
1582
1583            if (v.isMovementUp) {
1584                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
1585            }
1586            else {
1587                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
1588            }
1589
1590            silentScroll($(SECTION_ACTIVE_SEL).position().top);
1591
1592            // Maintain the active slides visible in the viewport
1593            keepSlidesPosition();
1594        }
1595
1596
1597        /**
1598        * Actions to do once the section is loaded.
1599        */
1600        function afterSectionLoads (v){
1601            continuousVerticalFixSectionOrder(v);
1602
1603            //callback (afterLoad) if the site is not just resizing and readjusting the slides
1604            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
1605            options.scrollOverflowHandler.afterLoad();
1606
1607            if(!v.localIsResizing){
1608                playMedia(v.element);
1609            }
1610
1611            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
1612
1613            canScroll = true;
1614
1615            $.isFunction(v.callback) && v.callback.call(this);
1616        }
1617
1618        /**
1619        * Sets the value for the given attribute from the `data-` attribute with the same suffix
1620        * ie: data-srcset ==> srcset  |  data-src ==> src
1621        */
1622        function setSrc(element, attribute){
1623            element
1624                .attr(attribute, element.data(attribute))
1625                .removeAttr('data-' + attribute);
1626        }
1627
1628        /**
1629        * Lazy loads image, video and audio elements.
1630        */
1631        function lazyLoad(destiny){
1632            if (!options.lazyLoading){
1633                return;
1634            }
1635
1636            var panel = getSlideOrSection(destiny);
1637            var element;
1638            
1639            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
1640                element = $(this);
1641
1642                $.each(['src', 'srcset'], function(index, type){
1643                    var attribute = element.attr('data-' + type);
1644                    if(typeof attribute !== 'undefined' && attribute){
1645                        setSrc(element, type);
1646                    }
1647                });
1648
1649                if(element.is('source')){
1650                    element.closest('video').get(0).load();
1651                }
1652            });
1653        }
1654
1655        /**
1656        * Plays video and audio elements.
1657        */
1658        function playMedia(destiny){
1659            var panel = getSlideOrSection(destiny);
1660
1661            //playing HTML5 media elements
1662            panel.find('video, audio').each(function(){
1663                var element = $(this).get(0);
1664
1665                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
1666                    element.play();
1667                }
1668            });
1669
1670            //youtube videos
1671            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
1672                var element = $(this).get(0);
1673
1674                if ( element.hasAttribute('data-autoplay') ){
1675                    playYoutube(element);
1676                }
1677
1678                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
1679                element.onload = function() {
1680                    if ( element.hasAttribute('data-autoplay') ){
1681                        playYoutube(element);
1682                    }
1683                };
1684            });
1685        }
1686
1687        /**
1688        * Plays a youtube video
1689        */
1690        function playYoutube(element){
1691            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
1692        }
1693
1694        /**
1695        * Stops video and audio elements.
1696        */
1697        function stopMedia(destiny){
1698            var panel = getSlideOrSection(destiny);
1699
1700            //stopping HTML5 media elements
1701            panel.find('video, audio').each(function(){
1702                var element = $(this).get(0);
1703
1704                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
1705                    element.pause();
1706                }
1707            });
1708
1709            //youtube videos
1710            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
1711                var element = $(this).get(0);
1712
1713                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
1714                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
1715                }
1716            });
1717        }
1718
1719        /**
1720        * Gets the active slide (or section) for the given section
1721        */
1722        function getSlideOrSection(destiny){
1723            var slide = destiny.find(SLIDE_ACTIVE_SEL);
1724            if( slide.length ) {
1725                destiny = $(slide);
1726            }
1727
1728            return destiny;
1729        }
1730
1731        /**
1732        * Scrolls to the anchor in the URL when loading the site
1733        */
1734        function scrollToAnchor(){
1735            //getting the anchor link in the URL and deleting the `#`
1736            var value =  window.location.hash.replace('#', '').split('/');
1737            var sectionAnchor = decodeURIComponent(value[0]);
1738            var slideAnchor = decodeURIComponent(value[1]);
1739
1740            if(sectionAnchor){  //if theres any #
1741                if(options.animateAnchor){
1742                    scrollPageAndSlide(sectionAnchor, slideAnchor);
1743                }else{
1744                    silentMoveTo(sectionAnchor, slideAnchor);
1745                }
1746            }
1747        }
1748
1749        /**
1750        * Detecting any change on the URL to scroll to the given anchor link
1751        * (a way to detect back history button as we play with the hashes on the URL)
1752        */
1753        function hashChangeHandler(){
1754            if(!isScrolling && !options.lockAnchors){
1755                var value =  window.location.hash.replace('#', '').split('/');
1756                var sectionAnchor = decodeURIComponent(value[0]);
1757                var slideAnchor = decodeURIComponent(value[1]);
1758
1759                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
1760                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
1761                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
1762
1763
1764                if(sectionAnchor.length){
1765                    /*in order to call scrollpage() only once for each destination at a time
1766                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
1767                    event is fired on every scroll too.*/
1768                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
1769                        scrollPageAndSlide(sectionAnchor, slideAnchor);
1770                    }
1771                }
1772            }
1773        }
1774
1775        //Sliding with arrow keys, both, vertical and horizontal
1776        function keydownHandler(e) {
1777
1778            clearTimeout(keydownId);
1779
1780            var activeElement = $(':focus');
1781
1782            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
1783                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
1784                options.keyboardScrolling && options.autoScrolling){
1785                var keyCode = e.which;
1786
1787                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
1788                var keyControls = [40, 38, 32, 33, 34];
1789                if($.inArray(keyCode, keyControls) > -1){
1790                    e.preventDefault();
1791                }
1792
1793                controlPressed = e.ctrlKey;
1794
1795                keydownId = setTimeout(function(){
1796                    onkeydown(e);
1797                },150);
1798            }
1799        }
1800
1801        function tooltipTextHandler(){
1802            $(this).prev().trigger('click');
1803        }
1804
1805        //to prevent scrolling while zooming
1806        function keyUpHandler(e){
1807            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
1808                controlPressed = e.ctrlKey;
1809            }
1810        }
1811
1812        //binding the mousemove when the mouse's middle button is released
1813        function mouseDownHandler(e){
1814            //middle button
1815            if (e.which == 2){
1816                oldPageY = e.pageY;
1817                container.on('mousemove', mouseMoveHandler);
1818            }
1819        }
1820
1821        //unbinding the mousemove when the mouse's middle button is released
1822        function mouseUpHandler(e){
1823            //middle button
1824            if (e.which == 2){
1825                container.off('mousemove');
1826            }
1827        }
1828
1829        //Scrolling horizontally when clicking on the slider controls.
1830        function slideArrowHandler(){
1831            var section = $(this).closest(SECTION_SEL);
1832
1833            if ($(this).hasClass(SLIDES_PREV)) {
1834                if(isScrollAllowed.m.left){
1835                    moveSlideLeft(section);
1836                }
1837            } else {
1838                if(isScrollAllowed.m.right){
1839                    moveSlideRight(section);
1840                }
1841            }
1842        }
1843
1844        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
1845        function blurHandler(){
1846            isWindowFocused = false;
1847            controlPressed = false;
1848        }
1849
1850        //Scrolls to the section when clicking the navigation bullet
1851        function sectionBulletHandler(e){
1852            e.preventDefault();
1853            var index = $(this).parent().index();
1854            scrollPage($(SECTION_SEL).eq(index));
1855        }
1856
1857        //Scrolls the slider to the given slide destination for the given section
1858        function slideBulletHandler(e){
1859            e.preventDefault();
1860            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
1861            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
1862
1863            landscapeScroll(slides, destiny);
1864        }
1865
1866        /**
1867        * Keydown event
1868        */
1869        function onkeydown(e){
1870            var shiftPressed = e.shiftKey;
1871
1872            //do nothing if we can not scroll or we are not using horizotnal key arrows.
1873            if(!canScroll && [37,39].indexOf(e.which) < 0){
1874                return;
1875            }
1876
1877            switch (e.which) {
1878                //up
1879                case 38:
1880                case 33:
1881                    if(isScrollAllowed.k.up){
1882                        moveSectionUp();
1883                    }
1884                    break;
1885
1886                //down
1887                case 32: //spacebar
1888                    if(shiftPressed && isScrollAllowed.k.up){
1889                        moveSectionUp();
1890                        break;
1891                    }
1892                /* falls through */
1893                case 40:
1894                case 34:
1895                    if(isScrollAllowed.k.down){
1896                        moveSectionDown();
1897                    }
1898                    break;
1899
1900                //Home
1901                case 36:
1902                    if(isScrollAllowed.k.up){
1903                        moveTo(1);
1904                    }
1905                    break;
1906
1907                //End
1908                case 35:
1909                     if(isScrollAllowed.k.down){
1910                        moveTo( $(SECTION_SEL).length );
1911                    }
1912                    break;
1913
1914                //left
1915                case 37:
1916                    if(isScrollAllowed.k.left){
1917                        moveSlideLeft();
1918                    }
1919                    break;
1920
1921                //right
1922                case 39:
1923                    if(isScrollAllowed.k.right){
1924                        moveSlideRight();
1925                    }
1926                    break;
1927
1928                default:
1929                    return; // exit this handler for other keys
1930            }
1931        }
1932
1933        /**
1934        * Detecting the direction of the mouse movement.
1935        * Used only for the middle button of the mouse.
1936        */
1937        var oldPageY = 0;
1938        function mouseMoveHandler(e){
1939            if(canScroll){
1940                // moving up
1941                if (e.pageY < oldPageY && isScrollAllowed.m.up){
1942                    moveSectionUp();
1943                }
1944
1945                // moving down
1946                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
1947                    moveSectionDown();
1948                }
1949            }
1950            oldPageY = e.pageY;
1951        }
1952
1953        /**
1954        * Scrolls horizontal sliders.
1955        */
1956        function landscapeScroll(slides, destiny, direction){
1957            var section = slides.closest(SECTION_SEL);
1958            var v = {
1959                slides: slides,
1960                destiny: destiny,
1961                direction: direction,
1962                destinyPos: destiny.position(),
1963                slideIndex: destiny.index(),
1964                section: section,
1965                sectionIndex: section.index(SECTION_SEL),
1966                anchorLink: section.data('anchor'),
1967                slidesNav: section.find(SLIDES_NAV_SEL),
1968                slideAnchor:  getAnchor(destiny),
1969                prevSlide: section.find(SLIDE_ACTIVE_SEL),
1970                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
1971
1972                //caching the value of isResizing at the momment the function is called
1973                //because it will be checked later inside a setTimeout and the value might change
1974                localIsResizing: isResizing
1975            };
1976            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
1977
1978            //important!! Only do it when not resizing
1979            if(!v.localIsResizing){
1980                //preventing from scrolling to the next/prev section when using scrollHorizontally
1981                canScroll = false;
1982            }
1983
1984            if(options.onSlideLeave){
1985
1986                //if the site is not just resizing and readjusting the slides
1987                if(!v.localIsResizing && v.xMovement!=='none'){
1988                    if($.isFunction( options.onSlideLeave )){
1989                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
1990                            slideMoving = false;
1991                            return;
1992                        }
1993                    }
1994                }
1995            }
1996
1997            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
1998
1999            if(!v.localIsResizing){
2000                stopMedia(v.prevSlide);
2001                lazyLoad(destiny);
2002            }
2003
2004            if(!options.loopHorizontal && options.controlArrows){
2005                //hidding it for the fist slide, showing for the rest
2006                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
2007
2008                //hidding it for the last slide, showing for the rest
2009                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
2010            }
2011
2012            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
2013            if(section.hasClass(ACTIVE) && !v.localIsResizing){
2014                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
2015            }
2016
2017            performHorizontalMove(slides, v, true);
2018        }
2019
2020
2021        function afterSlideLoads(v){
2022            activeSlidesNavigation(v.slidesNav, v.slideIndex);
2023
2024            //if the site is not just resizing and readjusting the slides
2025            if(!v.localIsResizing){
2026                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
2027
2028                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
2029                //and to prevent double scroll right after a windows resize
2030                canScroll = true;
2031
2032                playMedia(v.destiny);
2033            }
2034
2035            //letting them slide again
2036            slideMoving = false;
2037        }
2038
2039        /**
2040        * Performs the horizontal movement. (CSS3 or jQuery)
2041        *
2042        * @param fireCallback {Bool} - determines whether or not to fire the callback
2043        */
2044        function performHorizontalMove(slides, v, fireCallback){
2045            var destinyPos = v.destinyPos;
2046
2047            if(options.css3){
2048                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
2049
2050                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d));
2051
2052                afterSlideLoadsId = setTimeout(function(){
2053                    fireCallback && afterSlideLoads(v);
2054                }, options.scrollingSpeed, options.easing);
2055            }else{
2056                slides.animate({
2057                    scrollLeft : Math.round(destinyPos.left)
2058                }, options.scrollingSpeed, options.easing, function() {
2059
2060                    fireCallback && afterSlideLoads(v);
2061                });
2062            }
2063        }
2064
2065        /**
2066        * Sets the state for the horizontal bullet navigations.
2067        */
2068        function activeSlidesNavigation(slidesNav, slideIndex){
2069            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
2070            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
2071        }
2072
2073        var previousHeight = windowsHeight;
2074
2075        //when resizing the site, we adjust the heights of the sections, slimScroll...
2076        function resizeHandler(){
2077            //checking if it needs to get responsive
2078            responsive();
2079
2080            // rebuild immediately on touch devices
2081            if (isTouchDevice) {
2082                var activeElement = $(document.activeElement);
2083
2084                //if the keyboard is NOT visible
2085                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
2086                    var currentHeight = $window.height();
2087
2088                    //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)
2089                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
2090                        reBuild(true);
2091                        previousHeight = currentHeight;
2092                    }
2093                }
2094            }else{
2095                //in order to call the functions only when the resize is finished
2096                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
2097                clearTimeout(resizeId);
2098
2099                resizeId = setTimeout(function(){
2100                    reBuild(true);
2101                }, 350);
2102            }
2103        }
2104
2105        /**
2106        * Checks if the site needs to get responsive and disables autoScrolling if so.
2107        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
2108        */
2109        function responsive(){
2110            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
2111            var heightLimit = options.responsiveHeight;
2112
2113            //only calculating what we need. Remember its called on the resize event.
2114            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
2115            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
2116
2117            if(widthLimit && heightLimit){
2118                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
2119            }
2120            else if(widthLimit){
2121                setResponsive(isBreakingPointWidth);
2122            }
2123            else if(heightLimit){
2124                setResponsive(isBreakingPointHeight);
2125            }
2126        }
2127
2128        /**
2129        * Adds transition animations for the given element
2130        */
2131        function addAnimation(element){
2132            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
2133
2134            element.removeClass(NO_TRANSITION);
2135            return element.css({
2136                '-webkit-transition': transition,
2137                'transition': transition
2138            });
2139        }
2140
2141        /**
2142        * Remove transition animations for the given element
2143        */
2144        function removeAnimation(element){
2145            return element.addClass(NO_TRANSITION);
2146        }
2147
2148        /**
2149        * Activating the vertical navigation bullets according to the given slide name.
2150        */
2151        function activateNavDots(name, sectionIndex){
2152            if(options.navigation){
2153                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
2154                if(name){
2155                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
2156                }else{
2157                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
2158                }
2159            }
2160        }
2161
2162        /**
2163        * Activating the website main menu elements according to the given slide name.
2164        */
2165        function activateMenuElement(name){
2166            if(options.menu){
2167                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
2168                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
2169            }
2170        }
2171
2172        /**
2173        * Sets to active the current menu and vertical nav items.
2174        */
2175        function activateMenuAndNav(anchor, index){
2176            activateMenuElement(anchor);
2177            activateNavDots(anchor, index);
2178        }
2179
2180        /**
2181        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
2182        * from the current section.
2183        */
2184        function getYmovement(destiny){
2185            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
2186            var toIndex = destiny.index(SECTION_SEL);
2187            if( fromIndex == toIndex){
2188                return 'none';
2189            }
2190            if(fromIndex > toIndex){
2191                return 'up';
2192            }
2193            return 'down';
2194        }
2195
2196        /**
2197        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
2198        * from the current slide.
2199        */
2200        function getXmovement(fromIndex, toIndex){
2201            if( fromIndex == toIndex){
2202                return 'none';
2203            }
2204            if(fromIndex > toIndex){
2205                return 'left';
2206            }
2207            return 'right';
2208        }
2209
2210        /**
2211        * Checks if the element needs scrollbar and if the user wants to apply it.
2212        * If so it creates it.
2213        *
2214        * @param {Object} element   jQuery object of the section or slide
2215        */
2216        function createScrollBar(element){
2217            //User doesn't want scrollbar here? Sayonara baby!
2218            if(element.hasClass('fp-noscroll')) return;
2219
2220            //needed to make `scrollHeight` work under Opera 12
2221            element.css('overflow', 'hidden');
2222
2223            var scrollOverflowHandler = options.scrollOverflowHandler;
2224            var wrap = scrollOverflowHandler.wrapContent();
2225            //in case element is a slide
2226            var section = element.closest(SECTION_SEL);
2227            var scrollable = scrollOverflowHandler.scrollable(element);
2228            var contentHeight;
2229
2230            //if there was scroll, the contentHeight will be the one in the scrollable section
2231            if(scrollable.length){
2232                contentHeight = scrollOverflowHandler.scrollHeight(element);
2233            }else{
2234                contentHeight = element.get(0).scrollHeight;
2235                if(options.verticalCentered){
2236                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
2237                }
2238            }
2239
2240            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
2241
2242            //needs scroll?
2243            if ( contentHeight > scrollHeight) {
2244                //did we already have an scrollbar ? Updating it
2245                if(scrollable.length){
2246                    scrollOverflowHandler.update(element, scrollHeight);
2247                }
2248                //creating the scrolling
2249                else{
2250                    if(options.verticalCentered){
2251                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
2252                    }else{
2253                        element.wrapInner(wrap);
2254                    }
2255                    scrollOverflowHandler.create(element, scrollHeight);
2256                }
2257            }
2258            //removing the scrolling when it is not necessary anymore
2259            else{
2260                scrollOverflowHandler.remove(element);
2261            }
2262
2263            //undo
2264            element.css('overflow', '');
2265        }
2266
2267        function addTableClass(element){
2268            //In case we are styling for the 2nd time as in with reponsiveSlides
2269            if(!element.hasClass(TABLE)){
2270                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
2271            }
2272        }
2273
2274        function getTableHeight(element){
2275            var sectionHeight = windowsHeight;
2276
2277            if(options.paddingTop || options.paddingBottom){
2278                var section = element;
2279                if(!section.hasClass(SECTION)){
2280                    section = element.closest(SECTION_SEL);
2281                }
2282
2283                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
2284                sectionHeight = (windowsHeight - paddings);
2285            }
2286
2287            return sectionHeight;
2288        }
2289
2290        /**
2291        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
2292        */
2293        function transformContainer(translate3d, animated){
2294            if(animated){
2295                addAnimation(container);
2296            }else{
2297                removeAnimation(container);
2298            }
2299
2300            container.css(getTransforms(translate3d));
2301
2302            //syncronously removing the class after the animation has been applied.
2303            setTimeout(function(){
2304                container.removeClass(NO_TRANSITION);
2305            },10);
2306        }
2307
2308        /**
2309        * Gets a section by its anchor / index
2310        */
2311        function getSectionByAnchor(sectionAnchor){
2312            if(!sectionAnchor) return [];
2313
2314            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
2315            if(!section.length){
2316                section = $(SECTION_SEL).eq( sectionAnchor -1);
2317            }
2318
2319            return section;
2320        }
2321
2322        /**
2323        * Gets a slide inside a given section by its anchor / index
2324        */
2325        function getSlideByAnchor(slideAnchor, section){
2326            var slides = section.find(SLIDES_WRAPPER_SEL);
2327            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
2328
2329            if(!slide.length){
2330                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
2331            }
2332
2333            return slide;
2334        }
2335
2336        /**
2337        * Scrolls to the given section and slide anchors
2338        */
2339        function scrollPageAndSlide(destiny, slide){
2340            var section = getSectionByAnchor(destiny);
2341
2342            //do nothing if there's no section with the given anchor name
2343            if(!section.length) return;
2344
2345            //default slide
2346            if (typeof slide === 'undefined') {
2347                slide = 0;
2348            }
2349
2350            //we need to scroll to the section and then to the slide
2351            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
2352                scrollPage(section, function(){
2353                    scrollSlider(section, slide);
2354                });
2355            }
2356            //if we were already in the section
2357            else{
2358                scrollSlider(section, slide);
2359            }
2360        }
2361
2362        /**
2363        * Scrolls the slider to the given slide destination for the given section
2364        */
2365        function scrollSlider(section, slideAnchor){
2366            if(typeof slideAnchor !== 'undefined'){
2367                var slides = section.find(SLIDES_WRAPPER_SEL);
2368                var destiny =  getSlideByAnchor(slideAnchor, section);
2369
2370                if(destiny.length){
2371                    landscapeScroll(slides, destiny);
2372                }
2373            }
2374        }
2375
2376        /**
2377        * Creates a landscape navigation bar with dots for horizontal sliders.
2378        */
2379        function addSlidesNavigation(section, numSlides){
2380            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
2381            var nav = section.find(SLIDES_NAV_SEL);
2382
2383            //top or bottom
2384            nav.addClass(options.slidesNavPosition);
2385
2386            for(var i=0; i< numSlides; i++){
2387                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
2388            }
2389
2390            //centering it
2391            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
2392
2393            nav.find('li').first().find('a').addClass(ACTIVE);
2394        }
2395
2396
2397        /**
2398        * Sets the state of the website depending on the active section/slide.
2399        * It changes the URL hash when needed and updates the body class.
2400        */
2401        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
2402            var sectionHash = '';
2403
2404            if(options.anchors.length && !options.lockAnchors){
2405
2406                //isn't it the first slide?
2407                if(slideIndex){
2408                    if(typeof anchorLink !== 'undefined'){
2409                        sectionHash = anchorLink;
2410                    }
2411
2412                    //slide without anchor link? We take the index instead.
2413                    if(typeof slideAnchor === 'undefined'){
2414                        slideAnchor = slideIndex;
2415                    }
2416
2417                    lastScrolledSlide = slideAnchor;
2418                    setUrlHash(sectionHash + '/' + slideAnchor);
2419
2420                //first slide won't have slide anchor, just the section one
2421                }else if(typeof slideIndex !== 'undefined'){
2422                    lastScrolledSlide = slideAnchor;
2423                    setUrlHash(anchorLink);
2424                }
2425
2426                //section without slides
2427                else{
2428                    setUrlHash(anchorLink);
2429                }
2430            }
2431
2432            setBodyClass();
2433        }
2434
2435        /**
2436        * Sets the URL hash.
2437        */
2438        function setUrlHash(url){
2439            if(options.recordHistory){
2440                location.hash = url;
2441            }else{
2442                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
2443                if(isTouchDevice || isTouch){
2444                    window.history.replaceState(undefined, undefined, '#' + url);
2445                }else{
2446                    var baseUrl = window.location.href.split('#')[0];
2447                    window.location.replace( baseUrl + '#' + url );
2448                }
2449            }
2450        }
2451
2452        /**
2453        * Gets the anchor for the given slide / section. Its index will be used if there's none.
2454        */
2455        function getAnchor(element){
2456            var anchor = element.data('anchor');
2457            var index = element.index();
2458
2459            //Slide without anchor link? We take the index instead.
2460            if(typeof anchor === 'undefined'){
2461                anchor = index;
2462            }
2463
2464            return anchor;
2465        }
2466
2467        /**
2468        * Sets a class for the body of the page depending on the active section / slide
2469        */
2470        function setBodyClass(){
2471            var section = $(SECTION_ACTIVE_SEL);
2472            var slide = section.find(SLIDE_ACTIVE_SEL);
2473
2474            var sectionAnchor = getAnchor(section);
2475            var slideAnchor = getAnchor(slide);
2476
2477            var text = String(sectionAnchor);
2478
2479            if(slide.length){
2480                text = text + '-' + slideAnchor;
2481            }
2482
2483            //changing slash for dash to make it a valid CSS style
2484            text = text.replace('/', '-').replace('#','');
2485
2486            //removing previous anchor classes
2487            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
2488            $body[0].className = $body[0].className.replace(classRe, '');
2489
2490            //adding the current anchor
2491            $body.addClass(VIEWING_PREFIX + '-' + text);
2492        }
2493
2494        /**
2495        * Checks for translate3d support
2496        * @return boolean
2497        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
2498        */
2499        function support3d() {
2500            var el = document.createElement('p'),
2501                has3d,
2502                transforms = {
2503                    'webkitTransform':'-webkit-transform',
2504                    'OTransform':'-o-transform',
2505                    'msTransform':'-ms-transform',
2506                    'MozTransform':'-moz-transform',
2507                    'transform':'transform'
2508                };
2509
2510            // Add it to the body to get the computed style.
2511            document.body.insertBefore(el, null);
2512
2513            for (var t in transforms) {
2514                if (el.style[t] !== undefined) {
2515                    el.style[t] = 'translate3d(1px,1px,1px)';
2516                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
2517                }
2518            }
2519
2520            document.body.removeChild(el);
2521
2522            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
2523        }
2524
2525        /**
2526        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
2527        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
2528        */
2529        function removeMouseWheelHandler(){
2530            if (document.addEventListener) {
2531                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
2532                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
2533                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
2534            } else {
2535                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
2536            }
2537        }
2538
2539        /**
2540        * Adds the auto scrolling action for the mouse wheel and trackpad.
2541        * After this function is called, the mousewheel and trackpad movements will scroll through sections
2542        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
2543        */
2544        function addMouseWheelHandler(){
2545            var prefix = '';
2546            var _addEventListener;
2547
2548            if (window.addEventListener){
2549                _addEventListener = "addEventListener";
2550            }else{
2551                _addEventListener = "attachEvent";
2552                prefix = 'on';
2553            }
2554
2555             // detect available wheel event
2556            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
2557                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
2558                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
2559
2560
2561            if(support == 'DOMMouseScroll'){
2562                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false);
2563            }
2564
2565            //handle MozMousePixelScroll in older Firefox
2566            else{
2567                document[ _addEventListener ](prefix + support, MouseWheelHandler, false);
2568            }
2569        }
2570
2571        /**
2572        * Binding the mousemove when the mouse's middle button is pressed
2573        */
2574        function addMiddleWheelHandler(){
2575            container
2576                .on('mousedown', mouseDownHandler)
2577                .on('mouseup', mouseUpHandler);
2578        }
2579
2580        /**
2581        * Unbinding the mousemove when the mouse's middle button is released
2582        */
2583        function removeMiddleWheelHandler(){
2584            container
2585                .off('mousedown', mouseDownHandler)
2586                .off('mouseup', mouseUpHandler);
2587        }
2588
2589        /**
2590        * Adds the possibility to auto scroll through sections on touch devices.
2591        */
2592        function addTouchHandler(){
2593            if(isTouchDevice || isTouch){
2594                if(options.autoScrolling){
2595                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
2596                }
2597
2598                $(WRAPPER_SEL)
2599                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
2600                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
2601            }
2602        }
2603
2604        /**
2605        * Removes the auto scrolling for touch devices.
2606        */
2607        function removeTouchHandler(){
2608            if(isTouchDevice || isTouch){
2609                $(WRAPPER_SEL)
2610                    .off(events.touchstart)
2611                    .off(events.touchmove);
2612            }
2613        }
2614
2615        /*
2616        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
2617        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
2618        */
2619        function getMSPointer(){
2620            var pointer;
2621
2622            //IE >= 11 & rest of browsers
2623            if(window.PointerEvent){
2624                pointer = { down: 'pointerdown', move: 'pointermove'};
2625            }
2626
2627            //IE < 11
2628            else{
2629                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
2630            }
2631
2632            return pointer;
2633        }
2634
2635        /**
2636        * Gets the pageX and pageY properties depending on the browser.
2637        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
2638        */
2639        function getEventsPage(e){
2640            var events = [];
2641
2642            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
2643            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
2644
2645            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
2646            if(isTouch && isReallyTouch(e) && options.scrollBar){
2647                events.y = e.touches[0].pageY;
2648                events.x = e.touches[0].pageX;
2649            }
2650
2651            return events;
2652        }
2653
2654        /**
2655        * Slides silently (with no animation) the active slider to the given slide.
2656        * @param noCallback {bool} true or defined -> no callbacks
2657        */
2658        function silentLandscapeScroll(activeSlide, noCallbacks){
2659            setScrollingSpeed (0, 'internal');
2660
2661            if(typeof noCallbacks !== 'undefined'){
2662                //preventing firing callbacks afterSlideLoad etc.
2663                isResizing = true;
2664            }
2665
2666            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
2667
2668            if(typeof noCallbacks !== 'undefined'){
2669                isResizing = false;
2670            }
2671
2672            setScrollingSpeed(originals.scrollingSpeed, 'internal');
2673        }
2674
2675        /**
2676        * Scrolls silently (with no animation) the page to the given Y position.
2677        */
2678        function silentScroll(top){
2679            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
2680            // that's why we round it to 0.
2681            var roundedTop = Math.round(top);
2682
2683            if (options.css3 && options.autoScrolling && !options.scrollBar){
2684                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
2685                transformContainer(translate3d, false);
2686            }
2687            else if(options.autoScrolling && !options.scrollBar){
2688                container.css('top', -roundedTop);
2689            }
2690            else{
2691                $htmlBody.scrollTop(roundedTop);
2692            }
2693        }
2694
2695        /**
2696        * Returns the cross-browser transform string.
2697        */
2698        function getTransforms(translate3d){
2699            return {
2700                '-webkit-transform': translate3d,
2701                '-moz-transform': translate3d,
2702                '-ms-transform':translate3d,
2703                'transform': translate3d
2704            };
2705        }
2706
2707        /**
2708        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
2709        * @type  m (mouse) or k (keyboard)
2710        */
2711        function setIsScrollAllowed(value, direction, type){
2712            switch (direction){
2713                case 'up': isScrollAllowed[type].up = value; break;
2714                case 'down': isScrollAllowed[type].down = value; break;
2715                case 'left': isScrollAllowed[type].left = value; break;
2716                case 'right': isScrollAllowed[type].right = value; break;
2717                case 'all':
2718                    if(type == 'm'){
2719                        setAllowScrolling(value);
2720                    }else{
2721                        setKeyboardScrolling(value);
2722                    }
2723            }
2724        }
2725
2726        /*
2727        * Destroys fullpage.js plugin events and optinally its html markup and styles
2728        */
2729        function destroy(all){
2730            setAutoScrolling(false, 'internal');
2731            setAllowScrolling(false);
2732            setKeyboardScrolling(false);
2733            container.addClass(DESTROYED);
2734
2735            clearTimeout(afterSlideLoadsId);
2736            clearTimeout(afterSectionLoadsId);
2737            clearTimeout(resizeId);
2738            clearTimeout(scrollId);
2739            clearTimeout(scrollId2);
2740
2741            $window
2742                .off('scroll', scrollHandler)
2743                .off('hashchange', hashChangeHandler)
2744                .off('resize', resizeHandler);
2745
2746            $document
2747                .off('click touchstart', SECTION_NAV_SEL + ' a')
2748                .off('mouseenter', SECTION_NAV_SEL + ' li')
2749                .off('mouseleave', SECTION_NAV_SEL + ' li')
2750                .off('click touchstart', SLIDES_NAV_LINK_SEL)
2751                .off('mouseover', options.normalScrollElements)
2752                .off('mouseout', options.normalScrollElements);
2753
2754            $(SECTION_SEL)
2755                .off('click touchstart', SLIDES_ARROW_SEL);
2756
2757            clearTimeout(afterSlideLoadsId);
2758            clearTimeout(afterSectionLoadsId);
2759
2760            //lets make a mess!
2761            if(all){
2762                destroyStructure();
2763            }
2764        }
2765
2766        /*
2767        * Removes inline styles added by fullpage.js
2768        */
2769        function destroyStructure(){
2770            //reseting the `top` or `translate` properties to 0
2771            silentScroll(0);
2772
2773            //loading all the lazy load content
2774            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
2775                setSrc($(this), 'src');
2776            });
2777
2778            container.find('img[data-srcset]').each(function(){
2779                setSrc($(this), 'srcset');
2780            });
2781
2782            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
2783
2784            //removing inline styles
2785            $(SECTION_SEL).css( {
2786                'height': '',
2787                'background-color' : '',
2788                'padding': ''
2789            });
2790
2791            $(SLIDE_SEL).css( {
2792                'width': ''
2793            });
2794
2795            container.css({
2796                'height': '',
2797                'position': '',
2798                '-ms-touch-action': '',
2799                'touch-action': ''
2800            });
2801
2802            $htmlBody.css({
2803                'overflow': '',
2804                'height': ''
2805            });
2806
2807            // remove .fp-enabled class
2808            $('html').removeClass(ENABLED);
2809
2810            // remove .fp-responsive class
2811            $body.removeClass(RESPONSIVE);
2812
2813            // remove all of the .fp-viewing- classes
2814            $.each($body.get(0).className.split(/\s+/), function (index, className) {
2815                if (className.indexOf(VIEWING_PREFIX) === 0) {
2816                    $body.removeClass(className);
2817                }
2818            });
2819
2820            //removing added classes
2821            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
2822                options.scrollOverflowHandler.remove($(this));
2823                $(this).removeClass(TABLE + ' ' + ACTIVE);
2824            });
2825
2826            removeAnimation(container);
2827
2828            //Unwrapping content
2829            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
2830                //unwrap not being use in case there's no child element inside and its just text
2831                $(this).replaceWith(this.childNodes);
2832            });
2833
2834            //removing the applied transition from the fullpage wrapper
2835            container.css({
2836                '-webkit-transition': 'none',
2837                'transition': 'none'
2838            });
2839
2840            //scrolling the page to the top with no animation
2841            $htmlBody.scrollTop(0);
2842
2843            //removing selectors
2844            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
2845            $.each(usedSelectors, function(index, value){
2846                $('.' + value).removeClass(value);
2847            });
2848        }
2849
2850        /*
2851        * Sets the state for a variable with multiple states (original, and temporal)
2852        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
2853        * This function is used to keep track of both states, the original and the temporal one.
2854        * If type is not 'internal', then we assume the user is globally changing the variable.
2855        */
2856        function setVariableState(variable, value, type){
2857            options[variable] = value;
2858            if(type !== 'internal'){
2859                originals[variable] = value;
2860            }
2861        }
2862
2863        /**
2864        * Displays warnings
2865        */
2866        function displayWarnings(){
2867            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
2868            if($('html').hasClass(ENABLED)){
2869                showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
2870                return;
2871            }
2872
2873            // Disable mutually exclusive settings
2874            if (options.continuousVertical &&
2875                (options.loopTop || options.loopBottom)) {
2876                options.continuousVertical = false;
2877                showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
2878            }
2879
2880            if(options.scrollBar && options.scrollOverflow){
2881                showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
2882            }
2883
2884            if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
2885                options.continuousVertical = false;
2886                showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
2887            }
2888
2889            //using extensions? Wrong file!
2890            $.each(extensions, function(index, extension){
2891                //is the option set to true?
2892                if(options[extension]){
2893                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
2894                }
2895            });
2896
2897            //anchors can not have the same value as any element ID or NAME
2898            $.each(options.anchors, function(index, name){
2899
2900                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
2901                var nameAttr = $document.find('[name]').filter(function() {
2902                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
2903                });
2904
2905                var idAttr = $document.find('[id]').filter(function() {
2906                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
2907                });
2908
2909                if(idAttr.length || nameAttr.length ){
2910                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
2911                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
2912                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
2913                }
2914            });
2915        }
2916
2917        /**
2918        * Shows a message in the console of the given type.
2919        */
2920        function showError(type, text){
2921            console && console[type] && console[type]('fullPage: ' + text);
2922        }
2923
2924    }; //end of $.fn.fullpage
2925
2926    if(typeof IScroll !== 'undefined'){
2927        /*
2928        * Turns iScroll `mousewheel` option off dynamically
2929        * https://github.com/cubiq/iscroll/issues/1036
2930        */
2931        IScroll.prototype.wheelOn = function () {
2932            this.wrapper.addEventListener('wheel', this);
2933            this.wrapper.addEventListener('mousewheel', this);
2934            this.wrapper.addEventListener('DOMMouseScroll', this);
2935        };
2936
2937        /*
2938        * Turns iScroll `mousewheel` option on dynamically
2939        * https://github.com/cubiq/iscroll/issues/1036
2940        */
2941        IScroll.prototype.wheelOff = function () {
2942            this.wrapper.removeEventListener('wheel', this);
2943            this.wrapper.removeEventListener('mousewheel', this);
2944            this.wrapper.removeEventListener('DOMMouseScroll', this);
2945        };
2946    }
2947
2948    /**
2949     * An object to handle overflow scrolling.
2950     * This uses jquery.slimScroll to accomplish overflow scrolling.
2951     * It is possible to pass in an alternate scrollOverflowHandler
2952     * to the fullpage.js option that implements the same functions
2953     * as this handler.
2954     *
2955     * @type {Object}
2956     */
2957    var iscrollHandler = {
2958        refreshId: null,
2959        iScrollInstances: [],
2960
2961        // Enables or disables the mouse wheel for the active section or all slides in it
2962        toggleWheel: function(value){
2963            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
2964            scrollable.each(function(){
2965                var iScrollInstance = $(this).data('iscrollInstance');
2966                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
2967                    if(value){
2968                        iScrollInstance.wheelOn();
2969                    }
2970                    else{
2971                        iScrollInstance.wheelOff();
2972                    }
2973                }
2974            });
2975        },
2976
2977        /**
2978        * Turns off iScroll for the destination section.
2979        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
2980        * scroll the destination section/slide before the sections animations ends.
2981        */
2982        onLeave: function(){
2983            iscrollHandler.toggleWheel(false);
2984        },
2985
2986        // Turns off iScroll for the leaving section
2987        beforeLeave: function(){
2988            iscrollHandler.onLeave()
2989        },
2990
2991        // Turns on iScroll on section load
2992        afterLoad: function(){
2993            iscrollHandler.toggleWheel(true);
2994        },
2995
2996        /**
2997         * Called when overflow scrolling is needed for a section.
2998         *
2999         * @param  {Object} element      jQuery object containing current section
3000         * @param  {Number} scrollHeight Current window height in pixels
3001         */
3002        create: function(element, scrollHeight) {
3003            var scrollable = element.find(SCROLLABLE_SEL);
3004
3005            scrollable.height(scrollHeight);
3006            scrollable.each(function() {
3007                var $this = $(this);
3008                var iScrollInstance = $this.data('iscrollInstance');
3009                if (iScrollInstance) {
3010                    $.each(iscrollHandler.iScrollInstances, function(){
3011                        $(this).destroy();
3012                    });
3013                }
3014
3015                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
3016                iscrollHandler.iScrollInstances.push(iScrollInstance);
3017
3018                //off by default until the section gets active
3019                iScrollInstance.wheelOff();
3020
3021                $this.data('iscrollInstance', iScrollInstance);
3022            });
3023        },
3024
3025        /**
3026         * Return a boolean depending on whether the scrollable element is a
3027         * the end or at the start of the scrolling depending on the given type.
3028         *
3029         * @param  {String}  type       Either 'top' or 'bottom'
3030         * @param  {Object}  scrollable jQuery object for the scrollable element
3031         * @return {Boolean}
3032         */
3033        isScrolled: function(type, scrollable) {
3034            var scroller = scrollable.data('iscrollInstance');
3035
3036            //no scroller?
3037            if (!scroller) {
3038                return true;
3039            }
3040
3041            if (type === 'top') {
3042                return scroller.y >= 0 && !scrollable.scrollTop();
3043            } else if (type === 'bottom') {
3044                return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHe
3044ight() >= scrollable[0].scrollHeight;
3045            }
3046        },
3047
3048        /**
3049         * Returns the scrollable element for the given section.
3050         * If there are landscape slides, will only return a scrollable element
3051         * if it is in the active slide.
3052         *
3053         * @param  {Object}  activeSection jQuery object containing current section
3054         * @return {Boolean}
3055         */
3056        scrollable: function(activeSection){
3057            // if there are landscape slides, we check if the scrolling bar is in the current one or not
3058            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
3059                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
3060            }
3061            return activeSection.find(SCROLLABLE_SEL);
3062        },
3063
3064        /**
3065         * Returns the scroll height of the wrapped content.
3066         * If this is larger than the window height minus section padding,
3067         * overflow scrolling is needed.
3068         *
3069         * @param  {Object} element jQuery object containing current section
3070         * @return {Number}
3071         */
3072        scrollHeight: function(element) {
3073            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
3074        },
3075
3076        /**
3077         * Called when overflow scrolling is no longer needed for a section.
3078         *
3079         * @param  {Object} element      jQuery object containing current section
3080         */
3081        remove: function(element) {
3082            var scrollable = element.find(SCROLLABLE_SEL);
3083            if (scrollable.length) {
3084                var iScrollInstance = scrollable.data('iscrollInstance');
3085                iScrollInstance.destroy();
3086
3087                scrollable.data('iscrollInstance', null);
3088            }
3089            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
3090        },
3091
3092        /**
3093         * Called when overflow scrolling has already been setup but the
3094         * window height has potentially changed.
3095         *
3096         * @param  {Object} element      jQuery object containing current section
3097         * @param  {Number} scrollHeight Current window height in pixels
3098         */
3099        update: function(element, scrollHeight) {
3100            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
3101            //short period of time.
3102            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
3103            clearTimeout(iscrollHandler.refreshId);
3104            iscrollHandler.refreshId = setTimeout(function(){
3105                $.each(iscrollHandler.iScrollInstances, function(){
3106                    $(this).get(0).refresh();
3107                });
3108            }, 150);
3109
3110            //updating the wrappers height
3111            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
3112        },
3113
3114        /**
3115         * Called to get any additional elements needed to wrap the section
3116         * content in order to facilitate overflow scrolling.
3117         *
3118         * @return {String|Object} Can be a string containing HTML,
3119         *                         a DOM element, or jQuery object.
3120         */
3121        wrapContent: function() {
3122            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
3123        }
3124    };
3125});

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.