Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
//@ts-check
import * as utils from './common/utils.js';
import { getYmovement } from './common/getYMovement.js';
import { silentScroll } from './common/silentScroll.js';
import { getState } from './state.js';
import { silentLandscapeScroll } from './slides.js';
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';
} from '../common/selectors.js';
import { getYmovement } from '../common/utilsFP.js';


/**
* Adds sections before or after the current one to create the infinite effect.
*/
export function createInfiniteSections(v){
setState({isDoingContinousVertical: true});

// Scrolling down
if (!v.isMovementUp) {
// Move all previous sections to after the active section
Expand Down Expand Up @@ -51,27 +54,3 @@ function keepSlidesPosition(){
}




/**
* 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(getState().sections[0].item, v.wrapAroundElements);
}
else {
utils.after(utils.getLast(getState().sections).item, v.wrapAroundElements);
}

silentScroll(getState().activeSection.item.offsetTop);

// Maintain the active slides visible in the viewport
keepSlidesPosition();
}
45 changes: 45 additions & 0 deletions src/js/infiniteScroll/fixPosition.js
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});
}
29 changes: 11 additions & 18 deletions src/js/instance.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import * as utils from './common/utils.js';
import { getOptions, getContainer, setOptionsFromDOM } from './options.js';
import { getOptions, getContainer, setOptionsFromDOM } from './common/options.js';
import { updateState, updateStructuralState } from './stateUpdates.js';
import { setAllowScrolling } from './scroll.js';
import { setAutoScrolling } from './autoScrolling.js';
import { prepareDom, afterRenderActions } from './dom.js';
import { setMouseHijack } from './wheel.js';
import { setMouseHijack } from './mouse/wheel.js';
import { responsive } from './responsive.js';
import { setBodyClass } from './stateClasses.js';
import { setKeyboardScrolling } from './keyboard.js';
import { setKeyboardScrolling } from './keyboard/setKeyboardScrolling.js';
import { toggleCssSnapsWhenPossible } from './fitToSection.js';
import { scrollToAnchor } from './scroll.js';
import { destroyStructure } from './dom.js';
import { support3d } from './common/constants.js';
import { DESTROYED } from './common/selectors.js';
import { FP } from './common/constants.js';
import { clearTimeouts } from './timeouts.js';
import { EventEmitter } from './common/eventEmitter.js';
import { prepareDom } from './dom/prepareDom.js';
import { afterRenderActions } from './dom/afterRenderActions.js';
import { setAllowScrolling } from './scroll/setAllowScrolling.js';
import { scrollToAnchor } from './scroll/scrollToAnchor.js';
import { destroyStructure } from './dom/destroyStructure.js';

FP.destroy = destroy;

export function init(){
//if css3 is not supported, it will use jQuery animations
if(getOptions().css3){
getOptions().css3 = support3d();
}

updateStructuralState();
updateState();

Expand All @@ -43,7 +38,7 @@ export function init(){
if(document.readyState === 'complete'){
scrollToAnchor();
}
window.addEventListener('load', scrollToAnchor);
utils.windowAddEvent('load', scrollToAnchor);

afterRenderActions();

Expand All @@ -62,9 +57,7 @@ export function destroy(all){
setKeyboardScrolling(false);
utils.addClass(getContainer(), DESTROYED);

clearTimeouts();

utils.trigger('fp:onDestroy', {});
EventEmitter.emit(document, 'onDestroy');

//lets make a mess!
if(all){
Expand Down
22 changes: 13 additions & 9 deletions src/js/jquery-adaptor.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import { FP } from "./common/constants.js";
import { getOptions } from "./options.js";

//using jQuery initialization? Creating the $.fn.fullpage object
if(getOptions().$){
Object.keys(FP).forEach(function (key) {
getOptions().$.fn.fullpage[key] = FP[key];
});
}
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) {
window.fp_utils.showError('error', 'jQuery is required to use the jQuery fullpage adapter!');
// @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);
}
96 changes: 50 additions & 46 deletions src/js/keyboard.js → src/js/keyboard/index.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
//@ts-check
import * as utils from './common/utils.js';
import { getOptions } from './options';
import {
moveSectionDown,
moveSectionUp,
} from './scroll.js';
import { FP, focusableElementsString } from './common/constants.js';
import { moveSlideLeft, moveSlideRight } from './slides.js';
import { getSlideOrSection } from './utilsFP.js';
import * as utils from '../common/utils.js';
import { getOptions } from '../common/options';
import { FP, focusableElementsString } from '../common/constants.js';
import { getSlideOrSection } from '../common/utilsFP.js';
import { getIsScrollAllowed, setIsScrollAllowed } from '../common/isScrollAllowed.js';
import {
SECTION_ACTIVE_SEL,
SLIDE_ACTIVE_SEL,
SLIDE_SEL,
SECTION_SEL
} from './common/selectors.js';
import { getState, setState, getStateVar } from './state.js';
import { scrollOverflowHandler } from './scrolloverflow.js';
import { getIsScrollAllowed, setIsScrollAllowed } from './common/isScrollAllowed.js';
} from '../common/selectors.js';
import { getState, setState, state } from '../common/state.js';
import { moveSlideLeft, moveSlideRight } from '../slides/moveSlide.js';
import { scrollOverflowHandler } from '../scrolloverflow.js';
import { EventEmitter } from '../common/eventEmitter.js';
import { moveSectionUp } from '../scroll/moveSectionUp.js';
import { moveSectionDown } from '../scroll/moveSectionDown.js';
import { moveTo } from '../scroll/moveTo.js';

let controlPressed;
FP.setKeyboardScrolling = setKeyboardScrolling;
let g_controlPressed;
let g_keydownId;

/**
* 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;
}
}
EventEmitter.on('bindEvents', bindEvents);

export function getControlPressed(){
return controlPressed;
function bindEvents(){
//when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
utils.windowAddEvent('blur', blurHandler);

//Sliding with arrow keys, both, vertical and horizontal
utils.docAddEvent('keydown', keydownHandler);

//to prevent scrolling while zooming
utils.docAddEvent('keyup', keyUpHandler);

EventEmitter.on('onDestroy', onDestroy);
}


function onDestroy(){
clearTimeout(g_keydownId);
utils.docRemoveEvent('keydown', keydownHandler);
utils.docRemoveEvent('keyup', keyUpHandler);
}

//Sliding with arrow keys, both, vertical and horizontal
export function keydownHandler(e) {
function keydownHandler(e) {
clearTimeout(g_keydownId);

var activeElement = document.activeElement;
Expand All @@ -60,12 +60,12 @@ export function keydownHandler(e) {
else if(!utils.matches(activeElement, 'textarea') &&
!utils.matches(activeElement, 'input') &&
!utils.matches(activeElement, 'select') &&
activeElement.getAttribute('contentEditable') !== "true" &&
activeElement.getAttribute('contentEditable') !== '' &&
utils.getAttr(activeElement, 'contentEditable') !== "true" &&
utils.getAttr(activeElement, 'contentEditable') !== '' &&
getOptions().keyboardScrolling &&
canScrollWithKeyboard){

controlPressed = e.ctrlKey;
g_controlPressed = e.ctrlKey;

g_keydownId = setTimeout(function(){
onkeydown(e);
Expand Down Expand Up @@ -93,11 +93,11 @@ function onkeydown(e){
}

//do nothing if we can not scroll or we are not using horizotnal key arrows.
if(!getStateVar('canScroll') && !isUsingHorizontalArrowKeys){
if(!state.canScroll && !isUsingHorizontalArrowKeys){
return;
}

setState('scrollTrigger', 'keydown');
setState({scrollTrigger: 'keydown'});

switch (e.keyCode) {
//up
Expand Down Expand Up @@ -160,17 +160,17 @@ function onkeydown(e){


//to prevent scrolling while zooming
export function keyUpHandler(e){
if(getStateVar('isWindowFocused')){ //the keyup gets fired on new tab ctrl + t in Firefox
controlPressed = e.ctrlKey;
function keyUpHandler(e){
if(state.isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
g_controlPressed = e.ctrlKey;
}
}


//when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
export function blurHandler(){
setState('isWindowFocused', false);
controlPressed = false;
function blurHandler(){
setState({isWindowFocused: false});
g_controlPressed = false;
}


Expand Down Expand Up @@ -220,9 +220,9 @@ function onTab(e){
/**
* Gets all the focusable elements inside the passed element.
*/
function getFocusables(el){
function getFocusables(el){
return [].slice.call(utils.$(focusableElementsString, el)).filter(function(item) {
return item.getAttribute('tabindex') !== '-1' &&
return utils.getAttr(item, 'tabindex') !== '-1' &&
//are also not hidden elements (or with hidden parents)
item.offsetParent !== null;
});
Expand All @@ -246,4 +246,8 @@ function isFocusOutside(e){
function shouldCancelKeyboardNavigation(e){
var keyControls = [40, 38, 32, 33, 34];
return keyControls.indexOf(e.keyCode) > -1;
}

export function getControlPressed(){
return g_controlPressed;
}
22 changes: 22 additions & 0 deletions src/js/keyboard/setKeyboardScrolling.js
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;
}
}
94 changes: 0 additions & 94 deletions src/js/lazyLoad.js

This file was deleted.

36 changes: 36 additions & 0 deletions src/js/lazyLoad/lazyLoad.js
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);
};
}
}
});
}
52 changes: 52 additions & 0 deletions src/js/lazyLoad/lazyLoadOthers.js
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;
}
8 changes: 4 additions & 4 deletions src/js/media.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as utils from './common/utils.js';
import { getSlideOrSection } from './utilsFP.js';
import { getContainer } from './options.js';
import { getSlideOrSection } from './common/utilsFP.js';
import { getContainer } from './common/options.js';

