Elia Schito

Smooth scrolling for Script.aculo.us

In Javascript, Programming, Prototype, Ruby on Rails, Script.aculo.us, Scriptaculous Effects on January 18, 2007 at 1:29 pm

From time to time while developing with script.aculo.us I needed smooth scrolling for an “overflow:auto” element:

finally I got it: http://dev.rubyonrails.org/ticket/5118

If you want to scroll to a specific element inside the container, follow this example:

function moveTo(container, element){
  Position.prepare();
  container_y = Position.cumulativeOffset($(container))[1]
  element_y = Position.cumulativeOffset($(element))[1]
  new Effect.Scroll(container, {x:0, y:(element_y-container_y)});
  return false;
}

where Position.cumulativeOffset($('target-id')) gives you an array with the absolute position of that element.

UPDATE the Source: If you’re looking for the source code of Effect.Scroll just click here …effectively the diff file is not so easy to work with (thank you Paul).

UPDATE/2 an Example:
Here’s the EXAMPLE. (Thank you for the advice Andreas)

UPDATE/3 get Horizontal: (after Ronnie’s comment)
Some guys did a very good work and got something similar to the Panic’s Coda website.
Visit Glider.js website to download the source.

  1. “Effect.Scroll is not a constructor” hrm?

  2. Would be nice to see an example of this script being used.

  3. Hi,

    great work!

    What would I have to change to make that thing work horizontal?

    Thanks&Cheers

  4. In this site http://familientagebuch.de/rainer/2007/26.html#i82 I tried to realize a “remote” scrolling. Links in one DIv should controll an other (overflow) DIV. My solution was to use the mootools-lib.
    But if I include this, a part of prototype-liv doesnt work.

    Now Im looking for a better solution with the patch.

    Can I control the scrolling in an other DIV like:

    Scroll(in:’divID’,to:’ID_in_DIV’); ??

    Rainer

  5. Updated version of your code below, which will take a to_element argument and scroll that element to the center of the div. If x and Y are also supplied it will use them as an offset

    Effect.MoveTo = Class.create();
    Object.extend(Object.extend(Effect.MoveTo.prototype, Effect.Base.prototype), {
    initialize: function(element) {
    this.element = $(element);
    var options = Object.extend({
    x: 0,
    y: 0,
    to_element: null,
    mode: ‘absolute’
    } , arguments[1] || {} );
    this.start(options);
    },
    setup: function() {
    if (this.options.continuous && !this.element._ext ) {
    this.element.cleanWhitespace();
    this.element._ext=true;
    this.element.appendChild(this.element.firstChild);
    }

    this.originalLeft=this.element.scrollLeft;
    this.originalTop=this.element.scrollTop;

    if (this.options.to_element) {
    toElement=$(this.options.to_element)
    container_dims=this.element.getDimensions()
    to_element_dims=toElement.getDimensions()
    Position.prepare();
    container_x = Position.cumulativeOffset(this.element)[0]
    element_x = Position.cumulativeOffset(toElement)[0]
    container_y = Position.cumulativeOffset(this.element)[1]
    element_y = Position.cumulativeOffset(toElement)[1]
    this.options.x=this.options.x+element_x-container_x-(container_dims.width/2 – to_element_dims.width/2)
    this.options.y=this.options.y+element_y-container_y-(container_dims.height/2 – to_element_dims.height/2)
    }

    if(this.options.mode == ‘absolute’) {
    this.options.x -= this.originalLeft;
    this.options.y -= this.originalTop;
    } else {

    }

    },
    update: function(position) {
    this.element.scrollLeft = this.options.x * position + this.originalLeft;
    this.element.scrollTop = this.options.y * position + this.originalTop;
    }
    });

  6. awesome!!!!
    you saved me hours of work switching to mootools for the scrolling effect.
    Thank you very much :)

  7. hello all, i have a stupid question that i need to ask because i’m kind of newbie on javascript programming…

    so i’d like to know where i can put the new effect scroll()

    i’ve tried to place it inside the scriptaculous effect.js => no success
    i’ve tried to place it inside a new js file inside the html header block => no succes

    everytime i get :

    Effect is not defined
    moveTo(“listeTarifs”, “femme-coiffure”)main (line 186)
    onclick(click clientX=0, clientY=0)main (line 1)
    [Break on this error] new Effect.Scroll(container, {x:0, y:(element_y-container_y)});

    thx in advance

  8. forgot something :

    the prototype lib and the scriptaculous lib are loader inside the html head block

    and the call of the moveTo() function is inside the html body block

  9. I didn’t used this library lately, so I don’t remeber how to fix that error… have you the page online somewhere?

    look also at mdmsrl.it with firebug for an example…

  10. for the error below, i think his effects.js is a custom file if i am not mistaken from reading this a while ago

  11. no hada el scroll en mozilla firefox =\

  12. Is it possible to control scroll speed? If yes, could you point to me where?
    Thanks and regards :)

  13. try passing a “duration” option

    • Thanks Elia,

      I did this:

      function moveTo(container, element){
      Position.prepare();
      container_y = Position.cumulativeOffset($(container))[1]
      element_y = Position.cumulativeOffset($(element))[1]
      new Effect.Scroll(container, {duration:1, x:0, y:(element_y-container_y)});
      return false;
      }

      – duration is set to 1 – a faster scroll can be obtained if setting duration below 1 eg. 0.3

  14. Below is code to add expand the Element.scrollTo to use ths effect directly.

    e.g. $(‘container’).scrollTo(‘child’);

    Element.addMethods({
    scrollTo: function(element, child){
    var element = $(element);
    if(arguments.length == 1) {
    var pos = element.cumulativeOffset();
    window.scrollTo(pos[0], pos[1]);
    } else {
    Position.prepare();
    container_y = Position.cumulativeOffset($(element))[1]
    element_y = Position.cumulativeOffset($(child))[1]
    new Effect.Scroll(element, {x:0, y:(element_y-container_y)});
    return false;
    }
    return element;
    }
    });

  15. […] quite frankly I didn’t want them on the side, after much searching I came across this blog: https://elia.wordpress.com/2007/01/18/overflow-smooth-scroll-with-scriptaculous/.  I actually found that using the Effect.MoveTo post is more effective and smooth than the […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: