| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| //@ts-check | ||
| import * as utils from '../common/utils.js'; | ||
| import { silentScroll } from '../common/silentScroll.js'; | ||
| import { getState, setState } from '../common/state.js'; | ||
| import { silentLandscapeScroll } from '../slides/silentLandscapeScroll.js'; | ||
| import { | ||
| SECTION_SEL, | ||
| SLIDE_ACTIVE_SEL | ||
| } from '../common/selectors.js'; | ||
|
|
||
| /** | ||
| * Maintains the active slides in the viewport | ||
| * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) | ||
| */ | ||
| function keepSlidesPosition(){ | ||
| var activeSlides = utils.$(SLIDE_ACTIVE_SEL); | ||
| for( var i =0; i<activeSlides.length; i++){ | ||
| silentLandscapeScroll(activeSlides[i], 'internal'); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Fix section order after continuousVertical changes have been animated | ||
| */ | ||
| export function continuousVerticalFixSectionOrder (v) { | ||
| // If continuousVertical is in effect (and autoScrolling would also be in effect then), | ||
| // finish moving the elements around so the direct navigation will function more simply | ||
| if (v.wrapAroundElements == null) { | ||
| return; | ||
| } | ||
|
|
||
| if (v.isMovementUp) { | ||
| utils.before(utils.$(SECTION_SEL)[0], v.wrapAroundElements); | ||
| } | ||
| else { | ||
| utils.after(utils.$(SECTION_SEL)[getState().sections.length -1 ], v.wrapAroundElements); | ||
| } | ||
|
|
||
| silentScroll(getState().activeSection.item.offsetTop); | ||
|
|
||
| // Maintain the active slides visible in the viewport | ||
| keepSlidesPosition(); | ||
|
|
||
| setState({isDoingContinousVertical: false}); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,29 +1,33 @@ | ||
| import { FP } from "./common/constants.js"; | ||
| import { getOptions } from "./common/options.js"; | ||
| import * as utils from './common/utils.js'; | ||
|
|
||
| /** | ||
| * jQuery adapter for fullPage.js 3.0.0 | ||
| */ | ||
| // @ts-ignore | ||
| if(window.jQuery && window.fullpage){ | ||
| (function ($, fullpage) { | ||
| 'use strict'; | ||
|
|
||
| // No jQuery No Go | ||
| if (!$ || !fullpage) { | ||
| // @ts-ignore | ||
| utils.showError('error', 'jQuery is required to use the jQuery fullpage adapter!'); | ||
| return; | ||
| } | ||
|
|
||
| $.fn.fullpage = function(options) { | ||
| options = $.extend({}, options, {'$': $}); | ||
| var instance = new fullpage(this[0], options); | ||
|
|
||
| // Creating the $.fn.fullpage object | ||
| Object.keys(FP).forEach(function (key) { | ||
| getOptions().$.fn.fullpage[key] = FP[key]; | ||
| }); | ||
| }; | ||
|
|
||
|
|
||
| // @ts-ignore | ||
| })(window.jQuery, window.fullpage); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| //@ts-check | ||
| import { getOptions } from '../common/options'; | ||
| import { FP } from '../common/constants.js'; | ||
| import { setIsScrollAllowed } from '../common/isScrollAllowed.js'; | ||
|
|
||
| FP.setKeyboardScrolling = setKeyboardScrolling; | ||
|
|
||
| /** | ||
| * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys | ||
| */ | ||
| export function setKeyboardScrolling(value, directions){ | ||
| if(typeof directions !== 'undefined'){ | ||
| directions = directions.replace(/ /g,'').split(','); | ||
|
|
||
| directions.forEach(function(direction){ | ||
| setIsScrollAllowed(value, direction, 'k'); | ||
| }); | ||
| }else{ | ||
| setIsScrollAllowed(value, 'all', 'k'); | ||
| getOptions().keyboardScrolling = value; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getSlideOrSection } from '../common/utilsFP.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { onMediaLoad } from '../media.js'; | ||
| /** | ||
| * Lazy loads image, video and audio elements. | ||
| */ | ||
| export function lazyLoad(destiny){ | ||
| if (!getOptions().lazyLoading){ | ||
| return; | ||
| } | ||
|
|
||
| var panel = getSlideOrSection(destiny); | ||
|
|
||
| utils.$('img[data-src], img[data-srcset], source[data-src], source[data-srcset], video[data-src], audio[data-src], iframe[data-src]', panel).forEach(function(element){ | ||
| ['src', 'srcset'].forEach(function(type){ | ||
| var attribute = utils.getAttr(element, 'data-' + type); | ||
| if(attribute != null && attribute){ | ||
| utils.setSrc(element, type); | ||
| element.addEventListener('load', function(){ | ||
| onMediaLoad(destiny); | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| if(utils.matches(element, 'source')){ | ||
| var elementToPlay = utils.closest(element, 'video, audio'); | ||
| if(elementToPlay){ | ||
| elementToPlay.load(); | ||
| elementToPlay.onloadeddata = function(){ | ||
| onMediaLoad(destiny); | ||
| }; | ||
| } | ||
| } | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { | ||
| AUTO_HEIGHT_SEL, | ||
| AUTO_HEIGHT_RESPONSIVE_SEL, | ||
| SECTION_SEL, | ||
| ACTIVE_SEL | ||
| } from '../common/selectors.js'; | ||
| import { state } from '../common/state.js'; | ||
| import { isResponsiveMode } from '../responsive.js'; | ||
| import { lazyLoad } from './lazyLoad.js'; | ||
|
|
||
| /** | ||
| * Makes sure lazyload is done for other sections in the viewport that are not the | ||
| * active one. | ||
| */ | ||
| export function lazyLoadOthers(){ | ||
| var hasAutoHeightSections = utils.$(AUTO_HEIGHT_SEL)[0] || isResponsiveMode() && utils.$(AUTO_HEIGHT_RESPONSIVE_SEL)[0]; | ||
|
|
||
| //quitting when it doesn't apply | ||
| if (!getOptions().lazyLoading || !hasAutoHeightSections){ | ||
| return; | ||
| } | ||
|
|
||
| //making sure to lazy load auto-height sections that are in the viewport | ||
| utils.$(SECTION_SEL + ':not(' + ACTIVE_SEL + ')').forEach(function(section){ | ||
| if(isSectionInViewport(section)){ | ||
| lazyLoad(section); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Determines whether a section is in the viewport or not. | ||
| */ | ||
| function isSectionInViewport (el) { | ||
| var rect = el.getBoundingClientRect(); | ||
| var top = rect.top; | ||
| var bottom = rect.bottom; | ||
|
|
||
| //sometimes there's a 1px offset on the bottom of the screen even when the | ||
| //section's height is the window.innerHeight one. I guess because pixels won't allow decimals. | ||
| //using this prevents from lazyLoading the section that is not yet visible | ||
| //(only 1 pixel offset is) | ||
| var pixelOffset = 2; | ||
|
|
||
| var isTopInView = top + pixelOffset < state.windowsHeight && top > 0; | ||
| var isBottomInView = bottom > pixelOffset && bottom < state.windowsHeight; | ||
|
|
||
| return isTopInView || isBottomInView; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { activateNavDots } from '../nav/sections.js'; | ||
| import { | ||
| ACTIVE, | ||
| ACTIVE_SEL, | ||
| } from '../common/selectors.js'; | ||
|
|
||
| /** | ||
| * Sets to active the current menu and vertical nav items. | ||
| */ | ||
| export function activateMenuAndNav(anchor, index){ | ||
| activateMenuElement(anchor); | ||
| activateNavDots(anchor, index); | ||
| } | ||
|
|
||
| /** | ||
| * Activating the website main menu elements according to the given slide name. | ||
| */ | ||
| function activateMenuElement(name){ | ||
| utils.$(getOptions().menu).forEach(function(menu) { | ||
| if(getOptions().menu && menu != null){ | ||
| utils.removeClass(utils.$(ACTIVE_SEL, menu), ACTIVE); | ||
| utils.addClass(utils.$('[data-menuanchor="'+name+'"]', menu), ACTIVE); | ||
| } | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
|
|
||
| EventEmitter.on('bindEvents', bindEvents); | ||
|
|
||
| function bindEvents(){ | ||
| EventEmitter.on('onClickOrTouch', onClickOrTouch); | ||
| } | ||
|
|
||
| function onClickOrTouch(params){ | ||
| var target = params.target; | ||
|
|
||
| if(utils.closest(target, getOptions().menu + ' [data-menuanchor]')){ | ||
| menuItemsHandler.call(target, params); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| //Menu item handler when not using anchors or using lockAnchors:true | ||
| function menuItemsHandler(e){ | ||
| if(utils.$(getOptions().menu)[0] && (getOptions().lockAnchors || !getOptions().anchors.length)){ | ||
| utils.preventDefault(e); | ||
| /*jshint validthis:true */ | ||
| EventEmitter.emit('onMenuClick', {anchor: | ||
| utils.getAttr(this, 'data-menuanchor') | ||
| }); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { $body } from '../common/cache.js'; | ||
| import { WRAPPER_SEL } from '../common/selectors.js'; | ||
| import { activateMenuAndNav } from './activateMenuAndNav.js'; | ||
|
|
||
| /** | ||
| * Sets the data-anchor attributes to the menu elements and activates the current one. | ||
| */ | ||
| export function styleMenu(section){ | ||
| var index = section.index(); | ||
|
|
||
| if (typeof getOptions().anchors[index] !== 'undefined') { | ||
| //activating the menu / nav element on load | ||
| if(section.isActive){ | ||
| activateMenuAndNav(getOptions().anchors[index], index); | ||
| } | ||
| } | ||
|
|
||
| //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) | ||
| if(getOptions().menu && getOptions().css3 && utils.closest(utils.$(getOptions().menu)[0], WRAPPER_SEL) != null){ | ||
| utils.$(getOptions().menu).forEach(function(menu) { | ||
| $body.appendChild(menu); | ||
| }); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
| import { state } from '../common/state.js'; | ||
|
|
||
| EventEmitter.on('bindEvents', showLicenseWarning); | ||
|
|
||
| function showLicenseWarning(){ | ||
| const waterMark = ` | ||
| <div class="fp-warning" style="left: 0;"> | ||
| The license key for fullPage.js is missing or is not valid. | ||
| <a href="https://alvarotrigo.com/fullPage/" | ||
| rel="nofollow noopener" | ||
| target="_blank" | ||
| style="text-decoration:underline; color: #104acc;"> | ||
| Read More here. | ||
| </a> | ||
| </div> | ||
| `; | ||
| if(!state.isValid){ | ||
| document.body.insertAdjacentHTML('beforeend', waterMark); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { state } from '../common/state.js'; | ||
| import { getLast } from '../common/utils.js'; | ||
|
|
||
| EventEmitter.on('bindEvents', init); | ||
|
|
||
| function init(){ | ||
| console.log(getOptions().credits); | ||
| const position = getOptions().credits.position; | ||
| const positionStyle = ['left', 'right'].indexOf(position) > -1 ? `${position}: 0;` : ''; | ||
| const waterMark = ` | ||
| <div class="fp-watermark" style="${positionStyle}"> | ||
| <a href="https://alvarotrigo.com/fullPage/" | ||
| rel="nofollow noopener" | ||
| target="_blank" | ||
| style="text-decoration:none; color: #000;"> | ||
| ${getOptions().credits.label} | ||
| </a> | ||
| </div> | ||
| `; | ||
| const lastSection = getLast(state.sections); | ||
| const shouldUseWaterMark = getOptions().credits.enabled && !state.isValid; | ||
|
|
||
| if(lastSection && lastSection.item && shouldUseWaterMark){ | ||
| lastSection.item.insertAdjacentHTML('beforeend', waterMark); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from "../common/options.js"; | ||
|
|
||
| /** | ||
| * Gets the name for screen readers for a section/slide navigation bullet. | ||
| */ | ||
| export function getBulletLinkName(i, defaultName, item){ | ||
| var anchor = defaultName === 'Section' ? getOptions().anchors[i] : utils.getAttr(item, 'data-anchor'); | ||
| return getOptions().navigationTooltips[i] || | ||
| anchor || | ||
| defaultName + ' ' + (i+1); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { | ||
| SECTION_NAV_SEL, | ||
| SECTION_NAV_TOOLTIP_SEL, | ||
| SLIDES_NAV_LINK_SEL, | ||
| } from '../common/selectors.js'; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
| import { slideBulletHandler } from './slides.js'; | ||
| import { sectionBulletHandler, tooltipTextHandler } from './sections.js'; | ||
|
|
||
| EventEmitter.on('bindEvents', bindEvents); | ||
|
|
||
| function bindEvents(){ | ||
| EventEmitter.on('onClickOrTouch', onClickOrTouch); | ||
| } | ||
|
|
||
| function onClickOrTouch(params){ | ||
| var target = params.target; | ||
|
|
||
| if(target && utils.closest(target, SECTION_NAV_SEL + ' a')){ | ||
| sectionBulletHandler.call(target, params.e); | ||
| } | ||
|
|
||
| else if(utils.matches(target, SECTION_NAV_TOOLTIP_SEL)){ | ||
| tooltipTextHandler.call(target); | ||
| } | ||
|
|
||
| else if(utils.matches(target, SLIDES_NAV_LINK_SEL) || utils.closest(target, SLIDES_NAV_LINK_SEL) != null){ | ||
| console.log("pincho en dot"); | ||
| slideBulletHandler.call(target, params.e); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { getState, setState } from '../common/state.js'; | ||
| import { $body } from '../common/cache.js'; | ||
| import { | ||
| ACTIVE, | ||
| ACTIVE_SEL, | ||
| SECTION_NAV_SEL, | ||
| SECTION_NAV, | ||
| SECTION_NAV_TOOLTIP, | ||
| SHOW_ACTIVE_TOOLTIP | ||
| } from '../common/selectors.js'; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
| import { getBulletLinkName } from './getBulletLinkName.js'; | ||
|
|
||
| export function tooltipTextHandler(){ | ||
| /*jshint validthis:true */ | ||
| utils.trigger(utils.prev(this), 'click'); | ||
| } | ||
|
|
||
| /** | ||
| * Activating the vertical navigation bullets according to the given slide name. | ||
| */ | ||
| export function activateNavDots(name, sectionIndex){ | ||
| var nav = utils.$(SECTION_NAV_SEL)[0]; | ||
| if(getOptions().navigation && nav != null && nav.style.display !== 'none'){ | ||
| utils.removeClass(utils.$(ACTIVE_SEL, nav), ACTIVE); | ||
| if(name){ | ||
| utils.addClass( utils.$('a[href="#' + name + '"]', nav), ACTIVE); | ||
| }else{ | ||
| utils.addClass(utils.$('a', utils.$('li', nav)[sectionIndex]), ACTIVE); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Creates a vertical navigation bar. | ||
| */ | ||
| export function addVerticalNavigation(){ | ||
| utils.remove(utils.$(SECTION_NAV_SEL)); | ||
|
|
||
| var navigation = document.createElement('div'); | ||
| navigation.setAttribute('id', SECTION_NAV); | ||
|
|
||
| var divUl = document.createElement('ul'); | ||
| navigation.appendChild(divUl); | ||
|
|
||
| utils.appendTo(navigation, $body); | ||
| var nav = utils.$(SECTION_NAV_SEL)[0]; | ||
|
|
||
| utils.addClass(nav, 'fp-' + getOptions().navigationPosition); | ||
|
|
||
| if(getOptions().showActiveTooltip){ | ||
| utils.addClass(nav, SHOW_ACTIVE_TOOLTIP); | ||
| } | ||
|
|
||
| var li = ''; | ||
|
|
||
| for (var i = 0; i < getState().sections.length; i++) { | ||
| var section = getState().sections[i]; | ||
| var link = ''; | ||
| if (getOptions().anchors.length) { | ||
| link = section.anchor; | ||
| } | ||
|
|
||
| li += '<li><a href="#' + link + '"><span class="fp-sr-only">' + getBulletLinkName(section.index(), 'Section') + '</span><span></span></a>'; | ||
|
|
||
| // Only add tooltip if needed (defined by user) | ||
| var tooltip = getOptions().navigationTooltips[section.index()]; | ||
|
|
||
| if (typeof tooltip !== 'undefined' && tooltip !== '') { | ||
| li += '<div class="' + SECTION_NAV_TOOLTIP + ' fp-' + getOptions().navigationPosition + '">' + tooltip + '</div>'; | ||
| } | ||
|
|
||
| li += '</li>'; | ||
| } | ||
| utils.$('ul', nav)[0].innerHTML = li; | ||
|
|
||
| //activating the current active section | ||
| var bullet = utils.$('li', utils.$(SECTION_NAV_SEL)[0])[getState().activeSection.index()]; | ||
| utils.addClass(utils.$('a', bullet), ACTIVE); | ||
| } | ||
|
|
||
|
|
||
| //Scrolls to the section when clicking the navigation bullet | ||
| export function sectionBulletHandler(e){ | ||
| if(e.preventDefault){ | ||
| utils.preventDefault(e); | ||
| } | ||
|
|
||
| setState({scrollTrigger: 'verticalNav'}); | ||
|
|
||
| /*jshint validthis:true */ | ||
| // @ts-ignore | ||
| var indexBullet = utils.index(utils.closest(this, SECTION_NAV_SEL + ' li')); | ||
|
|
||
| EventEmitter.emit('scrollPage', { | ||
| destination: getState().sections[indexBullet] | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { getState, setState } from '../common/state.js'; | ||
| import { | ||
| ACTIVE, | ||
| ACTIVE_SEL, | ||
| SLIDES_NAV_SEL, | ||
| SLIDES_NAV, | ||
| SLIDE_SEL, | ||
| SLIDES_WRAPPER_SEL, | ||
| SECTION_SEL | ||
| } from '../common/selectors.js'; | ||
| import { getPanelByElement } from '../common/item.js'; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
| import { getBulletLinkName } from './getBulletLinkName.js'; | ||
|
|
||
| //Scrolls the slider to the given slide destination for the given section | ||
| export function slideBulletHandler(e){ | ||
| console.log(this); | ||
| utils.preventDefault(e); | ||
|
|
||
| setState({scrollTrigger: 'horizontalNav'}); | ||
|
|
||
| /*jshint validthis:true */ | ||
| var sectionElem = utils.closest(this, SECTION_SEL); | ||
| var slides = utils.$(SLIDES_WRAPPER_SEL, utils.closest(this, SECTION_SEL))[0]; | ||
| var section = getPanelByElement(getState().sections, sectionElem); | ||
| var destiny = section.slides[utils.index(utils.closest(this, 'li'))]; | ||
|
|
||
| EventEmitter.emit('landscapeScroll', { | ||
| slides: slides, | ||
| destination: destiny.item | ||
| }); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Sets the state for the horizontal bullet navigations. | ||
| */ | ||
| export function activeSlidesNavigation(slidesNav, slideIndex){ | ||
| if(getOptions().slidesNavigation && slidesNav != null){ | ||
| utils.removeClass(utils.$(ACTIVE_SEL, slidesNav), ACTIVE); | ||
| utils.addClass( utils.$('a', utils.$('li', slidesNav)[slideIndex] ), ACTIVE); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Creates a landscape navigation bar with dots for horizontal sliders. | ||
| */ | ||
| export function addSlidesNavigation(section){ | ||
| var sectionElem = section.item; | ||
| var numSlides = section.slides.length; | ||
| utils.appendTo(utils.createElementFromHTML('<div class="' + SLIDES_NAV + '"><ul></ul></div>'), sectionElem); | ||
| var nav = utils.$(SLIDES_NAV_SEL, sectionElem)[0]; | ||
|
|
||
| //top or bottom | ||
| utils.addClass(nav, 'fp-' + getOptions().slidesNavPosition); | ||
|
|
||
| for(var i=0; i< numSlides; i++){ | ||
| var slide = utils.$(SLIDE_SEL, sectionElem)[i]; | ||
| utils.appendTo(utils.createElementFromHTML('<li><a href="#"><span class="fp-sr-only">'+ getBulletLinkName(i, 'Slide', slide) +'</span><span></span></a></li>'), utils.$('ul', nav)[0] ); | ||
| } | ||
|
|
||
| //centering it | ||
| utils.css(nav, {'margin-left': '-' + (nav.innerWidth/2) + 'px'}); | ||
|
|
||
| utils.addClass(utils.$('a', utils.$('li', nav)[0] ), ACTIVE); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // https://tc39.github.io/ecma262/#sec-array.prototype.find | ||
| if (!Array.prototype.find) { | ||
| Object.defineProperty(Array.prototype, 'find', { | ||
| value: function(predicate) { | ||
| // 1. Let O be ? ToObject(this value). | ||
| if (this == null) { | ||
| throw new TypeError('"this" is null or not defined'); | ||
| } | ||
|
|
||
| var o = Object(this); | ||
|
|
||
| // 2. Let len be ? ToLength(? Get(O, "length")). | ||
| var len = o.length >>> 0; | ||
|
|
||
| // 3. If IsCallable(predicate) is false, throw a TypeError exception. | ||
| if (typeof predicate !== 'function') { | ||
| throw new TypeError('predicate must be a function'); | ||
| } | ||
|
|
||
| // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. | ||
| var thisArg = arguments[1]; | ||
|
|
||
| // 5. Let k be 0. | ||
| var k = 0; | ||
|
|
||
| // 6. Repeat, while k < len | ||
| while (k < len) { | ||
| // a. Let Pk be ! ToString(k). | ||
| // b. Let kValue be ? Get(O, Pk). | ||
| // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). | ||
| // d. If testResult is true, return kValue. | ||
| var kValue = o[k]; | ||
| if (predicate.call(thisArg, kValue, k, o)) { | ||
| return kValue; | ||
| } | ||
| // e. Increase k by 1. | ||
| k++; | ||
| } | ||
|
|
||
| // 7. Return undefined. | ||
| return undefined; | ||
| } | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /** | ||
| * forEach polyfill for IE | ||
| * https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Browser_Compatibility | ||
| */ | ||
| if (window.NodeList && !NodeList.prototype.forEach) { | ||
| NodeList.prototype.forEach = function (callback, thisArg) { | ||
| thisArg = thisArg || window; | ||
| for (var i = 0; i < this.length; i++) { | ||
| callback.call(thisArg, this[i], i, this); | ||
| } | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| // Production steps of ECMA-262, Edition 6, 22.1.2.1 | ||
| if (!Array.from) { | ||
| Array.from = (function() { | ||
| var toStr = Object.prototype.toString; | ||
| var isCallable = function(fn) { | ||
| return ( | ||
| typeof fn === 'function' || | ||
| toStr.call(fn) === '[object Function]' | ||
| ); | ||
| }; | ||
| var toInteger = function(value) { | ||
| var number = Number(value); | ||
| if (isNaN(number)) { | ||
| return 0; | ||
| } | ||
| if (number === 0 || !isFinite(number)) { | ||
| return number; | ||
| } | ||
| return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); | ||
| }; | ||
| var maxSafeInteger = Math.pow(2, 53) - 1; | ||
| var toLength = function(value) { | ||
| var len = toInteger(value); | ||
| return Math.min(Math.max(len, 0), maxSafeInteger); | ||
| }; | ||
|
|
||
| // The length property of the from method is 1. | ||
| return function from(arrayLike /*, mapFn, thisArg */) { | ||
| // 1. Let C be the this value. | ||
| var C = this; | ||
|
|
||
| // 2. Let items be ToObject(arrayLike). | ||
| var items = Object(arrayLike); | ||
|
|
||
| // 3. ReturnIfAbrupt(items). | ||
| if (arrayLike == null) { | ||
| throw new TypeError( | ||
| 'Array.from requires an array-like object - not null or undefined' | ||
| ); | ||
| } | ||
|
|
||
| // 4. If mapfn is undefined, then let mapping be false. | ||
| var mapFn = arguments.length > 1 ? arguments[1] : void undefined; | ||
| var T; | ||
| if (typeof mapFn !== 'undefined') { | ||
| // 5. else | ||
| // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. | ||
| if (!isCallable(mapFn)) { | ||
| throw new TypeError( | ||
| 'Array.from: when provided, the second argument must be a function' | ||
| ); | ||
| } | ||
|
|
||
| // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. | ||
| if (arguments.length > 2) { | ||
| T = arguments[2]; | ||
| } | ||
| } | ||
|
|
||
| // 10. Let lenValue be Get(items, "length"). | ||
| // 11. Let len be ToLength(lenValue). | ||
| var len = toLength(items.length); | ||
|
|
||
| // 13. If IsConstructor(C) is true, then | ||
| // 13. a. Let A be the result of calling the [[Construct]] internal method | ||
| // of C with an argument list containing the single item len. | ||
| // 14. a. Else, Let A be ArrayCreate(len). | ||
| var A = isCallable(C) ? Object(new C(len)) : new Array(len); | ||
|
|
||
| // 16. Let k be 0. | ||
| var k = 0; | ||
| // 17. Repeat, while k < len… (also steps a - h) | ||
| var kValue; | ||
| while (k < len) { | ||
| kValue = items[k]; | ||
| if (mapFn) { | ||
| A[k] = | ||
| typeof T === 'undefined' | ||
| ? mapFn(kValue, k) | ||
| : mapFn.call(T, kValue, k); | ||
| } else { | ||
| A[k] = kValue; | ||
| } | ||
| k += 1; | ||
| } | ||
| // 18. Let putStatus be Put(A, "length", len, true). | ||
| A.length = len; | ||
| // 20. Return A. | ||
| return A; | ||
| }; | ||
| })(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import './array.find.js'; | ||
| import './array.from.js'; | ||
| import './array.foreach.js'; | ||
| import './object.assign.js'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| if (typeof Object.assign != 'function') { | ||
| // Must be writable: true, enumerable: false, configurable: true | ||
| Object.defineProperty(Object, 'assign', { | ||
| value: function assign(target, varArgs) { | ||
| // .length of function is 2 | ||
| 'use strict'; | ||
| if (target == null) { | ||
| // TypeError if undefined or null | ||
| throw new TypeError( | ||
| 'Cannot convert undefined or null to object' | ||
| ); | ||
| } | ||
|
|
||
| var to = Object(target); | ||
|
|
||
| for (var index = 1; index < arguments.length; index++) { | ||
| var nextSource = arguments[index]; | ||
|
|
||
| if (nextSource != null) { | ||
| // Skip over if undefined or null | ||
| for (var nextKey in nextSource) { | ||
| // Avoid bugs when hasOwnProperty is shadowed | ||
| if ( | ||
| Object.prototype.hasOwnProperty.call( | ||
| nextSource, | ||
| nextKey | ||
| ) | ||
| ) { | ||
| to[nextKey] = nextSource[nextKey]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return to; | ||
| }, | ||
| writable: true, | ||
| configurable: true | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
| import { scrollHandler } from './scrollHandler.js'; | ||
| import { scrollPageAndSlide } from './scrollPageAndSlide.js'; | ||
| import { moveTo } from './moveTo.js'; | ||
| import { moveSectionDown } from './moveSectionDown.js'; | ||
| import { moveSectionUp } from './moveSectionUp.js'; | ||
| import { scrollPage } from './scrollPage.js'; | ||
|
|
||
| EventEmitter.on('bindEvents', bindEvents); | ||
| EventEmitter.on('onDestroy', onDestroy); | ||
|
|
||
| function onDestroy(){ | ||
| utils.windowRemoveEvent('scroll', scrollHandler); | ||
| } | ||
|
|
||
| function bindEvents(){ | ||
| utils.windowAddEvent('scroll', scrollHandler); | ||
| document.body.addEventListener('scroll', scrollHandler); | ||
| console.log("adding... onScrollPageAndSlide "); | ||
| EventEmitter.on('onScrollPageAndSlide', function(params){ | ||
| console.log("on onScrollPageAndSlide..."); | ||
| scrollPageAndSlide(params.sectionAnchor, params.slideAnchor); | ||
| }); | ||
|
|
||
| EventEmitter.on('onMenuClick', function(params){ | ||
| moveTo(params.anchor, undefined); | ||
| }); | ||
|
|
||
| EventEmitter.on('onScrollOverflowScrolled', function(params){ | ||
| var scrollSection = (params.direction === 'down') ? moveSectionDown : moveSectionUp; | ||
| scrollSection(); | ||
| }); | ||
|
|
||
| EventEmitter.on('scrollPage', function(params){ | ||
| scrollPage(params.destination); | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import { getContainer, getOptions } from "../common/options.js"; | ||
| import { getState } from "../common/state.js"; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
| import { FP } from '../common/constants'; | ||
| import { $body } from "../common/cache.js"; | ||
| import { scrollPage } from "./scrollPage.js"; | ||
| import { moveSectionUp } from "./moveSectionUp.js"; | ||
|
|
||
| FP.moveSectionDown = moveSectionDown; | ||
|
|
||
| /** | ||
| * Moves the page down one section. | ||
| */ | ||
| export function moveSectionDown(){ | ||
| var next = getState().activeSection.next(); | ||
|
|
||
| //looping to the top if there's no more sections below | ||
| if(!next && | ||
| (getOptions().loopBottom || getOptions().continuousVertical)){ | ||
| next = getState().sections[0]; | ||
| } | ||
|
|
||
| if(next != null){ | ||
| scrollPage(next, null, false); | ||
| } | ||
| else if(hasContentBeyondFullPage()){ | ||
| EventEmitter.emit('scrollBeyondFullpage'); | ||
| } | ||
| } | ||
|
|
||
| function hasContentBeyondFullPage(){ | ||
| return getContainer().scrollHeight < $body.scrollHeight; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from "../common/options.js"; | ||
| import { getState } from "../common/state.js"; | ||
| import { FP } from '../common/constants'; | ||
| import { scrollPage } from './scrollPage.js'; | ||
|
|
||
| FP.moveSectionUp = moveSectionUp; | ||
|
|
||
| /** | ||
| * Moves the page up one section. | ||
| */ | ||
| export function moveSectionUp(){ | ||
| var prev = getState().activeSection.prev(); | ||
|
|
||
| //looping to the bottom if there's no more sections above | ||
| if (!prev && (getOptions().loopTop || getOptions().continuousVertical)) { | ||
| prev = utils.getLast(getState().sections); | ||
| } | ||
|
|
||
| if (prev != null) { | ||
| scrollPage(prev, null, true); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { getSectionByAnchor } from "../common/getSectionByAnchor.js"; | ||
| import { scrollPage } from "./scrollPage.js"; | ||
| import { scrollPageAndSlide } from "./scrollPageAndSlide.js"; | ||
| import { FP } from '../common/constants'; | ||
|
|
||
| FP.moveTo = moveTo; | ||
|
|
||
| /** | ||
| * Moves the page to the given section and slide. | ||
| * Anchors or index positions can be used as params. | ||
| */ | ||
| export function moveTo(sectionAnchor, slideAnchor){ | ||
| var destiny = getSectionByAnchor(sectionAnchor); | ||
|
|
||
| if (typeof slideAnchor !== 'undefined'){ | ||
| scrollPageAndSlide(sectionAnchor, slideAnchor); | ||
| }else if(destiny != null){ | ||
| scrollPage(destiny); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { stopMedia, playMedia} from '../media.js'; | ||
| import { updateState } from '../stateUpdates.js'; | ||
| import { getState, setState, state } from '../common/state.js'; | ||
| import { lazyLoad } from '../lazyLoad/lazyLoad.js'; | ||
| import { g_isCssSnapsSupported, fitToSection } from '../fitToSection.js'; | ||
| import { setPageStatus } from '../anchors/setPageStatus.js'; | ||
| import { activateMenuAndNav } from '../menu/activateMenuAndNav.js'; | ||
| import { $body } from '../common/cache.js'; | ||
| import { getYmovement } from '../common/utilsFP.js'; | ||
| import { | ||
| COMPLETELY, | ||
| ACTIVE | ||
| } from '../common/selectors.js'; | ||
| import { fireCallbackOncePerScroll } from '../callbacks/fireCallbacksOncePerScroll.js'; | ||
| import { fireCallback } from '../callbacks/fireCallback.js'; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
|
|
||
| var lastScroll = 0; | ||
| let g_scrollId; | ||
| let g_scrollId2; | ||
|
|
||
| EventEmitter.on('onDestroy', onDestroy); | ||
|
|
||
| //when scrolling... | ||
| export function scrollHandler(e){ | ||
| var currentSection; | ||
| var currentSectionElem; | ||
|
|
||
| if(state.isResizing || !getState().activeSection){ | ||
| return; | ||
| } | ||
|
|
||
| var lastSection = utils.getLast(getState().sections); | ||
| if(getState().isBeyondFullpage || getState().isAboutToScrollToFullPage){ | ||
| return; | ||
| } | ||
|
|
||
| if(!getOptions().autoScrolling || getOptions().scrollBar){ | ||
| var currentScroll = utils.getScrollTop(getOptions()); | ||
| var scrollDirection = getScrollDirection(currentScroll); | ||
| var visibleSectionIndex = 0; | ||
| var screen_mid = currentScroll + (utils.getWindowHeight() / 2.0); | ||
| var isAtBottom = $body.scrollHeight - utils.getWindowHeight() === currentScroll; | ||
| var sections = getState().sections; | ||
|
|
||
| //when using `auto-height` for a small last section it won't be centered in the viewport | ||
| if(isAtBottom){ | ||
| visibleSectionIndex = sections.length - 1; | ||
| } | ||
| //is at top? when using `auto-height` for a small first section it won't be centered in the viewport | ||
| else if(!currentScroll){ | ||
| visibleSectionIndex = 0; | ||
| } | ||
|
|
||
| //taking the section which is showing more content in the viewport | ||
| else{ | ||
| for (var i = 0; i < sections.length; ++i) { | ||
| var section = sections[i].item; | ||
|
|
||
| // Pick the the last section which passes the middle line of the screen. | ||
| if (section.offsetTop <= screen_mid) | ||
| { | ||
| visibleSectionIndex = i; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if(isCompletelyInViewPort(scrollDirection)){ | ||
| if(!utils.hasClass(getState().activeSection.item, COMPLETELY)){ | ||
| utils.addClass(getState().activeSection.item, COMPLETELY); | ||
| utils.removeClass(utils.siblings(getState().activeSection.item), COMPLETELY); | ||
| } | ||
| } | ||
|
|
||
| //geting the last one, the current one on the screen | ||
| currentSection = sections[visibleSectionIndex]; | ||
| currentSectionElem = currentSection.item; | ||
|
|
||
| //setting the visible section as active when manually scrolling | ||
| //executing only once the first time we reach the section | ||
| if(!currentSection.isActive){ | ||
| setState({isScrolling: true}); | ||
| var leavingSection = getState().activeSection.item; | ||
| var leavingSectionIndex = getState().activeSection.index() + 1; | ||
| var yMovement = getYmovement(getState().activeSection, currentSectionElem); | ||
| var anchorLink = currentSection.anchor; | ||
| var sectionIndex = currentSection.index() + 1; | ||
| var activeSlide = currentSection.activeSlide; | ||
| var slideIndex; | ||
| var slideAnchorLink; | ||
| var callbacksParams = { | ||
| activeSection: leavingSection, | ||
| sectionIndex: sectionIndex -1, | ||
| anchorLink: anchorLink, | ||
| element: currentSectionElem, | ||
| leavingSection: leavingSectionIndex, | ||
| direction: yMovement, | ||
|
|
||
| items: { | ||
| origin: getState().activeSection, | ||
| destination: currentSection | ||
| } | ||
| }; | ||
|
|
||
| if(activeSlide){ | ||
| slideAnchorLink = activeSlide.anchor; | ||
| slideIndex = activeSlide.index(); | ||
| } | ||
|
|
||
| if(state.canScroll){ | ||
| utils.addClass(currentSectionElem, ACTIVE); | ||
| utils.removeClass(utils.siblings(currentSectionElem), ACTIVE); | ||
|
|
||
| if(utils.isFunction( getOptions().beforeLeave )){ | ||
| fireCallbackOncePerScroll('beforeLeave', callbacksParams); | ||
| } | ||
|
|
||
| if(utils.isFunction( getOptions().onLeave )){ | ||
| fireCallback('onLeave', callbacksParams); | ||
| } | ||
| if(utils.isFunction( getOptions().afterLoad )){ | ||
| fireCallback('afterLoad', callbacksParams); | ||
| } | ||
|
|
||
| stopMedia(leavingSection); | ||
| lazyLoad(currentSectionElem); | ||
| playMedia(currentSectionElem); | ||
|
|
||
| activateMenuAndNav(anchorLink, sectionIndex - 1); | ||
|
|
||
| if(getOptions().anchors.length){ | ||
| //needed to enter in hashChange event when using the menu with anchor links | ||
| setState({lastScrolledDestiny: anchorLink}); | ||
| } | ||
| setPageStatus(slideIndex, slideAnchorLink, anchorLink); | ||
| updateState(); | ||
| } | ||
|
|
||
| //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet | ||
| clearTimeout(g_scrollId); | ||
| g_scrollId = setTimeout(function(){ | ||
| setState({isScrolling: false}); | ||
| }, 100); | ||
| } | ||
|
|
||
| if(getOptions().fitToSection && (!g_isCssSnapsSupported || getOptions().scrollBar)){ | ||
| //for the auto adjust of the viewport to fit a whole section | ||
| clearTimeout(g_scrollId2); | ||
|
|
||
| g_scrollId2 = setTimeout(function(){ | ||
| //checking it again in case it changed during the delay | ||
| if(getOptions().fitToSection && | ||
|
|
||
| //is the destination element bigger than the viewport? | ||
| getState().activeSection.item.offsetHeight <= state.windowsHeight | ||
| ){ | ||
| fitToSection(); | ||
| } | ||
| }, getOptions().fitToSectionDelay); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| function onDestroy(){ | ||
| clearTimeout(g_scrollId); | ||
| clearTimeout(g_scrollId2); | ||
| } | ||
|
|
||
| /** | ||
| * Gets the directon of the the scrolling fired by the scroll event. | ||
| */ | ||
| function getScrollDirection(currentScroll){ | ||
| var direction = currentScroll > lastScroll ? 'down' : 'up'; | ||
|
|
||
| lastScroll = currentScroll; | ||
|
|
||
| //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination | ||
| setState({previousDestTop: currentScroll}); | ||
|
|
||
| return direction; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| /** | ||
| * Determines whether the active section has seen in its whole or not. | ||
| */ | ||
| function isCompletelyInViewPort(movement){ | ||
| var top = getState().activeSection.item.offsetTop; | ||
| var bottom = top + utils.getWindowHeight(); | ||
|
|
||
| if(movement == 'up'){ | ||
| return bottom >= (utils.getScrollTop(getOptions()) + utils.getWindowHeight()); | ||
| } | ||
| return top <= utils.getScrollTop(getOptions()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,285 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { getOptions } from '../common/options.js'; | ||
| import { getState, setState, state } from '../common/state.js'; | ||
| import { FP } from '../common/constants.js'; | ||
| import { $htmlBody } from '../common/cache.js'; | ||
| import { transformContainer } from '../common/transformContainer.js'; | ||
| import { scrollTo } from '../common/scrollTo.js'; | ||
| import { getScrollSettings, getYmovement } from '../common/utilsFP.js'; | ||
| import { createInfiniteSections } from '../infiniteScroll/createInfiniteSections.js'; | ||
| import { continuousVerticalFixSectionOrder } from '../infiniteScroll/fixPosition.js'; | ||
| import { stopMedia, playMedia} from '../media.js'; | ||
| import { updateState } from '../stateUpdates.js'; | ||
| import { lazyLoad } from '../lazyLoad/lazyLoad.js'; | ||
| import { lazyLoadOthers } from '../lazyLoad/lazyLoadOthers.js'; | ||
| import { scrollOverflowHandler } from '../scrolloverflow.js'; | ||
| import { setPageStatus } from '../anchors/setPageStatus.js'; | ||
| import { activateMenuAndNav } from '../menu/activateMenuAndNav.js'; | ||
| import { | ||
| AUTO_HEIGHT, | ||
| COMPLETELY, | ||
| ACTIVE | ||
| } from '../common/selectors.js'; | ||
| import { fireCallbackOncePerScroll } from '../callbacks/fireCallbacksOncePerScroll.js'; | ||
| import { fireCallback } from '../callbacks/fireCallback.js'; | ||
| import { EventEmitter } from '../common/eventEmitter.js'; | ||
|
|
||
| FP.moveTo = moveTo; | ||
|
|
||
| let g_afterSectionLoadsId; | ||
| let g_transitionLapseId; | ||
|
|
||
| EventEmitter.on('onDestroy', onDestroy); | ||
|
|
||
| /** | ||
| * Scrolls the site to the given element and scrolls to the slide if a callback is given. | ||
| */ | ||
| export function scrollPage(section, callback, isMovementUp){ | ||
| var element = section.item; | ||
| if(element == null){ return; } //there's no element to scroll, leaving the function | ||
|
|
||
| var dtop = getDestinationPosition(element); | ||
| var slideAnchorLink; | ||
| var slideIndex; | ||
|
|
||
| //local variables | ||
| var v = { | ||
| "element": element, | ||
| "callback": callback, | ||
| "isMovementUp": isMovementUp, | ||
| "dtop": dtop, | ||
| "yMovement": getYmovement(getState().activeSection, element), | ||
| "anchorLink": section.anchor, | ||
| "sectionIndex": section.index(), | ||
| "activeSlide": section.activeSlide ? section.activeSlide.item : null, | ||
| "activeSection": getState().activeSection.item, | ||
| "leavingSection": getState().activeSection.index() + 1, | ||
|
|
||
| //caching the value of isResizing at the momment the function is called | ||
| //because it will be checked later inside a setTimeout and the value might change | ||
| "localIsResizing": state.isResizing, | ||
|
|
||
| "items": { | ||
| "origin": getState().activeSection, | ||
| "destination": section | ||
| }, | ||
| "direction": null | ||
| }; | ||
|
|
||
| //quiting when destination scroll is the same as the current one | ||
| if((v.activeSection == element && !state.isResizing) || (getOptions().scrollBar && utils.getScrollTop(getOptions()) === v.dtop && !utils.hasClass(element, AUTO_HEIGHT) )){ return; } | ||
|
|
||
| if(v.activeSlide != null){ | ||
| slideAnchorLink = utils.getAttr(v.activeSlide, 'data-anchor'); | ||
| slideIndex = utils.index(v.activeSlide, null); | ||
| } | ||
|
|
||
| //callback (onLeave) if the site is not just resizing and readjusting the slides | ||
| if(!v.localIsResizing){ | ||
| var direction = v.yMovement; | ||
|
|
||
| //required for continousVertical | ||
| if(typeof isMovementUp !== 'undefined'){ | ||
| direction = isMovementUp ? 'up' : 'down'; | ||
| } | ||
|
|
||
| //for the callback | ||
| v.direction = direction; | ||
| setState({direction: direction}); | ||
|
|
||
| if(utils.isFunction( getOptions().beforeLeave )){ | ||
|
|
||
| if(fireCallbackOncePerScroll('beforeLeave', v) === false){ | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| if(utils.isFunction(getOptions().onLeave)){ | ||
| if(!fireCallback('onLeave', v)){ | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // If continuousVertical && we need to wrap around | ||
| if (getOptions().autoScrolling && getOptions().continuousVertical && typeof (v.isMovementUp) !== "undefined" && | ||
| ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or | ||
| (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down | ||
|
|
||
| v = createInfiniteSections(v); | ||
| } | ||
|
|
||
| //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) | ||
| if(!v.localIsResizing){ | ||
| stopMedia(v.activeSection); | ||
| } | ||
|
|
||
| utils.addClass(element, ACTIVE); | ||
| utils.removeClass(utils.siblings(element), ACTIVE); | ||
| updateState(); | ||
| lazyLoad(element); | ||
|
|
||
| //preventing from activating the MouseWheelHandler event | ||
| //more than once if the page is scrolling | ||
| setState({canScroll: false || FP.test.isTesting}); | ||
|
|
||
| setPageStatus(slideIndex, slideAnchorLink, v.anchorLink); | ||
|
|
||
| performMovement(v); | ||
|
|
||
| //flag to avoid callingn `scrollPage()` twice in case of using anchor links | ||
| setState({lastScrolledDestiny: v.anchorLink}); | ||
|
|
||
| //avoid firing it twice (as it does also on scroll) | ||
| activateMenuAndNav(v.anchorLink, v.sectionIndex); | ||
| } | ||
|
|
||
| function onDestroy(){ | ||
| clearTimeout(g_afterSectionLoadsId); | ||
| clearTimeout(g_transitionLapseId); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Returns the destination Y position based on the scrolling direction and | ||
| * the height of the section. | ||
| */ | ||
| function getDestinationPosition(element){ | ||
| var elementHeight = element.offsetHeight; | ||
| var elementTop = element.offsetTop; | ||
|
|
||
| //top of the desination will be at the top of the viewport | ||
| var position = elementTop; | ||
| var isScrollingDown = elementTop > state.previousDestTop; | ||
| var sectionBottom = position - utils.getWindowHeight() + elementHeight; | ||
| var bigSectionsDestination = getOptions().bigSectionsDestination; | ||
|
|
||
| //is the destination element bigger than the viewport? | ||
| if(elementHeight > utils.getWindowHeight()){ | ||
| //scrolling up? | ||
| if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ | ||
| position = sectionBottom; | ||
| } | ||
| } | ||
|
|
||
| //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section | ||
| else if(isScrollingDown || (state.isResizing && utils.next(element) == null) ){ | ||
| //The bottom of the destination will be at the bottom of the viewport | ||
| position = sectionBottom; | ||
| } | ||
|
|
||
| /* | ||
| Keeping record of the last scrolled position to determine the scrolling direction. | ||
| No conventional methods can be used as the scroll bar might not be present | ||
| AND the section might not be active if it is auto-height and didnt reach the middle | ||
| of the viewport. | ||
| */ | ||
| setState({previousDestTop: position}); | ||
| return position; | ||
| } | ||
|
|
||
| /** | ||
| * Performs the vertical movement (by CSS3 or by jQuery) | ||
| */ | ||
| function performMovement(v){ | ||
| var isFastSpeed = getOptions().scrollingSpeed < 700; | ||
| var transitionLapse = isFastSpeed ? 700 : getOptions().scrollingSpeed; | ||
| setState({touchDirection: 'none'}); | ||
|
|
||
| // using CSS3 translate functionality | ||
| if (getOptions().css3 && getOptions().autoScrolling && !getOptions().scrollBar) { | ||
|
|
||
| // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 | ||
| // that's why we round it to 0. | ||
| var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; | ||
| transformContainer(translate3d, true); | ||
|
|
||
| //even when the scrollingSpeed is 0 there's a little delay, which might cause the | ||
| //scrollingSpeed to change in case of using silentMoveTo();ç | ||
| if(getOptions().scrollingSpeed){ | ||
| clearTimeout(g_afterSectionLoadsId); | ||
| g_afterSectionLoadsId = setTimeout(function () { | ||
| afterSectionLoads(v); | ||
|
|
||
| //disabling canScroll when using fastSpeed | ||
| setState({canScroll: !isFastSpeed || FP.test.isTesting}); | ||
| }, getOptions().scrollingSpeed); | ||
| }else{ | ||
| afterSectionLoads(v); | ||
| } | ||
| } | ||
|
|
||
| // using JS to animate | ||
| else{ | ||
| var scrollSettings = getScrollSettings(v.dtop); | ||
| FP.test.top = -v.dtop + 'px'; | ||
|
|
||
| utils.css($htmlBody, {'scroll-behavior': 'unset'}); | ||
|
|
||
| scrollTo(scrollSettings.element, scrollSettings.options, getOptions().scrollingSpeed, function(){ | ||
| if(getOptions().scrollBar){ | ||
|
|
||
| /* Hack! | ||
| The timeout prevents setting the most dominant section in the viewport as "active" when the user | ||
| scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. | ||
| When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. | ||
| */ | ||
| setTimeout(function(){ | ||
| afterSectionLoads(v); | ||
| },30); | ||
| }else{ | ||
|
|
||
| afterSectionLoads(v); | ||
|
|
||
| //disabling canScroll when using fastSpeed | ||
| setState({canScroll: !isFastSpeed || FP.test.isTesting}); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| // enabling canScroll after the minimum transition laps | ||
| if(isFastSpeed){ | ||
| clearTimeout(g_transitionLapseId); | ||
| g_transitionLapseId = setTimeout(function(){ | ||
| setState({canScroll: true}); | ||
| }, transitionLapse); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Actions to do once the section is loaded. | ||
| */ | ||
| function afterSectionLoads(v){ | ||
| if(getOptions().fitToSection){ | ||
| utils.css(document.body, {'scroll-snap-type': 'y mandatory'}); | ||
| } | ||
|
|
||
| setState({isBeyondFullpage: false}); | ||
| console.error("afterSectionLoads"); | ||
| continuousVerticalFixSectionOrder(v); | ||
|
|
||
| //callback (afterLoad) if the site is not just resizing and readjusting the slides | ||
| if(utils.isFunction(getOptions().afterLoad) && !v.localIsResizing){ | ||
| fireCallback('afterLoad', v); | ||
| } | ||
|
|
||
| updateState(); | ||
|
|
||
| if(!v.localIsResizing){ | ||
| playMedia(v.element); | ||
| } | ||
|
|
||
| utils.addClass(v.element, COMPLETELY); | ||
| utils.removeClass(utils.siblings(v.element), COMPLETELY); | ||
|
|
||
| lazyLoadOthers(); | ||
|
|
||
| scrollOverflowHandler.afterSectionLoads(); | ||
|
|
||
| setState({canScroll: true}); | ||
|
|
||
| if(utils.isFunction(v.callback)){ | ||
| v.callback(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import * as utils from '../common/utils.js'; | ||
| import { state } from '../common/state.js'; | ||
| import { scrollSlider } from '../slides/scrollSlider.js'; | ||
| import { getSectionByAnchor } from '../common/getSectionByAnchor.js'; | ||
| import { ACTIVE } from '../common/selectors.js'; | ||
| import { scrollPage } from './scrollPage.js'; | ||
|
|
||
| /** | ||
| * Scrolls to the given section and slide anchors | ||
| */ | ||
| export function scrollPageAndSlide(sectionAnchor, slideAnchor){ | ||
| var section = getSectionByAnchor(sectionAnchor); | ||
|
|
||
| //do nothing if there's no section with the given anchor name | ||
| if(section == null) return; | ||
|
|
||
| var slideElem = getSlideByAnchor(slideAnchor, section); | ||
|
|
||
| //we need to scroll to the section and then to the slide | ||
| if (section.anchor !== state.lastScrolledDestiny && !utils.hasClass(section.item, ACTIVE)){ | ||
|
|
||
| scrollPage(section, function(){ | ||
| scrollSlider(slideElem); | ||
| }); | ||
| } | ||
| //if we were already in the section | ||
| else{ | ||
| scrollSlider(slideElem); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Gets a slide inside a given section by its anchor / index | ||
| */ | ||
| function getSlideByAnchor(slideAnchor, section){ | ||
| var slide = section.slides.filter(slide => slide.anchor === slideAnchor)[0]; | ||
| if(slide == null){ | ||
| slideAnchor = typeof slideAnchor !== 'undefined' ? slideAnchor : 0; | ||
| slide = section.slides[slideAnchor]; | ||
| } | ||
|
|
||
| return slide ? slide.item : null; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { getOptions } from '../common/options.js'; | ||
| import { getAnchorsURL } from '../anchors/getAnchorsURL.js'; | ||
| import { scrollPageAndSlide } from './scrollPageAndSlide.js'; | ||
| import { silentMoveTo } from './silentMove.js'; | ||
|
|
||
| /** | ||
| * Scrolls to the anchor in the URL when loading the site | ||
| */ | ||
| export function scrollToAnchor(){ | ||
| var anchors = getAnchorsURL(); | ||
| var sectionAnchor = anchors.section; | ||
| var slideAnchor = anchors.slide; | ||
|
|
||
| if(sectionAnchor){ //if theres any # | ||
| if(getOptions().animateAnchor){ | ||
| scrollPageAndSlide(sectionAnchor, slideAnchor); | ||
| }else{ | ||
| silentMoveTo(sectionAnchor, slideAnchor); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import { getIsScrollAllowed } from "../common/isScrollAllowed.js"; | ||
| import { getOptions } from "../common/options.js"; | ||
| import { getState } from "../common/state.js"; | ||
| import { scrollOverflowHandler } from "../scrolloverflow.js"; | ||
| import { moveSectionDown } from "./moveSectionDown.js"; | ||
| import { moveSectionUp } from "./moveSectionUp.js"; | ||
|
|
||
| /** | ||
| * Determines the way of scrolling up or down: | ||
| * by 'automatically' scrolling a section or by using the default and normal scrolling. | ||
| */ | ||
| export function scrolling(type){ | ||
| if (!getIsScrollAllowed().m[type]){ | ||
| return; | ||
| } | ||
|
|
||
| var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; | ||
|
|
||
| if(getOptions().scrollOverflow && scrollOverflowHandler.isScrollable(getState().activeSection)){ | ||
|
|
||
| //is the scrollbar at the start/end of the scroll? | ||
| if(scrollOverflowHandler.isScrolled(type, getState().activeSection.item) && | ||
| scrollOverflowHandler.shouldMovePage() | ||
| ){ | ||
| scrollSection(); | ||
| } | ||
| } | ||
| else{ | ||
| scrollSection(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import { setIsScrollAllowed } from "../common/isScrollAllowed.js"; | ||
| import { FP } from '../common/constants'; | ||
|
|
||
| FP.setAllowScrolling = setAllowScrolling; | ||
|
|
||
| /** | ||
| * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. | ||
| * Optionally a second parameter can be used to specify the direction for which the action will be applied. | ||
| * | ||
| * @param directions string containing the direction or directions separated by comma. | ||
| */ | ||
| export function setAllowScrolling(value, directions){ | ||
| if(typeof directions !== 'undefined'){ | ||
| directions = directions.replace(/ /g,'').split(','); | ||
|
|
||
| directions.forEach(function (direction){ | ||
| setIsScrollAllowed(value, direction, 'm'); | ||
| }); | ||
| } | ||
| else{ | ||
| setIsScrollAllowed(value, 'all', 'm'); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import { getOriginals } from "../common/options.js"; | ||
| import { setScrollingSpeed } from "../speed.js"; | ||
| import { FP } from '../common/constants'; | ||
| import { moveTo } from './moveTo.js'; | ||
|
|
||
| FP.silentMoveTo = silentMoveTo; | ||
|
|
||
| /** | ||
| * Moves the page to the given section and slide with no animation. | ||
| * Anchors or index positions can be used as params. | ||
| */ | ||
| export function silentMoveTo(sectionAnchor, slideAnchor){ | ||
| setScrollingSpeed (0, 'internal'); | ||
| moveTo(sectionAnchor, slideAnchor); | ||
| setScrollingSpeed (getOriginals().scrollingSpeed, 'internal'); | ||
| } |