├── tsconfig.json ├── .gitignore ├── README.md ├── package.json ├── gulpfile.js ├── dist ├── sticky-event-listener.esm.js └── sticky-event-listener.js ├── src └── sticky-event-listener.ts └── index.html /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "src/**/*.ts" 4 | ], 5 | "compilerOptions": { 6 | "target": "es5" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Mac system files. 2 | ._* 3 | .DS_Store 4 | 5 | # Ignore sass-cache files. 6 | *.sass-cache* 7 | *.scssc 8 | 9 | # Ignore Gulp modules 10 | node_modules 11 | 12 | # Ignore TODO 13 | TODO.txt 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sticky Event Listener 2 | ================ 3 | 4 | A small javascript plugin for adding an event listener for sticky elements, without the need for an onscroll listener. 5 | 6 | ### Demo 7 | Have a look at [this demo](https://frebsite.nl/sticky). 8 | 9 | ### Licence 10 | The Sticky Event Listener plugin is licensed under the [CC-BY-4.0 license](http://creativecommons.org/licenses/by/4.0/). 11 | 12 | ### Development 13 | This project uses [Gulp(4)](http://gulpjs.com/) to compile and minify Typescript to Javascript. 14 | If you are unfamiliar with Gulp, check [this tutorial](https://travismaynard.com/writing/getting-started-with-gulp) on how to get started.
15 | Run `gulp watch` in the command-line to put a watch on the files and run all scripts immediately after saving your changes. 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sticky-event-listener", 3 | "version": "1.0.0", 4 | "main": "dist/sticky-event-listener.js", 5 | "module": "dist/sticky-event-listener.esm.js", 6 | "author": "Fred Heusschen ", 7 | "license": "CC-BY-4.0", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/FrDH/sticky-event-listener.git" 11 | }, 12 | "description": "Add an event listener for sticky elements, without the need for an onscroll listener.", 13 | "keywords": [ 14 | "stick", 15 | "sticky", 16 | "stuck", 17 | "unstuck", 18 | "event", 19 | "listener", 20 | "javascript" 21 | ], 22 | "scripts": { 23 | "build": "gulp default" 24 | }, 25 | "devDependencies": { 26 | "gulp": "^4.0.2", 27 | "gulp-rename": "^1.4.0", 28 | "gulp-typescript": "^5.0.1", 29 | "typescript": "^3.9.7", 30 | "webpack-stream": "^5.2.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | Tasks: 3 | 4 | $ gulp : Runs the "js" task. 5 | $ gulp watch : Starts a watch on the "js" task. 6 | 7 | */ 8 | 9 | const { src, dest, watch, series, parallel } = require('gulp'); 10 | 11 | const rename = require('gulp-rename'); 12 | const typescript = require('gulp-typescript'); 13 | const webpack = require('webpack-stream'); 14 | 15 | // Dirs 16 | const inputDir = 'src'; 17 | const outputDir = 'dist'; 18 | 19 | /** JS transpile task */ 20 | const jsTtranspile = () => { 21 | return src([ 22 | inputDir + '/**/*.d.ts', // Include all typings. 23 | inputDir + '/**/*.ts' // Include the needed ts files. 24 | ]) 25 | .pipe( 26 | typescript({ 27 | target: 'es5', 28 | module: 'es6' 29 | }) 30 | ) 31 | .pipe(rename('sticky-event-listener.esm.js')) 32 | .pipe(dest(outputDir)); 33 | }; 34 | 35 | /** JS Pack task */ 36 | const jsPack = () => { 37 | return src(outputDir + '/sticky-event-listener.esm.js') 38 | .pipe( 39 | webpack({ 40 | // mode: 'development', 41 | mode: 'production', 42 | output: { 43 | filename: 'sticky-event-listener.js' 44 | }, 45 | optimization: { 46 | minimize: false 47 | } 48 | }) 49 | ) 50 | .pipe(dest(outputDir)); 51 | }; 52 | 53 | /* 54 | $ gulp js 55 | */ 56 | const js = cb => { 57 | series(jsTtranspile, jsPack)(cb); 58 | }; 59 | 60 | /* 61 | $ gulp 62 | */ 63 | exports.default = js; 64 | 65 | /* 66 | $ gulp watch 67 | */ 68 | exports.watch = cb => { 69 | watch(inputDir + '/**/*.ts', js); 70 | cb(); 71 | }; 72 | -------------------------------------------------------------------------------- /dist/sticky-event-listener.esm.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) Fred Heusschen 3 | * www.frebsite.nl 4 | * 5 | * License: CC-BY-4.0 6 | * http://creativecommons.org/licenses/by/4.0/ 7 | */ 8 | var StickyEventListener = /** @class */ (function () { 9 | function StickyEventListener(elem, options) { 10 | if (options === void 0) { options = {}; } 11 | // Exit for old browsers. 12 | if (!('IntersectionObserver' in window)) { 13 | return; 14 | } 15 | this.options = {}; 16 | var defaults = { 17 | monitorTop: true, 18 | monitorBottom: false 19 | }; 20 | for (var option in defaults) { 21 | this.options[option] = 22 | typeof options[option] != 'undefined' 23 | ? options[option] 24 | : defaults[option]; 25 | } 26 | this.sticker = elem; 27 | this.sentinels = {}; 28 | this._isStuck = false; 29 | this._stuckAt = { 30 | top: false, 31 | bottom: false 32 | }; 33 | // Detect sticking to the top. 34 | if (this.options.monitorTop) { 35 | this.sentinels.top = document.createElement('em'); 36 | this.sentinels.top.style.marginBottom = '1px'; 37 | this.sticker.prepend(this.sentinels.top); 38 | this._addObserver('top'); 39 | } 40 | else { 41 | this._stuckAt.top = true; 42 | } 43 | // Detect unsticking from the bottom. 44 | if (this.options.monitorBottom) { 45 | this.sentinels.bottom = document.createElement('em'); 46 | this.sticker.prepend(this.sentinels.bottom); 47 | this._addObserver('bottom'); 48 | } 49 | this._setSentinelsStyles(); 50 | } 51 | /** 52 | * Set the styles for the sentinels. 53 | */ 54 | StickyEventListener.prototype._setSentinelsStyles = function () { 55 | var sentinelStyles = { 56 | width: '0px', 57 | position: 'absolute', 58 | zIndex: '-100', 59 | pointerEvents: 'none' 60 | }; 61 | for (var pos in this.sentinels) { 62 | for (var prop in sentinelStyles) { 63 | this.sentinels[pos].style[prop] = sentinelStyles[prop]; 64 | } 65 | } 66 | this.setStickerTop(); 67 | this.setStickerPosition(); 68 | }; 69 | /** 70 | * Remeasures the "top" property for the sticker and update the position for the sentinels, 71 | * Should be called when the CSS "top" property for the sticker changes. 72 | */ 73 | StickyEventListener.prototype.setStickerTop = function () { 74 | for (var pos in this.sentinels) { 75 | this.sentinels[pos].style.bottom = 76 | 'calc(100% + ' + 77 | window.getComputedStyle(this.sticker).top + 78 | ')'; 79 | } 80 | }; 81 | /** 82 | * Update the height for the sentinels, 83 | * Should be called when the height of the changes. 84 | */ 85 | StickyEventListener.prototype.setStickerPosition = function () { 86 | for (var pos in this.sentinels) { 87 | this.sentinels[pos].style.height = 88 | document.body.scrollHeight + 'px'; 89 | } 90 | }; 91 | /** 92 | * Add an observer for the specified sentinel. 93 | * @param {string} pos The position for the sentinel. Can be "top" or "bottom". 94 | */ 95 | StickyEventListener.prototype._addObserver = function (pos) { 96 | var _this = this; 97 | var observer = new IntersectionObserver(function (entries) { 98 | _this._stuckAt[pos] = !entries[0].isIntersecting; 99 | var isStuck = _this._stuckAt.top && !_this._stuckAt.bottom; 100 | if (isStuck != _this._isStuck) { 101 | _this._isStuck = isStuck; 102 | _this.sticker.dispatchEvent(new CustomEvent('sticky', { detail: { stuck: isStuck } })); 103 | } 104 | }); 105 | observer.observe(this.sentinels[pos]); 106 | }; 107 | return StickyEventListener; 108 | }()); 109 | // Export module 110 | export default StickyEventListener; 111 | // Global namespace 112 | window['StickyEventListener'] = StickyEventListener; 113 | -------------------------------------------------------------------------------- /src/sticky-event-listener.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) Fred Heusschen 3 | * www.frebsite.nl 4 | * 5 | * License: CC-BY-4.0 6 | * http://creativecommons.org/licenses/by/4.0/ 7 | */ 8 | 9 | class StickyEventListener { 10 | /** Options */ 11 | options: { 12 | /** Whether or not to monitor the sticker to stick to the top. */ 13 | monitorTop?: boolean; 14 | 15 | /** Whether or not to monitor the sticker to unstick from the bottom. */ 16 | monitorBottom?: boolean; 17 | }; 18 | 19 | /** The sticky element. */ 20 | sticker: HTMLElement; 21 | 22 | /** The sentinel elements. */ 23 | sentinels: { 24 | top?: HTMLElement; 25 | bottom?: HTMLElement; 26 | }; 27 | 28 | /** Variable to keep track of the sticky state. */ 29 | _isStuck: boolean; 30 | 31 | /** Variable to keep track of the sticky states. */ 32 | _stuckAt: { 33 | top?: boolean; 34 | bottom?: boolean; 35 | }; 36 | 37 | constructor(elem, options = {}) { 38 | // Exit for old browsers. 39 | if (!('IntersectionObserver' in window)) { 40 | return; 41 | } 42 | 43 | this.options = {}; 44 | const defaults = { 45 | monitorTop: true, 46 | monitorBottom: false 47 | }; 48 | 49 | for (let option in defaults) { 50 | this.options[option] = 51 | typeof options[option] != 'undefined' 52 | ? options[option] 53 | : defaults[option]; 54 | } 55 | 56 | this.sticker = elem; 57 | this.sentinels = {}; 58 | this._isStuck = false; 59 | this._stuckAt = { 60 | top: false, 61 | bottom: false 62 | }; 63 | 64 | // Detect sticking to the top. 65 | if (this.options.monitorTop) { 66 | this.sentinels.top = document.createElement('em'); 67 | this.sentinels.top.style.marginBottom = '1px'; 68 | this.sticker.prepend(this.sentinels.top); 69 | 70 | this._addObserver('top'); 71 | } else { 72 | this._stuckAt.top = true; 73 | } 74 | 75 | // Detect unsticking from the bottom. 76 | if (this.options.monitorBottom) { 77 | this.sentinels.bottom = document.createElement('em'); 78 | this.sticker.prepend(this.sentinels.bottom); 79 | 80 | this._addObserver('bottom'); 81 | } 82 | 83 | this._setSentinelsStyles(); 84 | } 85 | 86 | /** 87 | * Set the styles for the sentinels. 88 | */ 89 | _setSentinelsStyles() { 90 | const sentinelStyles = { 91 | width: '0px', 92 | position: 'absolute', 93 | zIndex: '-100', 94 | pointerEvents: 'none' 95 | }; 96 | 97 | for (let pos in this.sentinels) { 98 | for (let prop in sentinelStyles) { 99 | this.sentinels[pos].style[prop] = sentinelStyles[prop]; 100 | } 101 | } 102 | 103 | this.setStickerTop(); 104 | this.setStickerPosition(); 105 | } 106 | 107 | /** 108 | * Remeasures the "top" property for the sticker and update the position for the sentinels, 109 | * Should be called when the CSS "top" property for the sticker changes. 110 | */ 111 | setStickerTop() { 112 | for (let pos in this.sentinels) { 113 | this.sentinels[pos].style.bottom = 114 | 'calc(100% + ' + 115 | window.getComputedStyle(this.sticker).top + 116 | ')'; 117 | } 118 | } 119 | 120 | /** 121 | * Update the height for the sentinels, 122 | * Should be called when the height of the changes. 123 | */ 124 | setStickerPosition() { 125 | for (let pos in this.sentinels) { 126 | this.sentinels[pos].style.height = 127 | document.body.scrollHeight + 'px'; 128 | } 129 | } 130 | 131 | /** 132 | * Add an observer for the specified sentinel. 133 | * @param {string} pos The position for the sentinel. Can be "top" or "bottom". 134 | */ 135 | _addObserver(pos: 'top' | 'bottom') { 136 | const observer = new IntersectionObserver(entries => { 137 | this._stuckAt[pos] = !entries[0].isIntersecting; 138 | 139 | let isStuck = this._stuckAt.top && !this._stuckAt.bottom; 140 | 141 | if (isStuck != this._isStuck) { 142 | this._isStuck = isStuck; 143 | this.sticker.dispatchEvent( 144 | new CustomEvent('sticky', { detail: { stuck: isStuck } }) 145 | ); 146 | } 147 | }); 148 | observer.observe(this.sentinels[pos]); 149 | } 150 | } 151 | 152 | // Export module 153 | export default StickyEventListener; 154 | 155 | // Global namespace 156 | window['StickyEventListener'] = StickyEventListener; 157 | -------------------------------------------------------------------------------- /dist/sticky-event-listener.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = ""; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = 0); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ([ 88 | /* 0 */ 89 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 90 | 91 | "use strict"; 92 | __webpack_require__.r(__webpack_exports__); 93 | /*! 94 | * Copyright (c) Fred Heusschen 95 | * www.frebsite.nl 96 | * 97 | * License: CC-BY-4.0 98 | * http://creativecommons.org/licenses/by/4.0/ 99 | */ 100 | var StickyEventListener = /** @class */ (function () { 101 | function StickyEventListener(elem, options) { 102 | if (options === void 0) { options = {}; } 103 | // Exit for old browsers. 104 | if (!('IntersectionObserver' in window)) { 105 | return; 106 | } 107 | this.options = {}; 108 | var defaults = { 109 | monitorTop: true, 110 | monitorBottom: false 111 | }; 112 | for (var option in defaults) { 113 | this.options[option] = 114 | typeof options[option] != 'undefined' 115 | ? options[option] 116 | : defaults[option]; 117 | } 118 | this.sticker = elem; 119 | this.sentinels = {}; 120 | this._isStuck = false; 121 | this._stuckAt = { 122 | top: false, 123 | bottom: false 124 | }; 125 | // Detect sticking to the top. 126 | if (this.options.monitorTop) { 127 | this.sentinels.top = document.createElement('em'); 128 | this.sentinels.top.style.marginBottom = '1px'; 129 | this.sticker.prepend(this.sentinels.top); 130 | this._addObserver('top'); 131 | } 132 | else { 133 | this._stuckAt.top = true; 134 | } 135 | // Detect unsticking from the bottom. 136 | if (this.options.monitorBottom) { 137 | this.sentinels.bottom = document.createElement('em'); 138 | this.sticker.prepend(this.sentinels.bottom); 139 | this._addObserver('bottom'); 140 | } 141 | this._setSentinelsStyles(); 142 | } 143 | /** 144 | * Set the styles for the sentinels. 145 | */ 146 | StickyEventListener.prototype._setSentinelsStyles = function () { 147 | var sentinelStyles = { 148 | width: '0px', 149 | position: 'absolute', 150 | zIndex: '-100', 151 | pointerEvents: 'none' 152 | }; 153 | for (var pos in this.sentinels) { 154 | for (var prop in sentinelStyles) { 155 | this.sentinels[pos].style[prop] = sentinelStyles[prop]; 156 | } 157 | } 158 | this.setStickerTop(); 159 | this.setStickerPosition(); 160 | }; 161 | /** 162 | * Remeasures the "top" property for the sticker and update the position for the sentinels, 163 | * Should be called when the CSS "top" property for the sticker changes. 164 | */ 165 | StickyEventListener.prototype.setStickerTop = function () { 166 | for (var pos in this.sentinels) { 167 | this.sentinels[pos].style.bottom = 168 | 'calc(100% + ' + 169 | window.getComputedStyle(this.sticker).top + 170 | ')'; 171 | } 172 | }; 173 | /** 174 | * Update the height for the sentinels, 175 | * Should be called when the height of the changes. 176 | */ 177 | StickyEventListener.prototype.setStickerPosition = function () { 178 | for (var pos in this.sentinels) { 179 | this.sentinels[pos].style.height = 180 | document.body.scrollHeight + 'px'; 181 | } 182 | }; 183 | /** 184 | * Add an observer for the specified sentinel. 185 | * @param {string} pos The position for the sentinel. Can be "top" or "bottom". 186 | */ 187 | StickyEventListener.prototype._addObserver = function (pos) { 188 | var _this = this; 189 | var observer = new IntersectionObserver(function (entries) { 190 | _this._stuckAt[pos] = !entries[0].isIntersecting; 191 | var isStuck = _this._stuckAt.top && !_this._stuckAt.bottom; 192 | if (isStuck != _this._isStuck) { 193 | _this._isStuck = isStuck; 194 | _this.sticker.dispatchEvent(new CustomEvent('sticky', { detail: { stuck: isStuck } })); 195 | } 196 | }); 197 | observer.observe(this.sentinels[pos]); 198 | }; 199 | return StickyEventListener; 200 | }()); 201 | // Export module 202 | /* harmony default export */ __webpack_exports__["default"] = (StickyEventListener); 203 | // Global namespace 204 | window['StickyEventListener'] = StickyEventListener; 205 | 206 | 207 | /***/ }) 208 | /******/ ]); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Sticky Event Listener 9 | 10 | 214 | 215 | 216 | 217 |
218 |
219 | 220 |
221 |

Sticky Event Listener

222 |

A small javascript plugin for adding an event listener for position: sticky; elements, 223 | without the need for an onscroll listener.

224 | 225 |

Just checkout the titles on this demo page, 226 | their appearance will change when entering or leaving the sticky state.

227 |
228 | 229 |
230 |

Installation 231 | Top 232 |

233 |
npm i sticky-event-listener
234 |
235 | 236 |
237 |

Usage 238 | Top 239 |

240 |

The setup is fairly easy, 241 | simply create a new instance of the StickyEventListener class for each sticky element 242 | and add an event listener.

243 | 244 |
import StickyEventListener from 'sticky-event-listener';
245 | 
246 | document
247 |     .querySelectorAll('.sticker')
248 |     .forEach(sticker => {
249 |         new StickyEventListener(sticker);
250 |         sticker.addEventListener('sticky', event => {
251 |             console.log( event.detail.stuck );
252 |         });
253 |     });
254 | 255 |

For most use-cases, 256 | this would be sufficient. 257 | For more options and a detailed information, 258 | checkout the documentation.

259 |
260 | 261 |
262 |

Documentation 263 | Top 264 |

265 | 266 |
267 |

Events

268 |

The StickyEventListener dispatches an event called sticky when the element enters or leaves the sticky state.

269 | 270 |
sticker.addEventListener('sticky', event => {
271 |     console.log( event.detail.stuck );
272 | });
273 | 274 |
275 | 276 |
277 |

Options

278 |

Pass options to the class to alter its behavior.

279 | 280 |
new StickyEventListener(sticker, {
281 |     monitorTop: true,
282 |     monitorBottom: false
283 | });
284 | 285 |
286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 |
NameTypeDefaultDescription
monitorTopBooleantrueWhether or not to monitor the element to enter the sticky state on the top.
monitorBottomBooleanfalseWhether or not to monitor the element to leave the sticky state from the bottom.
310 |
311 | 312 |
313 | 314 |
315 |

Methods

316 |

In some rare use-cases, 317 | you might need to invoke these methods for the plugin to function as intended.

318 | 319 |
320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 335 | 336 | 337 | 338 | 339 | 342 | 343 | 344 |
NameArgumentsDescription
setStickerTopnoneRemeasures the top property of the sticky element and updates the position for the sentinels, 333 | Should be called when the CSS top property for the sticky element changes, 334 | for example when entering or leaving a media query.
setStickerPositionnoneRemeasures the position of the sticky element and updates the height for the sentinels, 340 | Should be called when the position of the sticky element (relative to the top of the document) changes, 341 | for example when resizing the window.
345 |
346 | 347 |

For example 348 | (but again, only use these methods if the plugin otherwise does not function as intended):

349 | 350 |
const instance = new StickyEventListener(sticker);
351 | 
352 | //  Remeasure the "top" property.
353 | const mql = window.matchMedia('(max-width: 600px)');
354 | mql.addListener(event => {
355 |     instance.setStickerTop();
356 | });
357 | 
358 | //  Remeasure the position.
359 | window.addEventListener('resize', event => {
360 |     instance.setStickerPosition();
361 | });
362 | 363 |
364 |
365 | 366 |
367 |

License 368 | Top 369 |

370 |

The Sticky Event Listener plugin is licensed under the CC-BY-4.0 license. 371 |

372 |
373 |
374 | 375 | 376 | 377 | 400 | 401 | 402 | 403 | --------------------------------------------------------------------------------