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