Jquery UI自动完成组合框按钮单击事件

时间:2012-04-19 11:36:43

标签: javascript jquery jquery-ui combobox jquery-autocomplete

jquery ui autocomplete when using it to create a combobox我遇到了奇怪的行为。每当我点击滚动条滚动结果列表然后单击我的组合框按钮关闭结果列表关闭结果然后再次打开。我希望它关闭菜单。

重新制作的步骤

  1. open jsfiddle demo
  2. 在自动填充中键入“i”或按下下拉按钮。
  3. 单击垂直滚动以滚动结果
  4. 点击下拉按钮
  5. 创建按钮的脚本

     this.button = $("<button type='button'>&nbsp;</button>")
        .attr({ "tabIndex": -1, "title": "Show all items" })
        .insertAfter(input)
        .button({
             icons: {
                 primary: "ui-icon-triangle-1-s"
             },
             text: false
        })
        .removeClass("ui-corner-all")
        .addClass("ui-corner-right ui-button-icon")
        .click(function () {
    
            // when i put breakpoint here, and my focus is not on input, 
            // then this if steatment is false????
    
            if (input.autocomplete("widget").is(":visible")) {
                input.autocomplete("close");
                return;
            }
    
            // work around a bug (likely same cause as #5265)
            $(this).blur();
    
            // pass empty string as value to search for, displaying all results
            input.autocomplete("search", "");
            input.focus();
    });
    

    CSS(强制滚动结果菜单)

    .ui-autocomplete {
        max-height: 100px;
        overflow-y: auto;
        /* prevent horizontal scrollbar */
        overflow-x: hidden;
        /* add padding to account for vertical scrollbar */
        padding-right: 20px;
    }
    /* IE 6 doesn't support max-height
     * we use height instead, but this forces the menu to always be this tall
     */
    * html .ui-autocomplete {
        height: 100px;
    }
    

    即使焦点转移到小部件本身而不是输入元素,我的解决方案可能是关闭小部件吗?

    任何想法如何修改此代码以使其表现如此?

4 个答案:

答案 0 :(得分:5)

根据自动填充小部件的各种点击和鼠标事件的问题,我想出了这个: jsFiddle example

jQuery的:

var input = $('#txtComplete');

var data = [];
var isOpen = false;

function _init() {
    for (var idx = 0; idx <= 100; idx++) {
        data.push('item: ' + idx);
    };
    input.autocomplete({
        source: data,
        minLength: 0,
        open: function(event, ui) {
            isOpen = true;
        },
        select: function(event, ui) {
            isOpen = false;
        }
    });
}

function afterInit() {
    var button = $("<button type='button'>&nbsp;</button>").attr("tabIndex", -1).attr("title", "Show all items").insertAfter(input).button({
        icons: {
            primary: "ui-icon-triangle-1-s"
        },
        text: false
    }).removeClass("ui-corner-all").addClass("ui-corner-right ui-button-icon").click(function(event) {
        input.focus();
        if (isOpen) {
            input.autocomplete("close");
            isOpen = false;
        } else {
            input.autocomplete("search", "");
            event.stopImmediatePropagation();
        }
    });
}
$(window).click(function() {
    input.autocomplete("close");
    isOpen = false;
});
$(function() {
    _init();
    afterInit();
});​

答案 1 :(得分:3)

问题是由于在jquery ui自动完成中的解决方法。在某些条件下,有一个mousedown事件设置可以关闭菜单。在其中一个条件中,它会检查引发mousedown的项是否是自动完成小部件的一部分。如果没有,它会关闭菜单。由于您正在处理组合框行为并且您的按钮不是自动完成小部件的一部分,因此单击该按钮会因此事件而关闭菜单。

您可以看到有问题的条件以及autocomplete source on github中从第205行开始的原因。可能值得在jquery ui论坛上提出这个问题,因为他们的组合框演示也有这个bug。

<强>更新

此替换事件基于jquery-ui 1.8.18。此事件已发生变化,很可能会再次发生变化。如果你走这条路线,你可能需要手动更新这个代码。

如果在创建自动填充(jsfiddle demo)后运行以下内容而点击了组合按钮,则可以修补mousedown事件以关闭菜单。

var input = $('#combotextbox').autocomplete(/*options*/);
input.data('autocomplete').menu.element.unbind('mousedown').mousedown(function(event) {
        var self = input.data('autocomplete');
        event.preventDefault();
        // clicking on the scrollbar causes focus to shift to the body
        // but we can't detect a mouseup or a click immediately afterward
        // so we have to track the next mousedown and close the menu if
        // the user clicks somewhere outside of the autocomplete
        var menuElement = self.menu.element[0];
        if (!$(event.target).closest(".ui-menu-item").length) {
            setTimeout(function() {
                $(document).one('mousedown', function(event) {
                    var t = $(event.target);
                    if (event.target !== self.element[0] && event.target !== menuElement && !$.ui.contains(menuElement, event.target) && !t.hasClass('ui-combo-trigger') && !t.parent().hasClass('ui-combo-trigger')) {
                        self.close();
                    }
                });
            }, 1);
        }

        // use another timeout to make sure the blur-event-handler on the input was already triggered
        setTimeout(function() {
            clearTimeout(self.closing);
        }, 13);
    });

这将删除当前的mousedown事件,然后将其添加回来并添加一项检查以查看触发事件的元素或其父元素(单击按钮内的按钮或按钮内的ui图标)是否具有类{{1 }}

创建按钮的代码相对不变。我们只需要添加新类ui-combo-trigger

ui-combo-trigger

答案 2 :(得分:1)

试试这个jsfiddle。我想它会帮助你。

var input = $('#txtComplete');

var data = [];
var openCheck = false;

function _init() {
    for (var idx = 0; idx <= 100; idx++) {
        data.push('item: ' + idx);
    };
    input.autocomplete({
        source: data,
        minLength: 0,
        open: function(event, ui) {
            openCheck = true;
        },
        select: function(event, ui) {
            openCheck = false;
        }
    });
}

function afterInit() {
    var button = $("<button type='button'>&nbsp;</button>").attr("tabIndex", -1).attr("title", "Show all items").insertAfter(input).button({
        icons: {
            primary: "ui-icon-triangle-1-s"
        },
        text: false
    }).removeClass("ui-corner-all").addClass("ui-corner-right ui-button-icon").click(function(event) {
        if (openCheck) {
            input.autocomplete("close");
            openCheck = false;
        } else {
            input.autocomplete("search", "");
        }
    });
}

$(function() {
    _init();
    afterInit();
});

答案 3 :(得分:0)

布莱恩解释说这个问题非常好。使用jquery ui 11,您可以执行以下操作:

wasOpen = false;
$button
  .mousedown(function() {
     wasOpen = input.autocomplete( "widget" ).is( ":visible" );
    })
   .click(function() {
       input.focus();

        // Close if already visible
        if ( wasOpen ) {
          return;
        }

参见http://jqueryui.com/autocomplete/#combobox

的示例