Skip to content

Commit

Permalink
- Fixed bug: scrollable content wasn't able to have background #4448 #…
Browse files Browse the repository at this point in the history
…4447

- Enhancement: dynamically adding content will automatically create scrollable elements when using scrollOverflow: true.
  • Loading branch information
alvarotrigo committed Sep 6, 2022
1 parent 614dcf4 commit 456b09b
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 56 deletions.
16 changes: 12 additions & 4 deletions src/css/fullpage.css
Original file line number Diff line number Diff line change
Expand Up @@ -224,24 +224,32 @@ html.fp-enabled,
height: auto !important;
}

.fp-responsive .fp-is-overflow.fp-section{
height: auto !important;
}

/* Used with autoScrolling: false */
.fp-scrollable.fp-responsive .fp-is-overflow.fp-section,
.fp-scrollable .fp-section,
.fp-scrollable .fp-slide{
/* Fallback for browsers that do not support Custom Properties */
height: 100vh;
min-height: 100vh;
height: calc(var(--vh, 1vh) * 100);
min-height: calc(var(--vh, 1vh) * 100);
}

/* Disabling vertical centering on scrollable elements */
.fp-overflow{
justify-content: flex-start;
}

.fp-overflow.fp-auto-height-responsive,
.fp-overflow.fp-auto-height,
.fp-is-overflow .fp-overflow.fp-auto-height-responsive,
.fp-is-overflow .fp-overflow.fp-auto-height,
.fp-is-overflow > .fp-overflow{
overflow-y: auto;
}
.fp-overflow{
overflow-y: scroll;
height: 100% !important;
outline:none;
}

