fullpagejs-rails 2.7.5.1

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