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