Expand Down
1 change: 1 addition & 0 deletions src/js/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Androi
export const isMacDevice = /(Mac|iPhone|iPod|iPad)/i.test(win.navigator.userAgent);
// @ts-ignore
export const isTouch = (('ontouchstart' in win) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
export const isIE11 = !!window.MSInputMethodContext && !!document.documentMode;

// taken from https://github.com/udacity/ud891/blob/gh-pages/lesson2-focus/07-modals-and-keyboard-traps/solution/modal.js
export const focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';
Expand Down
3 changes: 2 additions & 1 deletion src/js/common/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { state } from '../common/state.js';
import {
ACTIVE,
OVERFLOW,
OVERFLOW_SEL,
SLIDES_CONTAINER_SEL,
WRAPPER_SEL
} from '../common/selectors.js';
Expand All @@ -27,7 +28,7 @@ export const Item = function(el, selector){
this.item = el;
this.isVisible = utils.isVisible(el);
this.isActive = utils.hasClass(el, ACTIVE);
this.hasScroll = utils.hasClass(el, OVERFLOW);
this.hasScroll = utils.hasClass(el, OVERFLOW) || utils.$(OVERFLOW_SEL, el)[0] != null;
this.isSection = selector === getOptions().sectionSelector;
this.container = utils.closest(el, SLIDES_CONTAINER_SEL) || utils.closest(el, WRAPPER_SEL);
this.index = function(){
Expand Down
1 change: 1 addition & 0 deletions src/js/common/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER;
export const TABLE = 'fp-table';
export const OVERFLOW = 'fp-overflow';
export const OVERFLOW_SEL = '.' + OVERFLOW;
export const IS_OVERFLOW = 'fp-is-overflow';

// slide nav
export const SLIDES_NAV = 'fp-slidesNav';
Expand Down
17 changes: 17 additions & 0 deletions src/js/common/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,23 @@ export function wrapAll(toWrap, wrapper) {
wrap(toWrap, wrapper, true);
}

/**
* Usage:
* wrapInner(document.querySelector('#pepe'), '<div class="test">afdas</div>');
* wrapInner(document.querySelector('#pepe'), element);
*
* https://jsfiddle.net/zexxz0tw/6/
*
* https://stackoverflow.com/a/21817590/1081396
*/
export function wrapInner(parent, wrapper) {
parent.appendChild(wrapper);

while(parent.firstChild !== wrapper){
wrapper.appendChild(parent.firstChild);
}
}

/**
* Usage:
* unwrap(document.querySelector('#pepe'));
Expand Down
6 changes: 3 additions & 3 deletions src/js/dom/destroyStructure.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import {
SLIDES_CONTAINER,
SLIDES_CONTAINER_SEL,
SLIDES_WRAPPER_SEL,
SLIDES_ARROW_SEL,
OVERFLOW
SLIDES_ARROW_SEL
} from '../common/selectors.js';
import { win } from '../common/constants.js';
import { scrollOverflowHandler } from '../scrolloverflow.js';

/*
* Removes inline styles added by fullpage.js
Expand Down Expand Up @@ -82,7 +82,7 @@ export function destroyStructure(){
//removing added classes
getNodes(getState().panels).forEach(function(item){
if(getOptions().scrollOverflow){
utils.removeClass(item, OVERFLOW);
scrollOverflowHandler.destroyWrapper(item);
}
utils.removeClass(item, TABLE + ' ' + ACTIVE + ' ' + COMPLETELY);
var previousStyles = utils.getAttr(item, 'data-fp-styles');
Expand Down
6 changes: 5 additions & 1 deletion src/js/dom/prepareDom.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import { styleSlides } from '../slides/styleSlides.js';
import { styleMenu } from '../menu/styleMenu.js';
import { addVerticalNavigation } from '../nav/sections.js';
import { enableYoutubeAPI } from '../media.js';
import { scrollOverflowHandler } from '../scrolloverflow.js';
import {
WRAPPER,
ENABLED,
DESTROYED
} from '../common/selectors.js';
import { addInternalSelectors } from './addInternalSelectors.js';
import { scrollOverflowHandler } from '../scrolloverflow.js';

/**
* Works over the DOM structure to set it up for the current fullpage getOptions().
Expand Down Expand Up @@ -70,4 +70,8 @@ export function prepareDom(){
}

enableYoutubeAPI();

if(getOptions().scrollOverflow){
scrollOverflowHandler.makeScrollable();
}
}
2 changes: 1 addition & 1 deletion src/js/mixed/index.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 1 addition & 6 deletions src/js/responsive.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,7 @@ function setResponsive(active){
utils.addClass($body, RESPONSIVE);
if(utils.isFunction( getOptions().afterResponsive )){
getOptions().afterResponsive.call( getContainer(), active);
}

//when on page load, we will remove scrolloverflow if necessary
// if(getOptions().scrollOverflow){
// createScrollBarForAll();
// }
}
}
}
else if(isResponsive){
Expand Down
84 changes: 44 additions & 40 deletions src/js/scrolloverflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ 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, isTouchDevice, isTouch, win, doc } from './common/constants.js';
import { isMacDevice, isTouchDevice, isTouch, win, doc, isIE11 } from './common/constants.js';
import { $body } from './common/cache.js';
import {
AUTO_HEIGHT,
AUTO_HEIGHT_RESPONSIVE,
IS_OVERFLOW,
OVERFLOW,
OVERFLOW_SEL,
OVERFLOW_SEL
} from './common/selectors.js';
import { getNodes } from './common/item.js';
import { EventEmitter } from './common/eventEmitter.js';
import { getSlideOrSection } from './common/utilsFP.js';
import { getSectionFromPanel } from './sections.js';
Expand All @@ -27,15 +26,6 @@ function bindEvents(){
scrollOverflowHandler.afterSectionLoads();
}
});

if(getOptions().scrollOverflow){
getNodes(getState().panels).forEach(function(el){
scrollOverflowHandler.getScrollableItem(el).addEventListener('scroll', scrollOverflowHandler.onPanelScroll);

el.addEventListener('wheel', scrollOverflowHandler.preventScrollWhileMoving, {passive: false});
el.addEventListener('keydown', scrollOverflowHandler.preventScrollWhileMoving, {passive: false});
});
}
}

export const scrollOverflowHandler = {
Expand Down Expand Up @@ -75,6 +65,9 @@ export const scrollOverflowHandler = {
}

getState().panels.forEach(function(el){
if(el.slides && el.slides.length){
return;
}
if(
utils.hasClass(el.item, 'fp-noscroll') ||
utils.hasClass(el.item, AUTO_HEIGHT_RESPONSIVE) && isResponsiveMode()
Expand All @@ -83,44 +76,50 @@ export const scrollOverflowHandler = {
}else{
let item = getSlideOrSection(el.item);
const shouldBeScrollable = scrollOverflowHandler.shouldBeScrollable(el.item);
var section = getSectionFromPanel(el);

if(shouldBeScrollable){

if(isResponsiveMode()){
scrollOverflowHandler.addTmpAutoHeight(el);
}
else{
scrollOverflowHandler.removeTmpAutoHeight(el);

utils.addClass(item, OVERFLOW);
item.setAttribute('tabindex', '-1');
}
if(isIE11){
var toggleAction = shouldBeScrollable ? 'addClass' : 'removeClass';
utils[toggleAction](section.item, IS_OVERFLOW);
utils[toggleAction](el.item, IS_OVERFLOW);
}
else{
scrollOverflowHandler.removeTmpAutoHeight(el);

utils.removeClass(item, OVERFLOW);
item.removeAttribute('tabindex');
utils.addClass(section.item, IS_OVERFLOW);
utils.addClass(el.item, IS_OVERFLOW);
}

if(!el.hasScroll){
scrollOverflowHandler.createWrapper(item);
scrollOverflowHandler.bindEvents(item);
}

// updating the state now in case
// this is executed on page load (after images load)
el.hasScroll = shouldBeScrollable && !isResponsiveMode();
el.hasScroll = true;
}
});
},

addTmpAutoHeight: function(el){
var section = getSectionFromPanel(el);
utils.addClass(section.item, AUTO_HEIGHT);
section.tmpAutoHeight = true;
bindEvents: function(item){
scrollOverflowHandler.getScrollableItem(item).addEventListener('scroll', scrollOverflowHandler.onPanelScroll);

item.addEventListener('wheel', scrollOverflowHandler.preventScrollWhileMoving, {passive: false});
item.addEventListener('keydown', scrollOverflowHandler.preventScrollWhileMoving, {passive: false});
},

createWrapper: function(item){
var overflowWrapper = document.createElement('div');
overflowWrapper.className = OVERFLOW;

utils.wrapInner(item, overflowWrapper);
overflowWrapper.setAttribute('tabindex', '-1');
},

removeTmpAutoHeight: function(panel){
var section = getSectionFromPanel(panel);
if(section.tmpAutoHeight){
section.tmpAutoHeight = false;
utils.removeClass(section.item, AUTO_HEIGHT);
destroyWrapper: function(item){
var overflowWrapper = utils.$(OVERFLOW_SEL, item)[0];
if(overflowWrapper){
utils.unwrap(overflowWrapper);
item.removeAttribute('tabindex');
}
},

Expand All @@ -139,7 +138,8 @@ export const scrollOverflowHandler = {
},

shouldBeScrollable: function(item){
return item.scrollHeight > win.innerHeight;
var scrollable = scrollOverflowHandler.getScrollableItem(item);
return scrollable.scrollHeight > win.innerHeight;
},

isScrolled: function(direction, el){
Expand All @@ -153,9 +153,13 @@ export const scrollOverflowHandler = {
return true;
}

// ie11 wrongly calculates scrollHeight when using the CSS style
// overflow: auto It adds 1 more pixel compared to offsetHeight
var ie11offset = isIE11 ? 1 : 0;

var positionY = scrollableItem.scrollTop;
var isTopReached = direction === 'up' && positionY <=0;
var isBottomReached = direction === 'down' && scrollableItem.scrollHeight <= Math.ceil(scrollableItem.offsetHeight + positionY);
var isBottomReached = direction === 'down' && scrollableItem.scrollHeight <= Math.ceil(scrollableItem.offsetHeight + positionY) + ie11offset;
var isScrolled = isTopReached || isBottomReached;

if(!isScrolled){
Expand Down

0 comments on commit 456b09b

Please sign in to comment.