diff --git a/README.md b/README.md index 1ab27b7..80011f9 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# tp-element +# tp-scroll-threshold diff --git a/package.json b/package.json index c39fdff..b72a326 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { - "name": "@tp/tp-element", - "version": "0.0.1", + "name": "@tp/tp-scroll-threshold", + "version": "1.0.0", "description": "", - "main": "tp-element.js", + "main": "tp-scroll-threshold.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", - "url": "https://gitea.codeblob.work/tp-elements/tp-element.git" + "url": "https://gitea.codeblob.work/tp-elements/tp-scroll-threshold.git" }, "author": "trading_peter", "license": "Apache-2.0", diff --git a/tp-element.js b/tp-element.js deleted file mode 100644 index 6a92a2f..0000000 --- a/tp-element.js +++ /dev/null @@ -1,35 +0,0 @@ -/** -@license -Copyright (c) 2022 trading_peter -This program is available under Apache License Version 2.0 -*/ - -import { LitElement, html, css } from 'lit'; - -class TpElement extends LitElement { - static get styles() { - return [ - css` - :host { - display: block; - } - ` - ]; - } - - render() { - const { } = this; - - return html` - - `; - } - - static get properties() { - return { }; - } - - -} - -window.customElements.define('tp-element', TpElement); diff --git a/tp-scroll-threshold.js b/tp-scroll-threshold.js new file mode 100644 index 0000000..63a8d9a --- /dev/null +++ b/tp-scroll-threshold.js @@ -0,0 +1,99 @@ +/** +@license +Copyright (c) 2022 trading_peter +This program is available under Apache License Version 2.0 +*/ + +import { debounce } from '@tp/helpers/debounce.js'; +import { LitElement, css } from 'lit'; + +class TpScrollThreshold extends LitElement { + static get styles() { + return [ + css` + :host { + display: none; + } + ` + ]; + } + + static get properties() { + return { + target: { type: Object }, + upperThreshold: { type: Number }, + lowerThreshold: { type: Number }, + upperTriggered: { type: Boolean }, + lowerTriggered: { type: Boolean }, + }; + } + + constructor() { + super(); + this.onScroll = debounce(this.onScroll.bind(this), 200); + this.upperThreshold = 0; + this.lowerThreshold = 0; + this.upperTriggered = false; + this.lowerTriggered = false; + } + + firstUpdated() { + if (!this.target) { + console.error(this.tagname + ': Missing scroll target'); + return + } + + this.target.addEventListener('scroll', this.onScroll, { passive: true }); + } + + onScroll() { + this.checkScrollThresholds(); + } + + checkScrollThresholds() { + if (this.lowerTriggered && this.upperTriggered) { + return; + } + + const upperScrollValue = this.horizontal ? this._scrollLeft : this._scrollTop; + const lowerScrollValue = this.horizontal ? this.target.scrollWidth - this._targetWidth - this._scrollLeft : this.target.scrollHeight - this._targetHeight - this._scrollTop; + + // Detect upper threshold + if (upperScrollValue <= this.upperThreshold && !this.upperTriggered) { + this.upperTriggered = true; + this.dispatchEvent(new CustomEvent('upper-threshold', { detail: null, bubbles: true, composed: true })); + } + // Detect lower threshold + if (lowerScrollValue <= this.lowerThreshold && !this.lowerTriggered) { + this.lowerTriggered = true; + this.dispatchEvent(new CustomEvent('lower-threshold', { detail: null, bubbles: true, composed: true })); + } + } + + clearTriggers() { + this.upperTriggered = false; + this.lowerTriggered = false; + } + + get _doc() { + return this.ownerDocument.documentElement; + } + + get _scrollTop() { + return this.target === this._doc ? window.pageYOffset : this.target.scrollTop; + } + + get _scrollLeft() { + return this.target === this._doc ? window.pageXOffset : this.target.scrollLeft; + } + + get _targetWidth() { + return this.target === this._doc ? window.innerWidth : this.target.offsetWidth; + } + + get _targetHeight() { + return this.target === this._doc ? window.innerHeight : this.target.offsetHeight; + } +} + +window.customElements.define('tp-scroll-threshold', TpScrollThreshold); \ No newline at end of file