fullpage.js 156 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296
  1. /*!
  2. * fullPage 3.1.0
  3. * https://github.com/alvarotrigo/fullPage.js
  4. *
  5. * @license GPLv3 for open source use only
  6. * or Fullpage Commercial License for commercial use
  7. * http://alvarotrigo.com/fullPage/pricing/
  8. *
  9. * Copyright (C) 2018 http://alvarotrigo.com/fullPage - A project by Alvaro Trigo
  10. */
  11. (function (root, window, document, factory, undefined) {
  12. if (typeof define === 'function' && define.amd) {
  13. // AMD. Register as an anonymous module.
  14. define(function () {
  15. root.fullpage = factory(window, document);
  16. return root.fullpage;
  17. });
  18. } else if (typeof exports === 'object') {
  19. // Node. Does not work with strict CommonJS.
  20. module.exports = factory(window, document);
  21. } else {
  22. // Browser globals.
  23. window.fullpage = factory(window, document);
  24. }
  25. }(this, window, document, function (window, document) {
  26. 'use strict';
  27. // keeping central set of classnames and selectors
  28. var WRAPPER = 'fullpage-wrapper';
  29. var WRAPPER_SEL = '.' + WRAPPER;
  30. // slimscroll
  31. var SCROLLABLE = 'fp-scrollable';
  32. var SCROLLABLE_SEL = '.' + SCROLLABLE;
  33. // util
  34. var RESPONSIVE = 'fp-responsive';
  35. var NO_TRANSITION = 'fp-notransition';
  36. var DESTROYED = 'fp-destroyed';
  37. var ENABLED = 'fp-enabled';
  38. var VIEWING_PREFIX = 'fp-viewing';
  39. var ACTIVE = 'active';
  40. var ACTIVE_SEL = '.' + ACTIVE;
  41. var COMPLETELY = 'fp-completely';
  42. var COMPLETELY_SEL = '.' + COMPLETELY;
  43. // section
  44. var SECTION_DEFAULT_SEL = '.section';
  45. var SECTION = 'fp-section';
  46. var SECTION_SEL = '.' + SECTION;
  47. var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL;
  48. var TABLE_CELL = 'fp-tableCell';
  49. var TABLE_CELL_SEL = '.' + TABLE_CELL;
  50. var AUTO_HEIGHT = 'fp-auto-height';
  51. var AUTO_HEIGHT_SEL = '.' + AUTO_HEIGHT;
  52. var AUTO_HEIGHT_RESPONSIVE = 'fp-auto-height-responsive';
  53. var AUTO_HEIGHT_RESPONSIVE_SEL = '.' + AUTO_HEIGHT_RESPONSIVE;
  54. var NORMAL_SCROLL = 'fp-normal-scroll';
  55. var NORMAL_SCROLL_SEL = '.' + NORMAL_SCROLL;
  56. // section nav
  57. var SECTION_NAV = 'fp-nav';
  58. var SECTION_NAV_SEL = '#' + SECTION_NAV;
  59. var SECTION_NAV_TOOLTIP = 'fp-tooltip';
  60. var SECTION_NAV_TOOLTIP_SEL = '.' + SECTION_NAV_TOOLTIP;
  61. var SHOW_ACTIVE_TOOLTIP = 'fp-show-active';
  62. // slide
  63. var SLIDE_DEFAULT_SEL = '.slide';
  64. var SLIDE = 'fp-slide';
  65. var SLIDE_SEL = '.' + SLIDE;
  66. var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL;
  67. var SLIDES_WRAPPER = 'fp-slides';
  68. var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER;
  69. var SLIDES_CONTAINER = 'fp-slidesContainer';
  70. var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER;
  71. var TABLE = 'fp-table';
  72. // slide nav
  73. var SLIDES_NAV = 'fp-slidesNav';
  74. var SLIDES_NAV_SEL = '.' + SLIDES_NAV;
  75. var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a';
  76. var SLIDES_ARROW = 'fp-controlArrow';
  77. var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW;
  78. var SLIDES_PREV = 'fp-prev';
  79. var SLIDES_PREV_SEL = '.' + SLIDES_PREV;
  80. var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV;
  81. var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
  82. var SLIDES_NEXT = 'fp-next';
  83. var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT;
  84. var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT;
  85. var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
  86. function initialise(containerSelector, options) {
  87. var isOK = options && new RegExp('([\\d\\w]{8}-){3}[\\d\\w]{8}|^(?=.*?[A-Y])(?=.*?[a-y])(?=.*?[0-8])(?=.*?[#?!@$%^&*-]).{8,}$').test(options['li' + 'cen' + 'seK' + 'e' + 'y']) || document.domain.indexOf('al' + 'varotri' + 'go' + '.' + 'com') > -1;
  88. // cache common elements
  89. var $htmlBody = $('html, body');
  90. var $html = $('html')[0];
  91. var $body = $('body')[0];
  92. //only once my friend!
  93. if (hasClass($html, ENABLED)) {
  94. displayWarnings();
  95. return;
  96. }
  97. var FP = {};
  98. // Creating some defaults, extending them with any options that were provided
  99. options = deepExtend({
  100. //navigation
  101. menu: false,
  102. anchors: [],
  103. lockAnchors: false,
  104. navigation: false,
  105. navigationPosition: 'right',
  106. navigationTooltips: [],
  107. showActiveTooltip: false,
  108. slidesNavigation: false,
  109. slidesNavPosition: 'bottom',
  110. scrollBar: false,
  111. hybrid: false,
  112. //scrolling
  113. css3: true,
  114. scrollingSpeed: 700,
  115. autoScrolling: true,
  116. fitToSection: true,
  117. fitToSectionDelay: 1000,
  118. easing: 'easeInOutCubic',
  119. easingcss3: 'ease',
  120. loopBottom: false,
  121. loopTop: false,
  122. loopHorizontal: true,
  123. continuousVertical: false,
  124. continuousHorizontal: false,
  125. scrollHorizontally: false,
  126. interlockedSlides: false,
  127. dragAndMove: false,
  128. offsetSections: false,
  129. resetSliders: false,
  130. fadingEffect: false,
  131. normalScrollElements: null,
  132. scrollOverflow: false,
  133. scrollOverflowReset: false,
  134. scrollOverflowHandler: window.fp_scrolloverflow ? window.fp_scrolloverflow.iscrollHandler : null,
  135. scrollOverflowOptions: null,
  136. touchSensitivity: 5,
  137. touchWrapper: typeof containerSelector === 'string' ? $(containerSelector)[0] : containerSelector,
  138. bigSectionsDestination: null,
  139. //Accessibility
  140. keyboardScrolling: true,
  141. animateAnchor: true,
  142. recordHistory: true,
  143. //design
  144. controlArrows: true,
  145. controlArrowColor: '#fff',
  146. verticalCentered: true,
  147. sectionsColor: [],
  148. paddingTop: 0,
  149. paddingBottom: 0,
  150. fixedElements: null,
  151. responsive: 0, //backwards compabitility with responsiveWiddth
  152. responsiveWidth: 0,
  153. responsiveHeight: 0,
  154. responsiveSlides: false,
  155. parallax: false,
  156. parallaxOptions: {
  157. type: 'reveal',
  158. percentage: 62,
  159. property: 'translate'
  160. },
  161. cards: false,
  162. cardsOptions: {
  163. perspective: 100,
  164. fadeContent: true,
  165. fadeBackground: true
  166. },
  167. //Custom selectors
  168. sectionSelector: SECTION_DEFAULT_SEL,
  169. slideSelector: SLIDE_DEFAULT_SEL,
  170. //events
  171. v2compatible: false,
  172. afterLoad: null,
  173. onLeave: null,
  174. afterRender: null,
  175. afterResize: null,
  176. afterReBuild: null,
  177. afterSlideLoad: null,
  178. onSlideLeave: null,
  179. afterResponsive: null,
  180. lazyLoading: true
  181. }, options);
  182. //flag to avoid very fast sliding for landscape sliders
  183. var slideMoving = false;
  184. var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
  185. var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
  186. var container = typeof containerSelector === 'string' ? $(containerSelector)[0] : containerSelector;
  187. var windowsHeight = getWindowHeight();
  188. var windowsWidth = getWindowWidth();
  189. var isResizing = false;
  190. var isWindowFocused = true;
  191. var lastScrolledDestiny;
  192. var lastScrolledSlide;
  193. var canScroll = true;
  194. var scrollings = [];
  195. var controlPressed;
  196. var startingSection;
  197. var isScrollAllowed = {};
  198. isScrollAllowed.m = {
  199. 'up': true,
  200. 'down': true,
  201. 'left': true,
  202. 'right': true
  203. };
  204. isScrollAllowed.k = deepExtend({}, isScrollAllowed.m);
  205. var MSPointer = getMSPointer();
  206. var events = {
  207. touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move,
  208. touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down
  209. };
  210. var scrollBarHandler;
  211. // taken from https://github.com/udacity/ud891/blob/gh-pages/lesson2-focus/07-modals-and-keyboard-traps/solution/modal.js
  212. var focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';
  213. //cheks for passive event support
  214. var g_supportsPassive = false;
  215. try {
  216. var opts = Object.defineProperty({}, 'passive', {
  217. get: function () {
  218. g_supportsPassive = true;
  219. }
  220. });
  221. window.addEventListener("testPassive", null, opts);
  222. window.removeEventListener("testPassive", null, opts);
  223. } catch (e) {}
  224. //timeouts
  225. var resizeId;
  226. var resizeHandlerId;
  227. var afterSectionLoadsId;
  228. var afterSlideLoadsId;
  229. var scrollId;
  230. var scrollId2;
  231. var keydownId;
  232. var g_doubleCheckHeightId;
  233. var originals = deepExtend({}, options); //deep copy
  234. var activeAnimation;
  235. var g_initialAnchorsInDom = false;
  236. var g_canFireMouseEnterNormalScroll = true;
  237. var g_mediaLoadedId;
  238. var g_transitionLapseId;
  239. var extensions = [
  240. 'parallax',
  241. 'scrollOverflowReset',
  242. 'dragAndMove',
  243. 'offsetSections',
  244. 'fadingEffect',
  245. 'responsiveSlides',
  246. 'continuousHorizontal',
  247. 'interlockedSlides',
  248. 'scrollHorizontally',
  249. 'resetSliders',
  250. 'cards'
  251. ];
  252. displayWarnings();
  253. //easeInOutCubic animation included in the plugin
  254. window.fp_easings = deepExtend(window.fp_easings, {
  255. easeInOutCubic: function (t, b, c, d) {
  256. if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
  257. return c / 2 * ((t -= 2) * t * t + 2) + b;
  258. }
  259. });
  260. /**
  261. * Sets the autoScroll option.
  262. * It changes the scroll bar visibility and the history of the site as a result.
  263. */
  264. function setAutoScrolling(value, type) {
  265. //removing the transformation
  266. if (!value) {
  267. silentScroll(0);
  268. }
  269. setVariableState('autoScrolling', value, type);
  270. var element = $(SECTION_ACTIVE_SEL)[0];
  271. if (options.autoScrolling && !options.scrollBar) {
  272. css($htmlBody, {
  273. 'overflow': 'hidden',
  274. 'height': '100%'
  275. });
  276. setRecordHistory(originals.recordHistory, 'internal');
  277. //for IE touch devices
  278. css(container, {
  279. '-ms-touch-action': 'none',
  280. 'touch-action': 'none'
  281. });
  282. if (element != null) {
  283. //moving the container up
  284. silentScroll(element.offsetTop);
  285. }
  286. } else {
  287. css($htmlBody, {
  288. 'overflow': 'visible',
  289. 'height': 'initial'
  290. });
  291. var recordHistory = !options.autoScrolling ? false : originals.recordHistory;
  292. setRecordHistory(recordHistory, 'internal');
  293. //for IE touch devices
  294. css(container, {
  295. '-ms-touch-action': '',
  296. 'touch-action': ''
  297. });
  298. //scrolling the page to the section with no animation
  299. if (element != null) {
  300. var scrollSettings = getScrollSettings(element.offsetTop);
  301. scrollSettings.element.scrollTo(0, scrollSettings.options);
  302. }
  303. }
  304. }
  305. /**
  306. * Defines wheter to record the history for each hash change in the URL.
  307. */
  308. function setRecordHistory(value, type) {
  309. setVariableState('recordHistory', value, type);
  310. }
  311. /**
  312. * Defines the scrolling speed
  313. */
  314. function setScrollingSpeed(value, type) {
  315. setVariableState('scrollingSpeed', value, type);
  316. }
  317. /**
  318. * Sets fitToSection
  319. */
  320. function setFitToSection(value, type) {
  321. setVariableState('fitToSection', value, type);
  322. }
  323. /**
  324. * Sets lockAnchors
  325. */
  326. function setLockAnchors(value) {
  327. options.lockAnchors = value;
  328. }
  329. /**
  330. * Adds or remove the possibility of scrolling through sections by using the mouse wheel or the trackpad.
  331. */
  332. function setMouseWheelScrolling(value) {
  333. if (value) {
  334. addMouseWheelHandler();
  335. addMiddleWheelHandler();
  336. } else {
  337. removeMouseWheelHandler();
  338. removeMiddleWheelHandler();
  339. }
  340. }
  341. /**
  342. * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
  343. * Optionally a second parameter can be used to specify the direction for which the action will be applied.
  344. *
  345. * @param directions string containing the direction or directions separated by comma.
  346. */
  347. function setAllowScrolling(value, directions) {
  348. if (typeof directions !== 'undefined') {
  349. directions = directions.replace(/ /g, '').split(',');
  350. directions.forEach(function (direction) {
  351. setIsScrollAllowed(value, direction, 'm');
  352. });
  353. } else {
  354. setIsScrollAllowed(value, 'all', 'm');
  355. }
  356. }
  357. /**
  358. * Adds or remove the mouse wheel hijacking
  359. */
  360. function setMouseHijack(value) {
  361. if (value) {
  362. setMouseWheelScrolling(true);
  363. addTouchHandler();
  364. } else {
  365. setMouseWheelScrolling(false);
  366. removeTouchHandler();
  367. }
  368. }
  369. /**
  370. * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
  371. */
  372. function setKeyboardScrolling(value, directions) {
  373. if (typeof directions !== 'undefined') {
  374. directions = directions.replace(/ /g, '').split(',');
  375. directions.forEach(function (direction) {
  376. setIsScrollAllowed(value, direction, 'k');
  377. });
  378. } else {
  379. setIsScrollAllowed(value, 'all', 'k');
  380. options.keyboardScrolling = value;
  381. }
  382. }
  383. /**
  384. * Moves the page up one section.
  385. */
  386. function moveSectionUp() {
  387. var prev = prevUntil($(SECTION_ACTIVE_SEL)[0], SECTION_SEL);
  388. //looping to the bottom if there's no more sections above
  389. if (!prev && (options.loopTop || options.continuousVertical)) {
  390. prev = last($(SECTION_SEL));
  391. }
  392. if (prev != null) {
  393. scrollPage(prev, null, true);
  394. }
  395. }
  396. /**
  397. * Moves the page down one section.
  398. */
  399. function moveSectionDown() {
  400. var next = nextUntil($(SECTION_ACTIVE_SEL)[0], SECTION_SEL);
  401. //looping to the top if there's no more sections below
  402. if (!next &&
  403. (options.loopBottom || options.continuousVertical)) {
  404. next = $(SECTION_SEL)[0];
  405. }
  406. if (next != null) {
  407. scrollPage(next, null, false);
  408. }
  409. }
  410. /**
  411. * Moves the page to the given section and slide with no animation.
  412. * Anchors or index positions can be used as params.
  413. */
  414. function silentMoveTo(sectionAnchor, slideAnchor) {
  415. setScrollingSpeed(0, 'internal');
  416. moveTo(sectionAnchor, slideAnchor);
  417. setScrollingSpeed(originals.scrollingSpeed, 'internal');
  418. }
  419. /**
  420. * Moves the page to the given section and slide.
  421. * Anchors or index positions can be used as params.
  422. */
  423. function moveTo(sectionAnchor, slideAnchor) {
  424. var destiny = getSectionByAnchor(sectionAnchor);
  425. if (typeof slideAnchor !== 'undefined') {
  426. scrollPageAndSlide(sectionAnchor, slideAnchor);
  427. } else if (destiny != null) {
  428. scrollPage(destiny);
  429. }
  430. }
  431. /**
  432. * Slides right the slider of the active section.
  433. * Optional `section` param.
  434. */
  435. function moveSlideRight(section) {
  436. moveSlide('right', section);
  437. }
  438. /**
  439. * Slides left the slider of the active section.
  440. * Optional `section` param.
  441. */
  442. function moveSlideLeft(section) {
  443. moveSlide('left', section);
  444. }
  445. /**
  446. * When resizing is finished, we adjust the slides sizes and positions
  447. */
  448. function reBuild(resizing) {
  449. if (hasClass(container, DESTROYED)) {
  450. return;
  451. } //nothing to do if the plugin was destroyed
  452. isResizing = true;
  453. //updating global vars
  454. windowsHeight = getWindowHeight();
  455. windowsWidth = getWindowWidth();
  456. var sections = $(SECTION_SEL);
  457. for (var i = 0; i < sections.length; ++i) {
  458. var section = sections[i];
  459. var slidesWrap = $(SLIDES_WRAPPER_SEL, section)[0];
  460. var slides = $(SLIDE_SEL, section);
  461. //adjusting the height of the table-cell for IE and Firefox
  462. if (options.verticalCentered) {
  463. css($(TABLE_CELL_SEL, section), {
  464. 'height': getTableHeight(section) + 'px'
  465. });
  466. }
  467. css(section, {
  468. 'height': windowsHeight + 'px'
  469. });
  470. //adjusting the position fo the FULL WIDTH slides...
  471. if (slides.length > 1) {
  472. landscapeScroll(slidesWrap, $(SLIDE_ACTIVE_SEL, slidesWrap)[0]);
  473. }
  474. }
  475. if (options.scrollOverflow) {
  476. scrollBarHandler.createScrollBarForAll();
  477. }
  478. var activeSection = $(SECTION_ACTIVE_SEL)[0];
  479. var sectionIndex = index(activeSection, SECTION_SEL);
  480. //isn't it the first section?
  481. if (sectionIndex) {
  482. //adjusting the position for the current section
  483. silentMoveTo(sectionIndex + 1);
  484. }
  485. if (isFunction(options.afterResize) && resizing) {
  486. options.afterResize.call(container, window.innerWidth, window.innerHeight);
  487. }
  488. if (isFunction(options.afterReBuild) && !resizing) {
  489. options.afterReBuild.call(container);
  490. }
  491. }
  492. /**
  493. * Determines whether fullpage.js is in responsive mode or not.
  494. */
  495. function isResponsiveMode() {
  496. return hasClass($body, RESPONSIVE);
  497. }
  498. /**
  499. * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
  500. * are smaller than the set limit values.
  501. */
  502. function setResponsive(active) {
  503. var isResponsive = isResponsiveMode();
  504. if (active) {
  505. if (!isResponsive) {
  506. setAutoScrolling(false, 'internal');
  507. setFitToSection(false, 'internal');
  508. hide($(SECTION_NAV_SEL));
  509. addClass($body, RESPONSIVE);
  510. if (isFunction(options.afterResponsive)) {
  511. options.afterResponsive.call(container, active);
  512. }
  513. //when on page load, we will remove scrolloverflow if necessary
  514. if (options.scrollOverflow) {
  515. scrollBarHandler.createScrollBarForAll();
  516. }
  517. }
  518. } else if (isResponsive) {
  519. setAutoScrolling(originals.autoScrolling, 'internal');
  520. setFitToSection(originals.autoScrolling, 'internal');
  521. show($(SECTION_NAV_SEL));
  522. removeClass($body, RESPONSIVE);
  523. if (isFunction(options.afterResponsive)) {
  524. options.afterResponsive.call(container, active);
  525. }
  526. }
  527. }
  528. if (container) {
  529. //public functions
  530. FP.version = '3.1.0';
  531. FP.setAutoScrolling = setAutoScrolling;
  532. FP.setRecordHistory = setRecordHistory;
  533. FP.setScrollingSpeed = setScrollingSpeed;
  534. FP.setFitToSection = setFitToSection;
  535. FP.setLockAnchors = setLockAnchors;
  536. FP.setMouseWheelScrolling = setMouseWheelScrolling;
  537. FP.setAllowScrolling = setAllowScrolling;
  538. FP.setKeyboardScrolling = setKeyboardScrolling;
  539. FP.moveSectionUp = moveSectionUp;
  540. FP.moveSectionDown = moveSectionDown;
  541. FP.silentMoveTo = silentMoveTo;
  542. FP.moveTo = moveTo;
  543. FP.moveSlideRight = moveSlideRight;
  544. FP.moveSlideLeft = moveSlideLeft;
  545. FP.fitToSection = fitToSection;
  546. FP.reBuild = reBuild;
  547. FP.setResponsive = setResponsive;
  548. FP.getFullpageData = function () {
  549. return options;
  550. };
  551. FP.destroy = destroy;
  552. FP.getActiveSection = getActiveSection;
  553. FP.getActiveSlide = getActiveSlide;
  554. FP.test = {
  555. top: '0px',
  556. translate3d: 'translate3d(0px, 0px, 0px)',
  557. translate3dH: (function () {
  558. var a = [];
  559. for (var i = 0; i < $(options.sectionSelector, container).length; i++) {
  560. a.push('translate3d(0px, 0px, 0px)');
  561. }
  562. return a;
  563. })(),
  564. left: (function () {
  565. var a = [];
  566. for (var i = 0; i < $(options.sectionSelector, container).length; i++) {
  567. a.push(0);
  568. }
  569. return a;
  570. })(),
  571. options: options,
  572. setAutoScrolling: setAutoScrolling
  573. };
  574. //functions we want to share across files but which are not
  575. //mean to be used on their own by developers
  576. FP.shared = {
  577. afterRenderActions: afterRenderActions,
  578. isNormalScrollElement: false
  579. };
  580. window.fullpage_api = FP;
  581. //using jQuery initialization? Creating the $.fn.fullpage object
  582. if (options.$) {
  583. Object.keys(FP).forEach(function (key) {
  584. options.$.fn.fullpage[key] = FP[key];
  585. });
  586. }
  587. init();
  588. bindEvents();
  589. }
  590. function init() {
  591. //if css3 is not supported, it will use jQuery animations
  592. if (options.css3) {
  593. options.css3 = support3d();
  594. }
  595. options.scrollBar = options.scrollBar || options.hybrid;
  596. setOptionsFromDOM();
  597. prepareDom();
  598. setAllowScrolling(true);
  599. setMouseHijack(true);
  600. setAutoScrolling(options.autoScrolling, 'internal');
  601. responsive();
  602. //setting the class for the body element
  603. setBodyClass();
  604. if (document.readyState === 'complete') {
  605. scrollToAnchor();
  606. }
  607. window.addEventListener('load', scrollToAnchor);
  608. //if we use scrollOverflow we'll fire afterRender in the scrolloverflow file
  609. if (!options.scrollOverflow) {
  610. afterRenderActions();
  611. }
  612. doubleCheckHeight();
  613. }
  614. function bindEvents() {
  615. //when scrolling...
  616. window.addEventListener('scroll', scrollHandler);
  617. //detecting any change on the URL to scroll to the given anchor link
  618. //(a way to detect back history button as we play with the hashes on the URL)
  619. window.addEventListener('hashchange', hashChangeHandler);
  620. // on window focus
  621. window.addEventListener('focus', focusHandler);
  622. //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
  623. window.addEventListener('blur', blurHandler);
  624. //when resizing the site, we adjust the heights of the sections, slimScroll...
  625. window.addEventListener('resize', resizeHandler);
  626. //Sliding with arrow keys, both, vertical and horizontal
  627. document.addEventListener('keydown', keydownHandler);
  628. //to prevent scrolling while zooming
  629. document.addEventListener('keyup', keyUpHandler);
  630. //Scrolls to the section when clicking the navigation bullet
  631. //simulating the jQuery .on('click') event using delegation
  632. ['click', 'touchstart'].forEach(function (eventName) {
  633. document.addEventListener(eventName, delegatedEvents);
  634. });
  635. /**
  636. * Applying normalScroll elements.
  637. * Ignoring the scrolls over the specified selectors.
  638. */
  639. if (options.normalScrollElements) {
  640. ['mouseenter', 'touchstart'].forEach(function (eventName) {
  641. forMouseLeaveOrTouch(eventName, false);
  642. });
  643. ['mouseleave', 'touchend'].forEach(function (eventName) {
  644. forMouseLeaveOrTouch(eventName, true);
  645. });
  646. }
  647. }
  648. function delegatedEvents(e) {
  649. var target = e.target;
  650. if (target && closest(target, SECTION_NAV_SEL + ' a')) {
  651. sectionBulletHandler.call(target, e);
  652. } else if (matches(target, SECTION_NAV_TOOLTIP_SEL)) {
  653. tooltipTextHandler.call(target);
  654. } else if (matches(target, SLIDES_ARROW_SEL)) {
  655. slideArrowHandler.call(target, e);
  656. } else if (matches(target, SLIDES_NAV_LINK_SEL) || closest(target, SLIDES_NAV_LINK_SEL) != null) {
  657. slideBulletHandler.call(target, e);
  658. } else if (closest(target, options.menu + ' [data-menuanchor]')) {
  659. menuItemsHandler.call(target, e);
  660. }
  661. }
  662. function forMouseLeaveOrTouch(eventName, allowScrolling) {
  663. //a way to pass arguments to the onMouseEnterOrLeave function
  664. document['fp_' + eventName] = allowScrolling;
  665. document.addEventListener(eventName, onMouseEnterOrLeave, true); //capturing phase
  666. }
  667. function onMouseEnterOrLeave(e) {
  668. var type = e.type;
  669. var isInsideOneNormalScroll = false;
  670. var isUsingScrollOverflow = options.scrollOverflow;
  671. //onMouseLeave will use the destination target, not the one we are moving away from
  672. var target = type === 'mouseleave' ? e.toElement || e.relatedTarget : e.target;
  673. //coming from closing a normalScrollElements modal or moving outside viewport?
  674. if (target == document || !target) {
  675. setMouseHijack(true);
  676. if (isUsingScrollOverflow) {
  677. options.scrollOverflowHandler.setIscroll(target, true);
  678. }
  679. return;
  680. }
  681. if (type === 'touchend') {
  682. g_canFireMouseEnterNormalScroll = false;
  683. setTimeout(function () {
  684. g_canFireMouseEnterNormalScroll = true;
  685. }, 800);
  686. }
  687. //preventing mouseenter event to do anything when coming from a touchEnd event
  688. //fixing issue #3576
  689. if (type === 'mouseenter' && !g_canFireMouseEnterNormalScroll) {
  690. return;
  691. }
  692. var normalSelectors = options.normalScrollElements.split(',');
  693. normalSelectors.forEach(function (normalSelector) {
  694. if (!isInsideOneNormalScroll) {
  695. var isNormalScrollTarget = matches(target, normalSelector);
  696. //leaving a child inside the normalScoll element is not leaving the normalScroll #3661
  697. var isNormalScrollChildFocused = closest(target, normalSelector);
  698. if (isNormalScrollTarget || isNormalScrollChildFocused) {
  699. if (!FP.shared.isNormalScrollElement) {
  700. setMouseHijack(false);
  701. if (isUsingScrollOverflow) {
  702. options.scrollOverflowHandler.setIscroll(target, false);
  703. }
  704. }
  705. FP.shared.isNormalScrollElement = true;
  706. isInsideOneNormalScroll = true;
  707. }
  708. }
  709. });
  710. //not inside a single normal scroll element anymore?
  711. if (!isInsideOneNormalScroll && FP.shared.isNormalScrollElement) {
  712. setMouseHijack(true);
  713. if (isUsingScrollOverflow) {
  714. options.scrollOverflowHandler.setIscroll(target, true);
  715. }
  716. FP.shared.isNormalScrollElement = false;
  717. }
  718. }
  719. /**
  720. * Checks the viewport a few times on a define interval of time to
  721. * see if it has changed in any of those. If that's the case, it resizes.
  722. */
  723. function doubleCheckHeight() {
  724. for (var i = 1; i < 4; i++) {
  725. g_doubleCheckHeightId = setTimeout(adjustToNewViewport, 350 * i);
  726. }
  727. }
  728. /**
  729. * Adjusts a section to the viewport if it has changed.
  730. */
  731. function adjustToNewViewport() {
  732. var newWindowHeight = getWindowHeight();
  733. var newWindowWidth = getWindowWidth();
  734. if (windowsHeight !== newWindowHeight || windowsWidth !== newWindowWidth) {
  735. windowsHeight = newWindowHeight;
  736. windowsWidth = newWindowWidth;
  737. reBuild(true);
  738. }
  739. }
  740. /**
  741. * Setting options from DOM elements if they are not provided.
  742. */
  743. function setOptionsFromDOM() {
  744. //no anchors option? Checking for them in the DOM attributes
  745. if (!options.anchors.length) {
  746. var anchorsAttribute = '[data-anchor]';
  747. var anchors = $(options.sectionSelector.split(',').join(anchorsAttribute + ',') + anchorsAttribute, container);
  748. if (anchors.length && anchors.length === $(options.sectionSelector, container).length) {
  749. g_initialAnchorsInDom = true;
  750. anchors.forEach(function (item) {
  751. options.anchors.push(item.getAttribute('data-anchor').toString());
  752. });
  753. }
  754. }
  755. //no tooltips option? Checking for them in the DOM attributes
  756. if (!options.navigationTooltips.length) {
  757. var tooltipsAttribute = '[data-tooltip]';
  758. var tooltips = $(options.sectionSelector.split(',').join(tooltipsAttribute + ',') + tooltipsAttribute, container);
  759. if (tooltips.length) {
  760. tooltips.forEach(function (item) {
  761. options.navigationTooltips.push(item.getAttribute('data-tooltip').toString());
  762. });
  763. }
  764. }
  765. }
  766. /**
  767. * Works over the DOM structure to set it up for the current fullpage options.
  768. */
  769. function prepareDom() {
  770. css(container, {
  771. 'height': '100%',
  772. 'position': 'relative'
  773. });
  774. //adding a class to recognize the container internally in the code
  775. addClass(container, WRAPPER);
  776. addClass($html, ENABLED);
  777. //due to https://github.com/alvarotrigo/fullPage.js/issues/1502
  778. windowsHeight = getWindowHeight();
  779. removeClass(container, DESTROYED); //in case it was destroyed before initializing it again
  780. addInternalSelectors();
  781. var sections = $(SECTION_SEL);
  782. //styling the sections / slides / menu
  783. for (var i = 0; i < sections.length; i++) {
  784. var sectionIndex = i;
  785. var section = sections[i];
  786. var slides = $(SLIDE_SEL, section);
  787. var numSlides = slides.length;
  788. //caching the original styles to add them back on destroy('all')
  789. section.setAttribute('data-fp-styles', section.getAttribute('style'));
  790. styleSection(section, sectionIndex);
  791. styleMenu(section, sectionIndex);
  792. // if there's any slide
  793. if (numSlides > 0) {
  794. styleSlides(section, slides, numSlides);
  795. } else {
  796. if (options.verticalCentered) {
  797. addTableClass(section);
  798. }
  799. }
  800. }
  801. //fixed elements need to be moved out of the plugin container due to problems with CSS3.
  802. if (options.fixedElements && options.css3) {
  803. $(options.fixedElements).forEach(function (item) {
  804. $body.appendChild(item);
  805. });
  806. }
  807. //vertical centered of the navigation + active bullet
  808. if (options.navigation) {
  809. addVerticalNavigation();
  810. }
  811. enableYoutubeAPI();
  812. if (options.scrollOverflow) {
  813. scrollBarHandler = options.scrollOverflowHandler.init(options);
  814. }
  815. }
  816. /**
  817. * Styles the horizontal slides for a section.
  818. */
  819. function styleSlides(section, slides, numSlides) {
  820. var sliderWidth = numSlides * 100;
  821. var slideWidth = 100 / numSlides;
  822. var slidesWrapper = document.createElement('div');
  823. slidesWrapper.className = SLIDES_WRAPPER; //fp-slides
  824. wrapAll(slides, slidesWrapper);
  825. var slidesContainer = document.createElement('div');
  826. slidesContainer.className = SLIDES_CONTAINER; //fp-slidesContainer
  827. wrapAll(slides, slidesContainer);
  828. css($(SLIDES_CONTAINER_SEL, section), {
  829. 'width': sliderWidth + '%'
  830. });
  831. if (numSlides > 1) {
  832. if (options.controlArrows) {
  833. createSlideArrows(section);
  834. }
  835. if (options.slidesNavigation) {
  836. addSlidesNavigation(section, numSlides);
  837. }
  838. }
  839. slides.forEach(function (slide) {
  840. css(slide, {
  841. 'width': slideWidth + '%'
  842. });
  843. if (options.verticalCentered) {
  844. addTableClass(slide);
  845. }
  846. });
  847. var startingSlide = $(SLIDE_ACTIVE_SEL, section)[0];
  848. //if the slide won't be an starting point, the default will be the first one
  849. //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.
  850. if (startingSlide != null && (index($(SECTION_ACTIVE_SEL), SECTION_SEL) !== 0 || (index($(SECTION_ACTIVE_SEL), SECTION_SEL) === 0 && index(startingSlide) !== 0))) {
  851. silentLandscapeScroll(startingSlide, 'internal');
  852. } else {
  853. addClass(slides[0], ACTIVE);
  854. }
  855. }
  856. /**
  857. * Styling vertical sections
  858. */
  859. function styleSection(section, index) {
  860. //if no active section is defined, the 1st one will be the default one
  861. if (!index && $(SECTION_ACTIVE_SEL)[0] == null) {
  862. addClass(section, ACTIVE);
  863. }
  864. startingSection = $(SECTION_ACTIVE_SEL)[0];
  865. css(section, {
  866. 'height': windowsHeight + 'px'
  867. });
  868. if (options.paddingTop) {
  869. css(section, {
  870. 'padding-top': options.paddingTop
  871. });
  872. }
  873. if (options.paddingBottom) {
  874. css(section, {
  875. 'padding-bottom': options.paddingBottom
  876. });
  877. }
  878. if (typeof options.sectionsColor[index] !== 'undefined') {
  879. css(section, {
  880. 'background-color': options.sectionsColor[index]
  881. });
  882. }
  883. if (typeof options.anchors[index] !== 'undefined') {
  884. section.setAttribute('data-anchor', options.anchors[index]);
  885. }
  886. }
  887. /**
  888. * Sets the data-anchor attributes to the menu elements and activates the current one.
  889. */
  890. function styleMenu(section, index) {
  891. if (typeof options.anchors[index] !== 'undefined') {
  892. //activating the menu / nav element on load
  893. if (hasClass(section, ACTIVE)) {
  894. activateMenuAndNav(options.anchors[index], index);
  895. }
  896. }
  897. //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
  898. if (options.menu && options.css3 && closest($(options.menu)[0], WRAPPER_SEL) != null) {
  899. $(options.menu).forEach(function (menu) {
  900. $body.appendChild(menu);
  901. });
  902. }
  903. }
  904. /**
  905. * Adds internal classes to be able to provide customizable selectors
  906. * keeping the link with the style sheet.
  907. */
  908. function addInternalSelectors() {
  909. addClass($(options.sectionSelector, container), SECTION);
  910. addClass($(options.slideSelector, container), SLIDE);
  911. }
  912. /**
  913. * Creates the control arrows for the given section
  914. */
  915. function createSlideArrows(section) {
  916. var arrows = [createElementFromHTML('<div class="' + SLIDES_ARROW_PREV + '"></div>'), createElementFromHTML('<div class="' + SLIDES_ARROW_NEXT + '"></div>')];
  917. after($(SLIDES_WRAPPER_SEL, section)[0], arrows);
  918. if (options.controlArrowColor !== '#fff') {
  919. css($(SLIDES_ARROW_NEXT_SEL, section), {
  920. 'border-color': 'transparent transparent transparent ' + options.controlArrowColor
  921. });
  922. css($(SLIDES_ARROW_PREV_SEL, section), {
  923. 'border-color': 'transparent ' + options.controlArrowColor + ' transparent transparent'
  924. });
  925. }
  926. if (!options.loopHorizontal) {
  927. hide($(SLIDES_ARROW_PREV_SEL, section));
  928. }
  929. }
  930. /**
  931. * Creates a vertical navigation bar.
  932. */
  933. function addVerticalNavigation() {
  934. var navigation = document.createElement('div');
  935. navigation.setAttribute('id', SECTION_NAV);
  936. var divUl = document.createElement('ul');
  937. navigation.appendChild(divUl);
  938. appendTo(navigation, $body);
  939. var nav = $(SECTION_NAV_SEL)[0];
  940. addClass(nav, 'fp-' + options.navigationPosition);
  941. if (options.showActiveTooltip) {
  942. addClass(nav, SHOW_ACTIVE_TOOLTIP);
  943. }
  944. var li = '';
  945. for (var i = 0; i < $(SECTION_SEL).length; i++) {
  946. var link = '';
  947. if (options.anchors.length) {
  948. link = options.anchors[i];
  949. }
  950. li += '<li><a href="#' + link + '"><span class="fp-sr-only">' + getBulletLinkName(i, 'Section') + '</span><span></span></a>';
  951. // Only add tooltip if needed (defined by user)
  952. var tooltip = options.navigationTooltips[i];
  953. if (typeof tooltip !== 'undefined' && tooltip !== '') {
  954. li += '<div class="' + SECTION_NAV_TOOLTIP + ' fp-' + options.navigationPosition + '">' + tooltip + '</div>';
  955. }
  956. li += '</li>';
  957. }
  958. $('ul', nav)[0].innerHTML = li;
  959. //activating the current active section
  960. var bullet = $('li', $(SECTION_NAV_SEL)[0])[index($(SECTION_ACTIVE_SEL)[0], SECTION_SEL)];
  961. addClass($('a', bullet), ACTIVE);
  962. }
  963. /**
  964. * Gets the name for screen readers for a section/slide navigation bullet.
  965. */
  966. function getBulletLinkName(i, defaultName, item) {
  967. var anchor = defaultName === 'Section' ? options.anchors[i] : item.getAttribute('data-anchor');
  968. return options.navigationTooltips[i] ||
  969. anchor ||
  970. defaultName + ' ' + (i + 1);
  971. }
  972. /*
  973. * Enables the Youtube videos API so we can control their flow if necessary.
  974. */
  975. function enableYoutubeAPI() {
  976. $('iframe[src*="youtube.com/embed/"]', container).forEach(function (item) {
  977. addURLParam(item, 'enablejsapi=1');
  978. });
  979. }
  980. /**
  981. * Adds a new parameter and its value to the `src` of a given element
  982. */
  983. function addURLParam(element, newParam) {
  984. var originalSrc = element.getAttribute('src');
  985. element.setAttribute('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
  986. }
  987. /*
  988. * Returns the prefix sign to use for a new parameter in an existen URL.
  989. *
  990. * @return {String} ? | &
  991. */
  992. function getUrlParamSign(url) {
  993. return (!/\?/.test(url)) ? '?' : '&';
  994. }
  995. /**
  996. * Actions and callbacks to fire afterRender
  997. */
  998. function afterRenderActions() {
  999. var section = $(SECTION_ACTIVE_SEL)[0];
  1000. addClass(section, COMPLETELY);
  1001. lazyLoad(section);
  1002. lazyLoadOthers();
  1003. playMedia(section);
  1004. if (options.scrollOverflow) {
  1005. options.scrollOverflowHandler.afterLoad();
  1006. }
  1007. if (isDestinyTheStartingSection() && isFunction(options.afterLoad)) {
  1008. fireCallback('afterLoad', {
  1009. activeSection: section,
  1010. element: section,
  1011. direction: null,
  1012. //for backwards compatibility callback (to be removed in a future!)
  1013. anchorLink: section.getAttribute('data-anchor'),
  1014. sectionIndex: index(section, SECTION_SEL)
  1015. });
  1016. }
  1017. if (isFunction(options.afterRender)) {
  1018. fireCallback('afterRender');
  1019. }
  1020. }
  1021. /**
  1022. * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
  1023. */
  1024. function isDestinyTheStartingSection() {
  1025. var anchor = getAnchorsURL();
  1026. var destinationSection = getSectionByAnchor(anchor.section);
  1027. return !anchor.section || !destinationSection || typeof destinationSection !== 'undefined' && index(destinationSection) === index(startingSection);
  1028. }
  1029. var isScrolling = false;
  1030. var lastScroll = 0;
  1031. //when scrolling...
  1032. function scrollHandler() {
  1033. var currentSection;
  1034. if (isResizing) {
  1035. return;
  1036. }
  1037. if (!options.autoScrolling || options.scrollBar) {
  1038. var currentScroll = getScrollTop();
  1039. var scrollDirection = getScrollDirection(currentScroll);
  1040. var visibleSectionIndex = 0;
  1041. var screen_mid = currentScroll + (getWindowHeight() / 2.0);
  1042. var isAtBottom = $body.offsetHeight - getWindowHeight() === currentScroll;
  1043. var sections = $(SECTION_SEL);
  1044. //when using `auto-height` for a small last section it won't be centered in the viewport
  1045. if (isAtBottom) {
  1046. visibleSectionIndex = sections.length - 1;
  1047. }
  1048. //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
  1049. else if (!currentScroll) {
  1050. visibleSectionIndex = 0;
  1051. }
  1052. //taking the section which is showing more content in the viewport
  1053. else {
  1054. for (var i = 0; i < sections.length; ++i) {
  1055. var section = sections[i];
  1056. // Pick the the last section which passes the middle line of the screen.
  1057. if (section.offsetTop <= screen_mid) {
  1058. visibleSectionIndex = i;
  1059. }
  1060. }
  1061. }
  1062. if (isCompletelyInViewPort(scrollDirection)) {
  1063. if (!hasClass($(SECTION_ACTIVE_SEL)[0], COMPLETELY)) {
  1064. addClass($(SECTION_ACTIVE_SEL)[0], COMPLETELY);
  1065. removeClass(siblings($(SECTION_ACTIVE_SEL)[0]), COMPLETELY);
  1066. }
  1067. }
  1068. //geting the last one, the current one on the screen
  1069. currentSection = sections[visibleSectionIndex];
  1070. //setting the visible section as active when manually scrolling
  1071. //executing only once the first time we reach the section
  1072. if (!hasClass(currentSection, ACTIVE)) {
  1073. isScrolling = true;
  1074. var leavingSection = $(SECTION_ACTIVE_SEL)[0];
  1075. var leavingSectionIndex = index(leavingSection, SECTION_SEL) + 1;
  1076. var yMovement = getYmovement(currentSection);
  1077. var anchorLink = currentSection.getAttribute('data-anchor');
  1078. var sectionIndex = index(currentSection, SECTION_SEL) + 1;
  1079. var activeSlide = $(SLIDE_ACTIVE_SEL, currentSection)[0];
  1080. var slideIndex;
  1081. var slideAnchorLink;
  1082. var callbacksParams = {
  1083. activeSection: leavingSection,
  1084. sectionIndex: sectionIndex - 1,
  1085. anchorLink: anchorLink,
  1086. element: currentSection,
  1087. leavingSection: leavingSectionIndex,
  1088. direction: yMovement
  1089. };
  1090. if (activeSlide) {
  1091. slideAnchorLink = activeSlide.getAttribute('data-anchor');
  1092. slideIndex = index(activeSlide);
  1093. }
  1094. if (canScroll) {
  1095. addClass(currentSection, ACTIVE);
  1096. removeClass(siblings(currentSection), ACTIVE);
  1097. if (isFunction(options.onLeave)) {
  1098. fireCallback('onLeave', callbacksParams);
  1099. }
  1100. if (isFunction(options.afterLoad)) {
  1101. fireCallback('afterLoad', callbacksParams);
  1102. }
  1103. stopMedia(leavingSection);
  1104. lazyLoad(currentSection);
  1105. playMedia(currentSection);
  1106. activateMenuAndNav(anchorLink, sectionIndex - 1);
  1107. if (options.anchors.length) {
  1108. //needed to enter in hashChange event when using the menu with anchor links
  1109. lastScrolledDestiny = anchorLink;
  1110. }
  1111. setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
  1112. }
  1113. //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
  1114. clearTimeout(scrollId);
  1115. scrollId = setTimeout(function () {
  1116. isScrolling = false;
  1117. }, 100);
  1118. }
  1119. if (options.fitToSection) {
  1120. //for the auto adjust of the viewport to fit a whole section
  1121. clearTimeout(scrollId2);
  1122. scrollId2 = setTimeout(function () {
  1123. //checking it again in case it changed during the delay
  1124. if (options.fitToSection &&
  1125. //is the destination element bigger than the viewport?
  1126. $(SECTION_ACTIVE_SEL)[0].offsetHeight <= windowsHeight
  1127. ) {
  1128. fitToSection();
  1129. }
  1130. }, options.fitToSectionDelay);
  1131. }
  1132. }
  1133. }
  1134. /**
  1135. * Fits the site to the nearest active section
  1136. */
  1137. function fitToSection() {
  1138. //checking fitToSection again in case it was set to false before the timeout delay
  1139. if (canScroll) {
  1140. //allows to scroll to an active section and
  1141. //if the section is already active, we prevent firing callbacks
  1142. isResizing = true;
  1143. scrollPage($(SECTION_ACTIVE_SEL)[0]);
  1144. isResizing = false;
  1145. }
  1146. }
  1147. /**
  1148. * Determines whether the active section has seen in its whole or not.
  1149. */
  1150. function isCompletelyInViewPort(movement) {
  1151. var top = $(SECTION_ACTIVE_SEL)[0].offsetTop;
  1152. var bottom = top + getWindowHeight();
  1153. if (movement == 'up') {
  1154. return bottom >= (getScrollTop() + getWindowHeight());
  1155. }
  1156. return top <= getScrollTop();
  1157. }
  1158. /**
  1159. * Determines whether a section is in the viewport or not.
  1160. */
  1161. function isSectionInViewport(el) {
  1162. var rect = el.getBoundingClientRect();
  1163. var top = rect.top;
  1164. var bottom = rect.bottom;
  1165. //sometimes there's a 1px offset on the bottom of the screen even when the
  1166. //section's height is the window.innerHeight one. I guess because pixels won't allow decimals.
  1167. //using this prevents from lazyLoading the section that is not yet visible
  1168. //(only 1 pixel offset is)
  1169. var pixelOffset = 2;
  1170. var isTopInView = top + pixelOffset < windowsHeight && top > 0;
  1171. var isBottomInView = bottom > pixelOffset && bottom < windowsHeight;
  1172. return isTopInView || isBottomInView;
  1173. }
  1174. /**
  1175. * Gets the directon of the the scrolling fired by the scroll event.
  1176. */
  1177. function getScrollDirection(currentScroll) {
  1178. var direction = currentScroll > lastScroll ? 'down' : 'up';
  1179. lastScroll = currentScroll;
  1180. //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
  1181. previousDestTop = currentScroll;
  1182. return direction;
  1183. }
  1184. /**
  1185. * Determines the way of scrolling up or down:
  1186. * by 'automatically' scrolling a section or by using the default and normal scrolling.
  1187. */
  1188. function scrolling(type) {
  1189. if (!isScrollAllowed.m[type]) {
  1190. return;
  1191. }
  1192. var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
  1193. if (options.scrollOverflow) {
  1194. var scrollable = options.scrollOverflowHandler.scrollable($(SECTION_ACTIVE_SEL)[0]);
  1195. var check = (type === 'down') ? 'bottom' : 'top';
  1196. if (scrollable != null) {
  1197. //is the scrollbar at the start/end of the scroll?
  1198. if (options.scrollOverflowHandler.isScrolled(check, scrollable)) {
  1199. scrollSection();
  1200. } else {
  1201. return true;
  1202. }
  1203. } else {
  1204. // moved up/down
  1205. scrollSection();
  1206. }
  1207. } else {
  1208. // moved up/down
  1209. scrollSection();
  1210. }
  1211. }
  1212. /*
  1213. * Preventing bouncing in iOS #2285
  1214. */
  1215. function preventBouncing(e) {
  1216. if (options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up) {
  1217. //preventing the easing on iOS devices
  1218. preventDefault(e);
  1219. }
  1220. }
  1221. var touchStartY = 0;
  1222. var touchStartX = 0;
  1223. var touchEndY = 0;
  1224. var touchEndX = 0;
  1225. /* Detecting touch events
  1226. * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
  1227. * This way, the touchstart and the touch moves shows an small difference between them which is the
  1228. * used one to determine the direction.
  1229. */
  1230. function touchMoveHandler(e) {
  1231. var activeSection = closest(e.target, SECTION_SEL) || $(SECTION_ACTIVE_SEL)[0];
  1232. if (isReallyTouch(e)) {
  1233. if (options.autoScrolling) {
  1234. //preventing the easing on iOS devices
  1235. preventDefault(e);
  1236. }
  1237. var touchEvents = getEventsPage(e);
  1238. touchEndY = touchEvents.y;
  1239. touchEndX = touchEvents.x;
  1240. //if movement in the X axys is greater than in the Y and the currect section has slides...
  1241. if ($(SLIDES_WRAPPER_SEL, activeSection).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
  1242. //is the movement greater than the minimum resistance to scroll?
  1243. if (!slideMoving && Math.abs(touchStartX - touchEndX) > (getWindowWidth() / 100 * options.touchSensitivity)) {
  1244. if (touchStartX > touchEndX) {
  1245. if (isScrollAllowed.m.right) {
  1246. moveSlideRight(activeSection); //next
  1247. }
  1248. } else {
  1249. if (isScrollAllowed.m.left) {
  1250. moveSlideLeft(activeSection); //prev
  1251. }
  1252. }
  1253. }
  1254. }
  1255. //vertical scrolling (only when autoScrolling is enabled)
  1256. else if (options.autoScrolling && canScroll) {
  1257. //is the movement greater than the minimum resistance to scroll?
  1258. if (Math.abs(touchStartY - touchEndY) > (window.innerHeight / 100 * options.touchSensitivity)) {
  1259. if (touchStartY > touchEndY) {
  1260. scrolling('down');
  1261. } else if (touchEndY > touchStartY) {
  1262. scrolling('up');
  1263. }
  1264. }
  1265. }
  1266. }
  1267. }
  1268. /**
  1269. * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
  1270. * this way we make sure that is really a touch event what IE is detecting.
  1271. */
  1272. function isReallyTouch(e) {
  1273. //if is not IE || IE is detecting `touch` or `pen`
  1274. return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
  1275. }
  1276. /**
  1277. * Handler for the touch start event.
  1278. */
  1279. function touchStartHandler(e) {
  1280. //stopping the auto scroll to adjust to a section
  1281. if (options.fitToSection) {
  1282. activeAnimation = false;
  1283. }
  1284. if (isReallyTouch(e)) {
  1285. var touchEvents = getEventsPage(e);
  1286. touchStartY = touchEvents.y;
  1287. touchStartX = touchEvents.x;
  1288. }
  1289. }
  1290. /**
  1291. * Gets the average of the last `number` elements of the given array.
  1292. */
  1293. function getAverage(elements, number) {
  1294. var sum = 0;
  1295. //taking `number` elements from the end to make the average, if there are not enought, 1
  1296. var lastElements = elements.slice(Math.max(elements.length - number, 1));
  1297. for (var i = 0; i < lastElements.length; i++) {
  1298. sum = sum + lastElements[i];
  1299. }
  1300. return Math.ceil(sum / number);
  1301. }
  1302. /**
  1303. * Detecting mousewheel scrolling
  1304. *
  1305. * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
  1306. * http://www.sitepoint.com/html5-javascript-mouse-wheel/
  1307. */
  1308. var prevTime = new Date().getTime();
  1309. function MouseWheelHandler(e) {
  1310. var curTime = new Date().getTime();
  1311. var isNormalScroll = hasClass($(COMPLETELY_SEL)[0], NORMAL_SCROLL);
  1312. //is scroll allowed?
  1313. if (!isScrollAllowed.m.down && !isScrollAllowed.m.up) {
  1314. preventDefault(e);
  1315. return false;
  1316. }
  1317. //autoscrolling and not zooming?
  1318. if (options.autoScrolling && !controlPressed && !isNormalScroll) {
  1319. // cross-browser wheel delta
  1320. e = e || window.event;
  1321. var value = e.wheelDelta || -e.deltaY || -e.detail;
  1322. var delta = Math.max(-1, Math.min(1, value));
  1323. var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
  1324. var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX) < Math.abs(e.deltaY) || !horizontalDetection);
  1325. //Limiting the array to 150 (lets not waste memory!)
  1326. if (scrollings.length > 149) {
  1327. scrollings.shift();
  1328. }
  1329. //keeping record of the previous scrollings
  1330. scrollings.push(Math.abs(value));
  1331. //preventing to scroll the site on mouse wheel when scrollbar is present
  1332. if (options.scrollBar) {
  1333. preventDefault(e);
  1334. }
  1335. //time difference between the last scroll and the current one
  1336. var timeDiff = curTime - prevTime;
  1337. prevTime = curTime;
  1338. //haven't they scrolled in a while?
  1339. //(enough to be consider a different scrolling action to scroll another section)
  1340. if (timeDiff > 200) {
  1341. //emptying the array, we dont care about old scrollings for our averages
  1342. scrollings = [];
  1343. }
  1344. if (canScroll) {
  1345. var averageEnd = getAverage(scrollings, 10);
  1346. var averageMiddle = getAverage(scrollings, 70);
  1347. var isAccelerating = averageEnd >= averageMiddle;
  1348. //to avoid double swipes...
  1349. if (isAccelerating && isScrollingVertically) {
  1350. //scrolling down?
  1351. if (delta < 0) {
  1352. scrolling('down');
  1353. //scrolling up?
  1354. } else {
  1355. scrolling('up');
  1356. }
  1357. }
  1358. }
  1359. return false;
  1360. }
  1361. if (options.fitToSection) {
  1362. //stopping the auto scroll to adjust to a section
  1363. activeAnimation = false;
  1364. }
  1365. }
  1366. /**
  1367. * Slides a slider to the given direction.
  1368. * Optional `section` param.
  1369. */
  1370. function moveSlide(direction, section) {
  1371. var activeSection = section == null ? $(SECTION_ACTIVE_SEL)[0] : section;
  1372. var slides = $(SLIDES_WRAPPER_SEL, activeSection)[0];
  1373. // more than one slide needed and nothing should be sliding
  1374. if (slides == null || slideMoving || $(SLIDE_SEL, slides).length < 2) {
  1375. return;
  1376. }
  1377. var currentSlide = $(SLIDE_ACTIVE_SEL, slides)[0];
  1378. var destiny = null;
  1379. if (direction === 'left') {
  1380. destiny = prevUntil(currentSlide, SLIDE_SEL);
  1381. } else {
  1382. destiny = nextUntil(currentSlide, SLIDE_SEL);
  1383. }
  1384. //isn't there a next slide in the secuence?
  1385. if (destiny == null) {
  1386. //respect loopHorizontal settin
  1387. if (!options.loopHorizontal) return;
  1388. var slideSiblings = siblings(currentSlide);
  1389. if (direction === 'left') {
  1390. destiny = slideSiblings[slideSiblings.length - 1]; //last
  1391. } else {
  1392. destiny = slideSiblings[0]; //first
  1393. }
  1394. }
  1395. slideMoving = true && !FP.test.isTesting;
  1396. landscapeScroll(slides, destiny, direction);
  1397. }
  1398. /**
  1399. * Maintains the active slides in the viewport
  1400. * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
  1401. */
  1402. function keepSlidesPosition() {
  1403. var activeSlides = $(SLIDE_ACTIVE_SEL);
  1404. for (var i = 0; i < activeSlides.length; i++) {
  1405. silentLandscapeScroll(activeSlides[i], 'internal');
  1406. }
  1407. }
  1408. var previousDestTop = 0;
  1409. /**
  1410. * Returns the destination Y position based on the scrolling direction and
  1411. * the height of the section.
  1412. */
  1413. function getDestinationPosition(element) {
  1414. var elementHeight = element.offsetHeight;
  1415. var elementTop = element.offsetTop;
  1416. //top of the desination will be at the top of the viewport
  1417. var position = elementTop;
  1418. var isScrollingDown = elementTop > previousDestTop;
  1419. var sectionBottom = position - windowsHeight + elementHeight;
  1420. var bigSectionsDestination = options.bigSectionsDestination;
  1421. //is the destination element bigger than the viewport?
  1422. if (elementHeight > windowsHeight) {
  1423. //scrolling up?
  1424. if (!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom') {
  1425. position = sectionBottom;
  1426. }
  1427. }
  1428. //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section
  1429. else if (isScrollingDown || (isResizing && next(element) == null)) {
  1430. //The bottom of the destination will be at the bottom of the viewport
  1431. position = sectionBottom;
  1432. }
  1433. /*
  1434. Keeping record of the last scrolled position to determine the scrolling direction.
  1435. No conventional methods can be used as the scroll bar might not be present
  1436. AND the section might not be active if it is auto-height and didnt reach the middle
  1437. of the viewport.
  1438. */
  1439. previousDestTop = position;
  1440. return position;
  1441. }
  1442. /**
  1443. * Scrolls the site to the given element and scrolls to the slide if a callback is given.
  1444. */
  1445. function scrollPage(element, callback, isMovementUp) {
  1446. if (element == null) {
  1447. return;
  1448. } //there's no element to scroll, leaving the function
  1449. var dtop = getDestinationPosition(element);
  1450. var slideAnchorLink;
  1451. var slideIndex;
  1452. //local variables
  1453. var v = {
  1454. element: element,
  1455. callback: callback,
  1456. isMovementUp: isMovementUp,
  1457. dtop: dtop,
  1458. yMovement: getYmovement(element),
  1459. anchorLink: element.getAttribute('data-anchor'),
  1460. sectionIndex: index(element, SECTION_SEL),
  1461. activeSlide: $(SLIDE_ACTIVE_SEL, element)[0],
  1462. activeSection: $(SECTION_ACTIVE_SEL)[0],
  1463. leavingSection: index($(SECTION_ACTIVE_SEL), SECTION_SEL) + 1,
  1464. //caching the value of isResizing at the momment the function is called
  1465. //because it will be checked later inside a setTimeout and the value might change
  1466. localIsResizing: isResizing
  1467. };
  1468. //quiting when destination scroll is the same as the current one
  1469. if ((v.activeSection == element && !isResizing) || (options.scrollBar && getScrollTop() === v.dtop && !hasClass(element, AUTO_HEIGHT))) {
  1470. return;
  1471. }
  1472. if (v.activeSlide != null) {
  1473. slideAnchorLink = v.activeSlide.getAttribute('data-anchor');
  1474. slideIndex = index(v.activeSlide);
  1475. }
  1476. //callback (onLeave) if the site is not just resizing and readjusting the slides
  1477. if (!v.localIsResizing) {
  1478. var direction = v.yMovement;
  1479. //required for continousVertical
  1480. if (typeof isMovementUp !== 'undefined') {
  1481. direction = isMovementUp ? 'up' : 'down';
  1482. }
  1483. //for the callback
  1484. v.direction = direction;
  1485. if (isFunction(options.onLeave)) {
  1486. if (fireCallback('onLeave', v) === false) {
  1487. return;
  1488. }
  1489. }
  1490. }
  1491. // If continuousVertical && we need to wrap around
  1492. if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
  1493. ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
  1494. (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
  1495. v = createInfiniteSections(v);
  1496. }
  1497. //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
  1498. if (!v.localIsResizing) {
  1499. stopMedia(v.activeSection);
  1500. }
  1501. if (options.scrollOverflow) {
  1502. options.scrollOverflowHandler.beforeLeave();
  1503. }
  1504. addClass(element, ACTIVE);
  1505. removeClass(siblings(element), ACTIVE);
  1506. lazyLoad(element);
  1507. if (options.scrollOverflow) {
  1508. options.scrollOverflowHandler.onLeave();
  1509. }
  1510. //preventing from activating the MouseWheelHandler event
  1511. //more than once if the page is scrolling
  1512. canScroll = false || FP.test.isTesting;
  1513. setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
  1514. performMovement(v);
  1515. //flag to avoid callingn `scrollPage()` twice in case of using anchor links
  1516. lastScrolledDestiny = v.anchorLink;
  1517. //avoid firing it twice (as it does also on scroll)
  1518. activateMenuAndNav(v.anchorLink, v.sectionIndex);
  1519. }
  1520. /**
  1521. * Dispatch events & callbacks making sure it does it on the right format, depending on
  1522. * whether v2compatible is being used or not.
  1523. */
  1524. function fireCallback(eventName, v) {
  1525. var eventData = getEventData(eventName, v);
  1526. if (!options.v2compatible) {
  1527. trigger(container, eventName, eventData);
  1528. if (options[eventName].apply(eventData[Object.keys(eventData)[0]], toArray(eventData)) === false) {
  1529. return false;
  1530. }
  1531. } else {
  1532. if (options[eventName].apply(eventData[0], eventData.slice(1)) === false) {
  1533. return false;
  1534. }
  1535. }
  1536. return true;
  1537. }
  1538. /**
  1539. * Makes sure to only create a Panel object if the element exist
  1540. */
  1541. function nullOrSection(el) {
  1542. return el ? new Section(el) : null;
  1543. }
  1544. function nullOrSlide(el) {
  1545. return el ? new Slide(el) : null;
  1546. }
  1547. /**
  1548. * Gets the event's data for the given event on the right format. Depending on whether
  1549. * v2compatible is being used or not.
  1550. */
  1551. function getEventData(eventName, v) {
  1552. var paramsPerEvent;
  1553. if (!options.v2compatible) {
  1554. //using functions to run only the necessary bits within the object
  1555. paramsPerEvent = {
  1556. afterRender: function () {
  1557. return {
  1558. section: nullOrSection($(SECTION_ACTIVE_SEL)[0]),
  1559. slide: nullOrSlide($(SLIDE_ACTIVE_SEL, $(SECTION_ACTIVE_SEL)[0])[0])
  1560. };
  1561. },
  1562. onLeave: function () {
  1563. return {
  1564. origin: nullOrSection(v.activeSection),
  1565. destination: nullOrSection(v.element),
  1566. direction: v.direction
  1567. };
  1568. },
  1569. afterLoad: function () {
  1570. return paramsPerEvent.onLeave();
  1571. },
  1572. afterSlideLoad: function () {
  1573. return {
  1574. section: nullOrSection(v.section),
  1575. origin: nullOrSlide(v.prevSlide),
  1576. destination: nullOrSlide(v.destiny),
  1577. direction: v.direction
  1578. };
  1579. },
  1580. onSlideLeave: function () {
  1581. return paramsPerEvent.afterSlideLoad();
  1582. }
  1583. };
  1584. } else {
  1585. paramsPerEvent = {
  1586. afterRender: function () {
  1587. return [container];
  1588. },
  1589. onLeave: function () {
  1590. return [v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.direction];
  1591. },
  1592. afterLoad: function () {
  1593. return [v.element, v.anchorLink, (v.sectionIndex + 1)];
  1594. },
  1595. afterSlideLoad: function () {
  1596. return [v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex];
  1597. },
  1598. onSlideLeave: function () {
  1599. return [v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.direction, v.slideIndex];
  1600. },
  1601. };
  1602. }
  1603. return paramsPerEvent[eventName]();
  1604. }
  1605. /**
  1606. * Performs the vertical movement (by CSS3 or by jQuery)
  1607. */
  1608. function performMovement(v) {
  1609. var isFastSpeed = options.scrollingSpeed < 700;
  1610. var transitionLapse = isFastSpeed ? 700 : options.scrollingSpeed;
  1611. // using CSS3 translate functionality
  1612. if (options.css3 && options.autoScrolling && !options.scrollBar) {
  1613. // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
  1614. // that's why we round it to 0.
  1615. var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
  1616. transformContainer(translate3d, true);
  1617. //even when the scrollingSpeed is 0 there's a little delay, which might cause the
  1618. //scrollingSpeed to change in case of using silentMoveTo();
  1619. if (options.scrollingSpeed) {
  1620. clearTimeout(afterSectionLoadsId);
  1621. afterSectionLoadsId = setTimeout(function () {
  1622. afterSectionLoads(v);
  1623. //disabling canScroll when using fastSpeed
  1624. canScroll = !isFastSpeed;
  1625. }, options.scrollingSpeed);
  1626. } else {
  1627. afterSectionLoads(v);
  1628. }
  1629. }
  1630. // using JS to animate
  1631. else {
  1632. var scrollSettings = getScrollSettings(v.dtop);
  1633. FP.test.top = -v.dtop + 'px';
  1634. css($htmlBody, {
  1635. 'scroll-behavior': 'unset'
  1636. });
  1637. scrollTo(scrollSettings.element, scrollSettings.options, options.scrollingSpeed, function () {
  1638. if (options.scrollBar) {
  1639. /* Hack!
  1640. The timeout prevents setting the most dominant section in the viewport as "active" when the user
  1641. scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
  1642. When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
  1643. */
  1644. setTimeout(function () {
  1645. afterSectionLoads(v);
  1646. }, 30);
  1647. } else {
  1648. afterSectionLoads(v);
  1649. //disabling canScroll when using fastSpeed
  1650. canScroll = !isFastSpeed;
  1651. }
  1652. });
  1653. }
  1654. // enabling canScroll after the minimum transition laps
  1655. if (isFastSpeed) {
  1656. clearTimeout(g_transitionLapseId);
  1657. g_transitionLapseId = setTimeout(function () {
  1658. canScroll = true;
  1659. }, transitionLapse);
  1660. }
  1661. }
  1662. /**
  1663. * Gets the scrolling settings depending on the plugin autoScrolling option
  1664. */
  1665. function getScrollSettings(top) {
  1666. var scroll = {};
  1667. //top property animation
  1668. if (options.autoScrolling && !options.scrollBar) {
  1669. scroll.options = -top;
  1670. scroll.element = $(WRAPPER_SEL)[0];
  1671. }
  1672. //window real scrolling
  1673. else {
  1674. scroll.options = top;
  1675. scroll.element = window;
  1676. }
  1677. return scroll;
  1678. }
  1679. /**
  1680. * Adds sections before or after the current one to create the infinite effect.
  1681. */
  1682. function createInfiniteSections(v) {
  1683. // Scrolling down
  1684. if (!v.isMovementUp) {
  1685. // Move all previous sections to after the active section
  1686. after($(SECTION_ACTIVE_SEL)[0], prevAll(v.activeSection, SECTION_SEL).reverse());
  1687. } else { // Scrolling up
  1688. // Move all next sections to before the active section
  1689. before($(SECTION_ACTIVE_SEL)[0], nextAll(v.activeSection, SECTION_SEL));
  1690. }
  1691. // Maintain the displayed position (now that we changed the element order)
  1692. silentScroll($(SECTION_ACTIVE_SEL)[0].offsetTop);
  1693. // Maintain the active slides visible in the viewport
  1694. keepSlidesPosition();
  1695. // save for later the elements that still need to be reordered
  1696. v.wrapAroundElements = v.activeSection;
  1697. // Recalculate animation variables
  1698. v.dtop = v.element.offsetTop;
  1699. v.yMovement = getYmovement(v.element);
  1700. return v;
  1701. }
  1702. /**
  1703. * Fix section order after continuousVertical changes have been animated
  1704. */
  1705. function continuousVerticalFixSectionOrder(v) {
  1706. // If continuousVertical is in effect (and autoScrolling would also be in effect then),
  1707. // finish moving the elements around so the direct navigation will function more simply
  1708. if (v.wrapAroundElements == null) {
  1709. return;
  1710. }
  1711. if (v.isMovementUp) {
  1712. before($(SECTION_SEL)[0], v.wrapAroundElements);
  1713. } else {
  1714. after($(SECTION_SEL)[$(SECTION_SEL).length - 1], v.wrapAroundElements);
  1715. }
  1716. silentScroll($(SECTION_ACTIVE_SEL)[0].offsetTop);
  1717. // Maintain the active slides visible in the viewport
  1718. keepSlidesPosition();
  1719. }
  1720. /**
  1721. * Actions to do once the section is loaded.
  1722. */
  1723. function afterSectionLoads(v) {
  1724. continuousVerticalFixSectionOrder(v);
  1725. //callback (afterLoad) if the site is not just resizing and readjusting the slides
  1726. if (isFunction(options.afterLoad) && !v.localIsResizing) {
  1727. fireCallback('afterLoad', v);
  1728. }
  1729. if (options.scrollOverflow) {
  1730. options.scrollOverflowHandler.afterLoad();
  1731. }
  1732. if (!v.localIsResizing) {
  1733. playMedia(v.element);
  1734. }
  1735. addClass(v.element, COMPLETELY);
  1736. removeClass(siblings(v.element), COMPLETELY);
  1737. lazyLoadOthers();
  1738. canScroll = true;
  1739. if (isFunction(v.callback)) {
  1740. v.callback();
  1741. }
  1742. }
  1743. /**
  1744. * Sets the value for the given attribute from the `data-` attribute with the same suffix
  1745. * ie: data-srcset ==> srcset | data-src ==> src
  1746. */
  1747. function setSrc(element, attribute) {
  1748. element.setAttribute(attribute, element.getAttribute('data-' + attribute));
  1749. element.removeAttribute('data-' + attribute);
  1750. }
  1751. /**
  1752. * Makes sure lazyload is done for other sections in the viewport that are not the
  1753. * active one.
  1754. */
  1755. function lazyLoadOthers() {
  1756. var hasAutoHeightSections = $(AUTO_HEIGHT_SEL)[0] || isResponsiveMode() && $(AUTO_HEIGHT_RESPONSIVE_SEL)[0];
  1757. //quitting when it doesn't apply
  1758. if (!options.lazyLoading || !hasAutoHeightSections) {
  1759. return;
  1760. }
  1761. //making sure to lazy load auto-height sections that are in the viewport
  1762. $(SECTION_SEL + ':not(' + ACTIVE_SEL + ')').forEach(function (section) {
  1763. if (isSectionInViewport(section)) {
  1764. lazyLoad(section);
  1765. }
  1766. });
  1767. }
  1768. /**
  1769. * Lazy loads image, video and audio elements.
  1770. */
  1771. function lazyLoad(destiny) {
  1772. if (!options.lazyLoading) {
  1773. return;
  1774. }
  1775. var panel = getSlideOrSection(destiny);
  1776. $('img[data-src], img[data-srcset], source[data-src], source[data-srcset], video[data-src], audio[data-src], iframe[data-src]', panel).forEach(function (element) {
  1777. ['src', 'srcset'].forEach(function (type) {
  1778. var attribute = element.getAttribute('data-' + type);
  1779. if (attribute != null && attribute) {
  1780. setSrc(element, type);
  1781. element.addEventListener('load', function () {
  1782. onMediaLoad(destiny);
  1783. });
  1784. }
  1785. });
  1786. if (matches(element, 'source')) {
  1787. var elementToPlay = closest(element, 'video, audio');
  1788. if (elementToPlay) {
  1789. elementToPlay.load();
  1790. elementToPlay.onloadeddata = function () {
  1791. onMediaLoad(destiny);
  1792. };
  1793. }
  1794. }
  1795. });
  1796. }
  1797. /**
  1798. * Callback firing when a lazy load media element has loaded.
  1799. * Making sure it only fires one per section in normal conditions (if load time is not huge)
  1800. */
  1801. function onMediaLoad(section) {
  1802. if (options.scrollOverflow) {
  1803. clearTimeout(g_mediaLoadedId);
  1804. g_mediaLoadedId = setTimeout(function () {
  1805. if (!hasClass($body, RESPONSIVE)) {
  1806. scrollBarHandler.createScrollBar(section);
  1807. }
  1808. }, 200);
  1809. }
  1810. }
  1811. /**
  1812. * Plays video and audio elements.
  1813. */
  1814. function playMedia(destiny) {
  1815. var panel = getSlideOrSection(destiny);
  1816. //playing HTML5 media elements
  1817. $('video, audio', panel).forEach(function (element) {
  1818. if (element.hasAttribute('data-autoplay') && typeof element.play === 'function') {
  1819. element.play();
  1820. }
  1821. });
  1822. //youtube videos
  1823. $('iframe[src*="youtube.com/embed/"]', panel).forEach(function (element) {
  1824. if (element.hasAttribute('data-autoplay')) {
  1825. playYoutube(element);
  1826. }
  1827. //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
  1828. element.onload = function () {
  1829. if (element.hasAttribute('data-autoplay')) {
  1830. playYoutube(element);
  1831. }
  1832. };
  1833. });
  1834. }
  1835. /**
  1836. * Plays a youtube video
  1837. */
  1838. function playYoutube(element) {
  1839. element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
  1840. }
  1841. /**
  1842. * Stops video and audio elements.
  1843. */
  1844. function stopMedia(destiny) {
  1845. var panel = getSlideOrSection(destiny);
  1846. //stopping HTML5 media elements
  1847. $('video, audio', panel).forEach(function (element) {
  1848. if (!element.hasAttribute('data-keepplaying') && typeof element.pause === 'function') {
  1849. element.pause();
  1850. }
  1851. });
  1852. //youtube videos
  1853. $('iframe[src*="youtube.com/embed/"]', panel).forEach(function (element) {
  1854. if (/youtube\.com\/embed\//.test(element.getAttribute('src')) && !element.hasAttribute('data-keepplaying')) {
  1855. element.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
  1856. }
  1857. });
  1858. }
  1859. /**
  1860. * Gets the active slide (or section) for the given section
  1861. */
  1862. function getSlideOrSection(destiny) {
  1863. var slide = $(SLIDE_ACTIVE_SEL, destiny);
  1864. if (slide.length) {
  1865. destiny = slide[0];
  1866. }
  1867. return destiny;
  1868. }
  1869. /**
  1870. * Scrolls to the anchor in the URL when loading the site
  1871. */
  1872. function scrollToAnchor() {
  1873. var anchors = getAnchorsURL();
  1874. var sectionAnchor = anchors.section;
  1875. var slideAnchor = anchors.slide;
  1876. if (sectionAnchor) { //if theres any #
  1877. if (options.animateAnchor) {
  1878. scrollPageAndSlide(sectionAnchor, slideAnchor);
  1879. } else {
  1880. silentMoveTo(sectionAnchor, slideAnchor);
  1881. }
  1882. }
  1883. }
  1884. /**
  1885. * Detecting any change on the URL to scroll to the given anchor link
  1886. * (a way to detect back history button as we play with the hashes on the URL)
  1887. */
  1888. function hashChangeHandler() {
  1889. if (!isScrolling && !options.lockAnchors) {
  1890. var anchors = getAnchorsURL();
  1891. var sectionAnchor = anchors.section;
  1892. var slideAnchor = anchors.slide;
  1893. //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
  1894. var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined');
  1895. var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
  1896. if (sectionAnchor && sectionAnchor.length) {
  1897. /*in order to call scrollpage() only once for each destination at a time
  1898. It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
  1899. event is fired on every scroll too.*/
  1900. if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove ||
  1901. isFirstScrollMove ||
  1902. (!slideMoving && lastScrolledSlide != slideAnchor)) {
  1903. scrollPageAndSlide(sectionAnchor, slideAnchor);
  1904. }
  1905. }
  1906. }
  1907. }
  1908. //gets the URL anchors (section and slide)
  1909. function getAnchorsURL() {
  1910. var section;
  1911. var slide;
  1912. var hash = window.location.hash;
  1913. if (hash.length) {
  1914. //getting the anchor link in the URL and deleting the `#`
  1915. var anchorsParts = hash.replace('#', '').split('/');
  1916. //using / for visual reasons and not as a section/slide separator #2803
  1917. var isFunkyAnchor = hash.indexOf('#/') > -1;
  1918. section = isFunkyAnchor ? '/' + anchorsParts[1] : decodeURIComponent(anchorsParts[0]);
  1919. var slideAnchor = isFunkyAnchor ? anchorsParts[2] : anchorsParts[1];
  1920. if (slideAnchor && slideAnchor.length) {
  1921. slide = decodeURIComponent(slideAnchor);
  1922. }
  1923. }
  1924. return {
  1925. section: section,
  1926. slide: slide
  1927. };
  1928. }
  1929. //Sliding with arrow keys, both, vertical and horizontal
  1930. function keydownHandler(e) {
  1931. clearTimeout(keydownId);
  1932. var activeElement = document.activeElement;
  1933. var keyCode = e.keyCode;
  1934. //tab?
  1935. if (keyCode === 9) {
  1936. onTab(e);
  1937. } else if (!matches(activeElement, 'textarea') && !matches(activeElement, 'input') && !matches(activeElement, 'select') &&
  1938. activeElement.getAttribute('contentEditable') !== "true" && activeElement.getAttribute('contentEditable') !== '' &&
  1939. options.keyboardScrolling && options.autoScrolling) {
  1940. //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
  1941. var keyControls = [40, 38, 32, 33, 34];
  1942. if (keyControls.indexOf(keyCode) > -1) {
  1943. preventDefault(e);
  1944. }
  1945. controlPressed = e.ctrlKey;
  1946. keydownId = setTimeout(function () {
  1947. onkeydown(e);
  1948. }, 150);
  1949. }
  1950. }
  1951. function tooltipTextHandler() {
  1952. /*jshint validthis:true */
  1953. trigger(prev(this), 'click');
  1954. }
  1955. //to prevent scrolling while zooming
  1956. function keyUpHandler(e) {
  1957. if (isWindowFocused) { //the keyup gets fired on new tab ctrl + t in Firefox
  1958. controlPressed = e.ctrlKey;
  1959. }
  1960. }
  1961. //binding the mousemove when the mouse's middle button is released
  1962. function mouseDownHandler(e) {
  1963. //middle button
  1964. if (e.which == 2) {
  1965. oldPageY = e.pageY;
  1966. container.addEventListener('mousemove', mouseMoveHandler);
  1967. }
  1968. }
  1969. //unbinding the mousemove when the mouse's middle button is released
  1970. function mouseUpHandler(e) {
  1971. //middle button
  1972. if (e.which == 2) {
  1973. container.removeEventListener('mousemove', mouseMoveHandler);
  1974. }
  1975. }
  1976. /**
  1977. * Makes sure the tab key will only focus elements within the current section/slide
  1978. * preventing this way from breaking the page.
  1979. * Based on "Modals and keyboard traps"
  1980. * from https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex
  1981. */
  1982. function onTab(e) {
  1983. var isShiftPressed = e.shiftKey;
  1984. var activeElement = document.activeElement;
  1985. var focusableElements = getFocusables(getSlideOrSection($(SECTION_ACTIVE_SEL)[0]));
  1986. function preventAndFocusFirst(e) {
  1987. preventDefault(e);
  1988. return focusableElements[0] ? focusableElements[0].focus() : null;
  1989. }
  1990. //outside any section or slide? Let's not hijack the tab!
  1991. if (isFocusOutside(e)) {
  1992. return;
  1993. }
  1994. //is there an element with focus?
  1995. if (activeElement) {
  1996. if (closest(activeElement, SECTION_ACTIVE_SEL + ',' + SECTION_ACTIVE_SEL + ' ' + SLIDE_ACTIVE_SEL) == null) {
  1997. activeElement = preventAndFocusFirst(e);
  1998. }
  1999. }
  2000. //no element if focused? Let's focus the first one of the section/slide
  2001. else {
  2002. preventAndFocusFirst(e);
  2003. }
  2004. //when reached the first or last focusable element of the section/slide
  2005. //we prevent the tab action to keep it in the last focusable element
  2006. if (!isShiftPressed && activeElement == focusableElements[focusableElements.length - 1] ||
  2007. isShiftPressed && activeElement == focusableElements[0]
  2008. ) {
  2009. preventDefault(e);
  2010. }
  2011. }
  2012. /**
  2013. * Gets all the focusable elements inside the passed element.
  2014. */
  2015. function getFocusables(el) {
  2016. return [].slice.call($(focusableElementsString, el)).filter(function (item) {
  2017. return item.getAttribute('tabindex') !== '-1'
  2018. //are also not hidden elements (or with hidden parents)
  2019. &&
  2020. item.offsetParent !== null;
  2021. });
  2022. }
  2023. /**
  2024. * Determines whether the focus is outside fullpage.js sections/slides or not.
  2025. */
  2026. function isFocusOutside(e) {
  2027. var allFocusables = getFocusables(document);
  2028. var currentFocusIndex = allFocusables.indexOf(document.activeElement);
  2029. var focusDestinationIndex = e.shiftKey ? currentFocusIndex - 1 : currentFocusIndex + 1;
  2030. var focusDestination = allFocusables[focusDestinationIndex];
  2031. var destinationItemSlide = nullOrSlide(closest(focusDestination, SLIDE_SEL));
  2032. var destinationItemSection = nullOrSection(closest(focusDestination, SECTION_SEL));
  2033. return !destinationItemSlide && !destinationItemSection;
  2034. }
  2035. //Scrolling horizontally when clicking on the slider controls.
  2036. function slideArrowHandler() {
  2037. /*jshint validthis:true */
  2038. var section = closest(this, SECTION_SEL);
  2039. /*jshint validthis:true */
  2040. if (hasClass(this, SLIDES_PREV)) {
  2041. if (isScrollAllowed.m.left) {
  2042. moveSlideLeft(section);
  2043. }
  2044. } else {
  2045. if (isScrollAllowed.m.right) {
  2046. moveSlideRight(section);
  2047. }
  2048. }
  2049. }
  2050. // changing isWindowFocused to true on focus event
  2051. function focusHandler() {
  2052. isWindowFocused = true;
  2053. }
  2054. //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
  2055. function blurHandler() {
  2056. isWindowFocused = false;
  2057. controlPressed = false;
  2058. }
  2059. //Scrolls to the section when clicking the navigation bullet
  2060. function sectionBulletHandler(e) {
  2061. preventDefault(e);
  2062. /*jshint validthis:true */
  2063. var indexBullet = index(closest(this, SECTION_NAV_SEL + ' li'));
  2064. scrollPage($(SECTION_SEL)[indexBullet]);
  2065. }
  2066. //Scrolls the slider to the given slide destination for the given section
  2067. function slideBulletHandler(e) {
  2068. preventDefault(e);
  2069. /*jshint validthis:true */
  2070. var slides = $(SLIDES_WRAPPER_SEL, closest(this, SECTION_SEL))[0];
  2071. var destiny = $(SLIDE_SEL, slides)[index(closest(this, 'li'))];
  2072. landscapeScroll(slides, destiny);
  2073. }
  2074. //Menu item handler when not using anchors or using lockAnchors:true
  2075. function menuItemsHandler(e) {
  2076. if ($(options.menu)[0] && (options.lockAnchors || !options.anchors.length)) {
  2077. preventDefault(e);
  2078. /*jshint validthis:true */
  2079. moveTo(this.getAttribute('data-menuanchor'));
  2080. }
  2081. }
  2082. /**
  2083. * Keydown event
  2084. */
  2085. function onkeydown(e) {
  2086. var shiftPressed = e.shiftKey;
  2087. var activeElement = document.activeElement;
  2088. var isMediaFocused = matches(activeElement, 'video') || matches(activeElement, 'audio');
  2089. //do nothing if we can not scroll or we are not using horizotnal key arrows.
  2090. if (!canScroll && [37, 39].indexOf(e.keyCode) < 0) {
  2091. return;
  2092. }
  2093. switch (e.keyCode) {
  2094. //up
  2095. case 38:
  2096. case 33:
  2097. if (isScrollAllowed.k.up) {
  2098. moveSectionUp();
  2099. }
  2100. break;
  2101. //down
  2102. case 32: //spacebar
  2103. if (shiftPressed && isScrollAllowed.k.up && !isMediaFocused) {
  2104. moveSectionUp();
  2105. break;
  2106. }
  2107. /* falls through */
  2108. case 40:
  2109. case 34:
  2110. if (isScrollAllowed.k.down) {
  2111. // space bar?
  2112. if (e.keyCode !== 32 || !isMediaFocused) {
  2113. moveSectionDown();
  2114. }
  2115. }
  2116. break;
  2117. //Home
  2118. case 36:
  2119. if (isScrollAllowed.k.up) {
  2120. moveTo(1);
  2121. }
  2122. break;
  2123. //End
  2124. case 35:
  2125. if (isScrollAllowed.k.down) {
  2126. moveTo($(SECTION_SEL).length);
  2127. }
  2128. break;
  2129. //left
  2130. case 37:
  2131. if (isScrollAllowed.k.left) {
  2132. moveSlideLeft();
  2133. }
  2134. break;
  2135. //right
  2136. case 39:
  2137. if (isScrollAllowed.k.right) {
  2138. moveSlideRight();
  2139. }
  2140. break;
  2141. default:
  2142. return; // exit this handler for other keys
  2143. }
  2144. }
  2145. /**
  2146. * Detecting the direction of the mouse movement.
  2147. * Used only for the middle button of the mouse.
  2148. */
  2149. var oldPageY = 0;
  2150. function mouseMoveHandler(e) {
  2151. if (!options.autoScrolling) {
  2152. return;
  2153. }
  2154. if (canScroll) {
  2155. // moving up
  2156. if (e.pageY < oldPageY && isScrollAllowed.m.up) {
  2157. moveSectionUp();
  2158. }
  2159. // moving down
  2160. else if (e.pageY > oldPageY && isScrollAllowed.m.down) {
  2161. moveSectionDown();
  2162. }
  2163. }
  2164. oldPageY = e.pageY;
  2165. }
  2166. /**
  2167. * Scrolls horizontal sliders.
  2168. */
  2169. function landscapeScroll(slides, destiny, direction) {
  2170. var section = closest(slides, SECTION_SEL);
  2171. var v = {
  2172. slides: slides,
  2173. destiny: destiny,
  2174. direction: direction,
  2175. destinyPos: {
  2176. left: destiny.offsetLeft
  2177. },
  2178. slideIndex: index(destiny),
  2179. section: section,
  2180. sectionIndex: index(section, SECTION_SEL),
  2181. anchorLink: section.getAttribute('data-anchor'),
  2182. slidesNav: $(SLIDES_NAV_SEL, section)[0],
  2183. slideAnchor: getAnchor(destiny),
  2184. prevSlide: $(SLIDE_ACTIVE_SEL, section)[0],
  2185. prevSlideIndex: index($(SLIDE_ACTIVE_SEL, section)[0]),
  2186. //caching the value of isResizing at the momment the function is called
  2187. //because it will be checked later inside a setTimeout and the value might change
  2188. localIsResizing: isResizing
  2189. };
  2190. v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
  2191. v.direction = v.direction ? v.direction : v.xMovement;
  2192. //important!! Only do it when not resizing
  2193. if (!v.localIsResizing) {
  2194. //preventing from scrolling to the next/prev section when using scrollHorizontally
  2195. canScroll = false;
  2196. }
  2197. if (options.onSlideLeave) {
  2198. //if the site is not just resizing and readjusting the slides
  2199. if (!v.localIsResizing && v.xMovement !== 'none') {
  2200. if (isFunction(options.onSlideLeave)) {
  2201. if (fireCallback('onSlideLeave', v) === false) {
  2202. slideMoving = false;
  2203. return;
  2204. }
  2205. }
  2206. }
  2207. }
  2208. addClass(destiny, ACTIVE);
  2209. removeClass(siblings(destiny), ACTIVE);
  2210. if (!v.localIsResizing) {
  2211. stopMedia(v.prevSlide);
  2212. lazyLoad(destiny);
  2213. }
  2214. if (!options.loopHorizontal && options.controlArrows) {
  2215. //hidding it for the fist slide, showing for the rest
  2216. toggle($(SLIDES_ARROW_PREV_SEL, section), v.slideIndex !== 0);
  2217. //hidding it for the last slide, showing for the rest
  2218. toggle($(SLIDES_ARROW_NEXT_SEL, section), next(destiny) != null);
  2219. }
  2220. //only changing the URL if the slides are in the current section (not for resize re-adjusting)
  2221. if (hasClass(section, ACTIVE) && !v.localIsResizing) {
  2222. setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
  2223. }
  2224. performHorizontalMove(slides, v, true);
  2225. }
  2226. function afterSlideLoads(v) {
  2227. activeSlidesNavigation(v.slidesNav, v.slideIndex);
  2228. //if the site is not just resizing and readjusting the slides
  2229. if (!v.localIsResizing) {
  2230. if (isFunction(options.afterSlideLoad)) {
  2231. fireCallback('afterSlideLoad', v);
  2232. }
  2233. //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
  2234. //and to prevent double scroll right after a windows resize
  2235. canScroll = true;
  2236. playMedia(v.destiny);
  2237. }
  2238. //letting them slide again
  2239. slideMoving = false;
  2240. }
  2241. /**
  2242. * Performs the horizontal movement. (CSS3 or jQuery)
  2243. *
  2244. * @param fireCallback {Bool} - determines whether or not to fire the callback
  2245. */
  2246. function performHorizontalMove(slides, v, fireCallback) {
  2247. var destinyPos = v.destinyPos;
  2248. if (options.css3) {
  2249. var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
  2250. FP.test.translate3dH[v.sectionIndex] = translate3d;
  2251. css(addAnimation($(SLIDES_CONTAINER_SEL, slides)), getTransforms(translate3d));
  2252. afterSlideLoadsId = setTimeout(function () {
  2253. if (fireCallback) {
  2254. afterSlideLoads(v);
  2255. }
  2256. }, options.scrollingSpeed);
  2257. } else {
  2258. FP.test.left[v.sectionIndex] = Math.round(destinyPos.left);
  2259. scrollTo(slides, Math.round(destinyPos.left), options.scrollingSpeed, function () {
  2260. if (fireCallback) {
  2261. afterSlideLoads(v);
  2262. }
  2263. });
  2264. }
  2265. }
  2266. /**
  2267. * Sets the state for the horizontal bullet navigations.
  2268. */
  2269. function activeSlidesNavigation(slidesNav, slideIndex) {
  2270. if (options.slidesNavigation && slidesNav != null) {
  2271. removeClass($(ACTIVE_SEL, slidesNav), ACTIVE);
  2272. addClass($('a', $('li', slidesNav)[slideIndex]), ACTIVE);
  2273. }
  2274. }
  2275. var previousHeight = windowsHeight;
  2276. /*
  2277. * Resize event handler.
  2278. */
  2279. function resizeHandler() {
  2280. clearTimeout(resizeId);
  2281. //in order to call the functions only when the resize is finished
  2282. //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
  2283. resizeId = setTimeout(function () {
  2284. //issue #3336
  2285. //(some apps or browsers, like Chrome/Firefox for Mobile take time to report the real height)
  2286. //so we check it 3 times with intervals in that case
  2287. for (var i = 0; i < 4; i++) {
  2288. resizeHandlerId = setTimeout(resizeActions, 200 * i);
  2289. }
  2290. }, 200);
  2291. }
  2292. /**
  2293. * When resizing the site, we adjust the heights of the sections, slimScroll...
  2294. */
  2295. function resizeActions() {
  2296. isResizing = true;
  2297. //checking if it needs to get responsive
  2298. responsive();
  2299. // rebuild immediately on touch devices
  2300. if (isTouchDevice) {
  2301. var activeElement = document.activeElement;
  2302. //if the keyboard is NOT visible
  2303. if (!matches(activeElement, 'textarea') && !matches(activeElement, 'input') && !matches(activeElement, 'select')) {
  2304. var currentHeight = getWindowHeight();
  2305. //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)
  2306. if (Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100)) {
  2307. reBuild(true);
  2308. previousHeight = currentHeight;
  2309. }
  2310. }
  2311. } else {
  2312. adjustToNewViewport();
  2313. }
  2314. isResizing = false;
  2315. }
  2316. /**
  2317. * Checks if the site needs to get responsive and disables autoScrolling if so.
  2318. * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
  2319. */
  2320. function responsive() {
  2321. var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
  2322. var heightLimit = options.responsiveHeight;
  2323. //only calculating what we need. Remember its called on the resize event.
  2324. var isBreakingPointWidth = widthLimit && window.innerWidth < widthLimit;
  2325. var isBreakingPointHeight = heightLimit && window.innerHeight < heightLimit;
  2326. if (widthLimit && heightLimit) {
  2327. setResponsive(isBreakingPointWidth || isBreakingPointHeight);
  2328. } else if (widthLimit) {
  2329. setResponsive(isBreakingPointWidth);
  2330. } else if (heightLimit) {
  2331. setResponsive(isBreakingPointHeight);
  2332. }
  2333. }
  2334. /**
  2335. * Adds transition animations for the given element
  2336. */
  2337. function addAnimation(element) {
  2338. var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
  2339. removeClass(element, NO_TRANSITION);
  2340. return css(element, {
  2341. '-webkit-transition': transition,
  2342. 'transition': transition
  2343. });
  2344. }
  2345. /**
  2346. * Remove transition animations for the given element
  2347. */
  2348. function removeAnimation(element) {
  2349. return addClass(element, NO_TRANSITION);
  2350. }
  2351. /**
  2352. * Activating the vertical navigation bullets according to the given slide name.
  2353. */
  2354. function activateNavDots(name, sectionIndex) {
  2355. if (options.navigation && $(SECTION_NAV_SEL)[0] != null) {
  2356. removeClass($(ACTIVE_SEL, $(SECTION_NAV_SEL)[0]), ACTIVE);
  2357. if (name) {
  2358. addClass($('a[href="#' + name + '"]', $(SECTION_NAV_SEL)[0]), ACTIVE);
  2359. } else {
  2360. addClass($('a', $('li', $(SECTION_NAV_SEL)[0])[sectionIndex]), ACTIVE);
  2361. }
  2362. }
  2363. }
  2364. /**
  2365. * Activating the website main menu elements according to the given slide name.
  2366. */
  2367. function activateMenuElement(name) {
  2368. $(options.menu).forEach(function (menu) {
  2369. if (options.menu && menu != null) {
  2370. removeClass($(ACTIVE_SEL, menu), ACTIVE);
  2371. addClass($('[data-menuanchor="' + name + '"]', menu), ACTIVE);
  2372. }
  2373. });
  2374. }
  2375. /**
  2376. * Sets to active the current menu and vertical nav items.
  2377. */
  2378. function activateMenuAndNav(anchor, index) {
  2379. activateMenuElement(anchor);
  2380. activateNavDots(anchor, index);
  2381. }
  2382. /**
  2383. * Retuns `up` or `down` depending on the scrolling movement to reach its destination
  2384. * from the current section.
  2385. */
  2386. function getYmovement(destiny) {
  2387. var fromIndex = index($(SECTION_ACTIVE_SEL)[0], SECTION_SEL);
  2388. var toIndex = index(destiny, SECTION_SEL);
  2389. if (fromIndex == toIndex) {
  2390. return 'none';
  2391. }
  2392. if (fromIndex > toIndex) {
  2393. return 'up';
  2394. }
  2395. return 'down';
  2396. }
  2397. /**
  2398. * Retuns `right` or `left` depending on the scrolling movement to reach its destination
  2399. * from the current slide.
  2400. */
  2401. function getXmovement(fromIndex, toIndex) {
  2402. if (fromIndex == toIndex) {
  2403. return 'none';
  2404. }
  2405. if (fromIndex > toIndex) {
  2406. return 'left';
  2407. }
  2408. return 'right';
  2409. }
  2410. function addTableClass(element) {
  2411. //In case we are styling for the 2nd time as in with reponsiveSlides
  2412. if (!hasClass(element, TABLE)) {
  2413. var wrapper = document.createElement('div');
  2414. wrapper.className = TABLE_CELL;
  2415. wrapper.style.height = getTableHeight(element) + 'px';
  2416. addClass(element, TABLE);
  2417. wrapInner(element, wrapper);
  2418. }
  2419. }
  2420. function getTableHeight(element) {
  2421. var sectionHeight = windowsHeight;
  2422. if (options.paddingTop || options.paddingBottom) {
  2423. var section = element;
  2424. if (!hasClass(section, SECTION)) {
  2425. section = closest(element, SECTION_SEL);
  2426. }
  2427. var paddings = parseInt(getComputedStyle(section)['padding-top']) + parseInt(getComputedStyle(section)['padding-bottom']);
  2428. sectionHeight = (windowsHeight - paddings);
  2429. }
  2430. return sectionHeight;
  2431. }
  2432. /**
  2433. * Adds a css3 transform property to the container class with or without animation depending on the animated param.
  2434. */
  2435. function transformContainer(translate3d, animated) {
  2436. if (animated) {
  2437. addAnimation(container);
  2438. } else {
  2439. removeAnimation(container);
  2440. }
  2441. css(container, getTransforms(translate3d));
  2442. FP.test.translate3d = translate3d;
  2443. //syncronously removing the class after the animation has been applied.
  2444. setTimeout(function () {
  2445. removeClass(container, NO_TRANSITION);
  2446. }, 10);
  2447. }
  2448. /**
  2449. * Gets a section by its anchor / index
  2450. */
  2451. function getSectionByAnchor(sectionAnchor) {
  2452. var section = $(SECTION_SEL + '[data-anchor="' + sectionAnchor + '"]', container)[0];
  2453. if (!section) {
  2454. var sectionIndex = typeof sectionAnchor !== 'undefined' ? sectionAnchor - 1 : 0;
  2455. section = $(SECTION_SEL)[sectionIndex];
  2456. }
  2457. return section;
  2458. }
  2459. /**
  2460. * Gets a slide inside a given section by its anchor / index
  2461. */
  2462. function getSlideByAnchor(slideAnchor, section) {
  2463. var slide = $(SLIDE_SEL + '[data-anchor="' + slideAnchor + '"]', section)[0];
  2464. if (slide == null) {
  2465. slideAnchor = typeof slideAnchor !== 'undefined' ? slideAnchor : 0;
  2466. slide = $(SLIDE_SEL, section)[slideAnchor];
  2467. }
  2468. return slide;
  2469. }
  2470. /**
  2471. * Scrolls to the given section and slide anchors
  2472. */
  2473. function scrollPageAndSlide(sectionAnchor, slideAnchor) {
  2474. var section = getSectionByAnchor(sectionAnchor);
  2475. //do nothing if there's no section with the given anchor name
  2476. if (section == null) return;
  2477. var slide = getSlideByAnchor(slideAnchor, section);
  2478. //we need to scroll to the section and then to the slide
  2479. if (getAnchor(section) !== lastScrolledDestiny && !hasClass(section, ACTIVE)) {
  2480. scrollPage(section, function () {
  2481. scrollSlider(slide);
  2482. });
  2483. }
  2484. //if we were already in the section
  2485. else {
  2486. scrollSlider(slide);
  2487. }
  2488. }
  2489. /**
  2490. * Scrolls the slider to the given slide destination for the given section
  2491. */
  2492. function scrollSlider(slide) {
  2493. if (slide != null) {
  2494. landscapeScroll(closest(slide, SLIDES_WRAPPER_SEL), slide);
  2495. }
  2496. }
  2497. /**
  2498. * Creates a landscape navigation bar with dots for horizontal sliders.
  2499. */
  2500. function addSlidesNavigation(section, numSlides) {
  2501. appendTo(createElementFromHTML('<div class="' + SLIDES_NAV + '"><ul></ul></div>'), section);
  2502. var nav = $(SLIDES_NAV_SEL, section)[0];
  2503. //top or bottom
  2504. addClass(nav, 'fp-' + options.slidesNavPosition);
  2505. for (var i = 0; i < numSlides; i++) {
  2506. var slide = $(SLIDE_SEL, section)[i];
  2507. appendTo(createElementFromHTML('<li><a href="#"><span class="fp-sr-only">' + getBulletLinkName(i, 'Slide', slide) + '</span><span></span></a></li>'), $('ul', nav)[0]);
  2508. }
  2509. //centering it
  2510. css(nav, {
  2511. 'margin-left': '-' + (nav.innerWidth / 2) + 'px'
  2512. });
  2513. addClass($('a', $('li', nav)[0]), ACTIVE);
  2514. }
  2515. /**
  2516. * Sets the state of the website depending on the active section/slide.
  2517. * It changes the URL hash when needed and updates the body class.
  2518. */
  2519. function setState(slideIndex, slideAnchor, anchorLink, sectionIndex) {
  2520. var sectionHash = '';
  2521. if (options.anchors.length && !options.lockAnchors) {
  2522. //isn't it the first slide?
  2523. if (slideIndex) {
  2524. if (anchorLink != null) {
  2525. sectionHash = anchorLink;
  2526. }
  2527. //slide without anchor link? We take the index instead.
  2528. if (slideAnchor == null) {
  2529. slideAnchor = slideIndex;
  2530. }
  2531. lastScrolledSlide = slideAnchor;
  2532. setUrlHash(sectionHash + '/' + slideAnchor);
  2533. //first slide won't have slide anchor, just the section one
  2534. } else if (slideIndex != null) {
  2535. lastScrolledSlide = slideAnchor;
  2536. setUrlHash(anchorLink);
  2537. }
  2538. //section without slides
  2539. else {
  2540. setUrlHash(anchorLink);
  2541. }
  2542. }
  2543. setBodyClass();
  2544. }
  2545. /**
  2546. * Sets the URL hash.
  2547. */
  2548. function setUrlHash(url) {
  2549. if (options.recordHistory) {
  2550. location.hash = url;
  2551. } else {
  2552. //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
  2553. if (isTouchDevice || isTouch) {
  2554. window.history.replaceState(undefined, undefined, '#' + url);
  2555. } else {
  2556. var baseUrl = window.location.href.split('#')[0];
  2557. window.location.replace(baseUrl + '#' + url);
  2558. }
  2559. }
  2560. }
  2561. /**
  2562. * Gets the anchor for the given slide / section. Its index will be used if there's none.
  2563. */
  2564. function getAnchor(element) {
  2565. if (!element) {
  2566. return null;
  2567. }
  2568. var anchor = element.getAttribute('data-anchor');
  2569. var elementIndex = index(element);
  2570. //Slide without anchor link? We take the index instead.
  2571. if (anchor == null) {
  2572. anchor = elementIndex;
  2573. }
  2574. return anchor;
  2575. }
  2576. /**
  2577. * Sets a class for the body of the page depending on the active section / slide
  2578. */
  2579. function setBodyClass() {
  2580. var section = $(SECTION_ACTIVE_SEL)[0];
  2581. var slide = $(SLIDE_ACTIVE_SEL, section)[0];
  2582. var sectionAnchor = getAnchor(section);
  2583. var slideAnchor = getAnchor(slide);
  2584. var text = String(sectionAnchor);
  2585. if (slide) {
  2586. text = text + '-' + slideAnchor;
  2587. }
  2588. //changing slash for dash to make it a valid CSS style
  2589. text = text.replace('/', '-').replace('#', '');
  2590. //removing previous anchor classes
  2591. var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
  2592. $body.className = $body.className.replace(classRe, '');
  2593. //adding the current anchor
  2594. addClass($body, VIEWING_PREFIX + '-' + text);
  2595. }
  2596. /**
  2597. * Checks for translate3d support
  2598. * @return boolean
  2599. * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
  2600. */
  2601. function support3d() {
  2602. var el = document.createElement('p'),
  2603. has3d,
  2604. transforms = {
  2605. 'webkitTransform': '-webkit-transform',
  2606. 'OTransform': '-o-transform',
  2607. 'msTransform': '-ms-transform',
  2608. 'MozTransform': '-moz-transform',
  2609. 'transform': 'transform'
  2610. };
  2611. //preventing the style p:empty{display: none;} from returning the wrong result
  2612. el.style.display = 'block';
  2613. // Add it to the body to get the computed style.
  2614. document.body.insertBefore(el, null);
  2615. for (var t in transforms) {
  2616. if (el.style[t] !== undefined) {
  2617. el.style[t] = 'translate3d(1px,1px,1px)';
  2618. has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
  2619. }
  2620. }
  2621. document.body.removeChild(el);
  2622. return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
  2623. }
  2624. /**
  2625. * Removes the auto scrolling action fired by the mouse wheel and trackpad.
  2626. * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
  2627. */
  2628. function removeMouseWheelHandler() {
  2629. if (document.addEventListener) {
  2630. document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
  2631. document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
  2632. document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
  2633. } else {
  2634. document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
  2635. }
  2636. }
  2637. /**
  2638. * Adds the auto scrolling action for the mouse wheel and trackpad.
  2639. * After this function is called, the mousewheel and trackpad movements will scroll through sections
  2640. * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
  2641. */
  2642. function addMouseWheelHandler() {
  2643. var prefix = '';
  2644. var _addEventListener;
  2645. if (window.addEventListener) {
  2646. _addEventListener = "addEventListener";
  2647. } else {
  2648. _addEventListener = "attachEvent";
  2649. prefix = 'on';
  2650. }
  2651. // detect available wheel event
  2652. var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
  2653. document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
  2654. 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
  2655. var passiveEvent = g_supportsPassive ? {
  2656. passive: false
  2657. } : false;
  2658. if (support == 'DOMMouseScroll') {
  2659. document[_addEventListener](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
  2660. }
  2661. //handle MozMousePixelScroll in older Firefox
  2662. else {
  2663. document[_addEventListener](prefix + support, MouseWheelHandler, passiveEvent);
  2664. }
  2665. }
  2666. /**
  2667. * Binding the mousemove when the mouse's middle button is pressed
  2668. */
  2669. function addMiddleWheelHandler() {
  2670. container.addEventListener('mousedown', mouseDownHandler);
  2671. container.addEventListener('mouseup', mouseUpHandler);
  2672. }
  2673. /**
  2674. * Unbinding the mousemove when the mouse's middle button is released
  2675. */
  2676. function removeMiddleWheelHandler() {
  2677. container.removeEventListener('mousedown', mouseDownHandler);
  2678. container.removeEventListener('mouseup', mouseUpHandler);
  2679. }
  2680. /**
  2681. * Adds the possibility to auto scroll through sections on touch devices.
  2682. */
  2683. function addTouchHandler() {
  2684. if (isTouchDevice || isTouch) {
  2685. if (options.autoScrolling) {
  2686. $body.removeEventListener(events.touchmove, preventBouncing, {
  2687. passive: false
  2688. });
  2689. $body.addEventListener(events.touchmove, preventBouncing, {
  2690. passive: false
  2691. });
  2692. }
  2693. var touchWrapper = options.touchWrapper;
  2694. touchWrapper.removeEventListener(events.touchstart, touchStartHandler);
  2695. touchWrapper.removeEventListener(events.touchmove, touchMoveHandler, {
  2696. passive: false
  2697. });
  2698. touchWrapper.addEventListener(events.touchstart, touchStartHandler);
  2699. touchWrapper.addEventListener(events.touchmove, touchMoveHandler, {
  2700. passive: false
  2701. });
  2702. }
  2703. }
  2704. /**
  2705. * Removes the auto scrolling for touch devices.
  2706. */
  2707. function removeTouchHandler() {
  2708. if (isTouchDevice || isTouch) {
  2709. // normalScrollElements requires it off #2691
  2710. if (options.autoScrolling) {
  2711. $body.removeEventListener(events.touchmove, touchMoveHandler, {
  2712. passive: false
  2713. });
  2714. $body.removeEventListener(events.touchmove, preventBouncing, {
  2715. passive: false
  2716. });
  2717. }
  2718. var touchWrapper = options.touchWrapper;
  2719. touchWrapper.removeEventListener(events.touchstart, touchStartHandler);
  2720. touchWrapper.removeEventListener(events.touchmove, touchMoveHandler, {
  2721. passive: false
  2722. });
  2723. }
  2724. }
  2725. /*
  2726. * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
  2727. * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
  2728. */
  2729. function getMSPointer() {
  2730. var pointer;
  2731. //IE >= 11 & rest of browsers
  2732. if (window.PointerEvent) {
  2733. pointer = {
  2734. down: 'pointerdown',
  2735. move: 'pointermove'
  2736. };
  2737. }
  2738. //IE < 11
  2739. else {
  2740. pointer = {
  2741. down: 'MSPointerDown',
  2742. move: 'MSPointerMove'
  2743. };
  2744. }
  2745. return pointer;
  2746. }
  2747. /**
  2748. * Gets the pageX and pageY properties depending on the browser.
  2749. * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
  2750. */
  2751. function getEventsPage(e) {
  2752. var events = [];
  2753. events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
  2754. events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
  2755. //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
  2756. if (isTouch && isReallyTouch(e) && options.scrollBar && typeof e.touches !== 'undefined') {
  2757. events.y = e.touches[0].pageY;
  2758. events.x = e.touches[0].pageX;
  2759. }
  2760. return events;
  2761. }
  2762. /**
  2763. * Slides silently (with no animation) the active slider to the given slide.
  2764. * @param noCallback {bool} true or defined -> no callbacks
  2765. */
  2766. function silentLandscapeScroll(activeSlide, noCallbacks) {
  2767. setScrollingSpeed(0, 'internal');
  2768. if (typeof noCallbacks !== 'undefined') {
  2769. //preventing firing callbacks afterSlideLoad etc.
  2770. isResizing = true;
  2771. }
  2772. landscapeScroll(closest(activeSlide, SLIDES_WRAPPER_SEL), activeSlide);
  2773. if (typeof noCallbacks !== 'undefined') {
  2774. isResizing = false;
  2775. }
  2776. setScrollingSpeed(originals.scrollingSpeed, 'internal');
  2777. }
  2778. /**
  2779. * Scrolls silently (with no animation) the page to the given Y position.
  2780. */
  2781. function silentScroll(top) {
  2782. // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
  2783. // that's why we round it to 0.
  2784. var roundedTop = Math.round(top);
  2785. if (options.css3 && options.autoScrolling && !options.scrollBar) {
  2786. var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
  2787. transformContainer(translate3d, false);
  2788. } else if (options.autoScrolling && !options.scrollBar) {
  2789. css(container, {
  2790. 'top': -roundedTop + 'px'
  2791. });
  2792. FP.test.top = -roundedTop + 'px';
  2793. } else {
  2794. var scrollSettings = getScrollSettings(roundedTop);
  2795. setScrolling(scrollSettings.element, scrollSettings.options);
  2796. }
  2797. }
  2798. /**
  2799. * Returns the cross-browser transform string.
  2800. */
  2801. function getTransforms(translate3d) {
  2802. return {
  2803. '-webkit-transform': translate3d,
  2804. '-moz-transform': translate3d,
  2805. '-ms-transform': translate3d,
  2806. 'transform': translate3d
  2807. };
  2808. }
  2809. /**
  2810. * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
  2811. * @type m (mouse) or k (keyboard)
  2812. */
  2813. function setIsScrollAllowed(value, direction, type) {
  2814. //up, down, left, right
  2815. if (direction !== 'all') {
  2816. isScrollAllowed[type][direction] = value;
  2817. }
  2818. //all directions?
  2819. else {
  2820. Object.keys(isScrollAllowed[type]).forEach(function (key) {
  2821. isScrollAllowed[type][key] = value;
  2822. });
  2823. }
  2824. }
  2825. /*
  2826. * Destroys fullpage.js plugin events and optinally its html markup and styles
  2827. */
  2828. function destroy(all) {
  2829. setAutoScrolling(false, 'internal');
  2830. setAllowScrolling(true);
  2831. setMouseHijack(false);
  2832. setKeyboardScrolling(false);
  2833. addClass(container, DESTROYED);
  2834. [
  2835. afterSlideLoadsId,
  2836. afterSectionLoadsId,
  2837. resizeId,
  2838. scrollId,
  2839. scrollId2,
  2840. g_doubleCheckHeightId,
  2841. resizeHandlerId,
  2842. g_transitionLapseId
  2843. ].forEach(function (timeoutId) {
  2844. clearTimeout(timeoutId);
  2845. });
  2846. window.removeEventListener('scroll', scrollHandler);
  2847. window.removeEventListener('hashchange', hashChangeHandler);
  2848. window.removeEventListener('resize', resizeHandler);
  2849. document.removeEventListener('keydown', keydownHandler);
  2850. document.removeEventListener('keyup', keyUpHandler);
  2851. ['click', 'touchstart'].forEach(function (eventName) {
  2852. document.removeEventListener(eventName, delegatedEvents);
  2853. });
  2854. ['mouseenter', 'touchstart', 'mouseleave', 'touchend'].forEach(function (eventName) {
  2855. document.removeEventListener(eventName, onMouseEnterOrLeave, true); //true is required!
  2856. });
  2857. //lets make a mess!
  2858. if (all) {
  2859. destroyStructure();
  2860. }
  2861. }
  2862. /*
  2863. * Removes inline styles added by fullpage.js
  2864. */
  2865. function destroyStructure() {
  2866. //reseting the `top` or `translate` properties to 0
  2867. silentScroll(0);
  2868. //loading all the lazy load content
  2869. $('img[data-src], source[data-src], audio[data-src], iframe[data-src]', container).forEach(function (item) {
  2870. setSrc(item, 'src');
  2871. });
  2872. $('img[data-srcset]').forEach(function (item) {
  2873. setSrc(item, 'srcset');
  2874. });
  2875. remove($(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL));
  2876. //removing inline styles
  2877. css($(SECTION_SEL), {
  2878. 'height': '',
  2879. 'background-color': '',
  2880. 'padding': ''
  2881. });
  2882. css($(SLIDE_SEL), {
  2883. 'width': ''
  2884. });
  2885. css(container, {
  2886. 'height': '',
  2887. 'position': '',
  2888. '-ms-touch-action': '',
  2889. 'touch-action': ''
  2890. });
  2891. css($htmlBody, {
  2892. 'overflow': '',
  2893. 'height': ''
  2894. });
  2895. // remove .fp-enabled class
  2896. removeClass($html, ENABLED);
  2897. // remove .fp-responsive class
  2898. removeClass($body, RESPONSIVE);
  2899. // remove all of the .fp-viewing- classes
  2900. $body.className.split(/\s+/).forEach(function (className) {
  2901. if (className.indexOf(VIEWING_PREFIX) === 0) {
  2902. removeClass($body, className);
  2903. }
  2904. });
  2905. //removing added classes
  2906. $(SECTION_SEL + ', ' + SLIDE_SEL).forEach(function (item) {
  2907. if (options.scrollOverflowHandler && options.scrollOverflow) {
  2908. options.scrollOverflowHandler.remove(item);
  2909. }
  2910. removeClass(item, TABLE + ' ' + ACTIVE + ' ' + COMPLETELY);
  2911. var previousStyles = item.getAttribute('data-fp-styles');
  2912. if (previousStyles) {
  2913. item.setAttribute('style', item.getAttribute('data-fp-styles'));
  2914. }
  2915. //removing anchors if they were not set using the HTML markup
  2916. if (hasClass(item, SECTION) && !g_initialAnchorsInDom) {
  2917. item.removeAttribute('data-anchor');
  2918. }
  2919. });
  2920. //removing the applied transition from the fullpage wrapper
  2921. removeAnimation(container);
  2922. //Unwrapping content
  2923. [TABLE_CELL_SEL, SLIDES_CONTAINER_SEL, SLIDES_WRAPPER_SEL].forEach(function (selector) {
  2924. $(selector, container).forEach(function (item) {
  2925. //unwrap not being use in case there's no child element inside and its just text
  2926. unwrap(item);
  2927. });
  2928. });
  2929. //removing the applied transition from the fullpage wrapper
  2930. css(container, {
  2931. '-webkit-transition': 'none',
  2932. 'transition': 'none'
  2933. });
  2934. //scrolling the page to the top with no animation
  2935. window.scrollTo(0, 0);
  2936. //removing selectors
  2937. var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
  2938. usedSelectors.forEach(function (item) {
  2939. removeClass($('.' + item), item);
  2940. });
  2941. }
  2942. /*
  2943. * Sets the state for a variable with multiple states (original, and temporal)
  2944. * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
  2945. * This function is used to keep track of both states, the original and the temporal one.
  2946. * If type is not 'internal', then we assume the user is globally changing the variable.
  2947. */
  2948. function setVariableState(variable, value, type) {
  2949. options[variable] = value;
  2950. if (type !== 'internal') {
  2951. originals[variable] = value;
  2952. }
  2953. }
  2954. /**
  2955. * Displays warnings
  2956. */
  2957. function displayWarnings() {
  2958. var l = options['li' + 'c' + 'enseK' + 'e' + 'y'];
  2959. var msgStyle = 'font-size: 15px;background:yellow;';
  2960. if (!isOK) {
  2961. // showError('error', 'Fullpage.js version 3 has changed its license to GPLv3 and it requires a `licenseKey` option. Read about it here:');
  2962. // showError('error', 'https://github.com/alvarotrigo/fullPage.js#options');
  2963. } else if (l && l.length < 20) {
  2964. console.warn('%c This website was made using fullPage.js slider. More info on the following website:', msgStyle);
  2965. console.warn('%c https://alvarotrigo.com/fullPage/', msgStyle);
  2966. }
  2967. if (hasClass($html, ENABLED)) {
  2968. showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
  2969. return;
  2970. }
  2971. // Disable mutually exclusive settings
  2972. if (options.continuousVertical &&
  2973. (options.loopTop || options.loopBottom)) {
  2974. options.continuousVertical = false;
  2975. showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
  2976. }
  2977. if (options.scrollOverflow &&
  2978. (options.scrollBar || !options.autoScrolling)) {
  2979. showError('warn', 'Options scrollBar:true and autoScrolling:false are mutually exclusive with scrollOverflow:true. Sections with scrollOverflow might not work well in Firefox');
  2980. }
  2981. if (options.continuousVertical && (options.scrollBar || !options.autoScrolling)) {
  2982. options.continuousVertical = false;
  2983. showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
  2984. }
  2985. if (options.scrollOverflow && options.scrollOverflowHandler == null) {
  2986. options.scrollOverflow = false;
  2987. showError('error', 'The option `scrollOverflow:true` requires the file `scrolloverflow.min.js`. Please include it before fullPage.js.');
  2988. }
  2989. //using extensions? Wrong file!
  2990. extensions.forEach(function (extension) {
  2991. //is the option set to true?
  2992. if (options[extension]) {
  2993. showError('warn', 'fullpage.js extensions require fullpage.extensions.min.js file instead of the usual fullpage.js. Requested: ' + extension);
  2994. }
  2995. });
  2996. //anchors can not have the same value as any element ID or NAME
  2997. options.anchors.forEach(function (name) {
  2998. //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
  2999. var nameAttr = [].slice.call($('[name]')).filter(function (item) {
  3000. return item.getAttribute('name') && item.getAttribute('name').toLowerCase() == name.toLowerCase();
  3001. });
  3002. var idAttr = [].slice.call($('[id]')).filter(function (item) {
  3003. return item.getAttribute('id') && item.getAttribute('id').toLowerCase() == name.toLowerCase();
  3004. });
  3005. if (idAttr.length || nameAttr.length) {
  3006. showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
  3007. var propertyName = idAttr.length ? 'id' : 'name';
  3008. if (idAttr.length || nameAttr.length) {
  3009. showError('error', '"' + name + '" is is being used by another element `' + propertyName + '` property');
  3010. }
  3011. }
  3012. });
  3013. }
  3014. /**
  3015. * Getting the position of the element to scroll when using jQuery animations
  3016. */
  3017. function getScrolledPosition(element) {
  3018. var position;
  3019. //is not the window element and is a slide?
  3020. if (element.self != window && hasClass(element, SLIDES_WRAPPER)) {
  3021. position = element.scrollLeft;
  3022. } else if (!options.autoScrolling || options.scrollBar) {
  3023. position = getScrollTop();
  3024. } else {
  3025. position = element.offsetTop;
  3026. }
  3027. //gets the top property of the wrapper
  3028. return position;
  3029. }
  3030. /**
  3031. * Simulates the animated scrollTop of jQuery. Used when css3:false or scrollBar:true or autoScrolling:false
  3032. * http://stackoverflow.com/a/16136789/1081396
  3033. */
  3034. function scrollTo(element, to, duration, callback) {
  3035. var start = getScrolledPosition(element);
  3036. var change = to - start;
  3037. var currentTime = 0;
  3038. var increment = 20;
  3039. activeAnimation = true;
  3040. var animateScroll = function () {
  3041. if (activeAnimation) { //in order to stope it from other function whenever we want
  3042. var val = to;
  3043. currentTime += increment;
  3044. if (duration) {
  3045. val = window.fp_easings[options.easing](currentTime, start, change, duration);
  3046. }
  3047. setScrolling(element, val);
  3048. if (currentTime < duration) {
  3049. setTimeout(animateScroll, increment);
  3050. } else if (typeof callback !== 'undefined') {
  3051. callback();
  3052. }
  3053. } else if (currentTime < duration) {
  3054. callback();
  3055. }
  3056. };
  3057. animateScroll();
  3058. }
  3059. /**
  3060. * Scrolls the page / slider the given number of pixels.
  3061. * It will do it one or another way dependiong on the library's config.
  3062. */
  3063. function setScrolling(element, val) {
  3064. if (!options.autoScrolling || options.scrollBar || (element.self != window && hasClass(element, SLIDES_WRAPPER))) {
  3065. //scrolling horizontally through the slides?
  3066. if (element.self != window && hasClass(element, SLIDES_WRAPPER)) {
  3067. element.scrollLeft = val;
  3068. }
  3069. //vertical scroll
  3070. else {
  3071. element.scrollTo(0, val);
  3072. }
  3073. } else {
  3074. element.style.top = val + 'px';
  3075. }
  3076. }
  3077. /**
  3078. * Gets the active slide.
  3079. */
  3080. function getActiveSlide() {
  3081. var activeSlide = $(SLIDE_ACTIVE_SEL, $(SECTION_ACTIVE_SEL)[0])[0];
  3082. return nullOrSlide(activeSlide);
  3083. }
  3084. /**
  3085. * Gets the active section.
  3086. */
  3087. function getActiveSection() {
  3088. return new Section($(SECTION_ACTIVE_SEL)[0]);
  3089. }
  3090. /**
  3091. * Item. Slide or Section objects share the same properties.
  3092. */
  3093. function Item(el, selector) {
  3094. this.anchor = el.getAttribute('data-anchor');
  3095. this.item = el;
  3096. this.index = index(el, selector);
  3097. this.isLast = this.index === el.parentElement.querySelectorAll(selector).length - 1;
  3098. this.isFirst = !this.index;
  3099. }
  3100. /**
  3101. * Section object
  3102. */
  3103. function Section(el) {
  3104. Item.call(this, el, SECTION_SEL);
  3105. }
  3106. /**
  3107. * Slide object
  3108. */
  3109. function Slide(el) {
  3110. Item.call(this, el, SLIDE_SEL);
  3111. }
  3112. return FP;
  3113. } //end of $.fn.fullpage
  3114. //utils
  3115. /**
  3116. * Shows a message in the console of the given type.
  3117. */
  3118. function showError(type, text) {
  3119. window.console && window.console[type] && window.console[type]('fullPage: ' + text);
  3120. }
  3121. /**
  3122. * Equivalent of jQuery function $().
  3123. */
  3124. function $(selector, context) {
  3125. context = arguments.length > 1 ? context : document;
  3126. return context ? context.querySelectorAll(selector) : null;
  3127. }
  3128. /**
  3129. * Extends a given Object properties and its childs.
  3130. */
  3131. function deepExtend(out) {
  3132. out = out || {};
  3133. for (var i = 1, len = arguments.length; i < len; ++i) {
  3134. var obj = arguments[i];
  3135. if (!obj) {
  3136. continue;
  3137. }
  3138. for (var key in obj) {
  3139. if (!obj.hasOwnProperty(key)) {
  3140. continue;
  3141. }
  3142. // based on https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
  3143. if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
  3144. out[key] = deepExtend(out[key], obj[key]);
  3145. continue;
  3146. }
  3147. out[key] = obj[key];
  3148. }
  3149. }
  3150. return out;
  3151. }
  3152. /**
  3153. * Checks if the passed element contains the passed class.
  3154. */
  3155. function hasClass(el, className) {
  3156. if (el == null) {
  3157. return false;
  3158. }
  3159. if (el.classList) {
  3160. return el.classList.contains(className);
  3161. }
  3162. return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
  3163. }
  3164. /**
  3165. * Gets the window height. Crossbrowser.
  3166. */
  3167. function getWindowHeight() {
  3168. return 'innerHeight' in window ? window.innerHeight : document.documentElement.offsetHeight;
  3169. }
  3170. /**
  3171. * Gets the window width.
  3172. */
  3173. function getWindowWidth() {
  3174. return window.innerWidth;
  3175. }
  3176. /**
  3177. * Set's the CSS properties for the passed item/s.
  3178. * @param {NodeList|HTMLElement} items
  3179. * @param {Object} props css properties and values.
  3180. */
  3181. function css(items, props) {
  3182. items = getList(items);
  3183. var key;
  3184. for (key in props) {
  3185. if (props.hasOwnProperty(key)) {
  3186. if (key !== null) {
  3187. for (var i = 0; i < items.length; i++) {
  3188. var item = items[i];
  3189. item.style[key] = props[key];
  3190. }
  3191. }
  3192. }
  3193. }
  3194. return items;
  3195. }
  3196. /**
  3197. * Generic function to get the previous or next element.
  3198. */
  3199. function until(item, selector, fn) {
  3200. var sibling = item[fn];
  3201. while (sibling && !matches(sibling, selector)) {
  3202. sibling = sibling[fn];
  3203. }
  3204. return sibling;
  3205. }
  3206. /**
  3207. * Gets the previous element to the passed element that matches the passed selector.
  3208. */
  3209. function prevUntil(item, selector) {
  3210. return until(item, selector, 'previousElementSibling');
  3211. }
  3212. /**
  3213. * Gets the next element to the passed element that matches the passed selector.
  3214. */
  3215. function nextUntil(item, selector) {
  3216. return until(item, selector, 'nextElementSibling');
  3217. }
  3218. /**
  3219. * Gets the previous element to the passed element.
  3220. */
  3221. function prev(item) {
  3222. return item.previousElementSibling;
  3223. }
  3224. /**
  3225. * Gets the next element to the passed element.
  3226. */
  3227. function next(item) {
  3228. return item.nextElementSibling;
  3229. }
  3230. /**
  3231. * Gets the last element from the passed list of elements.
  3232. */
  3233. function last(item) {
  3234. return item[item.length - 1];
  3235. }
  3236. /**
  3237. * Gets index from the passed element.
  3238. * @param {String} selector is optional.
  3239. */
  3240. function index(item, selector) {
  3241. item = isArrayOrList(item) ? item[0] : item;
  3242. var children = selector != null ? $(selector, item.parentNode) : item.parentNode.childNodes;
  3243. var num = 0;
  3244. for (var i = 0; i < children.length; i++) {
  3245. if (children[i] == item) return num;
  3246. if (children[i].nodeType == 1) num++;
  3247. }
  3248. return -1;
  3249. }
  3250. /**
  3251. * Gets an iterable element for the passed element/s
  3252. */
  3253. function getList(item) {
  3254. return !isArrayOrList(item) ? [item] : item;
  3255. }
  3256. /**
  3257. * Adds the display=none property for the passed element/s
  3258. */
  3259. function hide(el) {
  3260. el = getList(el);
  3261. for (var i = 0; i < el.length; i++) {
  3262. el[i].style.display = 'none';
  3263. }
  3264. return el;
  3265. }
  3266. /**
  3267. * Adds the display=block property for the passed element/s
  3268. */
  3269. function show(el) {
  3270. el = getList(el);
  3271. for (var i = 0; i < el.length; i++) {
  3272. el[i].style.display = 'block';
  3273. }
  3274. return el;
  3275. }
  3276. /**
  3277. * Checks if the passed element is an iterable element or not
  3278. */
  3279. function isArrayOrList(el) {
  3280. return Object.prototype.toString.call(el) === '[object Array]' ||
  3281. Object.prototype.toString.call(el) === '[object NodeList]';
  3282. }
  3283. /**
  3284. * Adds the passed class to the passed element/s
  3285. */
  3286. function addClass(el, className) {
  3287. el = getList(el);
  3288. for (var i = 0; i < el.length; i++) {
  3289. var item = el[i];
  3290. if (item.classList) {
  3291. item.classList.add(className);
  3292. } else {
  3293. item.className += ' ' + className;
  3294. }
  3295. }
  3296. return el;
  3297. }
  3298. /**
  3299. * Removes the passed class to the passed element/s
  3300. * @param {String} `className` can be multiple classnames separated by whitespace
  3301. */
  3302. function removeClass(el, className) {
  3303. el = getList(el);
  3304. var classNames = className.split(' ');
  3305. for (var a = 0; a < classNames.length; a++) {
  3306. className = classNames[a];
  3307. for (var i = 0; i < el.length; i++) {
  3308. var item = el[i];
  3309. if (item.classList) {
  3310. item.classList.remove(className);
  3311. } else {
  3312. item.className = item.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
  3313. }
  3314. }
  3315. }
  3316. return el;
  3317. }
  3318. /**
  3319. * Appends the given element ot the given parent.
  3320. */
  3321. function appendTo(el, parent) {
  3322. parent.appendChild(el);
  3323. }
  3324. /**
  3325. Usage:
  3326. var wrapper = document.createElement('div');
  3327. wrapper.className = 'fp-slides';
  3328. wrap($('.slide'), wrapper);
  3329. https://jsfiddle.net/qwzc7oy3/15/ (vanilla)
  3330. https://jsfiddle.net/oya6ndka/1/ (jquery equivalent)
  3331. */
  3332. function wrap(toWrap, wrapper, isWrapAll) {
  3333. var newParent;
  3334. wrapper = wrapper || document.createElement('div');
  3335. for (var i = 0; i < toWrap.length; i++) {
  3336. var item = toWrap[i];
  3337. if (isWrapAll && !i || !isWrapAll) {
  3338. newParent = wrapper.cloneNode(true);
  3339. item.parentNode.insertBefore(newParent, item);
  3340. }
  3341. newParent.appendChild(item);
  3342. }
  3343. return toWrap;
  3344. }
  3345. /**
  3346. Usage:
  3347. var wrapper = document.createElement('div');
  3348. wrapper.className = 'fp-slides';
  3349. wrap($('.slide'), wrapper);
  3350. https://jsfiddle.net/qwzc7oy3/27/ (vanilla)
  3351. https://jsfiddle.net/oya6ndka/4/ (jquery equivalent)
  3352. */
  3353. function wrapAll(toWrap, wrapper) {
  3354. wrap(toWrap, wrapper, true);
  3355. }
  3356. /**
  3357. * Usage:
  3358. * wrapInner(document.querySelector('#pepe'), '<div class="test">afdas</div>');
  3359. * wrapInner(document.querySelector('#pepe'), element);
  3360. *
  3361. * https://jsfiddle.net/zexxz0tw/6/
  3362. *
  3363. * https://stackoverflow.com/a/21817590/1081396
  3364. */
  3365. function wrapInner(parent, wrapper) {
  3366. if (typeof wrapper === "string") {
  3367. wrapper = createElementFromHTML(wrapper);
  3368. }
  3369. parent.appendChild(wrapper);
  3370. while (parent.firstChild !== wrapper) {
  3371. wrapper.appendChild(parent.firstChild);
  3372. }
  3373. }
  3374. /**
  3375. * Usage:
  3376. * unwrap(document.querySelector('#pepe'));
  3377. * unwrap(element);
  3378. *
  3379. * https://jsfiddle.net/szjt0hxq/1/
  3380. *
  3381. */
  3382. function unwrap(wrapper) {
  3383. var wrapperContent = document.createDocumentFragment();
  3384. while (wrapper.firstChild) {
  3385. wrapperContent.appendChild(wrapper.firstChild);
  3386. }
  3387. wrapper.parentNode.replaceChild(wrapperContent, wrapper);
  3388. }
  3389. /**
  3390. * http://stackoverflow.com/questions/22100853/dom-pure-javascript-solution-to-jquery-closest-implementation
  3391. * Returns the element or `false` if there's none
  3392. */
  3393. function closest(el, selector) {
  3394. if (el && el.nodeType === 1) {
  3395. if (matches(el, selector)) {
  3396. return el;
  3397. }
  3398. return closest(el.parentNode, selector);
  3399. }
  3400. return null;
  3401. }
  3402. /**
  3403. * Places one element (rel) after another one or group of them (reference).
  3404. * @param {HTMLElement} reference
  3405. * @param {HTMLElement|NodeList|String} el
  3406. * https://jsfiddle.net/9s97hhzv/1/
  3407. */
  3408. function after(reference, el) {
  3409. insertBefore(reference, reference.nextSibling, el);
  3410. }
  3411. /**
  3412. * Places one element (rel) before another one or group of them (reference).
  3413. * @param {HTMLElement} reference
  3414. * @param {HTMLElement|NodeList|String} el
  3415. * https://jsfiddle.net/9s97hhzv/1/
  3416. */
  3417. function before(reference, el) {
  3418. insertBefore(reference, reference, el);
  3419. }
  3420. /**
  3421. * Based in https://stackoverflow.com/a/19316024/1081396
  3422. * and https://stackoverflow.com/a/4793630/1081396
  3423. */
  3424. function insertBefore(reference, beforeElement, el) {
  3425. if (!isArrayOrList(el)) {
  3426. if (typeof el == 'string') {
  3427. el = createElementFromHTML(el);
  3428. }
  3429. el = [el];
  3430. }
  3431. for (var i = 0; i < el.length; i++) {
  3432. reference.parentNode.insertBefore(el[i], beforeElement);
  3433. }
  3434. }
  3435. //http://stackoverflow.com/questions/3464876/javascript-get-window-x-y-position-for-scroll
  3436. function getScrollTop() {
  3437. var doc = document.documentElement;
  3438. return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
  3439. }
  3440. /**
  3441. * Gets the siblings of the passed element
  3442. */
  3443. function siblings(el) {
  3444. return Array.prototype.filter.call(el.parentNode.children, function (child) {
  3445. return child !== el;
  3446. });
  3447. }
  3448. //for IE 9 ?
  3449. function preventDefault(event) {
  3450. if (event.preventDefault) {
  3451. event.preventDefault();
  3452. } else {
  3453. event.returnValue = false;
  3454. }
  3455. }
  3456. /**
  3457. * Determines whether the passed item is of function type.
  3458. */
  3459. function isFunction(item) {
  3460. if (typeof item === 'function') {
  3461. return true;
  3462. }
  3463. var type = Object.prototype.toString(item);
  3464. return type === '[object Function]' || type === '[object GeneratorFunction]';
  3465. }
  3466. /**
  3467. * Trigger custom events
  3468. */
  3469. function trigger(el, eventName, data) {
  3470. var event;
  3471. data = typeof data === 'undefined' ? {} : data;
  3472. // Native
  3473. if (typeof window.CustomEvent === "function") {
  3474. event = new CustomEvent(eventName, {
  3475. detail: data
  3476. });
  3477. } else {
  3478. event = document.createEvent('CustomEvent');
  3479. event.initCustomEvent(eventName, true, true, data);
  3480. }
  3481. el.dispatchEvent(event);
  3482. }
  3483. /**
  3484. * Polyfill of .matches()
  3485. */
  3486. function matches(el, selector) {
  3487. return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
  3488. }
  3489. /**
  3490. * Toggles the visibility of the passed element el.
  3491. */
  3492. function toggle(el, value) {
  3493. if (typeof value === "boolean") {
  3494. for (var i = 0; i < el.length; i++) {
  3495. el[i].style.display = value ? 'block' : 'none';
  3496. }
  3497. }
  3498. //we don't use it in other way, so no else :)
  3499. return el;
  3500. }
  3501. /**
  3502. * Creates a HTMLElement from the passed HTML string.
  3503. * https://stackoverflow.com/a/494348/1081396
  3504. */
  3505. function createElementFromHTML(htmlString) {
  3506. var div = document.createElement('div');
  3507. div.innerHTML = htmlString.trim();
  3508. // Change this to div.childNodes to support multiple top-level nodes
  3509. return div.firstChild;
  3510. }
  3511. /**
  3512. * Removes the passed item/s from the DOM.
  3513. */
  3514. function remove(items) {
  3515. items = getList(items);
  3516. for (var i = 0; i < items.length; i++) {
  3517. var item = items[i];
  3518. if (item && item.parentElement) {
  3519. item.parentNode.removeChild(item);
  3520. }
  3521. }
  3522. }
  3523. /**
  3524. * Filters an array by the passed filter funtion.
  3525. */
  3526. function filter(el, filterFn) {
  3527. Array.prototype.filter.call(el, filterFn);
  3528. }
  3529. //https://jsfiddle.net/w1rktecz/
  3530. function untilAll(item, selector, fn) {
  3531. var sibling = item[fn];
  3532. var siblings = [];
  3533. while (sibling) {
  3534. if (matches(sibling, selector) || selector == null) {
  3535. siblings.push(sibling);
  3536. }
  3537. sibling = sibling[fn];
  3538. }
  3539. return siblings;
  3540. }
  3541. /**
  3542. * Gets all next elements matching the passed selector.
  3543. */
  3544. function nextAll(item, selector) {
  3545. return untilAll(item, selector, 'nextElementSibling');
  3546. }
  3547. /**
  3548. * Gets all previous elements matching the passed selector.
  3549. */
  3550. function prevAll(item, selector) {
  3551. return untilAll(item, selector, 'previousElementSibling');
  3552. }
  3553. /**
  3554. * Converts an object to an array.
  3555. */
  3556. function toArray(objectData) {
  3557. return Object.keys(objectData).map(function (key) {
  3558. return objectData[key];
  3559. });
  3560. }
  3561. /**
  3562. * forEach polyfill for IE
  3563. * https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Browser_Compatibility
  3564. */
  3565. if (window.NodeList && !NodeList.prototype.forEach) {
  3566. NodeList.prototype.forEach = function (callback, thisArg) {
  3567. thisArg = thisArg || window;
  3568. for (var i = 0; i < this.length; i++) {
  3569. callback.call(thisArg, this[i], i, this);
  3570. }
  3571. };
  3572. }
  3573. //utils are public, so we can use it wherever we want
  3574. window.fp_utils = {
  3575. $: $,
  3576. deepExtend: deepExtend,
  3577. hasClass: hasClass,
  3578. getWindowHeight: getWindowHeight,
  3579. css: css,
  3580. until: until,
  3581. prevUntil: prevUntil,
  3582. nextUntil: nextUntil,
  3583. prev: prev,
  3584. next: next,
  3585. last: last,
  3586. index: index,
  3587. getList: getList,
  3588. hide: hide,
  3589. show: show,
  3590. isArrayOrList: isArrayOrList,
  3591. addClass: addClass,
  3592. removeClass: removeClass,
  3593. appendTo: appendTo,
  3594. wrap: wrap,
  3595. wrapAll: wrapAll,
  3596. wrapInner: wrapInner,
  3597. unwrap: unwrap,
  3598. closest: closest,
  3599. after: after,
  3600. before: before,
  3601. insertBefore: insertBefore,
  3602. getScrollTop: getScrollTop,
  3603. siblings: siblings,
  3604. preventDefault: preventDefault,
  3605. isFunction: isFunction,
  3606. trigger: trigger,
  3607. matches: matches,
  3608. toggle: toggle,
  3609. createElementFromHTML: createElementFromHTML,
  3610. remove: remove,
  3611. filter: filter,
  3612. untilAll: untilAll,
  3613. nextAll: nextAll,
  3614. prevAll: prevAll,
  3615. showError: showError
  3616. };
  3617. return initialise;
  3618. }));
  3619. /**
  3620. * jQuery adapter for fullPage.js 3.0.0
  3621. */
  3622. if (window.jQuery && window.fullpage) {
  3623. (function ($, fullpage) {
  3624. 'use strict';
  3625. // No jQuery No Go
  3626. if (!$ || !fullpage) {
  3627. window.fp_utils.showError('error', 'jQuery is required to use the jQuery fullpage adapter!');
  3628. return;
  3629. }
  3630. $.fn.fullpage = function (options) {
  3631. options = $.extend({}, options, {
  3632. '$': $
  3633. });
  3634. var instance = new fullpage(this[0], options);
  3635. };
  3636. })(window.jQuery, window.fullpage);
  3637. }