Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery UI autocomplete not scrolling with arrow keys in Firefox

I am working with the JQuery UI autocomplete 1.8 with JQuery 1.6.1. (Getting newer versions of software is extremely difficult in my company so I am stuck with these.)

I have a long list of strings placed in the autocomplete pane, so I styled the .ui-autocomplete class like this

.ui-autocomplete {height:200px; overflow-y:scroll; overflow-x: hidden;}

Now when the autocomplete dropdown pops up it, it has a scroll bar as desired. However, when I use arrow keys to navigate the dropdown, the panel does not scroll with the selection. The selections still happen. Eventually I run off the bottom of the list and the cursor is returned to the top. Everything behaves as expected except that the scroll pane does not scroll.

In tests outside of work where I have access to other browsers, I find that chrome scrolls properly and IE 8 scrolls properly. Is this a bug with the firefox 3.6 linux browser or am I missing something?

I am handcuffed to Firefox 3.6 ua:(Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv1.9.2.12) Gecko/20101026 Firefox/3.6.1.2)

Is this a bug with this version of the browser or am I missing something?

EDIT: I was able to find a machine with ie6 and one with firefox 3.5.3. ie6 scrolled and firefox 3.5.3 did not. It appears it might be an issue with firefox.

like image 604
DRaehal Avatar asked Aug 12 '11 20:08

DRaehal


2 Answers

I had similar issue with our app running on jQuery v1.7.2 and jQuery UI v1.8.11 on any browser. However I have found out that it was fixed on jQuery UI v1.8.13 changelog.

So according to the fix in the changeset, all I did was just override two functions as below and it fixes the issue.

$.widget("ui.menu", $.extend({ }, $.ui.menu.prototype, {
activate: function (event, item) {
    this.deactivate();
    if (this.hasScroll()) {
        var offset = item.offset().top - this.element.offset().top,
            scroll = this.element.scrollTop(),
            elementHeight = this.element.height();
        if (offset < 0) {
            this.element.scrollTop(scroll + offset);
        } else if (offset >= elementHeight) {
            this.element.scrollTop(scroll + offset - elementHeight + item.height());
        }
    }
    this.active = item.eq(0)
                      .children("a")
                      .addClass("ui-state-hover")
                      .attr("id", "ui-active-menuitem")
                      .end();
    this._trigger("focus", event, { item: item });
},

hasScroll: function () {
    return this.element.height() < this.element[$.fn.prop ? "prop" : "attr"]("scrollHeight");
}}));
like image 174
InitialV Avatar answered Nov 10 '22 16:11

InitialV


Solution: Upgrading to jQuery UI 1.8.18 fixed this problem for me.

This isn't an answer but it might provide more information on the issue. If you follow the calls when you press the up or down keys when the menu is open, you get to the activate method of the menu widget which calls the hasScroll method (Line 5487 using v1.8.11);

hasScroll: function() {
    return this.element.height() < this.element.attr("scrollHeight");
},

It seems like the problem is that the scrollHeight attribute is not defined for the menu ul element and thus this method always returns false.

Here is the activate method:

activate: function( event, item ) {
        this.deactivate();
        if (this.hasScroll()) {
            var offset = item.offset().top - this.element.offset().top,
                scroll = this.element.attr("scrollTop"),
                elementHeight = this.element.height();
            if (offset < 0) {
                this.element.attr("scrollTop", scroll + offset);
            } else if (offset >= elementHeight) {
                this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
            }
        }
        this.active = item.eq(0)
            .children("a")
                .addClass("ui-state-hover")
                .attr("id", "ui-active-menuitem")
            .end();
        this._trigger("focus", event, { item: item });
    }

Even if you force the hasScroll method to return true, you run into another problem as the scrollTop attribute is not defined either.

I'll let you know if I figure out a solution to this as it is plaguing my application as well.

like image 32
Nick Olsen Avatar answered Nov 10 '22 15:11

Nick Olsen