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 n
1048ormal 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 1096 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 1097 * This way, the touchstart and the touch moves shows an small difference between them which is the 1098 * used one to determine the direction. 1099 */ 1100 function touchMoveHandler(event){ 1101 var e = event.originalEvent; 1102 var activeSection = $(e.target).closest(SECTION_SEL); 1103 1104 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 1105 if (isReallyTouch(e) ) { 1106 1107 if(options.autoScrolling){ 1108 //preventing the easing on iOS devices 1109 event.preventDefault(); 1110 } 1111 1112 var touchEvents = getEventsPage(e); 1113 1114 touchEndY = touchEvents.y; 1115 touchEndX = touchEvents.x; 1116 1117 //if movement in the X axys is greater than in the Y and the currect section has slides... 1118 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 1119 1120 //is the movement greater than the minimum resistance to scroll? 1121 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 1122 if (touchStartX > touchEndX) { 1123 if(isScrollAllowed.m.right){ 1124 moveSlideRight(activeSection); //next 1125 } 1126 } else { 1127 if(isScrollAllowed.m.left){ 1128 moveSlideLeft(activeSection); //prev 1129 } 1130 } 1131 } 1132 } 1133 1134 //vertical scrolling (only when autoScrolling is enabled) 1135 else if(options.autoScrolling && canScroll){ 1136 1137 //is the movement greater than the minimum resistance to scroll? 1138 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 1139 if (touchStartY > touchEndY) { 1140 scrolling('down'); 1141 } else if (touchEndY > touchStartY) { 1142 scrolling('up'); 1143 } 1144 } 1145 } 1146 } 1147 } 1148 1149 /** 1150 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 1151 * this way we make sure that is really a touch event what IE is detecting. 1152 */ 1153 function isReallyTouch(e){ 1154 //if is not IE || IE is detecting `touch` or `pen` 1155 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 1156 } 1157 1158 /** 1159 * Handler for the touch start event. 1160 */ 1161 function touchStartHandler(event){ 1162 var e = event.originalEvent; 1163 1164 //stopping the auto scroll to adjust to a section 1165 if(options.fitToSection){ 1166 $htmlBody.stop(); 1167 } 1168 1169 if(isReallyTouch(e)){ 1170 var touchEvents = getEventsPage(e); 1171 touchStartY = touchEvents.y; 1172 touchStartX = touchEvents.x; 1173 } 1174 } 1175 1176 /** 1177 * Gets the average of the last `number` elements of the given array. 1178 */ 1179 function getAverage(elements, number){
1180 var sum = 0; 1181 1182 //taking `number` elements from the end to make the average, if there are not enought, 1 1183 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 1184 1185 for(var i = 0; i < lastElements.length; i++){ 1186 sum = sum + lastElements[i]; 1187 } 1188 1189 return Math.ceil(sum/number); 1190 } 1191 1192 /** 1193 * Detecting mousewheel scrolling 1194 * 1195 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 1196 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 1197 */ 1198 var prevTime = new Date().getTime(); 1199 1200 function MouseWheelHandler(e) { 1201 var curTime = new Date().getTime(); 1202 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 1203 1204 //autoscrolling and not zooming? 1205 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 1206 // cross-browser wheel delta 1207 e = e || window.event; 1208 var value = e.wheelDelta || -e.deltaY || -e.detail; 1209 var delta = Math.max(-1, Math.min(1, value)); 1210 1211 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 1212 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 1213 1214 //Limiting the array to 150 (lets not waste memory!) 1215 if(scrollings.length > 149){ 1216 scrollings.shift(); 1217 } 1218 1219 //keeping record of the previous scrollings 1220 scrollings.push(Math.abs(value)); 1221 1222 //preventing to scroll the site on mouse wheel when scrollbar is present 1223 if(options.scrollBar){ 1224 e.preventDefault ? e.preventDefault() : e.returnValue = false; 1225 } 1226 1227 //time difference between the last scroll and the current one 1228 var timeDiff = curTime-prevTime; 1229 prevTime = curTime; 1230 1231 //haven't they scrolled in a while? 1232 //(enough to be consider a different scrolling action to scroll another section) 1233 if(timeDiff > 200){ 1234 //emptying the array, we dont care about old scrollings for our averages 1235 scrollings = []; 1236 } 1237 1238 if(canScroll){ 1239 var averageEnd = getAverage(scrollings, 10); 1240 var averageMiddle = getAverage(scrollings, 70); 1241 var isAccelerating = averageEnd >= averageMiddle; 1242 1243 //to avoid double swipes... 1244 if(isAccelerating && isScrollingVertically){ 1245 //scrolling down? 1246 if (delta < 0) { 1247 scrolling('down'); 1248 1249 //scrolling up? 1250 }else { 1251 scrolling('up'); 1252 } 1253 } 1254 } 1255 1256 return false; 1257 } 1258 1259 if(options.fitToSection){ 1260 //stopping the auto scroll to adjust to a section 1261 $htmlBody.stop(); 1262 } 1263 } 1264 1265 /** 1266 * Slides a slider to the given direction. 1267 * Optional `section` param. 1268 */ 1269 function moveSlide(direction, section){ 1270 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 1271 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 1272 var numSlides = slides.find(SLIDE_SEL).length; 1273 1274 // more than one slide needed and nothing should be sliding 1275 if (!slides.length || slideMoving || numSlides < 2) { 1276 return; 1277 } 1278 1279 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 1280 var destiny = null; 1281 1282 if(direction === 'left'){ 1283 destiny = currentSlide.prev(SLIDE_SEL); 1284 }else{ 1285 destiny = currentSlide.next(SLIDE_SEL); 1286 } 1287 1288 //isn't there a next slide in the secuence? 1289 if(!destiny.length){ 1290 //respect loopHorizontal settin 1291 if (!options.loopHorizontal) return; 1292 1293 if(direction === 'left'){ 1294 destiny = currentSlide.siblings(':last'); 1295 }else{ 1296 destiny = currentSlide.siblings(':first'); 1297 } 1298 } 1299 1300 slideMoving = true; 1301
1302 landscapeScroll(slides, destiny, direction); 1303 } 1304 1305 /** 1306 * Maintains the active slides in the viewport 1307 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 1308 */ 1309 function keepSlidesPosition(){ 1310 $(SLIDE_ACTIVE_SEL).each(function(){ 1311 silentLandscapeScroll($(this), 'internal'); 1312 }); 1313 } 1314 1315 var previousDestTop = 0; 1316 /** 1317 * Returns the destination Y position based on the scrolling direction and 1318 * the height of the section. 1319 */ 1320 function getDestinationPosition(element){ 1321 var elemPosition = element.position(); 1322 1323 //top of the desination will be at the top of the viewport 1324 var position = elemPosition.top; 1325 var isScrollingDown = elemPosition.top > previousDestTop; 1326 var sectionBottom = position - windowsHeight + element.outerHeight(); 1327 var bigSectionsDestination = options.bigSectionsDestination; 1328 1329 //is the destination element bigger than the viewport? 1330 if(element.outerHeight() > windowsHeight){ 1331 //scrolling up? 1332 if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 1333 position = sectionBottom; 1334 } 1335 } 1336 1337 //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 1338 else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 1339 //The bottom of the destination will be at the bottom of the viewport 1340 position = sectionBottom; 1341 } 1342 1343 /* 1344 Keeping record of the last scrolled position to determine the scrolling direction. 1345 No conventional methods can be used as the scroll bar might not be present 1346 AND the section might not be active if it is auto-height and didnt reach the middle 1347 of the viewport. 1348 */ 1349 previousDestTop = position; 1350 return position; 1351 } 1352 1353 /** 1354 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 1355 */ 1356 function scrollPage(element, callback, isMovementUp){ 1357 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 1358 1359 var dtop = getDestinationPosition(element); 1360 var slideAnchorLink; 1361 var slideIndex; 1362 1363 //local variables 1364 var v = { 1365 element: element, 1366 callback: callback, 1367 isMovementUp: isMovementUp, 1368 dtop: dtop, 1369 yMovement: getYmovement(element), 1370 anchorLink: element.data('anchor'), 1371 sectionIndex: element.index(SECTION_SEL), 1372 activeSlide: element.find(SLIDE_ACTIVE_SEL), 1373 activeSection: $(SECTION_ACTIVE_SEL), 1374 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 1375 1376 //caching the value of isResizing at the momment the function is called 1377 //because it will be checked later inside a setTimeout and the value might change 1378 localIsResizing: isResizing 1379 }; 1380 1381 //quiting when destination scroll is the same as the current one 1382 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 1383 1384 if(v.activeSlide.length){ 1385 slideAnchorLink = v.activeSlide.data('anchor'); 1386 slideIndex = v.activeSlide.index(); 1387 } 1388 1389 //callback (onLeave) if the site is not just resizing and readjusting the slides 1390 if($.isFunction(options.onLeave) && !v.localIsResizing){ 1391 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 1392 return; 1393 } 1394 } 1395 1396 // If continuousVertical && we need to wrap around 1397 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 1398 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 1399 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 1400 1401 v = createInfiniteSections(v); 1402 } 1403 1404 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 1405 if(!v.localIsResizing){ 1406 stopMedia(v.activeSection); 1407 } 1408 1409 if(options.scrollOverflow){ 1410 options.scrollOverflowHandler.beforeLeave(); 1411 } 1412 1413 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 1414 lazyLoad(element); 1415 1416 if(options.scrollOverflow){ 1417 options.scrollOverflowHandler.onLeave(); 1418 } 1419 1420 //preventing from activating the MouseWheelHandler event 1421 //more than once if the page is scrolling 1422 canScroll = false; 1423 1424 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 1425 1426 performMovement(v); 1427 1428 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 1429 lastScrolledDestiny = v.anchorLink; 1430 1431 //avoid firing it twice (as it does also on scroll) 1432 activateMenuAndNav(v.anchorLink, v.sectionIndex); 1433 } 1434 1435 /** 1436 * Performs the vertical movement (by CSS3 or by jQuery) 1437 */ 1438 function performMovement(v){ 1439 // using CSS3 translate functionality 1440 if (options.css3 && options.autoScrolling && !options.scrollBar) { 1441 1442 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 1443 // that's why we round it to 0. 1444 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 1445 transformContainer(translate3d, true); 1446 1447 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 1448 //scrollingSpeed to change in case of using silentMoveTo(); 1449 if(options.scrollingSpeed){ 1450 clearTimeout(afterSectionLoadsId); 1451 afterSectionLoadsId = setTimeout(function () { 1452 afterSectionLoads(v); 1453 }, options.scrollingSpeed); 1454 }else{ 1455 afterSectionLoads(v); 1456 } 1457 } 1458 1459 // using jQuery animate 1460 else{ 1461 var scrollSettings = getScrollSettings(v); 1462 1463 $(scrollSettings.element).animate( 1464 scrollSettings.options, 1465 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 1466 if(options.scrollBar){ 1467 1468 /* Hack! 1469 The timeout prevents setting the most dominant section in the viewport as "active" when the user 1470 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 1471 1472 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 1473 */ 1474 setTimeout(function(){ 1475 afterSectionLoads(v); 1476 },30); 1477 }else{ 1478 afterSectionLoads(v); 1479 } 1480 }); 1481 } 1482 } 1483 1484 /** 1485 * Gets the scrolling settings depending on the plugin autoScrolling option 1486 */ 1487 function getScrollSettings(v){ 1488 var scroll = {}; 1489 1490 if(options.autoScrolling && !options.scrollBar){ 1491 scroll.options = { 'top': -v.dtop}; 1492 scroll.element = WRAPPER_SEL; 1493 }else{ 1494 scroll.options = { 'scrollTop': v.dtop}; 1495 scroll.element = 'html, body'; 1496 } 1497 1498 return scroll; 1499 } 1500 1501 /** 1502 * Adds sections before or after the current one to create the infinite effect. 1503 */ 1504 function createInfiniteSections(v){ 1505 // Scrolling down 1506 if (!v.isMovementUp) { 1507 // Move all previous sections to after the active section 1508 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 1509 } 1510 else { // Scrolling up 1511 // Move all next sections to before the active section 1512 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 1513 } 1514 1515 // Maintain the displayed position (now that we changed the element order) 1516 silentScroll($(SECTION_ACTIVE_SEL).position().top); 1517 1518 // Maintain the active slides visible in the viewport 1519 keepSlidesPosition(); 1520 1521 // save for later the elements that still need to be reordered 1522 v.wrapAroundElements = v.activeSection; 1523 1524 // Recalculate animation variables 1525 v.dtop = v.element.position().top; 1526 v.yMovement = getYmovement(v.element); 1527 1528 //sections will temporally have another position in the DOM 1529 //updating this values in case we need them 1530 v.leavingSection = v.activeSection.index(SECTION_SEL) + 1; 1531 v.sectionIndex = v.element.index(SECTION_SEL); 1532 1533 return v; 1534 } 1535 1536 /** 1537 * Fix section order after continuousVertical changes have been animated 1538 */ 1539 function continuousVerticalFixSectionOrder (v) {
1540 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 1541 // finish moving the elements around so the direct navigation will function more simply 1542 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 1543 return; 1544 } 1545 1546 if (v.isMovementUp) { 1547 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 1548 } 1549 else { 1550 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 1551 } 1552 1553 silentScroll($(SECTION_ACTIVE_SEL).position().top); 1554 1555 // Maintain the active slides visible in the viewport 1556 keepSlidesPosition(); 1557 } 1558 1559 1560 /** 1561 * Actions to do once the section is loaded. 1562 */ 1563 function afterSectionLoads (v){ 1564 continuousVerticalFixSectionOrder(v); 1565 1566 //callback (afterLoad) if the site is not just resizing and readjusting the slides 1567 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 1568 1569 if(options.scrollOverflow){ 1570 options.scrollOverflowHandler.afterLoad(); 1571 } 1572 1573 if(!v.localIsResizing){ 1574 playMedia(v.element); 1575 } 1576 1577 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 1578 1579 canScroll = true; 1580 1581 $.isFunction(v.callback) && v.callback.call(this); 1582 } 1583 1584 /** 1585 * Sets the value for the given attribute from the `data-` attribute with the same suffix 1586 * ie: data-srcset ==> srcset | data-src ==> src 1587 */ 1588 function setSrc(element, attribute){ 1589 element 1590 .attr(attribute, element.data(attribute)) 1591 .removeAttr('data-' + attribute); 1592 } 1593 1594 /** 1595 * Lazy loads image, video and audio elements. 1596 */ 1597 function lazyLoad(destiny){ 1598 if (!options.lazyLoading){ 1599 return; 1600 } 1601 1602 var panel = getSlideOrSection(destiny); 1603 var element; 1604 1605 panel.find('img[data-src], img[data-srcset], source[data-src], video[data-src], audio[data-src], iframe[data-src]').each(function(){ 1606 element = $(this); 1607 1608 $.each(['src', 'srcset'], function(index, type){ 1609 var attribute = element.attr('data-' + type); 1610 if(typeof attribute !== 'undefined' && attribute){ 1611 setSrc(element, type); 1612 } 1613 }); 1614 1615 if(element.is('source')){ 1616 var typeToPlay = element.closest('video').length ? 'video' : 'audio'; 1617 element.closest(typeToPlay).get(0).load(); 1618 } 1619 }); 1620 } 1621 1622 /** 1623 * Plays video and audio elements. 1624 */ 1625 function playMedia(destiny){ 1626 var panel = getSlideOrSection(destiny); 1627 1628 //playing HTML5 media elements 1629 panel.find('video, audio').each(function(){ 1630 var element = $(this).get(0); 1631 1632 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 1633 element.play(); 1634 } 1635 }); 1636 1637 //youtube videos 1638 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 1639 var element = $(this).get(0); 1640 1641 if ( element.hasAttribute('data-autoplay') ){ 1642 playYoutube(element); 1643 } 1644 1645 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 1646 element.onload = function() { 1647 if ( element.hasAttribute('data-autoplay') ){ 1648 playYoutube(element); 1649 } 1650 }; 1651 }); 1652 } 1653 1654 /** 1655 * Plays a youtube video 1656 */ 1657 function playYoutube(element){ 1658 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 1659 } 1660 1661 /** 1662 * Stops video and audio elements. 1663 */ 1664 function stopMedia(destiny){ 1665 var panel = getSlideOrSection(destiny); 1666 1667 //stopping HTML5 media elements 1668 panel.find('video, audio').each(function(){ 1669 var element = $(this).get(0); 1670 1671 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 1672 element.pause(); 1673 } 1674 }); 1675 1676 //youtube videos 1677 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 1678 var element = $(this).get(0); 1679 1680 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 1681 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 1682 } 1683 }); 1684 } 1685 1686 /** 1687 * Gets the active slide (or section) for the given section 1688 */ 1689 function getSlideOrSection(destiny){ 1690 var slide = destiny.find(SLIDE_ACTIVE_SEL); 1691 if( slide.length ) { 1692 destiny = $(slide); 1693 } 1694 1695 return destiny; 1696 } 1697 1698 /**
1699 * Scrolls to the anchor in the URL when loading the site 1700 */ 1701 function scrollToAnchor(){ 1702 var anchors = getAnchorsURL(); 1703 var sectionAnchor = anchors.section; 1704 var slideAnchor = anchors.slide; 1705 1706 if(sectionAnchor){ //if theres any # 1707 if(options.animateAnchor){ 1708 scrollPageAndSlide(sectionAnchor, slideAnchor); 1709 }else{ 1710 silentMoveTo(sectionAnchor, slideAnchor); 1711 } 1712 } 1713 } 1714 1715 /** 1716 * Detecting any change on the URL to scroll to the given anchor link 1717 * (a way to detect back history button as we play with the hashes on the URL) 1718 */ 1719 function hashChangeHandler(){ 1720 if(!isScrolling && !options.lockAnchors){ 1721 var anchors = getAnchorsURL(); 1722 var sectionAnchor = anchors.section; 1723 var slideAnchor = anchors.slide; 1724 1725 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 1726 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 1727 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 1728 1729 if(sectionAnchor.length){ 1730 /*in order to call scrollpage() only once for each destination at a time 1731 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 1732 event is fired on every scroll too.*/ 1733 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 1734 scrollPageAndSlide(sectionAnchor, slideAnchor); 1735 } 1736 } 1737 } 1738 } 1739 1740 //gets the URL anchors (section and slide) 1741 function getAnchorsURL(){ 1742 //getting the anchor link in the URL and deleting the `#` 1743 var hash = window.location.hash; 1744 var anchorsParts = hash.replace('#', '').split('/'); 1745 1746 //using / for visual reasons and not as a section/slide separator #2803 1747 var isFunkyAnchor = hash.indexOf('#/') > -1; 1748 1749 return { 1750 section: isFunkyAnchor ? '/' + anchorsParts[1] : decodeURIComponent(anchorsParts[0]), 1751 slide: isFunkyAnchor ? decodeURIComponent(anchorsParts[2]) : decodeURIComponent(anchorsParts[1]) 1752 } 1753 } 1754 1755 //Sliding with arrow keys, both, vertical and horizontal 1756 function keydownHandler(e) { 1757 1758 clearTimeout(keydownId); 1759 1760 var activeElement = $(':focus'); 1761 1762 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 1763 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 1764 options.keyboardScrolling && options.autoScrolling){ 1765 var keyCode = e.which; 1766 1767 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 1768 var keyControls = [40, 38, 32, 33, 34]; 1769 if($.inArray(keyCode, keyControls) > -1){ 1770 e.preventDefault(); 1771 } 1772 1773 controlPressed = e.ctrlKey; 1774 1775 keydownId = setTimeout(function(){ 1776 onkeydown(e); 1777 },150); 1778 } 1779 } 1780 1781 function tooltipTextHandler(){ 1782 $(this).prev().trigger('click'); 1783 } 1784 1785 //to prevent scrolling while zooming 1786 function keyUpHandler(e){ 1787 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 1788 controlPressed = e.ctrlKey; 1789 } 1790 } 1791 1792 //binding the mousemove when the mouse's middle button is released 1793 function mouseDownHandler(e){ 1794 //middle button 1795 if (e.which == 2){ 1796 oldPageY = e.pageY; 1797 container.on('mousemove', mouseMoveHandler); 1798 } 1799 } 1800 1801 //unbinding the mousemove when the mouse's middle button is released 1802 function mouseUpHandler(e){ 1803 //middle button 1804 if (e.which == 2){ 1805 container.off('mousemove'); 1806 } 1807 } 1808 1809 //Scrolling horizontally when clicking on the slider controls. 1810 function slideArrowHandler(){ 1811 var section = $(this).closest(SECTION_SEL); 1812 1813 if ($(this).hasClass(SLIDES_PREV)) { 1814 if(isScrollAllowed.m.left){ 1815 moveSlideLeft(section); 1816 } 1817 } else { 1818 if(isScrollAllowed.m.right){ 1819 moveSlideRight(section); 1820 } 1821 } 1822 } 1823 1824 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 1825 function blurHandler(){ 1826 isWindowFocused = false; 1827 controlPressed = false; 1828 } 1829 1830 //Scrolls to the section when clicking the navigation bullet 1831 function sectionBulletHandler(e){ 1832 e.preventDefault(); 1833 var index = $(this).parent().index(); 1834 scrollPage($(SECTION_SEL).eq(index)); 1835 } 1836 1837 //Scrolls the slider to the given slide destination for the given section 1838 function slideBulletHandler(e){ 1839 e.preventDefault(); 1840 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 1841 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 1842
1843 landscapeScroll(slides, destiny); 1844 } 1845 1846 /** 1847 * Keydown event 1848 */ 1849 function onkeydown(e){ 1850 var shiftPressed = e.shiftKey; 1851 1852 //do nothing if we can not scroll or we are not using horizotnal key arrows. 1853 if(!canScroll && [37,39].indexOf(e.which) < 0){ 1854 return; 1855 } 1856 1857 switch (e.which) { 1858 //up 1859 case 38: 1860 case 33: 1861 if(isScrollAllowed.k.up){ 1862 moveSectionUp(); 1863 } 1864 break; 1865 1866 //down 1867 case 32: //spacebar 1868 if(shiftPressed && isScrollAllowed.k.up){ 1869 moveSectionUp(); 1870 break; 1871 } 1872 /* falls through */ 1873 case 40: 1874 case 34: 1875 if(isScrollAllowed.k.down){ 1876 moveSectionDown(); 1877 } 1878 break; 1879 1880 //Home 1881 case 36: 1882 if(isScrollAllowed.k.up){ 1883 moveTo(1); 1884 } 1885 break; 1886 1887 //End 1888 case 35: 1889 if(isScrollAllowed.k.down){ 1890 moveTo( $(SECTION_SEL).length ); 1891 } 1892 break; 1893 1894 //left 1895 case 37: 1896 if(isScrollAllowed.k.left){ 1897 moveSlideLeft(); 1898 } 1899 break; 1900 1901 //right 1902 case 39: 1903 if(isScrollAllowed.k.right){ 1904 moveSlideRight(); 1905 } 1906 break; 1907 1908 default: 1909 return; // exit this handler for other keys 1910 } 1911 } 1912 1913 /** 1914 * Detecting the direction of the mouse movement. 1915 * Used only for the middle button of the mouse. 1916 */ 1917 var oldPageY = 0; 1918 function mouseMoveHandler(e){ 1919 if(canScroll){ 1920 // moving up 1921 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 1922 moveSectionUp(); 1923 } 1924 1925 // moving down 1926 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 1927 moveSectionDown(); 1928 } 1929 } 1930 oldPageY = e.pageY; 1931 } 1932 1933 /** 1934 * Scrolls horizontal sliders. 1935 */ 1936 function landscapeScroll(slides, destiny, direction){ 1937 var section = slides.closest(SECTION_SEL); 1938 var v = { 1939 slides: slides, 1940 destiny: destiny, 1941 direction: direction, 1942 destinyPos: destiny.position(), 1943 slideIndex: destiny.index(), 1944 section: section, 1945 sectionIndex: section.index(SECTION_SEL), 1946 anchorLink: section.data('anchor'), 1947 slidesNav: section.find(SLIDES_NAV_SEL), 1948 slideAnchor: getAnchor(destiny), 1949 prevSlide: section.find(SLIDE_ACTIVE_SEL), 1950 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 1951 1952 //caching the value of isResizing at the momment the function is called 1953 //because it will be checked later inside a setTimeout and the value might change 1954 localIsResizing: isResizing 1955 }; 1956 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 1957 1958 //important!! Only do it when not resizing 1959 if(!v.localIsResizing){ 1960 //preventing from scrolling to the next/prev section when using scrollHorizontally 1961 canScroll = false; 1962 } 1963 1964 if(options.onSlideLeave){ 1965 1966 //if the site is not just resizing and readjusting the slides 1967 if(!v.localIsResizing && v.xMovement!=='none'){ 1968 if($.isFunction( options.onSlideLeave )){ 1969 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.direction, v.slideIndex ) === false){ 1970 slideMoving = false; 1971 return; 1972 } 1973 } 1974 } 1975 } 1976 1977 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 1978 1979 if(!v.localIsResizing){ 1980 stopMedia(v.prevSlide); 1981 lazyLoad(destiny); 1982 } 1983 1984 if(!options.loopHorizontal && options.controlArrows){ 1985 //hidding it for the fist slide, showing for the rest 1986 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 1987 1988 //hidding it for the last slide, showing for the rest 1989 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 1990 } 1991 1992 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 1993 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 1994 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 1995 } 1996 1997 performHorizontalMove(slides, v, true); 1998 } 1999 2000 2001 function afterSlideLoads(v){ 2002 activeSlidesNavigation(v.slidesNav, v.slideIndex); 2003 2004 //if the site is not just resizing and readjusting the slides 2005 if(!v.localIsResizing){ 2006 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 2007 2008 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 2009 //and to prevent double scroll right after a windows resize 2010 canScroll = true; 2011 2012 playMedia(v.destiny); 2013 } 2014 2015 //letting them slide again 2016 slideMoving = false; 2017 } 2018 2019 /** 2020 * Performs the horizontal movement. (CSS3 or jQuery) 2021 * 2022 * @param fireCallback {Bool} - determines whether or not to fire the callback 2023 */ 2024 function performHorizontalMove(slides, v, fireCallback){ 2025 var destinyPos = v.destinyPos; 2026 2027 if(options.css3){ 2028 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 2029 2030 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d)); 2031 2032 afterSlideLoadsId = setTimeout(function(){ 2033 fireCallback && afterSlideLoads(v); 2034 }, options.scrollingSpeed, options.easing); 2035 }else{ 2036 slides.animate({ 2037 scrollLeft : Math.round(destinyPos.left) 2038 }, options.scrollingSpeed, options.easing, function() { 2039 2040 fireCallback && afterSlideLoads(v); 2041 }); 2042 } 2043 } 2044 2045 /** 2046 * Sets the state for the horizontal bullet navigations. 2047 */ 2048 function activeSlidesNavigation(slidesNav, slideIndex){ 2049 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 2050 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 2051 } 2052 2053 var previousHeight = windowsHeight; 2054 2055 //when resizing the site, we adjust the heights of the sections, slimScroll... 2056 function resizeHandler(){ 2057 //checking if it needs to get responsive 2058 responsive(); 2059 2060 // rebuild immediately on touch devices 2061 if (isTouchDevice) { 2062 var activeElement = $(document.activeElement); 2063 2064 //if the keyboard is NOT visible 2065 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 2066 var currentHeight = $window.height(); 2067 2068 //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) 2069 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 2070 reBuild(true); 2071 previousHeight = currentHeight; 2072 } 2073 } 2074 }else{ 2075 //in order to call the functions only when the resize is finished 2076 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 2077 clearTimeout(resizeId); 2078 2079 resizeId = setTimeout(function(){ 2080 reBuild(true); 2081 }, 350); 2082 } 2083 } 2084 2085 /** 2086 * Checks if the site needs to get responsive and disables autoScrolling if so. 2087 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 2088 */ 2089 function responsive(){ 2090 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 2091 var heightLimit = options.responsiveHeight; 2092 2093 //only calculating what we need. Remember its called on the resize event. 2094 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 2095 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 2096 2097 if(widthLimit && heightLimit){ 2098 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 2099 } 2100 else if(widthLimit){ 2101 setResponsive(isBreakingPointWidth);
2102 } 2103 else if(heightLimit){ 2104 setResponsive(isBreakingPointHeight); 2105 } 2106 } 2107 2108 /** 2109 * Adds transition animations for the given element 2110 */ 2111 function addAnimation(element){ 2112 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 2113 2114 element.removeClass(NO_TRANSITION); 2115 return element.css({ 2116 '-webkit-transition': transition, 2117 'transition': transition 2118 }); 2119 } 2120 2121 /** 2122 * Remove transition animations for the given element 2123 */ 2124 function removeAnimation(element){ 2125 return element.addClass(NO_TRANSITION); 2126 } 2127 2128 /** 2129 * Activating the vertical navigation bullets according to the given slide name. 2130 */ 2131 function activateNavDots(name, sectionIndex){ 2132 if(options.navigation){ 2133 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 2134 if(name){ 2135 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 2136 }else{ 2137 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 2138 } 2139 } 2140 } 2141 2142 /** 2143 * Activating the website main menu elements according to the given slide name. 2144 */ 2145 function activateMenuElement(name){ 2146 if(options.menu){ 2147 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 2148 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 2149 } 2150 } 2151 2152 /** 2153 * Sets to active the current menu and vertical nav items. 2154 */ 2155 function activateMenuAndNav(anchor, index){ 2156 activateMenuElement(anchor); 2157 activateNavDots(anchor, index); 2158 } 2159 2160 /** 2161 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 2162 * from the current section. 2163 */ 2164 function getYmovement(destiny){ 2165 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 2166 var toIndex = destiny.index(SECTION_SEL); 2167 if( fromIndex == toIndex){ 2168 return 'none'; 2169 } 2170 if(fromIndex > toIndex){ 2171 return 'up'; 2172 } 2173 return 'down'; 2174 } 2175 2176 /** 2177 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 2178 * from the current slide. 2179 */ 2180 function getXmovement(fromIndex, toIndex){ 2181 if( fromIndex == toIndex){ 2182 return 'none'; 2183 } 2184 if(fromIndex > toIndex){ 2185 return 'left'; 2186 } 2187 return 'right'; 2188 } 2189 2190 function addTableClass(element){ 2191 //In case we are styling for the 2nd time as in with reponsiveSlides 2192 if(!element.hasClass(TABLE)){ 2193 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 2194 } 2195 } 2196 2197 function getTableHeight(element){ 2198 var sectionHeight = windowsHeight; 2199 2200 if(options.paddingTop || options.paddingBottom){ 2201 var section = element; 2202 if(!section.hasClass(SECTION)){ 2203 section = element.closest(SECTION_SEL); 2204 } 2205 2206 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 2207 sectionHeight = (windowsHeight - paddings); 2208 } 2209 2210 return sectionHeight; 2211 } 2212 2213 /** 2214 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 2215 */ 2216 function transformContainer(translate3d, animated){ 2217 if(animated){ 2218 addAnimation(container); 2219 }else{ 2220 removeAnimation(container); 2221 } 2222 2223 container.css(getTransforms(translate3d)); 2224 2225 //syncronously removing the class after the animation has been applied. 2226 setTimeout(function(){ 2227 container.removeClass(NO_TRANSITION); 2228 },10); 2229 } 2230 2231 /** 2232 * Gets a section by its anchor / index 2233 */ 2234 function getSectionByAnchor(sectionAnchor){ 2235 if(!sectionAnchor) return []; 2236 2237 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 2238 if(!section.length){ 2239 section = $(SECTION_SEL).eq( sectionAnchor -1);
2240 } 2241 2242 return section; 2243 } 2244 2245 /** 2246 * Gets a slide inside a given section by its anchor / index 2247 */ 2248 function getSlideByAnchor(slideAnchor, section){ 2249 var slides = section.find(SLIDES_WRAPPER_SEL); 2250 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 2251 2252 if(!slide.length){ 2253 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 2254 } 2255 2256 return slide; 2257 } 2258 2259 /** 2260 * Scrolls to the given section and slide anchors 2261 */ 2262 function scrollPageAndSlide(destiny, slide){ 2263 var section = getSectionByAnchor(destiny); 2264 2265 //do nothing if there's no section with the given anchor name 2266 if(!section.length) return; 2267 2268 //default slide 2269 if (typeof slide === 'undefined') { 2270 slide = 0; 2271 } 2272 2273 //we need to scroll to the section and then to the slide 2274 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 2275 scrollPage(section, function(){ 2276 scrollSlider(section, slide); 2277 }); 2278 } 2279 //if we were already in the section 2280 else{ 2281 scrollSlider(section, slide); 2282 } 2283 } 2284 2285 /** 2286 * Scrolls the slider to the given slide destination for the given section 2287 */ 2288 function scrollSlider(section, slideAnchor){ 2289 if(typeof slideAnchor !== 'undefined'){ 2290 var slides = section.find(SLIDES_WRAPPER_SEL); 2291 var destiny = getSlideByAnchor(slideAnchor, section); 2292 2293 if(destiny.length){ 2294 landscapeScroll(slides, destiny); 2295 } 2296 } 2297 } 2298 2299 /** 2300 * Creates a landscape navigation bar with dots for horizontal sliders. 2301 */ 2302 function addSlidesNavigation(section, numSlides){ 2303 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 2304 var nav = section.find(SLIDES_NAV_SEL); 2305 2306 //top or bottom 2307 nav.addClass(options.slidesNavPosition); 2308 2309 for(var i=0; i< numSlides; i++){ 2310 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 2311 } 2312 2313 //centering it 2314 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 2315 2316 nav.find('li').first().find('a').addClass(ACTIVE); 2317 } 2318 2319 2320 /** 2321 * Sets the state of the website depending on the active section/slide. 2322 * It changes the URL hash when needed and updates the body class. 2323 */ 2324 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 2325 var sectionHash = ''; 2326 2327 if(options.anchors.length && !options.lockAnchors){ 2328 2329 //isn't it the first slide? 2330 if(slideIndex){ 2331 if(typeof anchorLink !== 'undefined'){ 2332 sectionHash = anchorLink; 2333 } 2334 2335 //slide without anchor link? We take the index instead. 2336 if(typeof slideAnchor === 'undefined'){ 2337 slideAnchor = slideIndex; 2338 } 2339 2340 lastScrolledSlide = slideAnchor; 2341 setUrlHash(sectionHash + '/' + slideAnchor); 2342 2343 //first slide won't have slide anchor, just the section one 2344 }else if(typeof slideIndex !== 'undefined'){ 2345 lastScrolledSlide = slideAnchor; 2346 setUrlHash(anchorLink); 2347 } 2348 2349 //section without slides 2350 else{ 2351 setUrlHash(anchorLink); 2352 } 2353 } 2354 2355 setBodyClass(); 2356 } 2357 2358 /** 2359 * Sets the URL hash. 2360 */ 2361 function setUrlHash(url){ 2362 if(options.recordHistory){ 2363 location.hash = url; 2364 }else{ 2365 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 2366 if(isTouchDevice || isTouch){ 2367 window.history.replaceState(undefined, undefined, '#' + url); 2368 }else{ 2369 var baseUrl = window.location.href.split('#')[0]; 2370 window.location.replace( baseUrl + '#' + url ); 2371 } 2372 } 2373 } 2374 2375 /**
2376 * Gets the anchor for the given slide / section. Its index will be used if there's none. 2377 */ 2378 function getAnchor(element){ 2379 var anchor = element.data('anchor'); 2380 var index = element.index(); 2381 2382 //Slide without anchor link? We take the index instead. 2383 if(typeof anchor === 'undefined'){ 2384 anchor = index; 2385 } 2386 2387 return anchor; 2388 } 2389 2390 /** 2391 * Sets a class for the body of the page depending on the active section / slide 2392 */ 2393 function setBodyClass(){ 2394 var section = $(SECTION_ACTIVE_SEL); 2395 var slide = section.find(SLIDE_ACTIVE_SEL); 2396 2397 var sectionAnchor = getAnchor(section); 2398 var slideAnchor = getAnchor(slide); 2399 2400 var text = String(sectionAnchor); 2401 2402 if(slide.length){ 2403 text = text + '-' + slideAnchor; 2404 } 2405 2406 //changing slash for dash to make it a valid CSS style 2407 text = text.replace('/', '-').replace('#',''); 2408 2409 //removing previous anchor classes 2410 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 2411 $body[0].className = $body[0].className.replace(classRe, ''); 2412 2413 //adding the current anchor 2414 $body.addClass(VIEWING_PREFIX + '-' + text); 2415 } 2416 2417 /** 2418 * Checks for translate3d support 2419 * @return boolean 2420 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 2421 */ 2422 function support3d() { 2423 var el = document.createElement('p'), 2424 has3d, 2425 transforms = { 2426 'webkitTransform':'-webkit-transform',
2427 'OTransform':'-o-transform', 2428 'msTransform':'-ms-transform', 2429 'MozTransform':'-moz-transform', 2430 'transform':'transform' 2431 }; 2432 2433 // Add it to the body to get the computed style. 2434 document.body.insertBefore(el, null); 2435 2436 for (var t in transforms) { 2437 if (el.style[t] !== undefined) { 2438 el.style[t] = 'translate3d(1px,1px,1px)'; 2439 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 2440 } 2441 } 2442 2443 document.body.removeChild(el); 2444 2445 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 2446 } 2447 2448 /** 2449 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 2450 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 2451 */ 2452 function removeMouseWheelHandler(){ 2453 if (document.addEventListener) { 2454 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 2455 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 2456 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 2457 } else { 2458 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 2459 } 2460 } 2461 2462 /** 2463 * Adds the auto scrolling action for the mouse wheel and trackpad. 2464 * After this function is called, the mousewheel and trackpad movements will scroll through sections 2465 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 2466 */ 2467 function addMouseWheelHandler(){ 2468 var prefix = ''; 2469 var _addEventListener; 2470 2471 if (window.addEventListener){ 2472 _addEventListener = "addEventListener"; 2473 }else{ 2474 _addEventListener = "attachEvent"; 2475 prefix = 'on'; 2476 } 2477 2478 // detect available wheel event 2479 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 2480 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 2481 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 2482 2483 2484 if(support == 'DOMMouseScroll'){ 2485 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false); 2486 } 2487 2488 //handle MozMousePixelScroll in older Firefox 2489 else{ 2490 document[ _addEventListener ](prefix + support, MouseWheelHandler, false); 2491 } 2492 } 2493 2494 /** 2495 * Binding the mousemove when the mouse's middle button is pressed 2496 */ 2497 function addMiddleWheelHandler(){ 2498 container 2499 .on('mousedown', mouseDownHandler) 2500 .on('mouseup', mouseUpHandler); 2501 } 2502 2503 /** 2504 * Unbinding the mousemove when the mouse's middle button is released 2505 */ 2506 function removeMiddleWheelHandler(){ 2507 container 2508 .off('mousedown', mouseDownHandler) 2509 .off('mouseup', mouseUpHandler); 2510 } 2511 2512 /** 2513 * Adds the possibility to auto scroll through sections on touch devices. 2514 */ 2515 function addTouchHandler(){ 2516 if(isTouchDevice || isTouch){ 2517 if(options.autoScrolling){ 2518 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 2519 } 2520 2521 $(WRAPPER_SEL) 2522 .off(events.touchstart).on(events.touchstart, touchStartHandler) 2523 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 2524 } 2525 } 2526 2527 /** 2528 * Removes the auto scrolling for touch devices. 2529 */ 2530 function removeTouchHandler(){ 2531 if(isTouchDevice || isTouch){ 2532 if(options.autoScrolling){ 2533 $body.off(events.touchmove); 2534 } 2535 2536 $(WRAPPER_SEL) 2537 .off(events.touchstart) 2538 .off(events.touchmove); 2539 } 2540 } 2541 2542 /* 2543 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
2544 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 2545 */ 2546 function getMSPointer(){ 2547 var pointer; 2548 2549 //IE >= 11 & rest of browsers 2550 if(window.PointerEvent){ 2551 pointer = { down: 'pointerdown', move: 'pointermove'}; 2552 } 2553 2554 //IE < 11 2555 else{ 2556 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 2557 } 2558 2559 return pointer; 2560 } 2561 2562 /** 2563 * Gets the pageX and pageY properties depending on the browser. 2564 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 2565 */ 2566 function getEventsPage(e){ 2567 var events = []; 2568 2569 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 2570 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 2571 2572 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 2573 if(isTouch && isReallyTouch(e) && options.scrollBar){ 2574 events.y = e.touches[0].pageY; 2575 events.x = e.touches[0].pageX; 2576 } 2577 2578 return events; 2579 } 2580 2581 /** 2582 * Slides silently (with no animation) the active slider to the given slide. 2583 * @param noCallback {bool} true or defined -> no callbacks 2584 */ 2585 function silentLandscapeScroll(activeSlide, noCallbacks){ 2586 setScrollingSpeed (0, 'internal'); 2587 2588 if(typeof noCallbacks !== 'undefined'){ 2589 //preventing firing callbacks afterSlideLoad etc. 2590 isResizing = true; 2591 } 2592 2593 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 2594 2595 if(typeof noCallbacks !== 'undefined'){ 2596 isResizing = false; 2597 } 2598 2599 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 2600 } 2601 2602 /** 2603 * Scrolls silently (with no animation) the page to the given Y position. 2604 */ 2605 function silentScroll(top){ 2606 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 2607 // that's why we round it to 0. 2608 var roundedTop = Math.round(top); 2609 2610 if (options.css3 && options.autoScrolling && !options.scrollBar){ 2611 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 2612 transformContainer(translate3d, false); 2613 } 2614 else if(options.autoScrolling && !options.scrollBar){ 2615 container.css('top', -roundedTop); 2616 } 2617 else{ 2618 $htmlBody.scrollTop(roundedTop); 2619 } 2620 } 2621 2622 /** 2623 * Returns the cross-browser transform string. 2624 */ 2625 function getTransforms(translate3d){ 2626 return { 2627 '-webkit-transform': translate3d, 2628 '-moz-transform': translate3d, 2629 '-ms-transform':translate3d, 2630 'transform': translate3d 2631 }; 2632 } 2633 2634 /** 2635 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 2636 * @type m (mouse) or k (keyboard) 2637 */ 2638 function setIsScrollAllowed(value, direction, type){ 2639 //up, down, left, right 2640 if(direction !== 'all'){ 2641 isScrollAllowed[type][direction] = value; 2642 } 2643 2644 //all directions? 2645 else{ 2646 $.each(Object.keys(isScrollAllowed[type]), function(index, key){ 2647 isScrollAllowed[type][key] = value; 2648 }); 2649 } 2650 } 2651 2652 /* 2653 * Destroys fullpage.js plugin events and optinally its html markup and styles 2654 */ 2655 function destroy(all){ 2656 setAutoScrolling(false, 'internal'); 2657 setAllowScrolling(false); 2658 setKeyboardScrolling(false); 2659 container.addClass(DESTROYED); 2660 2661 clearTimeout(afterSlideLoadsId); 2662 clearTimeout(afterSectionLoadsId); 2663 clearTimeout(resizeId); 2664 clearTimeout(scrollId); 2665 clearTimeout(scrollId2); 2666 2667 $window 2668 .off('scroll', scrollHandler) 2669 .off('hashchange', hashChangeHandler) 2670 .off('resize', resizeHandler); 2671 2672 $document 2673 .off('click touchstart', SECTION_NAV_SEL + ' a') 2674 .off('mouseenter', SECTION_NAV_SEL + ' li') 2675 .off('mouseleave', SECTION_NAV_SEL + ' li') 2676 .off('click touchstart', SLIDES_NAV_LINK_SEL) 2677 .off('mouseover', options.normalScrollElements) 2678 .off('mouseout', options.normalScrollElements); 2679 2680 $(SECTION_SEL) 2681 .off('click touchstart', SLIDES_ARROW_SEL);
2682 2683 clearTimeout(afterSlideLoadsId); 2684 clearTimeout(afterSectionLoadsId); 2685 2686 //lets make a mess! 2687 if(all){ 2688 destroyStructure(); 2689 } 2690 } 2691 2692 /* 2693 * Removes inline styles added by fullpage.js 2694 */ 2695 function destroyStructure(){ 2696 //reseting the `top` or `translate` properties to 0 2697 silentScroll(0); 2698 2699 //loading all the lazy load content 2700 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 2701 setSrc($(this), 'src'); 2702 }); 2703 2704 container.find('img[data-srcset]').each(function(){ 2705 setSrc($(this), 'srcset'); 2706 }); 2707 2708 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 2709 2710 //removing inline styles 2711 $(SECTION_SEL).css( { 2712 'height': '', 2713 'background-color' : '', 2714 'padding': '' 2715 }); 2716 2717 $(SLIDE_SEL).css( { 2718 'width': '' 2719 }); 2720 2721 container.css({ 2722 'height': '', 2723 'position': '', 2724 '-ms-touch-action': '', 2725 'touch-action': '' 2726 }); 2727 2728 $htmlBody.css({ 2729 'overflow': '', 2730 'height': '' 2731 }); 2732 2733 // remove .fp-enabled class 2734 $('html').removeClass(ENABLED); 2735 2736 // remove .fp-responsive class 2737 $body.removeClass(RESPONSIVE); 2738 2739 // remove all of the .fp-viewing- classes 2740 $.each($body.get(0).className.split(/\s+/), function (index, className) { 2741 if (className.indexOf(VIEWING_PREFIX) === 0) { 2742 $body.removeClass(className); 2743 } 2744 }); 2745 2746 //removing added classes 2747 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 2748 if(options.scrollOverflowHandler){ 2749 options.scrollOverflowHandler.remove($(this)); 2750 } 2751 $(this).removeClass(TABLE + ' ' + ACTIVE); 2752 }); 2753 2754 removeAnimation(container); 2755 2756 //Unwrapping content 2757 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 2758 //unwrap not being use in case there's no child element inside and its just text 2759 $(this).replaceWith(this.childNodes); 2760 }); 2761 2762 //removing the applied transition from the fullpage wrapper 2763 container.css({ 2764 '-webkit-transition': 'none', 2765 'transition': 'none' 2766 }); 2767 2768 //scrolling the page to the top with no animation 2769 $htmlBody.scrollTop(0); 2770 2771 //removing selectors 2772 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 2773 $.each(usedSelectors, function(index, value){ 2774 $('.' + value).removeClass(value); 2775 }); 2776 } 2777 2778 /* 2779 * Sets the state for a variable with multiple states (original, and temporal) 2780 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 2781 * This function is used to keep track of both states, the original and the temporal one. 2782 * If type is not 'internal', then we assume the user is globally changing the variable. 2783 */ 2784 function setVariableState(variable, value, type){ 2785 options[variable] = value; 2786 if(type !== 'internal'){ 2787 originals[variable] = value; 2788 } 2789 } 2790 2791 /** 2792 * Displays warnings 2793 */ 2794 function displayWarnings(){ 2795 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 2796 if($('html').hasClass(ENABLED)){ 2797 showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 2798 return; 2799 } 2800 2801 // Disable mutually exclusive settings 2802 if (options.continuousVertical && 2803 (options.loopTop || options.loopBottom)) { 2804 options.continuousVertical = false; 2805 showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 2806 } 2807 2808 if(options.scrollBar && options.scrollOverflow){ 2809 showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 2810 } 2811 2812 if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 2813 options.continuousVertical = false; 2814 showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 2815 } 2816 2817 if(options.scrollOverflow && !options.scrollOverflowHandler){ 2818 options.scrollOverflow = false; 2819 showError('error', 'The option `scrollOverflow:true` requires the file `scrolloverflow.min.js`. Please include it before fullPage.js.'); 2820 } 2821 2822 //using extensions? Wrong file! 2823 $.each(extensions, function(index, extension){ 2824 //is the option set to true? 2825 if(options[extension]){ 2826 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 2827 } 2828 }); 2829 2830 //anchors can not have the same value as any element ID or NAME 2831 $.each(options.anchors, function(index, name){ 2832 2833 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 2834 var nameAttr = $document.find('[name]').filter(function() { 2835 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 2836 }); 2837 2838 var idAttr = $document.find('[id]').filter(function() { 2839 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 2840 }); 2841 2842 if(idAttr.length || nameAttr.length ){ 2843 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
2844 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 2845 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 2846 } 2847 }); 2848 } 2849 2850 /** 2851 * Shows a message in the console of the given type. 2852 */ 2853 function showError(type, text){ 2854 console && console[type] && console[type]('fullPage: ' + text); 2855 } 2856 2857 }; //end of $.fn.fullpage 2858});
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.