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