Sunday, November 11, 2007

Select and Scroll

A colleague asked how I would implement this --
  1. Click on an item in an list
  2. Vertical scroll to it
I can up with this --



I think the only way that this can be done is if the item ( in this case a div ) is absolutely positioned. For each item, you can get the value for CSS style "top" from the item's parent ( container ).

If the item uses default positioning ( i.e. static ), "top" is auto which is pretty much useless for moving the vertical scroll bar. If position is relative that's also not useful because "top" is relative to the previous element.

The idea is that we'll increment the parent's "scrollTop" property until that's equal to the top position of the item. This causes vertical animated scrolling ( if you don't want animation, you could just set "scrollTop" to "top"; however, keep in mind that this "jumps" rather than transitions to the item ).

We end up with a some simple JavaScript --

var doScroll = function(e){
var target = YAHOO.util.Event.getTarget(e);
var container = document.getElementById("container");
var targetTop = parseInt(YAHOO.util.Dom.getStyle(target, "top"));

var animateScroll = function() {
var maxScrollTop;
if (container.scrollTop !=
maxScrollTop = container.scrollTop; container.scrollTop+=2;
container.scrollTop == maxScrollTop ? clearInterval(intervalID) : "";
} else {
clearInterval(intervalID);
}
var info = "container.scrollTop = " + container.scrollTop;
document.getElementById("info").innerHTML = info;
}
var intervalID = setInterval(animateScroll, 1);
}
YAHOO.util.Event.on("container", "click", doScroll);

Note that we're using YUI, but that's not critical. YUI is used to handle events in a cross-browser manner as well as getting the CSS style ( you can do this with target.style.top, but I chose to use YAHOO.util.Dom.getStyle() ).

maxScrollTop tells us whether the scroll button is at it's maximum value. We know this when we increment the container's scrollTop and it doesn't change. When that happens, we stop the animation by clearing the timer.

You can see the full example
here.

If you can do this with static or relative positioning, I'd love to see your solution!

Have fun!

No comments: