简体   繁体   English

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

[英]Jquery UI autocomplete combobox button click event

I'm experiencing weird behavior with jquery ui autocomplete when using it to create a combobox . 使用jquery ui自动完成功能创建组合框时,我遇到了奇怪的行为。 Whenever I click on the scrollbar to scroll through the list of results AND then click on my combobox button to close the results the results list closes and then opens again. 每当我点击滚动条滚动结果列表然后单击我的组合框按钮关闭结果列表关闭结果然后再次打开。 I expect it to close the menu. 我希望它关闭菜单。

Steps to Repro Repro的步骤

  1. open jsfiddle demo 打开jsfiddle演示
  2. Type 'i' in the autocomplete OR hit the dropdown button. 在自动完成中键入“i”或按下下拉按钮。
  3. Click on the vertical scroll to scroll the results 单击垂直滚动以滚动结果
  4. Click on the dropdown button 单击下拉按钮

Script to Create Button 用于创建按钮的脚本

 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 (force long results menu to scroll) 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;
}

My solution could be closing the widget even if focus is transferred to widget itself and not the input element? 即使焦点转移到小部件本身而不是输入元素,我的解决方案可能是关闭小部件?

Any ideas how to modify this code so it behaves this way? 任何想法如何修改此代码,以便它以这种方式行事?

Based on issues with the various click and mouse events for the automplete widget, I came up with this: jsFiddle example . 根据自动完成小部件的各种点击和鼠标事件的问题,我想出了这个: jsFiddle示例

jQuery: 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();
});​

The problem is because of a work around in jquery ui autocomplete. 问题是因为在jquery ui自动完成中的解决方法。 There is a mousedown event setup to close the menu under certain conditions. 在某些条件下,有一个mousedown事件设置可以关闭菜单。 In one of the conditions it checks to see if the item that raised the mousedown is part of the autocomplete widget. 在其中一个条件中,它会检查引发mousedown的项是否是自动完成小部件的一部分。 If not, it closes the menu. 如果没有,它会关闭菜单。 Since you are tacking on combobox behaviour and your button is not part of the autocomplete widget, a click on the button is closing the menu because of this event. 由于您正在处理组合框行为并且您的按钮不是自动完成小部件的一部分,因此单击该按钮会因此事件而关闭菜单。

You can see the offending condition with the reason why it is there starting at line 205 in the autocomplete source on github . 您可以在github上自动完成源中的第205行开始查看有问题的条件。 It is probably worth raising the issue on the jquery ui forums since their combobox demo has this bug too. 可能值得在jquery ui论坛上提出这个问题,因为他们的组合框演示也有这个bug。

UPDATE UPDATE

This replacement event is based off of jquery-ui 1.8.18. 此替换事件基于jquery-ui 1.8.18。 This event has changed and will very likely change again. 此事件已发生变化,很可能会再次发生变化。 You might need to update this code manually with each release if you go this route. 如果你走这条路线,你可能需要手动更新每个版本的代码。

You can patch the mousedown event to not close the menu if it was your combo button that was clicked by running the following after you create your autocomplete ( jsfiddle demo ). 如果是在创建自动完成( jsfiddle演示 )后运行以下内容而单击的组合按钮,则可以修补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);
    });

This removes the current mousedown event and then adds it back in with an added check to see if the element that triggered the event or its parent (button clicked or ui-icon inside the button is clicked) has a class ui-combo-trigger . 这将删除当前的mousedown事件,然后将其添加回来,并添加检查以查看触发事件的元素或其父元素(单击按钮内的按钮或按钮内的ui图标)是否具有类ui-combo-trigger

The code to create your button is relatively unchanged. 创建按钮的代码相对不变。 We just need to add the new class ui-combo-trigger . 我们只需要添加新类ui-combo-trigger

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 ui-combo-trigger").click(function(event) {

        // 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();
        event.stopImmediatePropagation();
    });

Try this jsfiddle . 试试这个jsfiddle I think it ll help you. 我想它会帮助你。

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

Brian explained the problem very good. Brian解释这个问题非常好。 With jquery ui 11 you can do something like: 使用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;
        }

see example at http://jqueryui.com/autocomplete/#combobox 请参阅http://jqueryui.com/autocomplete/#combobox上的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM