仅在输入光标时如何显示easyautocomplete对话框

时间:2019-07-09 18:42:56

标签: javascript jquery easyautocomplete

我正在尝试在输入中设置easyautocomplete。我从ajax json获取数据集,并且有一些延迟。如果用户太快并且写例如“ Adam”并按Tab,光标将跳至下一个输入,但是在easyautocomplete之后,上一个输入将显示对话框,并且不会隐藏它。只有当我有光标输入时,有什么方法可以显示easyautocomplete对话框吗?

var options = {
    minCharNumber: 3,
    url: function(phrase) {
        return "data?q=" + phrase;
    },

    getValue: function(element) {

        return element.surname + " " + element.name;
    },

    template: {
        type: "description",
        fields: {
            description: "phone"
        }
    },

    ajaxSettings: {
        dataType: "json",
        method: "POST",
        data: {
            dataType: "json"
        }
    },

    list: {
        onClickEvent: function() {
            /*Some action*/
        },
        hideAnimation: {
            type: "slide", //normal|slide|fade
            time: 400,
            callback: function() {}
        }
    },
    requestDelay: 400
};

$(".autoComplete").easyAutocomplete(options);

1 个答案:

答案 0 :(得分:1)

最小,完整,可验证的示例

为了轻松查看此结果,您必须打开开发工具并限制网络流量,以便ajax连接花费一些时间

Here's a Demo of the issue in jsFiddle

Throttle Network Demo

处理库事件(无效)

我最初的想法是,您可以在触发的EAC lifecycle events期间处理此问题,例如onLoadEventonShowListEvent

var options = {
  url: "https://raw.githubusercontent.com/KyleMit/libraries/gh-pages/libraries/people.json",
  getValue: "name",
  list: {   
    match: {
      enabled: true
    },
    onLoadEvent: function() {
      console.log('LoadEvent', this)
    },
    onShowListEvent: function() {
      console.log('ShowListEvent', this)
    }
  },
};

但是,这些方法似乎没有提供改变控制流和防止将来发生事件的选项

更新源代码(Works)

Easy AutoComplete观察库的源代码,执行以下操作...

  1. Handles keyup events
  2. 然后致电loadData
  3. 哪个会触发AJAX request with the provided URL

    取决于网络和服务器的速度,在步骤4之前可以经过任何时间,并且输入可能失去焦点

  4. 一旦返回了ajax许诺,将调用showContainer()

  5. 在容器上的triggers the "show.eac" event
  6. 然后opens the list显示所选动画

在第6步中,我们可以添加最后一个检查以确认所选输入在实际打开之前仍具有焦点,如下所示:

$elements_container.on("show.eac", function() {

  // if input has lost focus, don't show container
  if (!$field.is(":focus")) {return}

  // ... rest of method ... 

Here's a working demo in Plunker会在新文件中修改库的源代码

不幸的是,这不是一个好习惯,因为它使您对将来的更改很脆弱,并且将lib维护的所有权转让给您的代码库。但这确实有效。

我根据拟议的更改创建了Pull Request #388,因此希望将来在某个时候可以对库本身进行长期修复。

包装器(目前推荐)

如果您不希望使用第三方代码,则有一些怪异的解决方法会干扰内部执行。我们无法修改showContainer方法,因为它位于闭包内部。

我们可以在show.eac事件上添加另一个侦听器,因此我们可以成为事件管道的一部分,但是这里也存在一些挑战。理想情况下,我们希望在执行库处理程序并有条件地停止传播之前触发。但是,初始化EAC会:a)创建我们必须侦听的容器,并且b)附加事件侦听器。

  

注意 jQuery中的事件处理程序将按其附加顺序触发!

因此,我们必须等到lib加载之后才能附加我们的处理程序,但这意味着我们只会在列表显示后才触发。

从问题How to order events bound with jQuery开始,我们可以进入jQuery内部并重新排序附加事件,以便我们可以在调用库的处理程序之前触发处理程序。看起来像这样:

$._data(element, 'events')["show"].reverse()
  

注意 e.stopPropagation()e.preventDefault()都不起作用,因为它们阻止了以后的事件;相反,我们需要对e.stopImmediatePropagation()

采取更直接的措施

因此包装器将如下所示:

$("#countries").easyAutocomplete(options);

$(".easy-autocomplete-container").on("show.eac", function(e) {
  var inputId = this.id.replace('eac-container-','')
  var isFocused = $("#"+inputId).is(":focus")
  if (!isFocused ) {
     e.stopImmediatePropagation()
  }
});

$(".easy-autocomplete-container").each(function() {
  $._data(this, 'events')["show"].reverse()
})

Here's a working demo in CodePen