From 8c0b6396a477a667b063db6490bb6d0f2cb5dd93 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 27 May 2020 09:56:57 +0200 Subject: [PATCH 1/2] Create scroll-box pattern out of scroll_detection --- src/{core/scroll_detection.js => pat/scroll-box/scroll-box.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{core/scroll_detection.js => pat/scroll-box/scroll-box.js} (100%) diff --git a/src/core/scroll_detection.js b/src/pat/scroll-box/scroll-box.js similarity index 100% rename from src/core/scroll_detection.js rename to src/pat/scroll-box/scroll-box.js From 76850bb85a142fb667ef7dfffc41b66a60b96357 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Wed, 27 May 2020 13:01:06 +0200 Subject: [PATCH 2/2] pat-scroll-box: New pattern for scrolling detection. Replaces the previous "scroll detection" module. --- CHANGES.md | 2 +- src/pat/scroll-box/documentation.md | 15 ++++ src/pat/scroll-box/index.html | 54 +++++++++++++ src/pat/scroll-box/scroll-box.js | 117 ++++++++++++++++------------ src/patterns.js | 4 +- webpack/base.config.js | 4 +- 6 files changed, 143 insertions(+), 53 deletions(-) create mode 100644 src/pat/scroll-box/documentation.md create mode 100644 src/pat/scroll-box/index.html diff --git a/CHANGES.md b/CHANGES.md index 376b1a388..7441d1e08 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,9 +5,9 @@ Features ~~~~~~~~ +- pat-scroll-box: New pattern for scrolling detection. Replaces the previous "scroll detection" module. - pat-inject: Rename undocumented ``selector`` property to ``defaultSelector``. - pat-inject: Fix typo in docs for the ``source`` property. -- scroll detection: Rework and optimize, set scroll classes on any scrolling event, fix problem with IE and set initial state. Fixes #701 - pat-scroll: Implement new special `selector:top` attribute value to scroll the scroll container just to the top of the page. Ref: #721. - pat-scroll: To define the scrollable target search also for `overflow-x` and `overflow-y` declarations. - Rework push message support for the STOMP message protocoll instead of backends instead of WAMP. diff --git a/src/pat/scroll-box/documentation.md b/src/pat/scroll-box/documentation.md new file mode 100644 index 000000000..b93117a7a --- /dev/null +++ b/src/pat/scroll-box/documentation.md @@ -0,0 +1,15 @@ +## Description + +The *scroll box* pattern adds some CSS classes to the element depending on it's scrolling position. + +The element where it is invoked upon has to be scrollable. +Therefore the eleme must have set the ``overflow`` or ``overflowY`` CSS property set to ``auto`` or ``scroll``. +Ho(horizontal scrolling is not yet supported. + +The classes are: + +- ``scroll-up``: when scrolling upwards, +- ``scroll-down``: when scrolling downwards, +- ``scroll-position-top``: when the scrolling container is scrolled to the top, +- ``scroll-position-bottom``: when the scrolling container is scrolled to the bottom. + diff --git a/src/pat/scroll-box/index.html b/src/pat/scroll-box/index.html new file mode 100644 index 000000000..9e08a123a --- /dev/null +++ b/src/pat/scroll-box/index.html @@ -0,0 +1,54 @@ + + + + + + Demo for pat-scroll + + + + + +
+
+ hello. +
+
+ + diff --git a/src/pat/scroll-box/scroll-box.js b/src/pat/scroll-box/scroll-box.js index edb19e3a1..b69e871f6 100644 --- a/src/pat/scroll-box/scroll-box.js +++ b/src/pat/scroll-box/scroll-box.js @@ -4,63 +4,84 @@ * Copyright 2020- Alexander Pilz, Syslab.com GmbH */ -define([ - "jquery" -], function($) { - var scroll_detection = { +define(["jquery", "pat-base"], function ($, Base) { + return Base.extend({ + name: "scroll-box", + trigger: ".pat-scroll-box", + timeout: 200, - init: function () { + init: function ($el) { + const el = $el[0]; + let scroll_listener = el; + if (scroll_listener === document.body) { + scroll_listener = window; + } + + // If scolling is not possible, exit. + if ( + ! scroll_listener == window && ( + ['auto', 'scroll'].indexOf(getComputedStyle(el).overflow) === -1 || + ['auto', 'scroll'].indexOf(getComputedStyle(el).overflowY) === -1 + ) + ) { + return; + } - let last_known_scroll_position = 0; - let scroll_y = 0; - let ticking = false; + let last_known_scroll_position = 0; + let scroll_y = 0; + let timeout_id = null; - let set_scroll_classes = (scroll_pos) => { - document.body.classList.remove("scroll-up"); - document.body.classList.remove("scroll-down"); - document.body.classList.remove("scroll-position-top"); - document.body.classList.remove("scroll-position-bottom"); - if (scroll_pos < last_known_scroll_position) { - document.body.classList.add("scroll-up"); - } else if (last_known_scroll_position < scroll_pos) { - document.body.classList.add("scroll-down"); - } + let set_scroll_classes = (scroll_pos) => { + el.classList.remove("scroll-up"); + el.classList.remove("scroll-down"); + el.classList.remove("scroll-position-top"); + el.classList.remove("scroll-position-bottom"); - if (scroll_pos === 0) { - document.body.classList.add("scroll-position-top"); - } else if ((window.innerHeight + scroll_pos) >= document.body.offsetHeight) { - document.body.classList.add("scroll-position-bottom"); - } + if (scroll_pos < last_known_scroll_position) { + el.classList.add("scroll-up"); + } else if (last_known_scroll_position < scroll_pos) { + el.classList.add("scroll-down"); } - window.addEventListener('scroll', (e) => { - // In case that's needed sometime: - // ``e.target.scrollTop`` would be the scrolling position of the DOM element. - // We're interested in the window scrolling position though. - if (!ticking) { - // Don't redo while we're already modifying the DOM. - window.requestAnimationFrame(() => { - scroll_y = this.get_scroll_y(); - set_scroll_classes(scroll_y); - last_known_scroll_position = scroll_y; - ticking = false; - }); - ticking = true; - } - }); - - // Set initial state - $().ready(() => set_scroll_classes(this.get_scroll_y())); + if (scroll_pos === 0) { + el.classList.add("scroll-position-top"); + } else if ( + scroll_listener === window && + window.innerHeight + scroll_pos >= + el.scrollHeight + ) { + el.classList.add("scroll-position-bottom"); + } else if ( + scroll_listener !== window && + el.clientHeight + scroll_pos >= + el.scrollHeight + ) { + el.classList.add("scroll-position-bottom"); + } - }, + }; - get_scroll_y: () => { - return window.scrollY !== undefined ? window.scrollY : window.pageYOffset; // pageYOffset for IE - } + scroll_listener.addEventListener("scroll", (e) => { + if (!timeout_id) { + scroll_y = this.get_scroll_y(scroll_listener); + set_scroll_classes(scroll_y); + last_known_scroll_position = scroll_y; + } + timeout_id = window.setTimeout(() => { timeout_id = null; }, this.timeout); + }); - }; + // Set initial state + $().ready(() => set_scroll_classes(this.get_scroll_y(scroll_listener))); + }, - scroll_detection.init(); - return scroll_detection; + get_scroll_y: (el) => { + if (el === window) { + // scrolling the window + return window.scrollY !== undefined ? window.scrollY : window.pageYOffset; // pageYOffset for IE + } + // scrolling a DOM element + return el.scrollTop; + }, + }); }); diff --git a/src/patterns.js b/src/patterns.js index c7c11df1c..798b8ebac 100644 --- a/src/patterns.js +++ b/src/patterns.js @@ -13,7 +13,6 @@ define([ "moment", "modernizr", "prefixfree", - "scroll-detection", "push-kit", "pat-ajax", "pat-autofocus", @@ -54,6 +53,7 @@ define([ "pat-masonry", "pat-placeholder", "pat-scroll", + "pat-scroll-box", "pat-selectbox", "pat-slides", "pat-slideshow-builder", @@ -102,7 +102,7 @@ define([ require("imports-loader?this=>window!jquery.browser"); $(function () { - registry.init(); + registry.init(); }); return registry; }); diff --git a/webpack/base.config.js b/webpack/base.config.js index 6d80b74cb..e6103b517 100644 --- a/webpack/base.config.js +++ b/webpack/base.config.js @@ -36,7 +36,7 @@ module.exports = { module: { rules: [ { - test: /(bumper|patterns|calendar|display-time|equaliser|focus|masonry|push_kit|scroll|scroll_detection|tooltip-ng)\.js$/, + test: /(bumper|patterns|calendar|display-time|equaliser|focus|masonry|push_kit|scroll|scroll-box|tooltip-ng)\.js$/, loader: 'babel-loader', query: { presets: [["@babel/env", { @@ -160,7 +160,6 @@ module.exports = { // Core "pat-compat": path.resolve(__dirname, "../src/core/compat.js"), "pat-base": path.resolve(__dirname, "../src/core/base.js"), - "scroll-detection": path.resolve(__dirname, "../src/core/scroll_detection.js"), "pat-date-picker": path.resolve(__dirname, "../src/pat/date-picker/date-picker.js"), "pat-datetime-picker": path.resolve(__dirname, "../src/pat/datetime-picker/datetime-picker.js"), "pat-depends_parse": path.resolve(__dirname, "../src/lib/depends_parse.js"), @@ -234,6 +233,7 @@ module.exports = { "pat-subform": path.resolve(__dirname, "../src/pat/subform/subform.js"), "pat-switch": path.resolve(__dirname, "../src/pat/switch/switch.js"), "pat-scroll": path.resolve(__dirname, "../src/pat/scroll/scroll.js"), + "pat-scroll-box": path.resolve(__dirname, "../src/pat/scroll-box/scroll-box.js"), "pat-tabs": path.resolve(__dirname, "../src/pat/tabs/tabs.js"), "pat-toggle": path.resolve(__dirname, "../src/pat/toggle/toggle.js"), "pat-tooltip": path.resolve(__dirname, "../src/pat/tooltip/tooltip.js"),