Detect when an element has scrolled into view
A question came up on one of our engineering lists the other day and I think it's innocent enough to go ahead and share a simple solution I had came up with that solves this particular issue. Needless to say, I believe I'm not breaking the birch of "don't be evil." Furthermore, this gives me an excuse to write about something since I haven't done so in a few months (*cough). Anyway, the idea is basic. You have an element in the DOM sitting somewhere below the fold (see above the fold), and you'd like to know when it has breached through the bottom threshold of your screen as a user is scrolling down a page. An example of an application that uses this kind of logic would be, for instance, Google reader, where stories are loaded dynamically as the user scrolls more headlines into view. Since there could potentially be hundreds or even thousands of RSS entries from any given feed, we wouldn't want to load all of them at once.Le Code
I went ahead and prototyped this out quickly using Y.U.I. to save time on simply proving a concept. The code that come of it essentially looks like this:JavaScript: scroll element into view
var Event = YAHOO.util.Event;
var Dom = YAHOO.util.Dom;
Event.on(window, 'load', function() {
var y = Dom.getY('ft');
Event.on(window, 'scroll', function() {
var top = (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
var vpH = Dom.getViewportHeight();
var coverage = parseInt(vpH + top);
if ( coverage >= y ) {
console.log('in view!!!');
}
});
});
What this logic is essentially telling us is that we need three key ingredients to solve for this.
- The Y coordinate of the target element
- The viewport height of the users window
- The amount a user has scrolled from the top
Modifications
Since we've proven the concept, we can now write a simple interface that allows us to pass any arbitrary element, and then turn it into a custom event. With that in mind, a la Sellsian approach (implement first, API later), we could do something like this:element viewer implementation
YAHOO.example.ElementViewer('my-element', function(Y) {
console.log('my-element is in view at:' + Y);
});
Simply pass in an element (id or HTMLElement), then add a callback method which will return the Y coordinate of how far you've scrolled to get there. The interface would now simply look like this using YUI's custom event interface:
JavaScript: Element Viewer API
YAHOO.example.ElementViewer = function(el, callback) {
var y = Dom.getY(el);
var o = new YAHOO.util.CustomEvent('element finder',
null,
true,
YAHOO.util.CustomEvent.FLAT
);
o.subscribe(callback);
function f() {
var top = (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
var vpH = Dom.getViewportHeight();
var view = parseInt(vpH + top);
if ( view >= y ) {
o.fire(view);
}
}
Event.on(window, 'scroll', f);
};
And there you have it. This allows us to do the same thing, except now with a fancy interface :). See the demonstration. Cheers.
recent
- Matador: The Obvious MVC Framework for Node
- Sandboxing JavaScript
- Crouching Ender, hidden command
- Ender.js - The open submodule library
- Qwery - The Tiny Selector Engine
- Klass
- Smallest DOMReady code, ever.
- $script.js - Another JavaScript loader
- About that slowness on Twitter...
- Autocomplete Fuzzy Matching
- JavaScript Cache Provider
- JavaScript Animate
- Asynchronous method queue chaining in JavaScript
- Something changed
- Unofficial Twitter Widget Documentation
i am dustin diaz

