【问题标题】:How show easyautocomplete dialog only if cursor is in input仅当光标在输入中时如何显示easyautocomplete对话框
【发布时间】:2019-11-19 09:10:14
【问题描述】:

我正在尝试在我的输入上设置 easyautocomplete。我从 ajax json 获取的数据集有一些延迟。如果用户太快并且写例如“Adam”并按下标签,光标会跳到下一个输入,但在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);

【问题讨论】:

    标签: javascript jquery easyautocomplete


    【解决方案1】:

    最低限度、完整、可验证、示例

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

    Here's a Demo of the issue in jsFiddle

    处理库事件(不起作用)

    我最初的想法是你可以在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)
        }
      },
    };

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

    更新源代码(作品)

    查看库的源代码,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

    【讨论】:

      猜你喜欢
      • 2010-11-26
      • 2011-10-05
      • 2019-09-23
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 2023-03-05
      • 2011-02-09
      相关资源
      最近更新 更多