jquery.fullPage.js 78 KB

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