Can't get jScrollPane plus SelectBox plugins to work together

1.4k views Asked by At

Ok, I have two plugins I am using, one that helps make fancy select box dropdowns - works fine. Plugin: jQuery Selectbox plugin

Then I have one so I can make a custom scroll on elements, that works fine too. Plugin: jScrollPane

However I cannot get them working together - a dropdown menu with a custom scroll.

You can see here working examples: http://jsfiddle.net/8VX4d/23/

The first box is a box without scroll (correct), the second is a working box with a scroll correctly working and the one below is a dropdown that I am trying to get the custom scroll working on but can't.

Not sure if it has anything to do with the selectbox instance having to be ready before I apply the custom scroll and I'm not sure how I can check if it is?

As you can see on jsFiddle I am using onDomReady and binding them via:

//$(".pretty_sb").selectbox();
$('.cat_list').jScrollPane();
$(".pretty_sb").selectbox();
$('.sbOptions').jScrollPane();
//$('.sbHolder').jScrollPane();

Edit:

This seems to work but for some reason it restricts the height it shows for the dropdown:

$(".pretty_sb").selectbox({
    onOpen: function (inst) {
        $('.sbOptions').jScrollPane({
            verticalDragMinHeight: 40
        });
    }
});
//$('.sbOptions').jScrollPane();
$('.cat_list').jScrollPane();

Edit #2: I have a min-height set for the sbOptions class and that is the height that jScrollPane seems to be taking for some reason!?

3

There are 3 answers

15
JSuar On BEST ANSWER

Solution 0 - Reinitialize and Destroy

Working Fiddle: http://jsfiddle.net/8VX4d/39/

$('.pretty_sb').selectbox({
    onOpen: function (inst) {
        var api = $('.sbOptions').data('jsp');
        api.reinitialise({
            autoReinitialise: true,
            autoReinitialiseDelay: 10,
        });
    },
    onClose: function (inst) {
        var api = $('.sbOptions').data('jsp');
        api.destroy();
        $('.sbOptions').jScrollPane();
    }
});
$('.sbOptions').jScrollPane();

Tested on:

  • Chrome v 31.0.1650.63 m
  • FireFox 26.0
  • IE10

Solution 1 - Reinitialize on a Delay

Working Fiddle: http://jsfiddle.net/8VX4d/36/

The following will force a reinitialization of the scroll pane which corrects the height. However, this requires a lot of overhead. The end goal would be to manually reinitialize as described in jScrollPane - dynamic content demo page.

$('.pretty_sb').selectbox({
    onOpen: function (inst) {
        $('.sbOptions').jScrollPane({
            autoReinitialise: true,
            autoReinitialiseDelay: 10,
        });
    }
});

Solution 2 - Explicitly Set Height

Working Fiddle: http://jsfiddle.net/8VX4d/29/

The following appears to produce the desired result. I got the idea of forcing the height before applying the jScrollPane from this blog post.

$(".pretty_sb").selectbox({
    onOpen: function (inst) {
        $('.sbOptions').height(300).jScrollPane();
    }
});
3
Oscar Jara On

Tested and working!

I discovered that there is a bug with jquery.jscrollpane.js plugin due to the following reasons:

First reason:

When doing the following...

$(function(){

   $('.pretty_sb').selectbox();
   $('.sbOptions').jScrollPane();

});

First line (..).selectbox() will customize the html select and create the following in DOM:

<ul id="sbOptions_82218379" class="sbOptions" style="display: none; (..)>

Then second line (..).jScrollPane() will create the following children element inside ul tag in the middle of script execution:

<div class="jspContainer" style="width: 155px; height: 454px;">

And also the following children element inside jspContainer:

<div class="jspPane" style="padding: 5px 0px 0px; top: 0px; left: 0px; width: 155px;">(..)</div>

At this point jspPane element contains the elements of the html select at first sight.

To finally try to get the scrollHeight (friendly known as height) of jspPane element in order to create the scrollbar. Seems that everything will work but NOT.

What's wrong?

Doing some debugging to the unminified version of jquery.jscrollpane.js plugin (obtained from the official site at: http://jscrollpane.kelvinluck.com/script/jquery.jscrollpane.js)

You will see that on line 177, the code is trying to get the scrollHeight of the pane by using simple javascript like this:

contentHeight = pane[0].scrollHeight;

This will be used in future for creating the scrollbar but when trying to get this CSS property of a display: none parent element this will result in 0.

So, at line 182 the script will determine that the area is not scrollable (isScrollableV = false) and the scrollbar will not appear due to this.

If you don't want to believe. Try getting the scrollHeight by yourself (I made a short example, just comment or uncomment the display: none; property of the child div at CSS side: http://jsfiddle.net/oscarj24/3Ycp7/).

Second reason:

This is really funny but check line 112 of jquery.jscrollpane.js plugin, you will see the following comment:

// TODO: Deal with where width/ height is 0 as it probably means the element is hidden and we should 
// come back to it later and check once it is unhidden...

It seems that the author is not handling when an element is hidden or not, so it will return 0 for the height or width making the area not scrollable (as first reason description).

But, why this code snippet works?

$('.pretty_sb').selectbox({
    onOpen: function (inst) {
        $('.sbOptions').jScrollPane();
    }
});

Because when opening the combobox, the content is not hidden anymore (onOpen listener makes the trick, you can check the DOM and look that display: none from ul tag is gone) and that allows the jquery.jscrollpane.js plugin to get what it wants and further add another CSS class (jspScrollable) to the ul element that means that the area is scrollable and everything will work fine with the new scrollbar.

Solution:

  • I really DON'T recommend this solution but maybe you can edit the unminified version of jquery.jscrollpane.js plugin just for yourself. But you will be responsible of author license infringement and others (just saying please don't be rude with me people). This way you will invoke just $(selector).jScrollPane(); and that's all.

  • Do what the author comment said and evaluate if the element is hidden or not but this will be really hard to accomplish for your case because ul tag will be hidden if the combobox is "closed" and an event listener will be needed (similar to your last approach to get this working).

  • I think the solution that fits your requirement is to continue using your last approach (the one using the onOpen listener with some "corrections" like I will put it later/below). But I don't like it at all because you are repeating the (..).jScrollPane() action again and again per click done. Also, I think that there is no other way to solve this.

Live Demo: http://jsfiddle.net/oscarj24/8VX4d/33/

jQuery code:

/* Define a default global variable with some value for scrollable area height. */
var DEFAULT_SBHEIGHT = 150;

$(function(){

    $('.cat_list').jScrollPane();

    $('.pretty_sb').selectbox({
        onOpen: function (inst) {
            $('.sbOptions')
            .height(DEFAULT_SBHEIGHT)
            .jScrollPane();
        }
    });

}); 

Just to know, there are many possible cases of "script execution" but I just tried to analyze in deep this situation.

Hope this helps.

0
Sanjeev On

Best Solution

The real solution for this lies in css,you have to specify max-height and height:auto for SelectBox menu so that jScrollPane works correctly. All the above solutions needs you to Reinitialize and Destroy scrollpane every time you open drop menu or set fixed height of menu() in onOpen method, but what if menu options are less, you will see blank space in menu. Below is the ideal solution that requires jScrollPane to initialize just once and no Reinitialize is needed. (Its a clean and optimal code)

CSS

/* This class on ul is must for jscrollpane to work correctly, else its height will keep on reducing */

.sbOptions{
max-height:200px !important;
height:auto !important;
}

Js

$(".pretty_sb").selectbox();
$('.sbOptions').jScrollPane();

Tested this solution in FF/Chrome/IE