views:

963

answers:

5

Slashdot has a little widget that allows you to tweak your comment threshold to filter out down-modded comments. It will be in one place if you scroll to the top of the page, and as you scroll down, at some point, where its original home is about to scroll off the page, it will switch to fixed position, and stay on your screen. (To see an example, click here.)

My question is, how can I accomplish the same effect of having a menu be in one place when scrolled up, and switch to fixed position as the user scrolls down? I know this will involve a combination of CSS and javascript. I'm not necessarily looking for a full example of working code, but what steps will my code need to go through?

+4  A: 

Okay, I figured it out. I will post it here in case it help anyone else. This solution uses prototype, and an internal library that gives me the registerEvent, getElementX and getElementY functions, which do what you would think.

var MenuManager = Class.create({
    initialize: function initialize(menuElt) {
     this.menu = $(menuElt);
     this.homePosn = { x: getElementX(this.menu), y: getElementY(this.menu) };
     registerEvent(document, 'scroll', this.handleScroll.bind(this));
     this.handleScroll();
    },
    handleScroll: function handleScroll() {
     this.scrollOffset = document.viewport.getScrollOffsets().top;
     if (this.scrollOffset > this.homePosn.y) {
      this.menu.style.position = 'fixed';
      this.menu.style.top = 0;
      this.menu.style.left = this.homePosn.x;
     } else {
      this.menu.style.position = 'absolute';
      this.menu.style.top = null;
      this.menu.style.left = null;
     }
    }
});

Just call the constructor with the id of your menu, and the class will take it from there.

pkaeding
+2  A: 

Thanks for the effort of sharing this code. I made some small changes to make it work with the current release of Prototype.

var TableHeaderManager = Class.create({
initialize: function initialize(headerElt) {
 this.tableHeader = $(headerElt);
 this.homePosn = { x: this.tableHeader.cumulativeOffset()[0], y: this.tableHeader.cumulativeOffset()[1] };
 Event.observe(window, 'scroll', this.handleScroll.bind(this));
 this.handleScroll();
},
handleScroll: function handleScroll() {
 this.scrollOffset = document.viewport.getScrollOffsets().top;
 if (this.scrollOffset > this.homePosn.y) {
  this.tableHeader.style.position = 'fixed';
  this.tableHeader.style.top = 0;
  this.tableHeader.style.left = this.homePosn.x;
 } else {
  this.tableHeader.style.position = 'absolute';
  this.tableHeader.style.top = null;
  this.tableHeader.style.left = null;
 }
}

});

A: 

Do either of you have a working example of the code you've pasted? I am extremely interested in implementing something much like this, with a different application altogether.

I'd be very very interested!

Clayton Bellmor
A: 

For some reason, using the valuable input indicated above, I do not seem to get it to work. Do you have a website with a working example using the code above?

A: 

I am so interested in a working example as well.