// let g_mediaLoadedId;

Expand Down Expand Up @@ -70,7 +70,7 @@ export function stopMedia(destiny){

//youtube videos
utils.$('iframe[src*="youtube.com/embed/"]', panel).forEach(function(element){
if( /youtube\.com\/embed\//.test(element.getAttribute('src')) && !element.hasAttribute('data-keepplaying')){
if( /youtube\.com\/embed\//.test(utils.getAttr(element, 'src')) && !element.hasAttribute('data-keepplaying')){
element.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
}
});
Expand All @@ -89,7 +89,7 @@ export function enableYoutubeAPI(){
* Adds a new parameter and its value to the `src` of a given element
*/
function addURLParam(element, newParam){
var originalSrc = element.getAttribute('src');
var originalSrc = utils.getAttr(element, 'src');
element.setAttribute('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
}

Expand Down
61 changes: 0 additions & 61 deletions src/js/menu.js

This file was deleted.

27 changes: 27 additions & 0 deletions src/js/menu/activateMenuAndNav.js
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);
}
});
}
29 changes: 29 additions & 0 deletions src/js/menu/index.js
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')
});
}
}
26 changes: 26 additions & 0 deletions src/js/menu/styleMenu.js
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);
});
}
}
1 change: 1 addition & 0 deletions src/js/mixed/index.min.js
21 changes: 21 additions & 0 deletions src/js/mixed/warnings.js
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);
}
}
28 changes: 28 additions & 0 deletions src/js/mixed/waterMark.js
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);
}
}
16 changes: 6 additions & 10 deletions src/js/mouse.js → src/js/mouse/move.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getIsScrollAllowed } from './common/isScrollAllowed.js';
import { getOptions } from './options.js';
import { moveSectionUp, moveSectionDown } from './scroll.js';
import { getStateVar } from './state.js';

