9

我正在使用带有 JQuery 1.6.1 的 JQuery UI 自动完成 1.8。(在我的公司获得更新版本的软件非常困难,所以我被这些卡住了。)

我在自动完成窗格中放置了一长串字符串,因此我将 .ui-autocomplete 类设置为这样

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

现在,当自动完成下拉菜单弹出它时,它会根据需要有一个滚动条。但是,当我使用箭头键导航下拉菜单时,面板不会随选择滚动。选择仍然发生。最终我跑出了列表的底部,光标返回到顶部。除了滚动窗格不滚动之外,一切都按预期运行。

在我可以访问其他浏览器的工作之外的测试中,我发现 chrome 可以正常滚动,而 IE 8 可以正常滚动。这是firefox 3.6 linux浏览器的错误还是我遗漏了什么?

我被 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)

这是此版本浏览器的错误还是我遗漏了什么?

编辑:我能够找到一台装有 ie6 的机器和一台装有 firefox 3.5.3 的机器。ie6 滚动,firefox 3.5.3 没有。看来这可能是firefox的问题。

4

3 回答 3

5

我在任何浏览器上运行在 jQuery v1.7.2 和 jQuery UI v1.8.11 上的应用程序都有类似的问题。但是我发现它已在jQuery UI v1.8.13 changelog上得到修复。

因此,根据变更集中的修复,我所做的只是覆盖下面的两个函数,它解决了这个问题。

$.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");
}}));
于 2012-11-28T22:38:15.347 回答
2

解决方案:升级到 jQuery UI 1.8.18 为我解决了这个问题。

这不是答案,但它可能会提供有关该问题的更多信息。如果您在菜单打开时按向上或向下键时跟随调用,您将进入菜单小部件的 activate 方法,该方法调用 hasScroll 方法(使用 v1.8.11 的第 5487 行);

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

似乎问题在于没有为菜单 ul 元素定义 scrollHeight 属性,因此此方法始终返回 false。

这是激活方法:

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 });
    }

即使你强制 hasScroll 方法返回 true,你也会遇到另一个问题,因为 scrollTop 属性也没有定义。

如果我找到解决方案,我会告诉你的,因为它也困扰着我的应用程序。

于 2011-12-21T18:01:26.803 回答
0

I noticed that this.element.attr("scrollHeight") in

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

returns undefined. If you change this.element.attr("scrollHeight") to this.element.prop("scrollHeight") instead, you will get a scrollHeight.

But then the same problem appears in activate: function (event, item) {, so you will also need to change all occurrences of

this.element.attr("scrollTop") to this.element.prop("scrollTop")

in that function as well to make it work.

You can read about .prop() in the jQuery API but basically the reason for this is

Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior. As of jQuery 1.6, the .prop() method provides a way to explicitly retrieve property values, while .attr() retrieves attributes.

于 2012-03-01T12:35:16.827 回答