views:

722

answers:

4

I'm trying to use jQuery.scrollTo plugin with accordion (where one block expands after clicking on it and another contracts), but it doesn't scroll to the right position.

Here is a demo: pelmeshkin.com/temp/scrolltoaccoridon

As you can see, the first click scrolls correctly, but every next one goes further than it should.

It seems to use target's initial position (where it was before the expansion/contraction), which makes sense, since both events are initiated at the same time, but even when I try to pause scrollTo and wait until the slideUp/slideDown transition is over, it still behaves the same. :(

+3  A: 

Because it's calculating the position based on the location before the animation occurs. Not sure how you would go about dealing with this to be honest except maybe to tinker with the internal calculate which probably isn't a simple matter.

altCognito
Thanks! Yeah, I don't think I want to dig in to that :) Perhaps, I could live with scrolling first, and only then expanding/contracting via a callback, but I am not sure how can I pass 'this' object to the callback.Something like this doesn't work:$.scrollTo($(this), 1000, function() { //expand(this); //contract(not(this));});
pelmeshkin
+2  A: 

Ok, I sort of solved it myself. I first find positions of all clickable elements on pageload using offset(), put them in array, and then feed these as pixel values to scrollTo on click event.

This way we're giving scrollTo exact pixel positions to scroll to on the page, rather than relying on it to calculate it from element ID by itself. Here's how it looks in the end: pelmeshkin.com

pelmeshkin
Please accept altCognito's answer, not your own
Chad Grant
altCognito's answer merely rewords what I'd already said in my question, but no practical solution. Since there are no more answers, mine at least provides one possible solution that may help someone that gets the same problem and finds this post. Or is there a rule on stackoverflow against accepting one's own answers?
pelmeshkin
A: 

Dude. N.S.F.W.

And after a bit of hacking around on Effect.ScrollTo:

Effect.LazyScrollTo = function(element) { try {
  var options = arguments[1] || { };
  scrollOffsets = document.viewport.getScrollOffsets();
  elementOffsets = $(element).cumulativeOffset();

  if (options.offset) elementOffsets[1] += options.offset;

  return new Effect.Tween(null,
    scrollOffsets.top,
    elementOffsets[1],
    options,
    function(p){
      try {
        this.lazy_offset = this.lazy_offset || $(element).cumulativeOffset();
        scrollTo(scrollOffsets.left, (p.round() - (elementOffsets[1] - this.lazy_offset[1])));
      } catch(e) {
        alert(e);
      }
    }.bind(this)
  ); 
} catch(e) { alert(e); }}

And then elsewhere...

new Effect.SlideDown('tab1-body', {queue: 'end'});
new Effect.LazyScrollTo('tab1-heading', {queue: 'end'});

Happy new year.

Ryan Angilly
... but your solution does work... so thanks :)
Ryan Angilly
A: 

@pelmeshkin would you be able to help me solve the same problem you faced so I may use it in my example?

When you click on Title 1, for example, it will scroll to the Title 1 just fine. It's when you now click Title 5, after you click Title 1, does the page scroll way past the Title 5.

Here's my demo with all my code: http://jsbin.com/anuzi3/5/

Evan