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