import { getIsScrollAllowed } from '../common/isScrollAllowed.js';
import { getOptions } from '../common/options.js';
import { moveSectionDown } from '../scroll/moveSectionDown.js';
import { moveSectionUp } from '../scroll/moveSectionUp.js';
import { state } from '../common/state.js';

let oldPageY = 0;

Expand All @@ -14,7 +14,7 @@ export function mouseMoveHandler(e) {
if (!getOptions().autoScrolling) {
return;
}
if (getStateVar('canScroll')) {
if (state.canScroll) {
// moving up
if (e.pageY < oldPageY && getIsScrollAllowed().m.up) {
moveSectionUp();
Expand All @@ -28,10 +28,6 @@ export function mouseMoveHandler(e) {
oldPageY = e.pageY;
}

export function getOldPageY(){
return oldPageY;
}

export function setOldPageY(value){
oldPageY = value;
}
43 changes: 23 additions & 20 deletions src/js/wheel.js → src/js/mouse/wheel.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import * as utils from './common/utils.js';
import { getOptions, getContainer } from './options.js';
import { getPassiveOptionsIfPossible } from './common/supportsPassive.js';
import { beyondFullPageHandler } from './beyondFullpage.js';
import { getStateVar, setState } from './state.js';
import { setOldPageY, mouseMoveHandler } from './mouse.js';
import { addTouchHandler, removeTouchHandler } from './touch';
import { scrolling } from './scroll.js';
import { getControlPressed } from './keyboard.js';
import { FP } from './common/constants.js';
import { getIsScrollAllowed } from './common/isScrollAllowed.js';
import * as utils from '../common/utils.js';
import { getIsScrollAllowed } from '../common/isScrollAllowed.js';
import { getPassiveOptionsIfPossible } from '../common/supportsPassive.js';
import { getOptions, getContainer } from '../common/options.js';
import { beyondFullPageHandler } from '../beyondFullpage/beyondFullPageHandler.js';
import { state, setState } from '../common/state.js';
import { setOldPageY, mouseMoveHandler } from '../mouse/move.js';
import { addTouchHandler, removeTouchHandler } from '../touch';
import { scrolling } from '../scroll/scrolling.js';
import { getControlPressed } from '../keyboard/index.js';
import { FP } from '../common/constants.js';
import {
COMPLETELY_SEL,
NORMAL_SCROLL
} from './common/selectors.js';
} from '../common/selectors.js';

let prevTime = new Date().getTime();
let scrollings = [];
Expand All @@ -21,7 +21,7 @@ FP.setMouseWheelScrolling = setMouseWheelScrolling;
/**
* Adds or remove the possibility of scrolling through sections by using the mouse wheel or the trackpad.
*/
export function setMouseWheelScrolling(value){
function setMouseWheelScrolling(value){
if(value){
addMouseWheelHandler();
addMiddleWheelHandler();
Expand Down Expand Up @@ -49,6 +49,7 @@ function addMouseWheelHandler(){

// detect available wheel event
var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
// @ts-ignore
document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
var passiveEvent = getPassiveOptionsIfPossible();
Expand Down Expand Up @@ -79,10 +80,11 @@ function addMiddleWheelHandler(){
*/
function removeMouseWheelHandler(){
if (document.addEventListener) {
document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
utils.docRemoveEvent('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
utils.docRemoveEvent('wheel', MouseWheelHandler, false); //Firefox
utils.docRemoveEvent('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
} else {
// @ts-ignore
document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
}
}
Expand Down Expand Up @@ -157,18 +159,19 @@ function MouseWheelHandler(e) {
}

if(getOptions().allowCorrectDirection){
setState('canScroll', getStateVar('canScroll') && getStateVar('direction') == direction || getDirection() !== direction);
setState({canScroll: state.canScroll && state.direction == direction || state.direction !== direction});
}

if(getStateVar('canScroll')){
if(state.canScroll){
console.log("MouseWheelHandler....");
var averageEnd = utils.getAverage(scrollings, 10);
var averageMiddle = utils.getAverage(scrollings, 70);
var isAccelerating = averageEnd >= averageMiddle;

//to avoid double swipes...
if(isAccelerating && isScrollingVertically){

setState('scrollTrigger', 'wheel');
setState({scrollTrigger: 'wheel'});

//scrolling down?
if (delta < 0) {
Expand All @@ -187,7 +190,7 @@ function MouseWheelHandler(e) {

if(getOptions().fitToSection){
//stopping the auto scroll to adjust to a section
setState('activeAnimation', false);
setState({activeAnimation: false});
}
}

Expand Down
138 changes: 0 additions & 138 deletions src/js/nav.js

This file was deleted.

12 changes: 12 additions & 0 deletions src/js/nav/getBulletLinkName.js
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);
}
32 changes: 32 additions & 0 deletions src/js/nav/index.js
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);
}
}
100 changes: 100 additions & 0 deletions src/js/nav/sections.js
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]
});
}
68 changes: 68 additions & 0 deletions src/js/nav/slides.js
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);
}
37 changes: 32 additions & 5 deletions src/js/normalScrollElements.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,44 @@
import * as utils from './common/utils.js';
import { setMouseHijack } from './wheel.js';
import { getOptions } from './options.js';
import { setMouseHijack } from './mouse/wheel.js';
import { getOptions } from './common/options.js';
import { FP } from './common/constants.js';
import { EventEmitter } from './common/eventEmitter.js';

let g_canFireMouseEnterNormalScroll = true;

export function forMouseLeaveOrTouch(eventName, allowScrolling){
EventEmitter.on('bindEvents', bindEvents);

function bindEvents(){
/**
* Applying normalScroll elements.
* Ignoring the scrolls over the specified selectors.
*/
if(getOptions().normalScrollElements){
['mouseenter', 'touchstart'].forEach(function(eventName){
forMouseLeaveOrTouch(eventName, false);
});

['mouseleave', 'touchend'].forEach(function(eventName){
forMouseLeaveOrTouch(eventName, true);
});
}

EventEmitter.on('onDestroy', onDestroy);
}

function onDestroy(){
['mouseenter', 'touchstart', 'mouseleave', 'touchend'].forEach(function(eventName){
utils.docRemoveEvent(eventName, onMouseEnterOrLeave, true); //true is required!
});
}

function forMouseLeaveOrTouch(eventName, allowScrolling){
//a way to pass arguments to the onMouseEnterOrLeave function
document['fp_' + eventName] = allowScrolling;
document.addEventListener(eventName, onMouseEnterOrLeave, true); //capturing phase
utils.docAddEvent(eventName, onMouseEnterOrLeave, true); //capturing phase
}

export function onMouseEnterOrLeave(e) {
function onMouseEnterOrLeave(e) {
var type = e.type;
var isInsideOneNormalScroll = false;

Expand Down
10 changes: 9 additions & 1 deletion src/js/optionsDefault.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ export const defaultOptions = {
scrollBar: false,
hybrid: false,

licenseKey: '',
credits: {
enabled: true,
label: 'Made with fullPage.js',
position: 'right'
},

//scrolling
css3: true,
scrollingSpeed: 700,
Expand All @@ -34,7 +41,7 @@ export const defaultOptions = {
resetSliders: false,
fadingEffect: false,
normalScrollElements: null,
scrollOverflow: false,
scrollOverflow: true,
scrollOverflowReset: false,
touchSensitivity: 5,
touchWrapper: null,
Expand Down Expand Up @@ -88,6 +95,7 @@ export const defaultOptions = {
onSlideLeave: null,
afterResponsive: null,

dynamic: true,
lazyLoading: true,
observer: true
};
44 changes: 44 additions & 0 deletions src/js/polyfills/array.find.js
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;
}
});
}
12 changes: 12 additions & 0 deletions src/js/polyfills/array.foreach.js
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);
}
};
}
92 changes: 92 additions & 0 deletions src/js/polyfills/array.from.js
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;
};
})();
}
4 changes: 4 additions & 0 deletions src/js/polyfills/index.js
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';
39 changes: 39 additions & 0 deletions src/js/polyfills/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
});
}
72 changes: 48 additions & 24 deletions src/js/resize.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,62 @@
import * as utils from './common/utils.js';
import { getOptions, getContainer } from './options.js';
import { onContentChange } from './dynamic.js';
import { getOptions, getContainer } from './common/options.js';
import { updateState } from './stateUpdates.js';
import { getState, setState } from './state.js';
import { getState, state, setState } from './common/state.js';
import { responsive } from './responsive.js';
import { isTouchDevice, FP } from './common/constants.js';
import { landscapeScroll } from './slides';
import { silentMoveTo } from './scroll.js';
import { isTouchDevice, FP, isTouch } from './common/constants.js';
import { landscapeScroll } from './slides/landscapeScroll.js';
import { scrollOverflowHandler } from './scrolloverflow.js';

