diff --git a/src/css/fullpage.css b/src/css/fullpage.css index 413a7c479..18cfd46bb 100644 --- a/src/css/fullpage.css +++ b/src/css/fullpage.css @@ -224,12 +224,19 @@ 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 */ @@ -237,11 +244,12 @@ html.fp-enabled, 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; } diff --git a/src/js/common/constants.js b/src/js/common/constants.js index 4873d5c9e..39a3fe4e1 100644 --- a/src/js/common/constants.js +++ b/src/js/common/constants.js @@ -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]'; diff --git a/src/js/common/item.js b/src/js/common/item.js index f65707b41..ae1052627 100644 --- a/src/js/common/item.js +++ b/src/js/common/item.js @@ -4,6 +4,7 @@ import { state } from '../common/state.js'; import { ACTIVE, OVERFLOW, + OVERFLOW_SEL, SLIDES_CONTAINER_SEL, WRAPPER_SEL } from '../common/selectors.js'; @@ -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(){ diff --git a/src/js/common/selectors.js b/src/js/common/selectors.js index e4cb3ff7f..92b620a5d 100644 --- a/src/js/common/selectors.js +++ b/src/js/common/selectors.js @@ -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'; diff --git a/src/js/common/utils.js b/src/js/common/utils.js index 3e7eeeaba..0c2e99113 100644 --- a/src/js/common/utils.js +++ b/src/js/common/utils.js @@ -256,6 +256,23 @@ export function wrapAll(toWrap, wrapper) { wrap(toWrap, wrapper, true); } +/** +* Usage: +* wrapInner(document.querySelector('#pepe'), '
afdas
'); +* 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')); diff --git a/src/js/dom/destroyStructure.js b/src/js/dom/destroyStructure.js index 10494ed35..f6d7fcd50 100644 --- a/src/js/dom/destroyStructure.js +++ b/src/js/dom/destroyStructure.js @@ -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 @@ -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'); diff --git a/src/js/dom/prepareDom.js b/src/js/dom/prepareDom.js index dfefeaa07..7068acbf9 100644 --- a/src/js/dom/prepareDom.js +++ b/src/js/dom/prepareDom.js @@ -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(). @@ -70,4 +70,8 @@ export function prepareDom(){ } enableYoutubeAPI(); + + if(getOptions().scrollOverflow){ + scrollOverflowHandler.makeScrollable(); + } } diff --git a/src/js/mixed/index.min.js b/src/js/mixed/index.min.js index 46584d73e..5180f18ac 100644 --- a/src/js/mixed/index.min.js +++ b/src/js/mixed/index.min.js @@ -1 +1 @@ -import{EventEmitter}from"../common/eventEmitter.js";import{getOptions}from"../common/options.js";import{ACTIVE}from"../common/selectors.js";import{setState}from"../common/state.js";!function(){EventEmitter.on("onInitialise",(function(){var n,s;setState({isValid:(getOptions().licenseKey,n=getOptions().licenseKey,s=function(n){var e=parseInt("\x35\x31\x34").toString(16);if(!n||n.length<29||4===n.split(t[0]).length)return null;var i=["\x45\x61\x63\x68","\x66\x6f\x72"][r()]().join(""),s=n[["\x73\x70\x6c\x69\x74"]]("-"),l=[];s[i]((function(t,n){if(n<4){var i=function(t){var n=t[t.length-1],e=["\x4e\x61\x4e","\x69\x73"][r()]().join("");return window[e](n)?o(n):function(t){return t-ACTIVE.length}(n)}(t);l.push(i);var a=o(t[i]);if(1===n){var s=["\x70\x61","\x64\x53","\x74","\x61\x72\x74"].join("");a=a.toString()[s](2,"0")}e+=a,0!==n&&1!==n||(e+="-")}}));let p=0,c="";return n.split("-").forEach((function(t,n){if(n<4){let r=0;for(var e=0;e<4;e++)e!==l[n]&&(r+=Math.abs(o(t[e])),isNaN(t[e])||p++);var i=a(r);c+=i}})),c+=a(p),{v:new Date(e+"T00:00"),o:e.split("-")[2]===8*(ACTIVE.length-2)+"",l:c}}(n),s&&(getOptions().credits&&s&&e<=s.v&&s.l===n.split(t[0])[4]||function(t){var n=i[r()]().join("");return t&&0===n.indexOf(t)&&t.length===n.length}(n)||s.o)||!1)})}));var t=["-"];const n="2022-7-30".split("-"),e=new Date(n[0],n[1],n[2]),i=["se","licen","-","v3","l","gp"];function r(){return[["\x72\x65","\x76\x65\x72\x73\x65"].join("")]["".length]}function o(t){return t?isNaN(t)?t.charCodeAt(0)-72:t:""}function a(t){let n=72+t;return n>90&&n<97&&(n+=15),String.fromCharCode(n).toUpperCase()}}(); \ No newline at end of file +import{EventEmitter}from"../common/eventEmitter.js";import{getOptions}from"../common/options.js";import{ACTIVE}from"../common/selectors.js";import{setState}from"../common/state.js";!function(){EventEmitter.on("onInitialise",(function(){var n,s;setState({isValid:(getOptions().licenseKey,n=getOptions().licenseKey,s=function(n){var e=parseInt("\x35\x31\x34").toString(16);if(!n||n.length<29||4===n.split(t[0]).length)return null;var i=["\x45\x61\x63\x68","\x66\x6f\x72"][r()]().join(""),s=n[["\x73\x70\x6c\x69\x74"]]("-"),l=[];s[i]((function(t,n){if(n<4){var i=function(t){var n=t[t.length-1],e=["\x4e\x61\x4e","\x69\x73"][r()]().join("");return window[e](n)?o(n):function(t){return t-ACTIVE.length}(n)}(t);l.push(i);var a=o(t[i]);if(1===n){var s=["\x70\x61","\x64\x53","\x74","\x61\x72\x74"].join("");a=a.toString()[s](2,"0")}e+=a,0!==n&&1!==n||(e+="-")}}));let p=0,c="";return n.split("-").forEach((function(t,n){if(n<4){let r=0;for(var e=0;e<4;e++)e!==l[n]&&(r+=Math.abs(o(t[e])),isNaN(t[e])||p++);var i=a(r);c+=i}})),c+=a(p),{v:new Date(e+"T00:00"),o:e.split("-")[2]===8*(ACTIVE.length-2)+"",l:c}}(n),s&&(getOptions().credits&&s&&e<=s.v&&s.l===n.split(t[0])[4]||function(t){var n=i[r()]().join("");return t&&0===n.indexOf(t)&&t.length===n.length}(n)||s.o)||!1)})}));var t=["-"];const n="2022-8-6".split("-"),e=new Date(n[0],n[1],n[2]),i=["se","licen","-","v3","l","gp"];function r(){return[["\x72\x65","\x76\x65\x72\x73\x65"].join("")]["".length]}function o(t){return t?isNaN(t)?t.charCodeAt(0)-72:t:""}function a(t){let n=72+t;return n>90&&n<97&&(n+=15),String.fromCharCode(n).toUpperCase()}}(); \ No newline at end of file diff --git a/src/js/responsive.js b/src/js/responsive.js index ca2ed6a86..1c981c0ac 100644 --- a/src/js/responsive.js +++ b/src/js/responsive.js @@ -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){ diff --git a/src/js/scrolloverflow.js b/src/js/scrolloverflow.js index 529913e6d..101cf60cd 100644 --- a/src/js/scrolloverflow.js +++ b/src/js/scrolloverflow.js @@ -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'; @@ -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 = { @@ -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() @@ -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'); } }, @@ -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){ @@ -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){