在IE8中淘汰+ jqueryui自动完成错误

时间:2014-06-10 17:32:23

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

我有这种情况。一个带有knockoutjs的jquery自动完成功能,除IE8外,适用于所有浏览器。当我们在自动完成列表中选择一个项目时,在我们单击(选择)一个列表项后,正常行为将关闭该列表。

但是,在IE8中,列表仍然打开。我已经做了几乎所有事情来破解这个bug,但没有成功。我们的客户是在所有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);
}

};

Knockout viewmodel:

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还是jquery ui,或两者兼而有之。

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

  • jquery 1.11.0 + jquery-ui-1.10.2 + knockout 3.0.0
  • jquery 1.9.1 + jquery-ui-1.10.2 + knockout 3.0.0

祝你好运, 马塞洛。

1 个答案:

答案 0 :(得分:0)

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

问题出在我公司的扩展中,该扩展使用了与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的错误。