import {
SLIDES_WRAPPER_SEL,
DESTROYED
} from './common/selectors.js';
import { EventEmitter } from './common/eventEmitter.js';
import { silentMoveTo } from './scroll/silentMove.js';

let previousHeight = utils.getWindowHeight();
let resizeId;
let windowsWidth = utils.getWindowWidth();

let g_resizeId;
let g_isConsecutiveResize = false;
FP.reBuild = reBuild;

EventEmitter.on('bindEvents', bindEvents);

function bindEvents(){
//when resizing the site, we adjust the heights of the sections, slimScroll...
utils.windowAddEvent('resize', resizeHandler);
EventEmitter.on('onDestroy', onDestroy);
}

function onDestroy(){
clearTimeout(g_resizeId);
utils.windowRemoveEvent('resize', resizeHandler);
}

/*
* Resize event handler.
*/
export function resizeHandler(){
function resizeHandler(){

if(!g_isConsecutiveResize){
// what is this for??!!
if(getOptions().autoScrolling && !getOptions().scrollBar || !getOptions().fitToSection){
setSectionsHeight(utils.getWindowHeight());
}
}

setSectionsHeight(utils.getWindowHeight());
g_isConsecutiveResize = true;

//in order to call the functions only when the resize is finished
//http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
clearTimeout(resizeId);
resizeId = setTimeout(function(){
clearTimeout(g_resizeId);
g_resizeId = setTimeout(function(){

//issue #3336
//(some apps or browsers, like Chrome/Firefox for Mobile take time to report the real height)
//so we check it 3 times with intervals in that case
// for(var i = 0; i< 4; i++){
resizeActions();
g_isConsecutiveResize = false;
// }
}, 400);
}
Expand All @@ -46,12 +66,15 @@ export function resizeHandler(){
* When resizing the site, we adjust the heights of the sections, slimScroll...
*/
function resizeActions(){
setState('isResizing', true);
setState({isResizing: true});

setSectionsHeight('');
setVhUnits();

onContentChange();
if(getOptions().fitToSection && !getOptions().autoScrolling && !state.isBeyondFullpage){
setVhUnits();
}

EventEmitter.emit('contentChanged');
updateState();

//checking if it needs to get responsive
Expand All @@ -76,20 +99,20 @@ function resizeActions(){
adjustToNewViewport();
}

setState('isResizing', false);
setState({isResizing: false});
}

/**
* When resizing is finished, we adjust the slides sizes and positions
*/
export function reBuild(resizing){
function reBuild(resizing){
if(utils.hasClass(getContainer(), DESTROYED)){ return; } //nothing to do if the plugin was destroyed

setState('isResizing', true);
setState({isResizing: true});

//updating global vars
windowsHeight = utils.getWindowHeight();
windowsWidth = utils.getWindowWidth();
setState({windowsHeight: utils.getWindowHeight()});
setState({windowsWidth: utils.getWindowWidth()});

var sections = getState().sections;
for (var i = 0; i < sections.length; ++i) {
Expand All @@ -115,7 +138,7 @@ export function reBuild(resizing){
silentMoveTo(sectionIndex + 1);
}

setState('isResizing', false);
setState({isResizing: false});

if(utils.isFunction( getOptions().afterResize ) && resizing){
getOptions().afterResize.call(getContainer(), window.innerWidth, window.innerHeight);
Expand All @@ -132,8 +155,8 @@ function adjustToNewViewport(){
var newWindowHeight = utils.getWindowHeight();
var newWindowWidth = utils.getWindowWidth();

if(windowsHeight !== newWindowHeight || windowsWidth !== newWindowWidth){
windowsHeight = newWindowHeight;
if(state.windowsHeight !== newWindowHeight || windowsWidth !== newWindowWidth){
setState({windowsHeight: newWindowHeight});
windowsWidth = newWindowWidth;
reBuild(true);
}
Expand All @@ -150,6 +173,7 @@ function setSectionsHeight(value){

/**
* Defining the value in px of a VH unit. (Used for autoScrolling: false)
* To fix the height issue on mobile devices when using VH units.
* https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
*/
function setVhUnits(){
Expand Down
7 changes: 4 additions & 3 deletions src/js/responsive.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as utils from './common/utils.js';
import { getOptions, getContainer, getOriginals} from './options.js';
import { getOptions, getContainer, getOriginals} from './common/options.js';
import { setAutoScrolling } from './autoScrolling.js';
import { setFitToSection } from './fitToSection.js';
import { $body, FP } from './common/constants.js';
import { FP } from './common/constants.js';
import { $body } from './common/cache.js';
import {
SECTION_NAV_SEL,
RESPONSIVE
Expand Down Expand Up @@ -38,7 +39,7 @@ export function responsive(){
* Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
* are smaller than the set limit values.
*/
export function setResponsive(active){
function setResponsive(active){
var isResponsive = isResponsiveMode();

if(active){
Expand Down
619 changes: 0 additions & 619 deletions src/js/scroll.js

This file was deleted.

38 changes: 38 additions & 0 deletions src/js/scroll/index.js
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);
});
}
33 changes: 33 additions & 0 deletions src/js/scroll/moveSectionDown.js
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;
}
23 changes: 23 additions & 0 deletions src/js/scroll/moveSectionUp.js
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);
}
}
20 changes: 20 additions & 0 deletions src/js/scroll/moveTo.js
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);
}
}
198 changes: 198 additions & 0 deletions src/js/scroll/scrollHandler.js
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());
}
285 changes: 285 additions & 0 deletions src/js/scroll/scrollPage.js
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();
}
}
43 changes: 43 additions & 0 deletions src/js/scroll/scrollPageAndSlide.js
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;
}
21 changes: 21 additions & 0 deletions src/js/scroll/scrollToAnchor.js
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);
}
}
}
31 changes: 31 additions & 0 deletions src/js/scroll/scrolling.js
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();
}
}
23 changes: 23 additions & 0 deletions src/js/scroll/setAllowScrolling.js
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');
}
}
16 changes: 16 additions & 0 deletions src/js/scroll/silentMove.js
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');
}
82 changes: 58 additions & 24 deletions src/js/scrolloverflow.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
import * as utils from './common/utils.js';
import { getOptions } from './options.js';
import { getState, getStateVar } from './state.js';
import { fireCallback } from './callbacks.js';
import { getOptions } from './common/options.js';
import { getState, state } from './common/state.js';
import { fireCallback } from './callbacks/fireCallback.js';
import { isResponsiveMode } from './responsive.js';

