【问题标题】:knockout + jqueryui autocomplete bug in IE8IE8 中的敲除 + jqueryui 自动完成错误
【发布时间】:2014-06-13 20:53:46
【问题描述】:

我有这种情况。一个带有 knockoutjs 的 jquery 自动完成功能,在所有浏览器上都可以正常工作,除了 IE8。当我们在自动完成列表中选择一个项目时,正常的行为是在我们单击(选择)一个列表项后关闭列表。

但是,在 IE8 中,列表仍然打开。我已经做了几乎所有的事情来破解这个错误,但没有成功。我们的客户是一家公司,在所有PC上都安装了IE8,我们需要将此功能适配到IE8上。

下面,我放了一些代码来说明问题:

HTML:

        <div class="lado-a-lado-linear" data-bind="visible: parametros().usaCentroDeCusto || plano().centroDeCusto()">
            <label>Centro de Custo <span class="requerido" data-bind="visible: parametros().centroDeCustoObrigatorio">*</span></label>
            <input type="text" data-bind="value: (plano().centroDeCusto() || {}).nome, autocomplete: { source: onRequestCentroDeCusto, minLength: 0, select: onSelectCentroDeCusto, change: onChangeCentroDeCusto, scroll: onScrollCentroDeCusto, requestOnFocus: true }, validationElement: plano().centroDeCusto, enable: editaDadosPlano" />
        </div>

自动完成的淘汰赛扩展:

ko.bindingHandlers.autocomplete = {
    init: function (element, valueAccessor) {
        var options = ko.utils.unwrapObservable(valueAccessor());
    $(element).autocomplete(options);

    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
        $(element).autocomplete("destroy");
    });

    if (options.requestOnFocus)
        $(element).focus(function(){
            if ($(element).autocomplete("widget").is(":visible")) 
                return;
            $(element).data("uiAutocomplete").search($(this).val());
        });

    if (options.multipleSelection) {
        $(element).parent().click(function () { Expense.mainViewModel.resizeAutocomplete($(element).parent()); });
        $(element).blur(function () { $(element).width(0); });
    }

    if (options.scroll)
        $(element).autocomplete("widget").scroll(function () {
            if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight)
                options.scroll(element);
        });

    $(element).bind('keydown', function (event) {
        var viewModel = Expense.mainViewModel || Expense.loginViewModel;
        return viewModel.onKeyDownAutocomplete(event, options.change);
    });
},
update: function (element, valueAccessor) {
    var options = ko.utils.unwrapObservable(valueAccessor());
    $(element).autocomplete("option", options);
}

};

淘汰视图模型:

self.centrosDeCusto = []
self.onRequestCentroDeCusto = function (request, response) {
    var append = request.term.indexOf('{append}') > -1;
    var skip = append ? '&$skip=' + self.centrosDeCusto.length.toString() : '';
    var terms = '?$top=30&select=id,nome&nome=' + request.term.replace('{append}', '') + skip;
    var url = self.resolveUrl('usuarios/' + self.plano().favorecido().id + '/centrosdecusto/' + terms);

    self.ajaxRequest('GET', url)
        .done(function (data) {
            if (append)
                self.centrosDeCusto = self.centrosDeCusto.concat(data);
            else
                self.centrosDeCusto = data;

            response($.map(self.centrosDeCusto, function (item) {
                return {
                    label: item.nome,
                    value: item.nome,
                    data: item
                }
            }));
        });
};

self.onScrollCentroDeCusto = function (element) {
    if (self.centrosDeCusto.length < 30 || self.centrosDeCusto.length % 30 == 0)
        $(element).autocomplete("search", $(element).val() + '{append}');
};

self.onSelectCentroDeCusto = function (event, ui) {
    self.plano().centroDeCusto(ui.item.data);
};

self.onChangeCentroDeCusto = function (event, ui) {
    ui = ui || {}; 

    if ($(event.currentTarget).val() == '')
        self.plano().centroDeCusto(null);
    else if (!ui.item && self.centrosDeCusto.length == 1)
        self.plano().centroDeCusto(self.centrosDeCusto[0]);
    else if (self.plano().centroDeCusto() && self.plano().centroDeCusto().nome == $(event.currentTarget).val()) {
    }
    else if (!ui.item && $(event.currentTarget).val() != '') {
        self.plano().centroDeCusto(null);
        setTimeout(function () { alert("É necessário selecionar um Centro de Custo da lista"); }, 0);
        $(event.currentTarget).focus();
        return false;
    }
    return true;
};

所以,我需要在所有浏览器中实现相同的行为,即:在我们编写搜索词后,自动完成触发并出现一个包含项目的列表。然后我们选择其中一项,列表消失/关闭。

仅在 IE8 中,此列表会继续打开,显示我选择的项目,就在输入字段的下方。此列表仅在我模糊该字段时关闭。但是,每次我单击输入字段时,都会再次显示该列表。

我不知道是knockoutjs 还是jq​​uery ui 的问题,或者两者兼而有之。

我已经尝试使用以下版本但没有成功。可能是某些版本的组合?!?!

  • jquery 1.11.0 + jquery-ui-1.10.2 + 淘汰赛 3.0.0
  • jquery 1.9.1 + jquery-ui-1.10.2 + 淘汰赛 3.0.0

最好的问候, 马塞洛。

【问题讨论】:

  • 根本没有抛出错误?
  • 不,没有错误!!!您可以使用 IE 10 或 11 与开发工具 (F12) 并配置到 IE8 来查看此行为。
  • 另一个信息......这种行为只是用鼠标点击。如果我使用带箭头和制表键的键盘,则列表关闭正常。但是,如果我用鼠标选择一个项目,该项目仍然显示在输入字段下方的列表中。

标签: jquery jquery-ui knockout.js internet-explorer-8


【解决方案1】:

对于需要解决与此类似的错误的每个人,我已经解决了这个错误,我将解决方案放在这里。

问题出在我公司的扩展中,它使用了与 jquery 自动完成关联的 focus() 事件。下面我展示原始事件源代码:

$(element).focus(function(){
   if ($(element).autocomplete("widget").is(":visible")) 
       return;
   $(element).data("uiAutocomplete").search($(this).val());
});

下面是新的源代码,我将 focus() 更改为 focusin() 和 focusout():

 $(element).focusin(function () {
   if ($(element).val().length == 0) {
       if ($(element).autocomplete("widget").is(":visible"))
          return;
       $(element).data("uiAutocomplete").search($(this).val());
   }
 });
 $(element).focusout(function () {
   if ($(element).autocomplete("widget").is(":hidden"))
       return;
 });

这样,我就可以解决 IE8 的问题了。

【讨论】:

    猜你喜欢
    • 2014-09-12
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多