gromo / jquery.scrollbar

jQuery CSS Customizable Scrollbar
GNU General Public License v2.0
756 stars 238 forks source link

"too much recursion" in Firefox with two scrollable elements at a time #140

Closed rgozdzialski closed 7 years ago

rgozdzialski commented 7 years ago

I have 2 containers on which I use the jquery.scrollbar plugin:

HTML

<div class="scrollbar-inner contaner-one">...</div>
<div class="scrollbar-inner contaner-two">...</div>

JS

$(function() {
    // some code skipped....
    $('.scrollbar-inner').scrollbar(); // all the default are used
});

The containers are hidden at first. When they are shown, their height is manually set. Then I initialize the .scrollbar() on each. All happens on DOM ready.

Chrome and Safari don't see the problem, but Firefox chokes and throws too much recursion error. If I remove the JS line, all is OK. Well, all is OK, but I have no scrollbars ;)

The error thrown in FF is linked to the _updateScroll function in your plugin. Apparently, the function calls itself when specific conditions are met.

I get that I have more JS in place, but no other .scrollbar() instance is created on the page in question. Do you have any ideas why the _updateScroll function would be called in an infinite loop when using the plugin? Or why only Firefox would have this problem?

(Of course, it may be that the other browsers simply handle the recursion issue differently.)

gromo commented 7 years ago

It may happen if styles are continuing changing when container's size is calculated (after applying custom scrollbar styles). So it depends on your styles - you can try to create example with this bug on jsFiddle.net with minimum possible JS/CSS/HTML code

rgozdzialski commented 7 years ago

Yeah, it has to be it: the combination of jQuery-set styles, CSS transitions, and the plugin's scrollbars updating.

I did not manage to provide an isolated example for you, unfortunately.

The two containers I mentioned need to have their height adjusted on window.resize event (which won't be often). I'm considering 2 solutions:

(1) destroy -> calculate -> redeclare

$(window).on('resize', function() {
    // destroy the scrollbar() instance on .scrollbar-inner elements
    // recalculate the heighs for the 2 containers
    // redeclare scrollbar()
});

(2) declare with autoUpdate: false -> calculate -> update manually

$('.scrollbar-inner').scrollbar({
    autoUpdate: false
});

$(window).on('resize', function() {
    // recalculate the heighs for the 2 containers
    // update the scrollbars manually
});

In option (1) I'm not sure how to destroy the instance. In option (2) I'm not sure how to manually update the scrollbars each time.

I know it's not really your concern, but I'd be grateful for any suggestions.

gromo commented 7 years ago
  1. $('.scrollbar-inner').scrollbar('destroy');
  2. $('.scrollbar-inner').scrollbar('init');
gromo commented 7 years ago

You can call init as many times as you want - it just recalculate container/scrollbar sizes if scrollbar was already initialized on element. But if you use CSS transition for element's height/width, you have to disable it before calling init function

rgozdzialski commented 7 years ago

Thanks a lot for the information. I ended up getting rid of CSS transitions and using jQuery instead. I also used option (2). All works fine now.