【问题标题】:trigger event on selecting item from datalist, not when typing从数据列表中选择项目时触发事件,而不是在键入时
【发布时间】:2017-07-25 21:05:28
【问题描述】:

我有这样的表格:

<input list='data-list' id='list'>
<datalist id='data-list'>
  <option>first</option>
  <option>second</option>
</datalist>

用户可以从数据列表中选择一个项目 - 或者 - 可以输入它自己的值。我通过对 PHP 脚本的 JSON 调用连接到数据库,以在表单的其余部分填写其他信息。我希望当用户在列表输入中键入名称(因此当内容模糊时)或当用户单击 datalist 中的选项时触发。

使用$( ':input#list' ).on( 'change', function...当输入丢失焦点时触发函数,但选择来自数据列表的项目时,它还等待'直到输入丢失焦点,我希望将事件直接射击

使用$( ':input#list' ).on( 'input', function...单击数据列表中的一个项目会立即触发该功能,这正是我想要的,但键入也会触发该事件,每次击键都会向我的 PHP 脚本发送大量不需要的请求。

我尝试将事件直接绑定到数据列表,但没有成功。

我希望在用户单击(或使用键盘选择)数据列表中的项目或用户输入单词并移至下一个输入时触发该功能。

【问题讨论】:

  • 使用$( ':input#list' ).on( 'input', function...时,您可以在发送另一个请求之前插入延迟,并检查延迟时输入值是否仍然相同
  • Scott,这仍然会在每次击键时触发事件,这是我试图避免的事情。我确实在stackoverflow.com/questions/30022728/… 上找到了一个有趣的解决方案,它基本上只在用户输入的输入也在数据列表中时才进行 JSON 调用,此外,我可以在尚未调用“更改”时调用它......我还看到该链接指向可能是“重复问题”,所以我可能会删除/关闭这个

标签: jquery html html-datalist


【解决方案1】:

我寻求的解决方案是结合这两个事件......

我跟踪变量window.latest_autofill_qeury 以防止连续两次加载相同的内容。我有以下onchange 函数,当用户将焦点从输入中移出时触发(标签退出,或点击其他地方)

$( ':input#list' ).on( 'change', function(){
   var current = $( this ).val();
   if( window.latest_autofill_query != current )
      load_autofill();
} );

还有另一个函数可以跟踪用户输入的内容,并检查输入的值是否在数据列表中。如果是这样,我们假设这是用户想要的,并查询下一个数据列表。这也会在用户单击数据列表中的项目时触发,这将始终导致输入的值出现在数据列表中,从而立即触发 load_autofill:

$( ':input#list' ).on( 'input', function(){
   var current = $( this ).val();
   $( 'datalist#data-list option' ).each( function(){
      if( $( this ).text() == current ){
         load_autofill();
         return false;     //* break out of jQuery each loop
   } );
} );

load_autofill 函数会跟踪它最后加载的内容,以防止双重加载。我不会详细介绍这个 load_autofill,因为它是非常特定于应用程序的,但框架是这样的:

function load_autofill(){
    var current = $( ':input#list' ).val();
    window.latest_autofill_query = current;

    //* ... perform loading of the next datalist
}

现在,只要用户从数据列表中选择了一个项目,下一个数据列表就会被加载,但不是在用户每次击键后,只有当输入的文本出现在数据列表中时才会加载。

【讨论】:

    【解决方案2】:

    我有类似的问题,这里是解决方案。基本上我想通过单独的输入或输入+keyup 事件来触发更改事件,因此引入了新变量来跟踪这一点,在 setTimeout 的帮助下。

    HTML

    <input list="search-list" value="" class="form-control search-list custom-select custom-select-sm" placeholder="...">
    <datalist id="search-list">
      <!-- filled with javascript, eg: <option value="ISO-8859-1">ISO-8859-1</option> -->
    </datalist>
    

    JS

    window.onlyInput = false; // true if selecting
    window.timeoutID;
    window.timeoutIDs = [];    
    $('.search-list')    
    .on('focus', function(){        
        console.log('focus');
        onlyInput = false;
        $(this).val(""); // reset input
    })
    .on('change', function(){        
        console.log('change');
        // YOUR CODE HERE, ex:
        // eg: var text = $(this).val().toLowerCase();     
        // $.ajax ....
        onlyInput = false;
    })
    .on('keyup', function(){        
        console.log('keyup');        
        onlyInput = false;
        clearTimeoutIDs();
        $(this).trigger('change');
    })
    .on('input', function(){   
        console.log('input');
        var $that = $(this);
        onlyInput = true;        
        timeoutID = setTimeout(function(){            
            if(onlyInput) {
                $that.trigger('change');
                $that.trigger('blur');
            }            
            onlyInput = false;
        }, 300);
        timeoutIDs.push(timeoutID);
    });
    
    function clearTimeoutIDs() {
        $.each(timeoutIDs, function(i, d){
            clearTimeout(d);
        });
    }
    

    【讨论】:

      【解决方案3】:

      您可以设置两个单独的事件监听器。

      监听新输入并检查新输入是否与数据列表中的任何选项相对应。

      另一个监听用户何时输入一个单词并继续下一个输入。

      工作示例:

      var myForm = document.getElementsByTagName('form')[0];
      var myInput = myForm.getElementsByTagName('input')[0];
      var myDataList = myForm.getElementsByTagName('datalist')[0];
      var myOptions = myDataList.getElementsByTagName('option');
      
      function listOptionSelected() {
          var myValue = myInput.value;
          for (var i = 0; i < myOptions.length; i++) {
              if (myOptions[i].value === myValue) {
                  console.log('Option Selected: ' + myValue);
              }
          }
      }
      
      function typedOptionSelected() {
          var myValue = myInput.value;
          if (myValue !== '') {
              console.log('Option Selected: ' + myInput.value);
          }
      }
      
      myInput.addEventListener('input', listOptionSelected, false);
      myInput.addEventListener('blur', typedOptionSelected, false);
      input {
      display: block;
      margin: 0 0 12px 0;
      }
      <form action="#">
      <input list='data-list' id='list'>
      <datalist id='data-list'>
        <option>first</option>
        <option>second</option>
      </datalist>
      
      <input id="next-input" />
      </form>

      【讨论】:

      • 不,这会在提交表单时触发。我在选择一个值时以相同的形式提供其他数据列表,提交将在整个表单提交后触发,这没有用......(虽然反对票不是我的)
      • 这没有帮助,也不起作用 - 我的浏览器不显示任何控制台消息(因为未提交表单),并且 OP 希望该事件立即触发 点击后(他甚至可能没有表格)。
      • 我添加了第二个函数,它在选择数据列表中的选项时触发。
      猜你喜欢
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      相关资源
      最近更新 更多