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