PageSourceSearch

https://www.chenonceau.com/wp-content/themes/netconcept_V2/js/jquery.fullPage.js

js chenonceau.com collected 2026-10-02 02:31:30 UTC 118,942 bytes, 3,083 lines download raw bytes

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

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.