jquery.fullPage.js 106 KB

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