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