import { isMacDevice, $body, isTouchDevice, isTouch } from './common/constants.js';
import { isMacDevice, isTouchDevice, isTouch } from './common/constants.js';
import { $body } from './common/cache.js';
import {
AUTO_HEIGHT,
AUTO_HEIGHT_RESPONSIVE,
SLIDE_ACTIVE_SEL
} from './common/selectors.js';
import { getNodes } from './common/item.js';
import { EventEmitter } from './common/eventEmitter.js';

EventEmitter.on('bindEvents', bindEvents);


function bindEvents(){

//after DOM and images are loaded
window.addEventListener('load', function(){
if(getOptions().scrollOverflow){
scrollOverflowHandler.makeScrollable();
scrollOverflowHandler.afterSectionLoads();
}
});

if(getOptions().scrollOverflow){
getNodes(getState().panels).forEach(function(el){
el.addEventListener('scroll', scrollOverflowHandler.onPanelScroll);
el.addEventListener('wheel', scrollOverflowHandler.preventScrollWhileMoving);
el.addEventListener('keydown', scrollOverflowHandler.preventScrollWhileMoving);
el.addEventListener('keydown', scrollOverflowHandler.blurFocusOnAfterLoad);
});
}
}

export const scrollOverflowHandler = {
focusedElem: null,
Expand All @@ -19,7 +44,7 @@ export const scrollOverflowHandler = {
timeLastScroll: null,

preventScrollWhileMoving: function(e){
if(!getStateVar('canScroll')){
if(!state.canScroll){
utils.preventDefault(e);
return false;
}
Expand All @@ -29,6 +54,7 @@ export const scrollOverflowHandler = {

// Unfocusing the scrollable element from the orgin section/slide
if( document.activeElement === this.focusedElem){
// @ts-ignore
this.focusedElem.blur();
}

Expand All @@ -45,21 +71,25 @@ export const scrollOverflowHandler = {

getState().panels.forEach(function(el){
if(
utils.hasClass(el.item, 'fp-noscroll')
|| utils.hasClass(el.item, AUTO_HEIGHT)
|| utils.hasClass(el.item, AUTO_HEIGHT_RESPONSIVE) && isResponsiveMode()
utils.hasClass(el.item, 'fp-noscroll') ||
utils.hasClass(el.item, AUTO_HEIGHT) ||
utils.hasClass(el.item, AUTO_HEIGHT_RESPONSIVE) && isResponsiveMode()
){
return;
}else{
let panel = scrollOverflowHandler.scrollable(el.item);

if(scrollOverflowHandler.shouldBeScrollable(el.item)){
utils.addClass(panel, 'fp-overflow');
panel.setAttribute('tabindex', '-1');
let item = scrollOverflowHandler.scrollable(el.item);
const shouldBeScrollable = scrollOverflowHandler.shouldBeScrollable(el.item);
if(shouldBeScrollable){
utils.addClass(item, 'fp-overflow');
item.setAttribute('tabindex', '-1');
}else{
utils.removeClass(panel, 'fp-overflow');
panel.removeAttribute('tabindex');
utils.removeClass(item, 'fp-overflow');
item.removeAttribute('tabindex');
}

// updating the state now in case
// this is executed on page load (after images load)
el.hasScroll = shouldBeScrollable;
}
});
},
Expand All @@ -73,17 +103,19 @@ export const scrollOverflowHandler = {
},

shouldBeScrollable: function(item){
console.log(item);
console.log(item.scrollHeight + ' vs ' + window.innerHeight);
return item.scrollHeight > window.innerHeight;
},

isScrolled: function(direction, el){
if(!getStateVar('canScroll')){
if(!state.canScroll){
return false;
}
if(!getOptions().scrollOverflow){
return true;
}
var scrollableItem = this.scrollable(el);
var scrollableItem = scrollOverflowHandler.scrollable(el);
var positionY = scrollableItem.scrollTop;
var isTopReached = direction === 'up' && positionY <=0;
var isBottomReached = direction === 'down' && scrollableItem.scrollHeight <= scrollableItem.offsetHeight + positionY;
Expand All @@ -97,19 +129,19 @@ export const scrollOverflowHandler = {

shouldMovePage: function(){
this.timeLastScroll = new Date().getTime();
var timeDiff = this.timeLastScroll - this.timeBeforeReachingLimit;
var timeDiff = this.timeLastScroll - scrollOverflowHandler.timeBeforeReachingLimit;
var isUsingTouch = isTouchDevice || isTouch;
var isGrabbing = isUsingTouch && getStateVar('isGrabbing');
var isGrabbing = isUsingTouch && state.isGrabbing;
var isNotFirstTimeReachingLimit = !isUsingTouch && timeDiff > 600;

return isGrabbing || isNotFirstTimeReachingLimit;
return isGrabbing && timeDiff > 400 || isNotFirstTimeReachingLimit;
},
onPanelScroll: (function(){
var prevPosition = 0;

return function(e){
var currentPosition = e.target.scrollTop;
var direction = getStateVar('touchDirection') !== 'none' ? getStateVar('touchDirection') : prevPosition < currentPosition ? 'down' : 'up';
var direction = state.touchDirection !== 'none' ? state.touchDirection : prevPosition < currentPosition ? 'down' : 'up';
prevPosition = currentPosition;

if(utils.isFunction(getOptions().onScrollOverflow) ){
Expand All @@ -118,12 +150,14 @@ export const scrollOverflowHandler = {
});
}

if(utils.hasClass(e.target, 'fp-overflow') && getStateVar('canScroll')){
if(utils.hasClass(e.target, 'fp-overflow') && state.canScroll){
if(
scrollOverflowHandler.isScrolled(direction, e.target) &&
scrollOverflowHandler.shouldMovePage()
){
utils.trigger('fp:onScrollOverflowScrolled', {scrollSection: scrollSection });
EventEmitter.emit('onScrollOverflowScrolled', {
direction: direction
});
}
}
};
Expand Down
7 changes: 3 additions & 4 deletions src/js/sections.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as utils from './common/utils.js';
import { getOptions } from "./options.js";
import { getOptions } from "./common/options.js";
import { ACTIVE } from './common/selectors.js';
import { updateState } from './stateUpdates.js';
import { getState } from './state.js';
import { getState } from './common/state.js';
import { FP } from './common/constants.js';

let startingSection = null;
Expand All @@ -12,7 +12,6 @@ export function getStartingSection(){
return startingSection;
}


/**
* Styling vertical sections
*/
Expand Down Expand Up @@ -47,6 +46,6 @@ export function styleSection(section){
/**
* Gets the active section.
*/
export function getActiveSection(){
function getActiveSection(){
return getState().activeSection;
}
Loading