Browse code

Implement a new fullpage.js based scrolling and slide handling and remove the old one

Benjamin Roth authored on27/03/2015 12:46:35
Showing1 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,2168 @@
1
+/**
2
+ * fullPage 2.6.2
3
+ * https://github.com/alvarotrigo/fullPage.js
4
+ * MIT licensed
5
+ *
6
+ * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
7
+ */
8
+(function($, window, document, Math, undefined) {
9
+    'use strict';
10
+
11
+    // keeping central set of classnames and selectors
12
+    var WRAPPER =               'fullpage-wrapper';
13
+    var WRAPPER_SEL =           '.' + WRAPPER;
14
+
15
+    // slimscroll
16
+    var SCROLLABLE =            'fp-scrollable';
17
+    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
18
+    var SLIMSCROLL_BAR_SEL =    '.slimScrollBar';
19
+    var SLIMSCROLL_RAIL_SEL =   '.slimScrollRail';
20
+
21
+    // util
22
+    var RESPONSIVE =            'fp-responsive';
23
+    var NO_TRANSITION =         'fp-notransition';
24
+    var DESTROYED =             'fp-destroyed';
25
+    var VIEWING_PREFIX =        'fp-viewing';
26
+    var ACTIVE =                'active';
27
+    var ACTIVE_SEL =            '.' + ACTIVE;
28
+
29
+    // section
30
+    var SECTION_DEFAULT_SEL =   '.section';
31
+    var SECTION =               'fp-section';
32
+    var SECTION_SEL =           '.' + SECTION;
33
+    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
34
+    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
35
+    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
36
+    var TABLE_CELL =            'fp-tableCell';
37
+    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
38
+
39
+    // section nav
40
+    var SECTION_NAV =           'fp-nav';
41
+    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
42
+    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
43
+    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
44
+
45
+    // slide
46
+    var SLIDE_DEFAULT_SEL =     '.slide';
47
+    var SLIDE =                 'fp-slide';
48
+    var SLIDE_SEL =             '.' + SLIDE;
49
+    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
50
+    var SLIDES_WRAPPER =        'fp-slides';
51
+    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
52
+    var SLIDES_CONTAINER =      'fp-slidesContainer';
53
+    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
54
+    var TABLE =                 'fp-table';
55
+
56
+    // slide nav
57
+    var SLIDES_NAV =            'fp-slidesNav';
58
+    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
59
+    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
60
+    var SLIDES_ARROW =          'fp-controlArrow';
61
+    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
62
+    var SLIDES_PREV =           'fp-prev';
63
+    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
64
+    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
65
+    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
66
+    var SLIDES_NEXT =           'fp-next';
67
+    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
68
+    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
69
+    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
70
+
71
+    var $window = $(window);
72
+    var $document = $(document);
73
+
74
+    $.fn.fullpage = function(options) {
75
+
76
+        // common jQuery objects
77
+        var $htmlBody = $('html, body');
78
+        var $body = $('body');
79
+
80
+        var FP = $.fn.fullpage;
81
+        // Create some defaults, extending them with any options that were provided
82
+        options = $.extend({
83
+            //navigation
84
+            menu: false,
85
+            anchors:[],
86
+            navigation: false,
87
+            navigationPosition: 'right',
88
+            navigationTooltips: [],
89
+            showActiveTooltip: false,
90
+            slidesNavigation: false,
91
+            slidesNavPosition: 'bottom',
92
+            scrollBar: false,
93
+
94
+            //scrolling
95
+            css3: true,
96
+            scrollingSpeed: 700,
97
+            autoScrolling: true,
98
+            fitToSection: true,
99
+            easing: 'easeInOutCubic',
100
+            easingcss3: 'ease',
101
+            loopBottom: false,
102
+            loopTop: false,
103
+            loopHorizontal: true,
104
+            continuousVertical: false,
105
+            normalScrollElements: null,
106
+            scrollOverflow: false,
107
+            touchSensitivity: 5,
108
+            normalScrollElementTouchThreshold: 5,
109
+
110
+            //Accessibility
111
+            keyboardScrolling: true,
112
+            animateAnchor: true,
113
+            recordHistory: true,
114
+
115
+            //design
116
+            controlArrows: true,
117
+            controlArrowColor: '#fff',
118
+            verticalCentered: true,
119
+            resize: false,
120
+            sectionsColor : [],
121
+            paddingTop: 0,
122
+            paddingBottom: 0,
123
+            fixedElements: null,
124
+            responsive: 0,
125
+
126
+            //Custom selectors
127
+            sectionSelector: SECTION_DEFAULT_SEL,
128
+            slideSelector: SLIDE_DEFAULT_SEL,
129
+
130
+
131
+            //events
132
+            afterLoad: null,
133
+            onLeave: null,
134
+            afterRender: null,
135
+            afterResize: null,
136
+            afterReBuild: null,
137
+            afterSlideLoad: null,
138
+            onSlideLeave: null
139
+        }, options);
140
+
141
+        displayWarnings();
142
+
143
+
144
+        //easeInOutCubic animation included in the plugin
145
+        $.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;}});
146
+
147
+        //TO BE REMOVED in future versions. Maintained temporaly for backwards compatibility.
148
+        $.extend($.easing,{ easeInQuart: function (x, t, b, c, d) { return c*(t/=d)*t*t*t + b; }});
149
+
150
+        FP.setAutoScrolling = function(value, type){
151
+            setVariableState('autoScrolling', value, type);
152
+
153
+            var element = $(SECTION_ACTIVE_SEL);
154
+
155
+            if(options.autoScrolling && !options.scrollBar){
156
+                $htmlBody.css({
157
+                    'overflow' : 'hidden',
158
+                    'height' : '100%'
159
+                });
160
+
161
+                FP.setRecordHistory(options.recordHistory, 'internal');
162
+
163
+                //for IE touch devices
164
+                container.css({
165
+                    '-ms-touch-action': 'none',
166
+                    'touch-action': 'none'
167
+                });
168
+
169
+                if(element.length){
170
+                    //moving the container up
171
+                    silentScroll(element.position().top);
172
+                }
173
+
174
+            }else{
175
+                $htmlBody.css({
176
+                    'overflow' : 'visible',
177
+                    'height' : 'initial'
178
+                });
179
+
180
+                FP.setRecordHistory(false, 'internal');
181
+
182
+                //for IE touch devices
183
+                container.css({
184
+                    '-ms-touch-action': '',
185
+                    'touch-action': ''
186
+                });
187
+
188
+                silentScroll(0);
189
+
190
+                //scrolling the page to the section with no animation
191
+                if (element.length) {
192
+                    $htmlBody.scrollTop(element.position().top);
193
+                }
194
+            }
195
+
196
+        };
197
+
198
+        /**
199
+        * Defines wheter to record the history for each hash change in the URL.
200
+        */
201
+        FP.setRecordHistory = function(value, type){
202
+            setVariableState('recordHistory', value, type);
203
+        };
204
+
205
+        /**
206
+        * Defines the scrolling speed
207
+        */
208
+        FP.setScrollingSpeed = function(value, type){
209
+            setVariableState('scrollingSpeed', value, type);
210
+        };
211
+
212
+        /**
213
+        * Sets fitToSection
214
+        */
215
+        FP.setFitToSection = function(value, type){
216
+            setVariableState('fitToSection', value, type);
217
+        };
218
+
219
+        /**
220
+        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
221
+        */
222
+        FP.setMouseWheelScrolling = function (value){
223
+            if(value){
224
+                addMouseWheelHandler();
225
+            }else{
226
+                removeMouseWheelHandler();
227
+            }
228
+        };
229
+
230
+        /**
231
+        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
232
+        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
233
+        *
234
+        * @param directions string containing the direction or directions separated by comma.
235
+        */
236
+        FP.setAllowScrolling = function (value, directions){
237
+            if(typeof directions != 'undefined'){
238
+                directions = directions.replace(' ', '').split(',');
239
+                $.each(directions, function (index, direction){
240
+                    setIsScrollable(value, direction);
241
+                });
242
+            }
243
+            else if(value){
244
+                FP.setMouseWheelScrolling(true);
245
+                addTouchHandler();
246
+            }else{
247
+                FP.setMouseWheelScrolling(false);
248
+                removeTouchHandler();
249
+            }
250
+        };
251
+
252
+        /**
253
+        * Adds or remove the possiblity of scrolling through sections by using the keyboard arrow keys
254
+        */
255
+        FP.setKeyboardScrolling = function (value){
256
+            options.keyboardScrolling = value;
257
+        };
258
+
259
+        FP.moveSectionUp = function(){
260
+            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
261
+
262
+            //looping to the bottom if there's no more sections above
263
+            if (!prev.length && (options.loopTop || options.continuousVertical)) {
264
+                prev = $(SECTION_SEL).last();
265
+            }
266
+
267
+            if (prev.length) {
268
+                scrollPage(prev, null, true);
269
+            }
270
+        };
271
+
272
+        FP.moveSectionDown = function (){
273
+            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
274
+
275
+            //looping to the top if there's no more sections below
276
+            if(!next.length &&
277
+                (options.loopBottom || options.continuousVertical)){
278
+                next = $(SECTION_SEL).first();
279
+            }
280
+
281
+            if(next.length){
282
+                scrollPage(next, null, false);
283
+            }
284
+        };
285
+
286
+        FP.moveTo = function (section, slide){
287
+            var destiny = '';
288
+
289
+            if(isNaN(section)){
290
+                destiny = $('[data-anchor="'+section+'"]');
291
+            }else{
292
+                destiny = $(SECTION_SEL).eq( (section -1) );
293
+            }
294
+
295
+            if (typeof slide !== 'undefined'){
296
+                scrollPageAndSlide(section, slide);
297
+            }else if(destiny.length > 0){
298
+                scrollPage(destiny);
299
+            }
300
+        };
301
+
302
+        FP.moveSlideRight = function(){
303
+            moveSlide('next');
304
+        };
305
+
306
+        FP.moveSlideLeft = function(){
307
+            moveSlide('prev');
308
+        };
309
+
310
+        /**
311
+         * When resizing is finished, we adjust the slides sizes and positions
312
+         */
313
+        FP.reBuild = function(resizing){
314
+            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
315
+
316
+            isResizing = true;
317
+
318
+            var windowsWidth = $window.width();
319
+            windowsHeight = $window.height();  //updating global var
320
+
321
+            //text and images resizing
322
+            if (options.resize) {
323
+                resizeMe(windowsHeight, windowsWidth);
324
+            }
325
+
326
+            $(SECTION_SEL).each(function(){
327
+                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
328
+                var slides = $(this).find(SLIDE_SEL);
329
+
330
+                //adjusting the height of the table-cell for IE and Firefox
331
+                if(options.verticalCentered){
332
+                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
333
+                }
334
+
335
+                $(this).css('height', windowsHeight + 'px');
336
+
337
+                //resizing the scrolling divs
338
+                if(options.scrollOverflow){
339
+                    if(slides.length){
340
+                        slides.each(function(){
341
+                            createSlimScrolling($(this));
342
+                        });
343
+                    }else{
344
+                        createSlimScrolling($(this));
345
+                    }
346
+                }
347
+
348
+                //adjusting the position fo the FULL WIDTH slides...
349
+                if (slides.length) {
350
+                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
351
+                }
352
+            });
353
+
354
+            var activeSection = $(SECTION_ACTIVE_SEL);
355
+
356
+            //isn't it the first section?
357
+            if(activeSection.index(SECTION_SEL)){
358
+                //adjusting the position for the current section
359
+                scrollPage(activeSection);
360
+            }
361
+
362
+            isResizing = false;
363
+            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
364
+            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
365
+        };
366
+
367
+        //flag to avoid very fast sliding for landscape sliders
368
+        var slideMoving = false;
369
+
370
+        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
371
+        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
372
+        var container = $(this);
373
+        var windowsHeight = $window.height();
374
+        var isResizing = false;
375
+        var lastScrolledDestiny;
376
+        var lastScrolledSlide;
377
+        var canScroll = true;
378
+        var scrollings = [];
379
+        var nav;
380
+        var isScrollAllowed = { 'up':true, 'down':true, 'left':true, 'right':true };
381
+        var originals = $.extend(true, {}, options); //deep copy
382
+
383
+        FP.setAllowScrolling(true);
384
+        container.removeClass(DESTROYED); //in case it was destroyed before initilizing it again
385
+
386
+        //if css3 is not supported, it will use jQuery animations
387
+        if(options.css3){
388
+            options.css3 = support3d();
389
+        }
390
+
391
+        if($(this).length){
392
+            container.css({
393
+                'height': '100%',
394
+                'position': 'relative'
395
+            });
396
+
397
+            //adding a class to recognize the container internally in the code
398
+            container.addClass(WRAPPER);
399
+        }
400
+
401
+        //trying to use fullpage without a selector?
402
+        else{
403
+            showError('error', 'Error! Fullpage.js needs to be initialized with a selector. For example: $(\'#myContainer\').fullpage();');
404
+        }
405
+
406
+        //adding internal class names to void problem with common ones
407
+        $(options.sectionSelector).each(function(){
408
+            $(this).addClass(SECTION);
409
+        });
410
+        $(options.slideSelector).each(function(){
411
+            $(this).addClass(SLIDE);
412
+        });
413
+
414
+        //creating the navigation dots
415
+        if (options.navigation) {
416
+            addVerticalNavigation();
417
+        }
418
+
419
+        $(SECTION_SEL).each(function(index){
420
+            var that = $(this);
421
+            var slides = $(this).find(SLIDE_SEL);
422
+            var numSlides = slides.length;
423
+
424
+            //if no active section is defined, the 1st one will be the default one
425
+            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
426
+                $(this).addClass(ACTIVE);
427
+            }
428
+
429
+            $(this).css('height', windowsHeight + 'px');
430
+
431
+            if(options.paddingTop){
432
+                $(this).css('padding-top', options.paddingTop);
433
+            }
434
+
435
+            if(options.paddingBottom){
436
+                $(this).css('padding-bottom', options.paddingBottom);
437
+            }
438
+
439
+            if (typeof options.sectionsColor[index] !==  'undefined') {
440
+                $(this).css('background-color', options.sectionsColor[index]);
441
+            }
442
+
443
+            if (typeof options.anchors[index] !== 'undefined') {
444
+                $(this).attr('data-anchor', options.anchors[index]);
445
+
446
+                //activating the menu / nav element on load
447
+                if($(this).hasClass(ACTIVE)){
448
+                    activateMenuAndNav(options.anchors[index], index);
449
+                }
450
+            }
451
+
452
+            // if there's any slide
453
+            if (numSlides > 1) {
454
+                var sliderWidth = numSlides * 100;
455
+                var slideWidth = 100 / numSlides;
456
+
457
+                slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
458
+                slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
459
+
460
+                $(this).find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
461
+
462
+                if(options.controlArrows){
463
+                    createSlideArrows($(this));
464
+                }
465
+
466
+                if(options.slidesNavigation){
467
+                    addSlidesNavigation($(this), numSlides);
468
+                }
469
+
470
+                slides.each(function(index) {
471
+                    $(this).css('width', slideWidth + '%');
472
+
473
+                    if(options.verticalCentered){
474
+                        addTableClass($(this));
475
+                    }
476
+                });
477
+
478
+                var startingSlide = that.find(SLIDE_ACTIVE_SEL);
479
+
480
+                //if the slide won#t be an starting point, the default will be the first one
481
+                if(!startingSlide.length){
482
+                    slides.eq(0).addClass(ACTIVE);
483
+                }
484
+
485
+                //is there a starting point for a non-starting section?
486
+                else{
487
+                    silentLandscapeScroll(startingSlide);
488
+                }
489
+
490
+            }else{
491
+                if(options.verticalCentered){
492
+                    addTableClass($(this));
493
+                }
494
+            }
495
+
496
+        }).promise().done(function(){
497
+            FP.setAutoScrolling(options.autoScrolling, 'internal');
498
+
499
+            //the starting point is a slide?
500
+            var activeSlide = $(SECTION_ACTIVE_SEL).find(SLIDE_ACTIVE_SEL);
501
+
502
+            //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.
503
+            if( activeSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && activeSlide.index() !== 0))){
504
+                silentLandscapeScroll(activeSlide);
505
+            }
506
+
507
+            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
508
+            if(options.fixedElements && options.css3){
509
+                $(options.fixedElements).appendTo($body);
510
+            }
511
+
512
+            //vertical centered of the navigation + first bullet active
513
+            if(options.navigation){
514
+                nav.css('margin-top', '-' + (nav.height()/2) + 'px');
515
+                nav.find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
516
+            }
517
+
518
+            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
519
+            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
520
+                $(options.menu).appendTo($body);
521
+            }
522
+
523
+            if(options.scrollOverflow){
524
+                if(document.readyState === 'complete'){
525
+                    createSlimScrollingHandler();
526
+                }
527
+                //after DOM and images are loaded
528
+                $window.on('load', createSlimScrollingHandler);
529
+            }else{
530
+                $.isFunction( options.afterRender ) && options.afterRender.call(container);
531
+            }
532
+
533
+            responsive();
534
+
535
+            //for animateAnchor:false
536
+            if(!options.animateAnchor){
537
+                //getting the anchor link in the URL and deleting the `#`
538
+                var value =  window.location.hash.replace('#', '').split('/');
539
+                var destiny = value[0];
540
+
541
+                if(destiny.length){
542
+                    var section = $('[data-anchor="'+destiny+'"]');
543
+
544
+                    if(section.length){
545
+                        if(options.autoScrolling){
546
+                            silentScroll(section.position().top);
547
+                        }
548
+                        else{
549
+                            silentScroll(0);
550
+
551
+                            //scrolling the page to the section with no animation
552
+                            $htmlBody.scrollTop(section.position().top);
553
+                        }
554
+                        activateMenuAndNav(destiny, null);
555
+
556
+                        $.isFunction( options.afterLoad ) && options.afterLoad.call( section, destiny, (section.index(SECTION_SEL) + 1));
557
+
558
+                        //updating the active class
559
+                        section.addClass(ACTIVE).siblings().removeClass(ACTIVE);
560
+                    }
561
+                }
562
+            }
563
+
564
+            //setting the class for the body element
565
+            setBodyClass();
566
+
567
+            $window.on('load', function() {
568
+                scrollToAnchor();
569
+            });
570
+
571
+        });
572
+
573
+
574
+        /**
575
+        * Creates the control arrows for the given section
576
+        */
577
+        function createSlideArrows(section){
578
+            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
579
+
580
+            if(options.controlArrowColor!='#fff'){
581
+                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
582
+                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
583
+            }
584
+
585
+            if(!options.loopHorizontal){
586
+                section.find(SLIDES_ARROW_PREV_SEL).hide();
587
+            }
588
+        }
589
+
590
+        /**
591
+        * Creates a vertical navigation bar.
592
+        */
593
+        function addVerticalNavigation(){
594
+            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
595
+            nav = $(SECTION_NAV_SEL);
596
+
597
+            nav.addClass(function() {
598
+                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
599
+            });
600
+
601
+            for (var i = 0; i < $(SECTION_SEL).length; i++) {
602
+                var link = '';
603
+                if (options.anchors.length) {
604
+                    link = options.anchors[i];
605
+                }
606
+
607
+                var li = '<li><a href="#' + link + '"><span></span></a>';
608
+
609
+                // Only add tooltip if needed (defined by user)
610
+                var tooltip = options.navigationTooltips[i];
611
+
612
+                if (typeof tooltip !== 'undefined' && tooltip !== '') {
613
+                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
614
+                }
615
+
616
+                li += '</li>';
617
+
618
+                nav.find('ul').append(li);
619
+            }
620
+        }
621
+
622
+        function createSlimScrollingHandler(){
623
+            $(SECTION_SEL).each(function(){
624
+                var slides = $(this).find(SLIDE_SEL);
625
+
626
+                if(slides.length){
627
+                    slides.each(function(){
628
+                        createSlimScrolling($(this));
629
+                    });
630
+                }else{
631
+                    createSlimScrolling($(this));
632
+                }
633
+
634
+            });
635
+            $.isFunction( options.afterRender ) && options.afterRender.call( this);
636
+        }
637
+
638
+        var scrollId;
639
+        var scrollId2;
640
+        var isScrolling = false;
641
+
642
+        //when scrolling...
643
+        $window.on('scroll', scrollHandler);
644
+
645
+        function scrollHandler(){
646
+            var currentSection;
647
+
648
+            if(!options.autoScrolling || options.scrollBar){
649
+                var currentScroll = $window.scrollTop();
650
+                var visibleSectionIndex = 0;
651
+                var initial = Math.abs(currentScroll - document.querySelectorAll(SECTION_SEL)[0].offsetTop);
652
+
653
+                //taking the section which is showing more content in the viewport
654
+                var sections =  document.querySelectorAll(SECTION_SEL);
655
+                for (var i = 0; i < sections.length; ++i) {
656
+                    var section = sections[i];
657
+
658
+                    var current = Math.abs(currentScroll - section.offsetTop);
659
+
660
+                    if(current < initial){
661
+                        visibleSectionIndex = i;
662
+                        initial = current;
663
+                    }
664
+                }
665
+
666
+                //geting the last one, the current one on the screen
667
+                currentSection = $(sections).eq(visibleSectionIndex);
668
+            }
669
+
670
+            if(!options.autoScrolling || options.scrollBar){
671
+                //executing only once the first time we reach the section
672
+                if(!currentSection.hasClass(ACTIVE)){
673
+                    isScrolling = true;
674
+                    var leavingSection = $(SECTION_ACTIVE_SEL);
675
+                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
676
+                    var yMovement = getYmovement(currentSection);
677
+                    var anchorLink  = currentSection.data('anchor');
678
+                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
679
+                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
680
+
681
+                    if(activeSlide.length){
682
+                        var slideAnchorLink = activeSlide.data('anchor');
683
+                        var slideIndex = activeSlide.index();
684
+                    }
685
+
686
+                    if(canScroll){
687
+                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
688
+
689
+                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
690
+
691
+                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
692
+
693
+                        activateMenuAndNav(anchorLink, sectionIndex - 1);
694
+
695
+                        if(options.anchors.length){
696
+                            //needed to enter in hashChange event when using the menu with anchor links
697
+                            lastScrolledDestiny = anchorLink;
698
+
699
+                            setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
700
+                        }
701
+                    }
702
+
703
+                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
704
+                    clearTimeout(scrollId);
705
+                    scrollId = setTimeout(function(){
706
+                        isScrolling = false;
707
+                    }, 100);
708
+                }
709
+
710
+                if(options.fitToSection){
711
+                    //for the auto adjust of the viewport to fit a whole section
712
+                    clearTimeout(scrollId2);
713
+
714
+                    scrollId2 = setTimeout(function(){
715
+                        if(canScroll){
716
+                            //allows to scroll to an active section and
717
+                            //if the section is already active, we prevent firing callbacks
718
+                            if($(SECTION_ACTIVE_SEL).is(currentSection)){
719
+                                isResizing = true;
720
+                            }
721
+                            scrollPage(currentSection);
722
+                            isResizing = false;
723
+                        }
724
+                    }, 1000);
725
+                }
726
+            }
727
+        }
728
+
729
+
730
+        /**
731
+        * Determines whether the active section or slide is scrollable through and scrolling bar
732
+        */
733
+        function isScrollable(activeSection){
734
+            //if there are landscape slides, we check if the scrolling bar is in the current one or not
735
+            if(activeSection.find(SLIDES_WRAPPER_SEL).length){
736
+                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
737
+            }
738
+
739
+            return activeSection.find(SCROLLABLE_SEL);
740
+        }
741
+
742
+        /**
743
+        * Determines the way of scrolling up or down:
744
+        * by 'automatically' scrolling a section or by using the default and normal scrolling.
745
+        */
746
+        function scrolling(type, scrollable){
747
+            if (!isScrollAllowed[type]){
748
+                return;
749
+            }
750
+            var check, scrollSection;
751
+
752
+            if(type == 'down'){
753
+                check = 'bottom';
754
+                scrollSection = FP.moveSectionDown;
755
+            }else{
756
+                check = 'top';
757
+                scrollSection = FP.moveSectionUp;
758
+            }
759
+
760
+            if(scrollable.length > 0 ){
761
+                //is the scrollbar at the start/end of the scroll?
762
+                if(isScrolled(check, scrollable)){
763
+                    scrollSection();
764
+                }else{
765
+                    return true;
766
+                }
767
+            }else{
768
+                // moved up/down
769
+                scrollSection();
770
+            }
771
+        }
772
+
773
+
774
+        var touchStartY = 0;
775
+        var touchStartX = 0;
776
+        var touchEndY = 0;
777
+        var touchEndX = 0;
778
+
779
+        /* Detecting touch events
780
+
781
+        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
782
+        * This way, the touchstart and the touch moves shows an small difference between them which is the
783
+        * used one to determine the direction.
784
+        */
785
+        function touchMoveHandler(event){
786
+            var e = event.originalEvent;
787
+
788
+            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
789
+            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
790
+
791
+                if(options.autoScrolling){
792
+                    //preventing the easing on iOS devices
793
+                    event.preventDefault();
794
+                }
795
+
796
+                var activeSection = $(SECTION_ACTIVE_SEL);
797
+                var scrollable = isScrollable(activeSection);
798
+
799
+                if (canScroll && !slideMoving) { //if theres any #
800
+                    var touchEvents = getEventsPage(e);
801
+
802
+                    touchEndY = touchEvents.y;
803
+                    touchEndX = touchEvents.x;
804
+
805
+                    //if movement in the X axys is greater than in the Y and the currect section has slides...
806
+                    if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
807
+
808
+                        //is the movement greater than the minimum resistance to scroll?
809
+                        if (Math.abs(touchStartX - touchEndX) > ($window.width() / 100 * options.touchSensitivity)) {
810
+                            if (touchStartX > touchEndX) {
811
+                                if(isScrollAllowed.right){
812
+                                    FP.moveSlideRight(); //next
813
+                                }
814
+                            } else {
815
+                                if(isScrollAllowed.left){
816
+                                    FP.moveSlideLeft(); //prev
817
+                                }
818
+                            }
819
+                        }
820
+                    }
821
+
822
+                    //vertical scrolling (only when autoScrolling is enabled)
823
+                    else if(options.autoScrolling){
824
+
825
+                        //is the movement greater than the minimum resistance to scroll?
826
+                        if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
827
+                            if (touchStartY > touchEndY) {
828
+                                scrolling('down', scrollable);
829
+                            } else if (touchEndY > touchStartY) {
830
+                                scrolling('up', scrollable);
831
+                            }
832
+                        }
833
+                    }
834
+                }
835
+            }
836
+
837
+        }
838
+
839
+        /**
840
+         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
841
+         * Currently works well for iOS - Android might need some testing
842
+         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
843
+         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
844
+         * @return {boolean} true if there is a match to options.normalScrollElements
845
+         */
846
+        function checkParentForNormalScrollElement (el, hop) {
847
+            hop = hop || 0;
848
+            var parent = $(el).parent();
849
+
850
+            if (hop < options.normalScrollElementTouchThreshold &&
851
+                parent.is(options.normalScrollElements) ) {
852
+                return true;
853
+            } else if (hop == options.normalScrollElementTouchThreshold) {
854
+                return false;
855
+            } else {
856
+                return checkParentForNormalScrollElement(parent, ++hop);
857
+            }
858
+        }
859
+
860
+        /**
861
+        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
862
+        * this way we make sure that is really a touch event what IE is detecting.
863
+        */
864
+        function isReallyTouch(e){
865
+            //if is not IE   ||  IE is detecting `touch` or `pen`
866
+            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
867
+        }
868
+
869
+        function touchStartHandler(event){
870
+            var e = event.originalEvent;
871
+
872
+            //stopping the auto scroll to adjust to a section
873
+            if(options.fitToSection){
874
+                $htmlBody.stop();
875
+            }
876
+
877
+            if(isReallyTouch(e)){
878
+                var touchEvents = getEventsPage(e);
879
+                touchStartY = touchEvents.y;
880
+                touchStartX = touchEvents.x;
881
+            }
882
+        }
883
+
884
+        function getAverage(elements, number){
885
+            var sum = 0;
886
+
887
+            //taking `number` elements from the end to make the average, if there are not enought, 1
888
+            var lastElements = elements.slice(Math.max(elements.length - number, 1));
889
+
890
+            for(var i = 0; i < lastElements.length; i++){
891
+                sum = sum + lastElements[i];
892
+            }
893
+
894
+            return Math.ceil(sum/number);
895
+        }
896
+
897
+        /**
898
+         * Detecting mousewheel scrolling
899
+         *
900
+         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
901
+         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
902
+         */
903
+        var prevTime = new Date().getTime();
904
+
905
+        function MouseWheelHandler(e) {
906
+            var curTime = new Date().getTime();
907
+
908
+            if(options.autoScrolling){
909
+                // cross-browser wheel delta
910
+                e = window.event || e;
911
+                var value = e.wheelDelta || -e.deltaY || -e.detail;
912
+                var delta = Math.max(-1, Math.min(1, value));
913
+
914
+                //Limiting the array to 150 (lets not waist memory!)
915
+                if(scrollings.length > 149){
916
+                    scrollings.shift();
917
+                }
918
+
919
+                //keeping record of the previous scrollings
920
+                scrollings.push(Math.abs(value));
921
+
922
+                //preventing to scroll the site on mouse wheel when scrollbar is present
923
+                if(options.scrollBar){
924
+                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
925
+                }
926
+
927
+                var activeSection = $(SECTION_ACTIVE_SEL);
928
+                var scrollable = isScrollable(activeSection);
929
+
930
+                //time difference between the last scroll and the current one
931
+                var timeDiff = curTime-prevTime;
932
+                prevTime = curTime;
933
+
934
+                //haven't they scrolled in a while?
935
+                //(enough to be consider a different scrolling action to scroll another section)
936
+                if(timeDiff > 200){
937
+                    //emptying the array, we dont care about old scrollings for our averages
938
+                    scrollings = [];
939
+                }
940
+
941
+                if(canScroll){
942
+                    var averageEnd = getAverage(scrollings, 10);
943
+                    var averageMiddle = getAverage(scrollings, 70);
944
+                    var isAccelerating = averageEnd >= averageMiddle;
945
+
946
+                    //to avoid double swipes...
947
+                    if(isAccelerating){
948
+                        //scrolling down?
949
+                        if (delta < 0) {
950
+                            scrolling('down', scrollable);
951
+
952
+                        //scrolling up?
953
+                        }else {
954
+                            scrolling('up', scrollable);
955
+                        }
956
+                    }
957
+                }
958
+
959
+                return false;
960
+            }
961
+
962
+            if(options.fitToSection){
963
+                //stopping the auto scroll to adjust to a section
964
+                $htmlBody.stop();
965
+            }
966
+        }
967
+
968
+        function moveSlide(direction){
969
+            var activeSection = $(SECTION_ACTIVE_SEL);
970
+            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
971
+
972
+            // more than one slide needed and nothing should be sliding
973
+            if (!slides.length || slideMoving) {
974
+                return;
975
+            }
976
+
977
+            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
978
+            var destiny = null;
979
+
980
+            if(direction === 'prev'){
981
+                destiny = currentSlide.prev(SLIDE_SEL);
982
+            }else{
983
+                destiny = currentSlide.next(SLIDE_SEL);
984
+            }
985
+
986
+            //isn't there a next slide in the secuence?
987
+            if(!destiny.length){
988
+                //respect loopHorizontal settin
989
+                if (!options.loopHorizontal) return;
990
+
991
+                if(direction === 'prev'){
992
+                    destiny = currentSlide.siblings(':last');
993
+                }else{
994
+                    destiny = currentSlide.siblings(':first');
995
+                }
996
+            }
997
+
998
+            slideMoving = true;
999
+
1000
+            landscapeScroll(slides, destiny);
1001
+        }
1002
+
1003
+        /**
1004
+        * Maintains the active slides in the viewport
1005
+        * (Because he `scroll` animation might get lost with some actions, such as when using continuousVertical)
1006
+        */
1007
+        function keepSlidesPosition(){
1008
+            $(SLIDE_ACTIVE_SEL).each(function(){
1009
+                silentLandscapeScroll($(this));
1010
+            });
1011
+        }
1012
+
1013
+        /**
1014
+        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
1015
+        */
1016
+        function scrollPage(element, callback, isMovementUp){
1017
+            var dest = element.position();
1018
+            if(typeof dest === 'undefined'){ return; } //there's no element to scroll, leaving the function
1019
+
1020
+            //local variables
1021
+            var v = {
1022
+                element: element,
1023
+                callback: callback,
1024
+                isMovementUp: isMovementUp,
1025
+                dest: dest,
1026
+                dtop: dest.top,
1027
+                yMovement: getYmovement(element),
1028
+                anchorLink: element.data('anchor'),
1029
+                sectionIndex: element.index(SECTION_SEL),
1030
+                activeSlide: element.find(SLIDE_ACTIVE_SEL),
1031
+                activeSection: $(SECTION_ACTIVE_SEL),
1032
+                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
1033
+
1034
+                //caching the value of isResizing at the momment the function is called
1035
+                //because it will be checked later inside a setTimeout and the value might change
1036
+                localIsResizing: isResizing
1037
+            };
1038
+
1039
+            //quiting when destination scroll is the same as the current one
1040
+            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop)){ return; }
1041
+
1042
+            if(v.activeSlide.length){
1043
+                var slideAnchorLink = v.activeSlide.data('anchor');
1044
+                var slideIndex = v.activeSlide.index();
1045
+            }
1046
+
1047
+            // If continuousVertical && we need to wrap around
1048
+            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
1049
+                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
1050
+                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
1051
+
1052
+                v = createInfiniteSections(v);
1053
+            }
1054
+
1055
+            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
1056
+
1057
+            //preventing from activating the MouseWheelHandler event
1058
+            //more than once if the page is scrolling
1059
+            canScroll = false;
1060
+
1061
+            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
1062
+
1063
+            //callback (onLeave) if the site is not just resizing and readjusting the slides
1064
+            $.isFunction(options.onLeave) && !v.localIsResizing && options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement);
1065
+
1066
+            performMovement(v);
1067
+
1068
+            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
1069
+            lastScrolledDestiny = v.anchorLink;
1070
+
1071
+            //avoid firing it twice (as it does also on scroll)
1072
+            activateMenuAndNav(v.anchorLink, v.sectionIndex);
1073
+        }
1074
+
1075
+        /**
1076
+        * Performs the movement (by CSS3 or by jQuery)
1077
+        */
1078
+        function performMovement(v){
1079
+            // using CSS3 translate functionality
1080
+            if (options.css3 && options.autoScrolling && !options.scrollBar) {
1081
+
1082
+                var translate3d = 'translate3d(0px, -' + v.dtop + 'px, 0px)';
1083
+                transformContainer(translate3d, true);
1084
+
1085
+                setTimeout(function () {
1086
+                    afterSectionLoads(v);
1087
+                }, options.scrollingSpeed);
1088
+            }
1089
+
1090
+            // using jQuery animate
1091
+            else{
1092
+                var scrollSettings = getScrollSettings(v);
1093
+
1094
+                $(scrollSettings.element).animate(
1095
+                    scrollSettings.options,
1096
+                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
1097
+                    afterSectionLoads(v);
1098
+                });
1099
+            }
1100
+        }
1101
+
1102
+        /**
1103
+        * Gets the scrolling settings depending on the plugin autoScrolling option
1104
+        */
1105
+        function getScrollSettings(v){
1106
+            var scroll = {};
1107
+
1108
+            if(options.autoScrolling && !options.scrollBar){
1109
+                scroll.options = { 'top': -v.dtop};
1110
+                scroll.element = WRAPPER_SEL;
1111
+            }else{
1112
+                scroll.options = { 'scrollTop': v.dtop};
1113
+                scroll.element = 'html, body';
1114
+            }
1115
+
1116
+            return scroll;
1117
+        }
1118
+
1119
+        /**
1120
+        * Adds sections before or after the current one to create the infinite effect.
1121
+        */
1122
+        function createInfiniteSections(v){
1123
+            // Scrolling down
1124
+            if (!v.isMovementUp) {
1125
+                // Move all previous sections to after the active section
1126
+                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
1127
+            }
1128
+            else { // Scrolling up
1129
+                // Move all next sections to before the active section
1130
+                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
1131
+            }
1132
+
1133
+            // Maintain the displayed position (now that we changed the element order)
1134
+            silentScroll($(SECTION_ACTIVE_SEL).position().top);
1135
+
1136
+            // Maintain the active slides visible in the viewport
1137
+            keepSlidesPosition();
1138
+
1139
+            // save for later the elements that still need to be reordered
1140
+            v.wrapAroundElements = v.activeSection;
1141
+
1142
+            // Recalculate animation variables
1143
+            v.dest = v.element.position();
1144
+            v.dtop = v.dest.top;
1145
+            v.yMovement = getYmovement(v.element);
1146
+
1147
+            return v;
1148
+        }
1149
+
1150
+        /**
1151
+        * Fix section order after continuousVertical changes have been animated
1152
+        */
1153
+        function continuousVerticalFixSectionOrder (v) {
1154
+            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
1155
+            // finish moving the elements around so the direct navigation will function more simply
1156
+            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
1157
+                return;
1158
+            }
1159
+
1160
+            if (v.isMovementUp) {
1161
+                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
1162
+            }
1163
+            else {
1164
+                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
1165
+            }
1166
+
1167
+            silentScroll($(SECTION_ACTIVE_SEL).position().top);
1168
+
1169
+            // Maintain the active slides visible in the viewport
1170
+            keepSlidesPosition();
1171
+        }
1172
+
1173
+
1174
+        /**
1175
+        * Actions to do once the section is loaded
1176
+        */
1177
+        function afterSectionLoads (v){
1178
+            continuousVerticalFixSectionOrder(v);
1179
+            //callback (afterLoad) if the site is not just resizing and readjusting the slides
1180
+            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
1181
+            canScroll = true;
1182
+
1183
+            setTimeout(function () {
1184
+                $.isFunction(v.callback) && v.callback.call(this);
1185
+            }, 600);
1186
+        }
1187
+
1188
+        /**
1189
+        * Scrolls to the anchor in the URL when loading the site
1190
+        */
1191
+        function scrollToAnchor(){
1192
+            //getting the anchor link in the URL and deleting the `#`
1193
+            var value =  window.location.hash.replace('#', '').split('/');
1194
+            var section = value[0];
1195
+            var slide = value[1];
1196
+
1197
+            if(section){  //if theres any #
1198
+                scrollPageAndSlide(section, slide);
1199
+            }
1200
+        }
1201
+
1202
+        //detecting any change on the URL to scroll to the given anchor link
1203
+        //(a way to detect back history button as we play with the hashes on the URL)
1204
+        $window.on('hashchange', hashChangeHandler);
1205
+
1206
+        function hashChangeHandler(){
1207
+            if(!isScrolling){
1208
+                var value =  window.location.hash.replace('#', '').split('/');
1209
+                var section = value[0];
1210
+                var slide = value[1];
1211
+
1212
+                if(section.length){
1213
+                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
1214
+                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
1215
+                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slide === 'undefined' && !slideMoving);
1216
+
1217
+                    /*in order to call scrollpage() only once for each destination at a time
1218
+                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
1219
+                    event is fired on every scroll too.*/
1220
+                    if ((section && section !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slide ))  {
1221
+                        scrollPageAndSlide(section, slide);
1222
+                    }
1223
+                }
1224
+            }
1225
+        }
1226
+
1227
+        /**
1228
+         * Sliding with arrow keys, both, vertical and horizontal
1229
+         */
1230
+        $document.keydown(keydownHandler);
1231
+
1232
+        var keydownId;
1233
+        function keydownHandler(e) {
1234
+            clearTimeout(keydownId);
1235
+
1236
+            var activeElement = $(document.activeElement);
1237
+
1238
+            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
1239
+                options.keyboardScrolling && options.autoScrolling){
1240
+                var keyCode = e.which;
1241
+
1242
+                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
1243
+                var keyControls = [40, 38, 32, 33, 34];
1244
+                if($.inArray(keyCode, keyControls) > -1){
1245
+                    e.preventDefault();
1246
+                }
1247
+
1248
+                keydownId = setTimeout(function(){
1249
+                    onkeydown(e);
1250
+                },150);
1251
+            }
1252
+        }
1253
+
1254
+        function onkeydown(e){
1255
+            var shiftPressed = e.shiftKey;
1256
+
1257
+            switch (e.which) {
1258
+                //up
1259
+                case 38:
1260
+                case 33:
1261
+                    FP.moveSectionUp();
1262
+                    break;
1263
+
1264
+                //down
1265
+                case 32: //spacebar
1266
+                    if(shiftPressed){
1267
+                        FP.moveSectionUp();
1268
+                        break;
1269
+                    }
1270
+                case 40:
1271
+                case 34:
1272
+                    FP.moveSectionDown();
1273
+                    break;
1274
+
1275
+                //Home
1276
+                case 36:
1277
+                    FP.moveTo(1);
1278
+                    break;
1279
+
1280
+                //End
1281
+                case 35:
1282
+                    FP.moveTo( $(SECTION_SEL).length );
1283
+                    break;
1284
+
1285
+                //left
1286
+                case 37:
1287
+                    FP.moveSlideLeft();
1288
+                    break;
1289
+
1290
+                //right
1291
+                case 39:
1292
+                    FP.moveSlideRight();
1293
+                    break;
1294
+
1295
+                default:
1296
+                    return; // exit this handler for other keys
1297
+            }
1298
+        }
1299
+
1300
+        //binding the mousemove when the mouse's middle button is released
1301
+        container.mousedown(function(e){
1302
+            //middle button
1303
+            if (e.which == 2){
1304
+                oldPageY = e.pageY;
1305
+                container.on('mousemove', mouseMoveHandler);
1306
+            }
1307
+        });
1308
+
1309
+        //unbinding the mousemove when the mouse's middle button is released
1310
+        container.mouseup(function(e){
1311
+            //middle button
1312
+            if (e.which == 2){
1313
+                container.off('mousemove');
1314
+            }
1315
+        });
1316
+
1317
+        /**
1318
+        * Detecting the direction of the mouse movement.
1319
+        * Used only for the middle button of the mouse.
1320
+        */
1321
+        var oldPageY = 0;
1322
+        function mouseMoveHandler(e){
1323
+            // moving up
1324
+            if(canScroll){
1325
+                if (e.pageY < oldPageY){
1326
+                    FP.moveSectionUp();
1327
+
1328
+                // moving downw
1329
+                }else if(e.pageY > oldPageY){
1330
+                    FP.moveSectionDown();
1331
+                }
1332
+            }
1333
+            oldPageY = e.pageY;
1334
+        }
1335
+
1336
+        /**
1337
+        * Scrolls to the section when clicking the navigation bullet
1338
+        */
1339
+        $document.on('click touchstart', SECTION_NAV_SEL + ' a', function(e){
1340
+            e.preventDefault();
1341
+            var index = $(this).parent().index();
1342
+            scrollPage($(SECTION_SEL).eq(index));
1343
+        });
1344
+
1345
+        /**
1346
+        * Scrolls the slider to the given slide destination for the given section
1347
+        */
1348
+        $document.on('click touchstart', SLIDES_NAV_LINK_SEL, function(e){
1349
+            e.preventDefault();
1350
+            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
1351
+            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
1352
+
1353
+            landscapeScroll(slides, destiny);
1354
+        });
1355
+
1356
+        if(options.normalScrollElements){
1357
+            $document.on('mouseenter', options.normalScrollElements, function () {
1358
+                FP.setMouseWheelScrolling(false);
1359
+            });
1360
+
1361
+            $document.on('mouseleave', options.normalScrollElements, function(){
1362
+                FP.setMouseWheelScrolling(true);
1363
+            });
1364
+        }
1365
+
1366
+        /**
1367
+         * Scrolling horizontally when clicking on the slider controls.
1368
+         */
1369
+        $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, function() {
1370
+            if ($(this).hasClass(SLIDES_PREV)) {
1371
+                FP.moveSlideLeft();
1372
+            } else {
1373
+                FP.moveSlideRight();
1374
+            }
1375
+        });
1376
+
1377
+        /**
1378
+        * Scrolls horizontal sliders.
1379
+        */
1380
+        function landscapeScroll(slides, destiny){
1381
+            var destinyPos = destiny.position();
1382
+            var slideIndex = destiny.index();
1383
+            var section = slides.closest(SECTION_SEL);
1384
+            var sectionIndex = section.index(SECTION_SEL);
1385
+            var anchorLink = section.data('anchor');
1386
+            var slidesNav = section.find(SLIDES_NAV_SEL);
1387
+            var slideAnchor = getSlideAnchor(destiny);
1388
+
1389
+            //caching the value of isResizing at the momment the function is called
1390
+            //because it will be checked later inside a setTimeout and the value might change
1391
+            var localIsResizing = isResizing;
1392
+
1393
+            if(options.onSlideLeave){
1394
+                var prevSlide = section.find(SLIDE_ACTIVE_SEL);
1395
+                var prevSlideIndex = prevSlide.index();
1396
+                var xMovement = getXmovement(prevSlideIndex, slideIndex);
1397
+
1398
+                //if the site is not just resizing and readjusting the slides
1399
+                if(!localIsResizing && xMovement!=='none'){
1400
+                    $.isFunction( options.onSlideLeave ) && options.onSlideLeave.call( prevSlide, anchorLink, (sectionIndex + 1), prevSlideIndex, xMovement);
1401
+                }
1402
+            }
1403
+
1404
+            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
1405
+
1406
+            if(!options.loopHorizontal && options.controlArrows){
1407
+                //hidding it for the fist slide, showing for the rest
1408
+                section.find(SLIDES_ARROW_PREV_SEL).toggle(slideIndex!==0);
1409
+
1410
+                //hidding it for the last slide, showing for the rest
1411
+                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
1412
+            }
1413
+
1414
+            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
1415
+            if(section.hasClass(ACTIVE)){
1416
+                setState(slideIndex, slideAnchor, anchorLink, sectionIndex);
1417
+            }
1418
+
1419
+            var afterSlideLoads = function(){
1420
+                //if the site is not just resizing and readjusting the slides
1421
+                if(!localIsResizing){
1422
+                    $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( destiny, anchorLink, (sectionIndex + 1), slideAnchor, slideIndex);
1423
+                }
1424
+                //letting them slide again
1425
+                slideMoving = false;
1426
+            };
1427
+
1428
+            if(options.css3){
1429
+                var translate3d = 'translate3d(-' + destinyPos.left + 'px, 0px, 0px)';
1430
+
1431
+                addAnimation(slides.find(SLIDES_CONTAINER_SEL), options.scrollingSpeed>0).css(getTransforms(translate3d));
1432
+
1433
+                setTimeout(function(){
1434
+                    afterSlideLoads();
1435
+                }, options.scrollingSpeed, options.easing);
1436
+            }else{
1437
+                slides.animate({
1438
+                    scrollLeft : destinyPos.left
1439
+                }, options.scrollingSpeed, options.easing, function() {
1440
+
1441
+                    afterSlideLoads();
1442
+                });
1443
+            }
1444
+
1445
+            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
1446
+            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
1447
+        }
1448
+
1449
+        //when resizing the site, we adjust the heights of the sections, slimScroll...
1450
+        $window.resize(resizeHandler);
1451
+
1452
+        var previousHeight = windowsHeight;
1453
+        var resizeId;
1454
+        function resizeHandler(){
1455
+            //checking if it needs to get responsive
1456
+            responsive();
1457
+
1458
+            // rebuild immediately on touch devices
1459
+            if (isTouchDevice) {
1460
+                var activeElement = $(document.activeElement);
1461
+
1462
+                //if the keyboard is NOT visible
1463
+                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
1464
+                    var currentHeight = $window.height();
1465
+
1466
+                    //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)
1467
+                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
1468
+                        FP.reBuild(true);
1469
+                        previousHeight = currentHeight;
1470
+                    }
1471
+                }
1472
+            }else{
1473
+                //in order to call the functions only when the resize is finished
1474
+                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
1475
+                clearTimeout(resizeId);
1476
+
1477
+                resizeId = setTimeout(function(){
1478
+                    FP.reBuild(true);
1479
+                }, 500);
1480
+            }
1481
+        }
1482
+
1483
+        /**
1484
+        * Checks if the site needs to get responsive and disables autoScrolling if so.
1485
+        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
1486
+        */
1487
+        function responsive(){
1488
+            if(options.responsive){
1489
+                var isResponsive = container.hasClass(RESPONSIVE);
1490
+                if ($window.width() < options.responsive ){
1491
+                    if(!isResponsive){
1492
+                        FP.setAutoScrolling(false, 'internal');
1493
+                        FP.setFitToSection(false, 'internal');
1494
+                        $(SECTION_NAV_SEL).hide();
1495
+                        container.addClass(RESPONSIVE);
1496
+                    }
1497
+                }else if(isResponsive){
1498
+                    FP.setAutoScrolling(originals.autoScrolling, 'internal');
1499
+                    FP.setFitToSection(originals.autoScrolling, 'internal');
1500
+                    $(SECTION_NAV_SEL).show();
1501
+                    container.removeClass(RESPONSIVE);
1502
+                }
1503
+            }
1504
+        }
1505
+
1506
+        /**
1507
+        * Adds transition animations for the given element
1508
+        */
1509
+        function addAnimation(element){
1510
+            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
1511
+
1512
+            element.removeClass(NO_TRANSITION);
1513
+            return element.css({
1514
+                '-webkit-transition': transition,
1515
+                'transition': transition
1516
+            });
1517
+        }
1518
+
1519
+        /**
1520
+        * Remove transition animations for the given element
1521
+        */
1522
+        function removeAnimation(element){
1523
+            return element.addClass(NO_TRANSITION);
1524
+        }
1525
+
1526
+        /**
1527
+         * Resizing of the font size depending on the window size as well as some of the images on the site.
1528
+         */
1529
+        function resizeMe(displayHeight, displayWidth) {
1530
+            //Standard dimensions, for which the body font size is correct
1531
+            var preferredHeight = 825;
1532
+            var preferredWidth = 900;
1533
+
1534
+            if (displayHeight < preferredHeight || displayWidth < preferredWidth) {
1535
+                var heightPercentage = (displayHeight * 100) / preferredHeight;
1536
+                var widthPercentage = (displayWidth * 100) / preferredWidth;
1537
+                var percentage = Math.min(heightPercentage, widthPercentage);
1538
+                var newFontSize = percentage.toFixed(2);
1539
+
1540
+                $body.css('font-size', newFontSize + '%');
1541
+            } else {
1542
+                $body.css('font-size', '100%');
1543
+            }
1544
+        }
1545
+
1546
+        /**
1547
+         * Activating the website navigation dots according to the given slide name.
1548
+         */
1549
+        function activateNavDots(name, sectionIndex){
1550
+            if(options.navigation){
1551
+                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
1552
+                if(name){
1553
+                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
1554
+                }else{
1555
+                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
1556
+                }
1557
+            }
1558
+        }
1559
+
1560
+        /**
1561
+         * Activating the website main menu elements according to the given slide name.
1562
+         */
1563
+        function activateMenuElement(name){
1564
+            if(options.menu){
1565
+                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
1566
+                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
1567
+            }
1568
+        }
1569
+
1570
+        function activateMenuAndNav(anchor, index){
1571
+            activateMenuElement(anchor);
1572
+            activateNavDots(anchor, index);
1573
+        }
1574
+
1575
+        /**
1576
+        * Return a boolean depending on whether the scrollable element is at the end or at the start of the scrolling
1577
+        * depending on the given type.
1578
+        */
1579
+        function isScrolled(type, scrollable){
1580
+            if(type === 'top'){
1581
+                return !scrollable.scrollTop();
1582
+            }else if(type === 'bottom'){
1583
+                return scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
1584
+            }
1585
+        }
1586
+
1587
+        /**
1588
+        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
1589
+        * from the current section.
1590
+        */
1591
+        function getYmovement(destiny){
1592
+            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
1593
+            var toIndex = destiny.index(SECTION_SEL);
1594
+            if( fromIndex == toIndex){
1595
+                return 'none';
1596
+            }
1597
+            if(fromIndex > toIndex){
1598
+                return 'up';
1599
+            }
1600
+            return 'down';
1601
+        }
1602
+
1603
+        /**
1604
+        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
1605
+        * from the current slide.
1606
+        */
1607
+        function getXmovement(fromIndex, toIndex){
1608
+            if( fromIndex == toIndex){
1609
+                return 'none';
1610
+            }
1611
+            if(fromIndex > toIndex){
1612
+                return 'left';
1613
+            }
1614
+            return 'right';
1615
+        }
1616
+
1617
+
1618
+        function createSlimScrolling(element){
1619
+            //needed to make `scrollHeight` work under Opera 12
1620
+            element.css('overflow', 'hidden');
1621
+
1622
+            //in case element is a slide
1623
+            var section = element.closest(SECTION_SEL);
1624
+            var scrollable = element.find(SCROLLABLE_SEL);
1625
+            var contentHeight;
1626
+
1627
+            //if there was scroll, the contentHeight will be the one in the scrollable section
1628
+            if(scrollable.length){
1629
+                contentHeight = scrollable.get(0).scrollHeight;
1630
+            }else{
1631
+                contentHeight = element.get(0).scrollHeight;
1632
+                if(options.verticalCentered){
1633
+                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
1634
+                }
1635
+            }
1636
+
1637
+            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
1638
+
1639
+            //needs scroll?
1640
+            if ( contentHeight > scrollHeight) {
1641
+                //was there already an scroll ? Updating it
1642
+                if(scrollable.length){
1643
+                    scrollable.css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
1644
+                }
1645
+                //creating the scrolling
1646
+                else{
1647
+                    if(options.verticalCentered){
1648
+                        element.find(TABLE_CELL_SEL).wrapInner('<div class="' + SCROLLABLE + '" />');
1649
+                    }else{
1650
+                        element.wrapInner('<div class="' + SCROLLABLE + '" />');
1651
+                    }
1652
+
1653
+                    element.find(SCROLLABLE_SEL).slimScroll({
1654
+                        allowPageScroll: true,
1655
+                        height: scrollHeight + 'px',
1656
+                        size: '10px',
1657
+                        alwaysVisible: true
1658
+                    });
1659
+                }
1660
+            }
1661
+
1662
+            //removing the scrolling when it is not necessary anymore
1663
+            else{
1664
+                removeSlimScroll(element);
1665
+            }
1666
+
1667
+            //undo
1668
+            element.css('overflow', '');
1669
+        }
1670
+
1671
+        function removeSlimScroll(element){
1672
+            element.find(SCROLLABLE_SEL).children().first().unwrap().unwrap();
1673
+            element.find(SLIMSCROLL_BAR_SEL).remove();
1674
+            element.find(SLIMSCROLL_RAIL_SEL).remove();
1675
+        }
1676
+
1677
+        function addTableClass(element){
1678
+            element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
1679
+        }
1680
+
1681
+        function getTableHeight(element){
1682
+            var sectionHeight = windowsHeight;
1683
+
1684
+            if(options.paddingTop || options.paddingBottom){
1685
+                var section = element;
1686
+                if(!section.hasClass(SECTION)){
1687
+                    section = element.closest(SECTION_SEL);
1688
+                }
1689
+
1690
+                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
1691
+                sectionHeight = (windowsHeight - paddings);
1692
+            }
1693
+
1694
+            return sectionHeight;
1695
+        }
1696
+
1697
+        /**
1698
+        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
1699
+        */
1700
+        function transformContainer(translate3d, animated){
1701
+            if(animated){
1702
+                addAnimation(container);
1703
+            }else{
1704
+                removeAnimation(container);
1705
+            }
1706
+
1707
+            container.css(getTransforms(translate3d));
1708
+
1709
+            //syncronously removing the class after the animation has been applied.
1710
+            setTimeout(function(){
1711
+                container.removeClass(NO_TRANSITION);
1712
+            },10);
1713
+        }
1714
+
1715
+
1716
+        /**
1717
+        * Scrolls to the given section and slide
1718
+        */
1719
+        function scrollPageAndSlide(destiny, slide){
1720
+            var section;
1721
+
1722
+            if (typeof slide === 'undefined') {
1723
+                slide = 0;
1724
+            }
1725
+
1726
+            if(isNaN(destiny)){
1727
+                section = $('[data-anchor="'+destiny+'"]');
1728
+            }else{
1729
+                section = $(SECTION_SEL).eq( (destiny -1) );
1730
+            }
1731
+
1732
+
1733
+            //we need to scroll to the section and then to the slide
1734
+            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
1735
+                scrollPage(section, function(){
1736
+                    scrollSlider(section, slide);
1737
+                });
1738
+            }
1739
+            //if we were already in the section
1740
+            else{
1741
+                scrollSlider(section, slide);
1742
+            }
1743
+        }
1744
+
1745
+        /**
1746
+        * Scrolls the slider to the given slide destination for the given section
1747
+        */
1748
+        function scrollSlider(section, slide){
1749
+            if(typeof slide != 'undefined'){
1750
+                var slides = section.find(SLIDES_WRAPPER_SEL);
1751
+                var destiny =  slides.find('[data-anchor="'+slide+'"]');
1752
+
1753
+                if(!destiny.length){
1754
+                    destiny = slides.find(SLIDE_SEL).eq(slide);
1755
+                }
1756
+
1757
+                if(destiny.length){
1758
+                    landscapeScroll(slides, destiny);
1759
+                }
1760
+            }
1761
+        }
1762
+
1763
+        /**
1764
+        * Creates a landscape navigation bar with dots for horizontal sliders.
1765
+        */
1766
+        function addSlidesNavigation(section, numSlides){
1767
+            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
1768
+            var nav = section.find(SLIDES_NAV_SEL);
1769
+
1770
+            //top or bottom
1771
+            nav.addClass(options.slidesNavPosition);
1772
+
1773
+            for(var i=0; i< numSlides; i++){
1774
+                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
1775
+            }
1776
+
1777
+            //centering it
1778
+            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
1779
+
1780
+            nav.find('li').first().find('a').addClass(ACTIVE);
1781
+        }
1782
+
1783
+
1784
+        /**
1785
+        * Sets the state of the website depending on the active section/slide.
1786
+        * It changes the URL hash when needed and updates the body class.
1787
+        */
1788
+        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
1789
+            var sectionHash = '';
1790
+
1791
+            if(options.anchors.length){
1792
+
1793
+                //isn't it the first slide?
1794
+                if(slideIndex){
1795
+                    if(typeof anchorLink !== 'undefined'){
1796
+                        sectionHash = anchorLink;
1797
+                    }
1798
+
1799
+                    //slide without anchor link? We take the index instead.
1800
+                    if(typeof slideAnchor === 'undefined'){
1801
+                        slideAnchor = slideIndex;
1802
+                    }
1803
+
1804
+                    lastScrolledSlide = slideAnchor;
1805
+                    setUrlHash(sectionHash + '/' + slideAnchor);
1806
+
1807
+                //first slide won't have slide anchor, just the section one
1808
+                }else if(typeof slideIndex !== 'undefined'){
1809
+                    lastScrolledSlide = slideAnchor;
1810
+                    setUrlHash(anchorLink);
1811
+                }
1812
+
1813
+                //section without slides
1814
+                else{
1815
+                    setUrlHash(anchorLink);
1816
+                }
1817
+            }
1818
+
1819
+            setBodyClass();
1820
+        }
1821
+
1822
+        /**
1823
+        * Sets the URL hash.
1824
+        */
1825
+        function setUrlHash(url){
1826
+            if(options.recordHistory){
1827
+                location.hash = url;
1828
+            }else{
1829
+                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
1830
+                if(isTouchDevice || isTouch){
1831
+                    history.replaceState(undefined, undefined, '#' + url);
1832
+                }else{
1833
+                    var baseUrl = window.location.href.split('#')[0];
1834
+                    window.location.replace( baseUrl + '#' + url );
1835
+                }
1836
+            }
1837
+        }
1838
+
1839
+        /**
1840
+        * Gets the anchor for the given slide. Its index will be used if there's none.
1841
+        */
1842
+        function getSlideAnchor(slide){
1843
+            var slideAnchor = slide.data('anchor');
1844
+            var slideIndex = slide.index(SLIDE_SEL);
1845
+
1846
+            //Slide without anchor link? We take the index instead.
1847
+            if(typeof slideAnchor === 'undefined'){
1848
+                slideAnchor = slideIndex;
1849
+            }
1850
+
1851
+            return slideAnchor;
1852
+        }
1853
+
1854
+        /**
1855
+        * Sets a class for the body of the page depending on the active section / slide
1856
+        */
1857
+        function setBodyClass(){
1858
+            var section = $(SECTION_ACTIVE_SEL);
1859
+            var slide = section.find(SLIDE_ACTIVE_SEL);
1860
+
1861
+            var sectionAnchor = section.data('anchor');
1862
+            var slideAnchor = getSlideAnchor(slide);
1863
+
1864
+            var sectionIndex = section.index(SECTION_SEL);
1865
+
1866
+            var text = String(sectionIndex);
1867
+
1868
+            if(options.anchors.length){
1869
+                text = sectionAnchor;
1870
+            }
1871
+
1872
+            if(slide.length){
1873
+                text = text + '-' + slideAnchor;
1874
+            }
1875
+
1876
+            //changing slash for dash to make it a valid CSS style
1877
+            text = text.replace('/', '-').replace('#','');
1878
+
1879
+            //removing previous anchor classes
1880
+            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
1881
+            $body[0].className = $body[0].className.replace(classRe, '');
1882
+
1883
+            //adding the current anchor
1884
+            $body.addClass(VIEWING_PREFIX + '-' + text);
1885
+        }
1886
+
1887
+        /**
1888
+        * Checks for translate3d support
1889
+        * @return boolean
1890
+        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
1891
+        */
1892
+        function support3d() {
1893
+            var el = document.createElement('p'),
1894
+                has3d,
1895
+                transforms = {
1896
+                    'webkitTransform':'-webkit-transform',
1897
+                    'OTransform':'-o-transform',
1898
+                    'msTransform':'-ms-transform',
1899
+                    'MozTransform':'-moz-transform',
1900
+                    'transform':'transform'
1901
+                };
1902
+
1903
+            // Add it to the body to get the computed style.
1904
+            document.body.insertBefore(el, null);
1905
+
1906
+            for (var t in transforms) {
1907
+                if (el.style[t] !== undefined) {
1908
+                    el.style[t] = 'translate3d(1px,1px,1px)';
1909
+                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
1910
+                }
1911
+            }
1912
+
1913
+            document.body.removeChild(el);
1914
+
1915
+            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
1916
+        }
1917
+
1918
+
1919
+
1920
+        /**
1921
+        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
1922
+        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
1923
+        */
1924
+        function removeMouseWheelHandler(){
1925
+            if (document.addEventListener) {
1926
+                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
1927
+                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
1928
+            } else {
1929
+                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
1930
+            }
1931
+        }
1932
+
1933
+
1934
+        /**
1935
+        * Adds the auto scrolling action for the mouse wheel and trackpad.
1936
+        * After this function is called, the mousewheel and trackpad movements will scroll through sections
1937
+        */
1938
+        function addMouseWheelHandler(){
1939
+            if (document.addEventListener) {
1940
+                document.addEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
1941
+                document.addEventListener('wheel', MouseWheelHandler, false); //Firefox
1942
+            } else {
1943
+                document.attachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
1944
+            }
1945
+        }
1946
+
1947
+
1948
+        /**
1949
+        * Adds the possibility to auto scroll through sections on touch devices.
1950
+        */
1951
+        function addTouchHandler(){
1952
+            if(isTouchDevice || isTouch){
1953
+                //Microsoft pointers
1954
+                var MSPointer = getMSPointer();
1955
+
1956
+                $document.off('touchstart ' +  MSPointer.down).on('touchstart ' + MSPointer.down, touchStartHandler);
1957
+                $document.off('touchmove ' + MSPointer.move).on('touchmove ' + MSPointer.move, touchMoveHandler);
1958
+            }
1959
+        }
1960
+
1961
+        /**
1962
+        * Removes the auto scrolling for touch devices.
1963
+        */
1964
+        function removeTouchHandler(){
1965
+            if(isTouchDevice || isTouch){
1966
+                //Microsoft pointers
1967
+                var MSPointer = getMSPointer();
1968
+
1969
+                $document.off('touchstart ' + MSPointer.down);
1970
+                $document.off('touchmove ' + MSPointer.move);
1971
+            }
1972
+        }
1973
+
1974
+
1975
+        /*
1976
+        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
1977
+        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
1978
+        */
1979
+        function getMSPointer(){
1980
+            var pointer;
1981
+
1982
+            //IE >= 11 & rest of browsers
1983
+            if(window.PointerEvent){
1984
+                pointer = { down: 'pointerdown', move: 'pointermove'};
1985
+            }
1986
+
1987
+            //IE < 11
1988
+            else{
1989
+                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
1990
+            }
1991
+
1992
+            return pointer;
1993
+        }
1994
+        /**
1995
+        * Gets the pageX and pageY properties depending on the browser.
1996
+        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
1997
+        */
1998
+        function getEventsPage(e){
1999
+            var events = [];
2000
+
2001
+            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
2002
+            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
2003
+
2004
+            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
2005
+            if(isTouch && isReallyTouch(e)){
2006
+                events.y = e.touches[0].pageY;
2007
+                events.x = e.touches[0].pageX;
2008
+            }
2009
+
2010
+            return events;
2011
+        }
2012
+
2013
+        function silentLandscapeScroll(activeSlide){
2014
+            FP.setScrollingSpeed (0, 'internal');
2015
+            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
2016
+            FP.setScrollingSpeed(originals.scrollingSpeed, 'internal');
2017
+        }
2018
+
2019
+        function silentScroll(top){
2020
+            if(options.scrollBar){
2021
+                container.scrollTop(top);
2022
+            }
2023
+            else if (options.css3) {
2024
+                var translate3d = 'translate3d(0px, -' + top + 'px, 0px)';
2025
+                transformContainer(translate3d, false);
2026
+            }
2027
+            else {
2028
+                container.css('top', -top);
2029
+            }
2030
+        }
2031
+
2032
+        function getTransforms(translate3d){
2033
+            return {
2034
+                '-webkit-transform': translate3d,
2035
+                '-moz-transform': translate3d,
2036
+                '-ms-transform':translate3d,
2037
+                'transform': translate3d
2038
+            };
2039
+        }
2040
+
2041
+        function setIsScrollable(value, direction){
2042
+            switch (direction){
2043
+                case 'up': isScrollAllowed.up = value; break;
2044
+                case 'down': isScrollAllowed.down = value; break;
2045
+                case 'left': isScrollAllowed.left = value; break;
2046
+                case 'right': isScrollAllowed.right = value; break;
2047
+                case 'all': FP.setAllowScrolling(value);
2048
+            }
2049
+        }
2050
+
2051
+
2052
+        /*
2053
+        * Destroys fullpage.js plugin events and optinally its html markup and styles
2054
+        */
2055
+        FP.destroy = function(all){
2056
+            FP.setAutoScrolling(false, 'internal');
2057
+            FP.setAllowScrolling(false);
2058
+            FP.setKeyboardScrolling(false);
2059
+            container.addClass(DESTROYED);
2060
+
2061
+            $window
2062
+                .off('scroll', scrollHandler)
2063
+                .off('hashchange', hashChangeHandler)
2064
+                .off('resize', resizeHandler);
2065
+
2066
+            $document
2067
+                .off('click', SECTION_NAV_SEL + ' a')
2068
+                .off('mouseenter', SECTION_NAV_SEL + ' li')
2069
+                .off('mouseleave', SECTION_NAV_SEL + ' li')
2070
+                .off('click', SLIDES_NAV_LINK_SEL)
2071
+                .off('mouseover', options.normalScrollElements)
2072
+                .off('mouseout', options.normalScrollElements);
2073
+
2074
+            $(SECTION_SEL)
2075
+                .off('click', SLIDES_ARROW_SEL);
2076
+
2077
+            //lets make a mess!
2078
+            if(all){
2079
+                destroyStructure();
2080
+            }
2081
+        };
2082
+
2083
+        /*
2084
+        * Removes inline styles added by fullpage.js
2085
+        */
2086
+        function destroyStructure(){
2087
+            //reseting the `top` or `translate` properties to 0
2088
+            silentScroll(0);
2089
+
2090
+            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
2091
+
2092
+            //removing inline styles
2093
+            $(SECTION_SEL).css( {
2094
+                'height': '',
2095
+                'background-color' : '',
2096
+                'padding': ''
2097
+            });
2098
+
2099
+            $(SLIDE_SEL).css( {
2100
+                'width': ''
2101
+            });
2102
+
2103
+            container.css({
2104
+                'height': '',
2105
+                'position': '',
2106
+                '-ms-touch-action': '',
2107
+                'touch-action': ''
2108
+            });
2109
+
2110
+            //removing added classes
2111
+            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
2112
+                removeSlimScroll($(this));
2113
+                $(this).removeClass(TABLE + ' ' + ACTIVE);
2114
+            });
2115
+
2116
+            removeAnimation(container);
2117
+
2118
+            //Unwrapping content
2119
+            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
2120
+                //unwrap not being use in case there's no child element inside and its just text
2121
+                $(this).replaceWith(this.childNodes);
2122
+            });
2123
+
2124
+            //scrolling the page to the top with no animation
2125
+            $htmlBody.scrollTop(0);
2126
+        }
2127
+
2128
+        /*
2129
+        * Sets the state for a variable with multiple states (original, and temporal)
2130
+        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
2131
+        * This function is used to keep track of both states, the original and the temporal one.
2132
+        * If type is not 'internal', then we assume the user is globally changing the variable.
2133
+        */
2134
+        function setVariableState(variable, value, type){
2135
+            options[variable] = value;
2136
+            if(type !== 'internal'){
2137
+                originals[variable] = value;
2138
+            }
2139
+        }
2140
+
2141
+        /**
2142
+        * Displays warnings
2143
+        */
2144
+        function displayWarnings(){
2145
+            // Disable mutually exclusive settings
2146
+            if (options.continuousVertical &&
2147
+                (options.loopTop || options.loopBottom)) {
2148
+                options.continuousVertical = false;
2149
+                showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
2150
+            }
2151
+            if(options.continuousVertical && options.scrollBar){
2152
+                options.continuousVertical = false;
2153
+                showError('warn', 'Option `scrollBar` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
2154
+            }
2155
+
2156
+            //anchors can not have the same value as any element ID or NAME
2157
+            $.each(options.anchors, function(index, name){
2158
+                if($('#' + name).length || $('[name="'+name+'"]').length ){
2159
+                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
2160
+                }
2161
+            });
2162
+        }
2163
+
2164
+        function showError(type, text){
2165
+            console && console[type] && console[type]('fullPage: ' + text);
2166
+        }
2167
+    };
2168
+})(jQuery, window, document, Math);