{"id":13760436,"url":"https://github.com/stutrek/scrollMonitor","last_synced_at":"2025-05-10T10:32:53.617Z","repository":{"id":6271422,"uuid":"7504919","full_name":"stutrek/scrollmonitor","owner":"stutrek","description":"A simple and fast API to monitor elements as you scroll","archived":false,"fork":false,"pushed_at":"2023-07-17T20:03:30.000Z","size":308,"stargazers_count":3300,"open_issues_count":21,"forks_count":244,"subscribers_count":75,"default_branch":"master","last_synced_at":"2024-11-11T13:50:18.515Z","etag":null,"topics":["dom","javascript","scroll","viewport"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"sanzgiri/dash-sms","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stutrek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2013-01-08T16:26:16.000Z","updated_at":"2024-11-10T18:34:02.000Z","dependencies_parsed_at":"2024-01-02T23:18:14.544Z","dependency_job_id":"2194df5e-0468-455c-9670-58adf8a3e06e","html_url":"https://github.com/stutrek/scrollmonitor","commit_stats":{"total_commits":142,"total_committers":20,"mean_commits":7.1,"dds":0.6690140845070423,"last_synced_commit":"36c0b0739383a20e45878b293af2fa5f3380d416"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stutrek%2Fscrollmonitor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stutrek%2Fscrollmonitor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stutrek%2Fscrollmonitor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stutrek%2Fscrollmonitor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stutrek","download_url":"https://codeload.github.com/stutrek/scrollmonitor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224949829,"owners_count":17397241,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dom","javascript","scroll","viewport"],"created_at":"2024-08-03T13:01:10.217Z","updated_at":"2024-11-16T17:31:09.580Z","avatar_url":"https://github.com/stutrek.png","language":"TypeScript","readme":"scrollMonitor\n=============\n\nThe scroll monitor allows you to receive events when elements enter or exit a viewport. It does this using watcher objects, which watch an element and trigger events. Watcher objects also contain information about the element they watch, including the element's visibility and location relative to the viewport. If your scroll container is an element other than the body you can create a container that creates watchers.\n\nThe scroll monitor was designed to be very fast. On each scroll event the DOM is only touched twice, once to find the document height and again to find the viewport top. No variables are declared, nor are any objects, arrays, or strings created. Watchers are _very_ cheap. Create them liberally.\n\nThe code is vanilla javascript and has no external dependencies, however _the script cannot be put in the head_.\n\nAlso see the [React hooks](https://github.com/stutrek/scrollmonitor-hooks), [React component](https://github.com/stutrek/scrollmonitor-react) and the [parallax library](https://github.com/stutrek/scrollmonitor-parallax).\n\n## Basic Usage\n\n### When the body scrolls\n\n```javascript\nvar scrollMonitor = require(\"scrollmonitor\"); // if you're old school you can use the scrollMonitor global.\nvar myElement = document.getElementById(\"itemToWatch\");\n\nvar elementWatcher = scrollMonitor.create( myElement );\n\nelementWatcher.enterViewport(function() {\n    console.log( 'I have entered the viewport' );\n});\nelementWatcher.exitViewport(function() {\n    console.log( 'I have left the viewport' );\n});\n```\n\n### For a scroll container\n\n```javascript\nvar containerElement = document.getElementById(\"container\");\n\nvar containerMonitor = scrollMonitor.createContainer(containerElement);\n// this containerMonitor is an instance of the scroll monitor\n// that listens to scroll events on your container.\n\nvar childElement = document.getElementById(\"child-of-container\");\nvar elementWatcher = containerMonitor.create(childElement);\n\nelementWatcher.enterViewport(function() {\n    console.log( 'I have entered the viewport' );\n});\nelementWatcher.exitViewport(function() {\n    console.log( 'I have left the viewport' );\n});\n```\n\n_Note: an element is said to be in the viewport if it is scrolled into its parent, it does not matter if the parent is in the viewport._\n\n## Demos\n\n* [Stress Test](http://stutrek.github.io/scrollmonitor/demos/stress.html) - Test with as many watchers as you'd like\n* [Stress Test in a div](http://stutrek.github.io/scrollmonitor/demos/stressTestInDiv.html) - Note how much slower scrolling a div is than scrolling the body.\n* [Nested scrollers](http://stutrek.github.io/scrollmonitor/demos/divInADiv.html)\n* [Fixed Positioning and Locking](http://stutrek.github.io/scrollmonitor/demos/fixed.html)\n* [Anchored section headers](http://stutrek.github.io/scrollmonitor/demos/list.html)\n* [Complex sidebar behavior](http://stutrek.github.io/scrollmonitor/demos/scoreboard.html)\n\n## Watcher Objects\n\nCreate watcher objects with `scrollMonitor.create( watchItem )`. An optional second argument lets you receive events before or after this element enters the viewport. _See \"[Offsets](#offsets)\"_.\n\n`watchItem` can be one of the following:\n\n* **DOM Element** - the watcher will watch the area contained by the DOM element.\n* **Object** - `obj.top` and `obj.bottom` will be used for watcher.top and watcher.bottom.\n* **Number** - the watcher will watch a 1px area this many pixels from the top. Negative numbers will watch from the bottom.\n* **jQuery object** - it will use the first DOM element.\n* **NodeList** or **Array** - it will use the first DOM element.\n* **string** - it will use the string as a CSS selector and watch the first match.\n\nWatchers are automatically recalculated on the first scroll event after the height of the document changes.\n\n### Events\n\nElement watchers trigger six events:\n\n* `visibilityChange` - when the element enters or exits the viewport.\n* `stateChange` - similar to `visibilityChange` but is also called if the element goes from below the viewport to above it in one scroll event or when the element goes from partially to fully visible or vice versa.\n* `enterViewport` - when the element enters the viewport.\n* `fullyEnterViewport` - when the element is completely in the viewport [1].\n* `exitViewport` - when the element completely leaves the viewport.\n* `partiallyExitViewport` - when the element goes from being fully in the viewport to only partially [2].\n\n1. If the element is larger than the viewport `fullyEnterViewport` will be triggered when the element spans the entire viewport.\n2. If the element is larger than the viewport `partiallyExitViewport` will be triggered when the element no longer spans the entire viewport.\n\n### Properties\n\n* `elementWatcher.isInViewport` - true if any part of the element is visible, false if not.\n* `elementWatcher.isFullyInViewport` - true if the entire element is visible [1].\n* `elementWatcher.isAboveViewport` - true if any part of the element is above the viewport.\n* `elementWatcher.isBelowViewport` - true if any part of the element is below the viewport.\n* `elementWatcher.top` - distance from the top of the document to the top of this watcher.\n* `elementWatcher.bottom` - distance from the top of the document to the bottom of this watcher.\n* `elementWatcher.height` - top - bottom.\n* `elementWatcher.watchItem` - the element, number, or object that this watcher is watching.\n* `elementWatcher.offsets` - an object that determines the offsets of this watcher. _See \"[Offsets](#offsets)\"_.\n\n1. If the element is larger than the viewport `isFullyInViewport` is true when the element spans the entire viewport.\n\n### Methods\n\n* `elementWatcher.on/off/one` - the standard event functions.\n* `elementWatcher.recalculateLocation` - recalculates the location of the element in relation to the document.\n* `elementWatcher.destroy` - removes this watcher and clears out its event listeners.\n* `elementWatcher.lock` - locks this watcher at its current location. _See \"[Locking](#locking)\"_.\n* `elementWatcher.unlock` - unlocks this watcher.\n\nThese methods are automatically called by the scrollMonitor, you should never need them:\n\n* `elementWatcher.update` - updates the boolean properties in relation to the viewport. Does not trigger events.\n* `elementWatcher.triggerCallbacks` - triggers any callbacks that need to be called.\n\n### Locking\n\nSometimes you want to change the element you're watching, but want to continue watching the original area. One common use case is setting `position: fixed` on an element when it exits the viewport, then removing positioning when it when it reenters.\n\n```javascript\nvar watcher = scrollMonitor.create( $element );\nwatcher.lock(); // ensure that we're always watching the place the element originally was\n\nwatcher.exitViewport(function() {\n    $element.addClass('fixed');\n});\nwatcher.enterViewport(function() {\n    $element.removeClass('fixed');\n});\n```\n\nBecause the watcher was locked on the second line, the scroll monitor will never recalculate its location.\n\n### Offsets\n\nIf you want to trigger an event when the edge of an element is near the edge of the viewport, you can use offsets. The offset is the second argument to `scrollMonitor.create`.\n\nThis will trigger events when an element gets within 200px of the viewport:\n```javascript\nscrollMonitor.create( element, 200 )\n```\n\nThis will trigger when the element is 200px inside the viewport:\n```javascript\nscrollMonitor.create( element, -200 )\n```\n\n If you only want it to affect the top and bottom differently you can send an object in.\n ```javascript\n scrollMonitor.create( element, {top: 200, bottom: 50})\n ```\n\n If you only want it to affect the top and not the bottom you can use only one property in.\n ```javascript\n scrollMonitor.create( element, {top: 200})\n ```\n\n## scrollMonitor Module\n\n### Methods\n* `scrollMonitor.createContainer( containerEl )` - returns a new ScrollMonitorContainer that can be used just like the scrollMonitor module.\n* `scrollMonitor.create( watchItem, offsets )` - Returns a new watcher. `watchItem` is a DOM element, jQuery object, NodeList, CSS selector, object with .top and .bottom, or a number.\n* `scrollMonitor.update()` - update and trigger all watchers.\n* `scrollMonitor.recalculateLocations()` - recalculate the location of all unlocked watchers and trigger if needed.\n\n### Properties\n* `scrollMonitor.viewportTop` - distance from the top of the document to the top of the viewport.\n* `scrollMonitor.viewportBottom` - distance from the top of the document to the bottom of the viewport.\n* `scrollMonitor.viewportHeight` - height of the viewport.\n* `scrollMonitor.documentHeight` - height of the document.\n\n# Contributing\n\nThere is a set of unit tests written with Mocha + Chai that run in testem. Getting them running is simple:\n\n```\nnpm install\nnpm test\n```\n\nthen open http://localhost:7357\n","funding_links":[],"categories":["Scroll","Scroll [🔝](#readme)","Programming Languages","Reporters"],"sub_categories":["Other","JavaScript","Scroll"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstutrek%2FscrollMonitor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstutrek%2FscrollMonitor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstutrek%2FscrollMonitor/lists"}