【问题标题】:How can I make a browser display all datalist options when a default value is set?设置默认值时,如何使浏览器显示所有数据列表选项?
【发布时间】:2016-09-25 12:18:36
【问题描述】:

我有一个带有数据列表的 HTML 表单,其中的值是用 PHP 设置的,比如

<input list="values" value="<?php echo $val; ?>">
 <datalist id="values">
  <option value="orange">
  <option value="banana">
 </datalist>

我希望用户看到数据列表中的选项,以及来自 PHP 的当前值。但是,“自动完成”操作会导致列表中与当前值不匹配(或以当前值开头)的值从列表中隐藏,例如 $val='apple'。有没有办法避免这种情况,或者浏览器是否修复了这种行为?

【问题讨论】:

  • 你的问题不清楚。
  • 请解释一下这个问题是怎么不清楚的。

标签: html browser datalist


【解决方案1】:

&lt;datalist&gt; 使用自动完成功能,因此这是正常行为。

例如,如果您将输入值设置为“o”,您将在 datalist 选项中看到 orange。它从第一个字母开始检查单词。但是,如果您将输入值设置为“a”,那么您将根本看不到选项。

因此,如果您在输入中已经有值,那么数据列表选项中将不会显示任何内容,除非该值存在(如果存在)。它的行为不像 select。

解决方法是像这样使用 jquery:

$('input').on('click', function() {
  $(this).val('');
});
$('input').on('mouseleave', function() {
  if ($(this).val() == '') {
    $(this).val('apple');
  }
});

在这里进行完整测试:https://jsfiddle.net/yw5wh4da/

或者你可以使用&lt;select&gt;。对我来说,在这种情况下这是更好的解决方案。

【讨论】:

  • 我意识到这种行为是正常的,但我想知道是否有办法改变它。我怀疑不是。我认为在我的情况下,解决方法是在列表中添加第二个输入元素,它会在提交时填充第一个元素,但这对于我的用例来说是非常具体的。
  • 如果你想用纯 HTML 改变它,那么据我所知,这是不可能的
  • @Dave W:我认为这是一个非常正常的用例。 W3C 只想专注于向 CSS 添加更多臃肿,而不是修复基本功能。
  • "Select" 是一个选项,但它也有一个可能无法满足 OP 问题的功能。使用“选择”,您无法在列表中输入全新的值,您受限于 HTML 中的选项。通常你想要的是一个文本输入字段,它可以接受一个新值,但也有一个预定义选项列表。
【解决方案2】:

HTML:

<input list="values" placeholder="select">
<datalist id="values">
  <option value="orange">
  <option value="banana">
  <option value="lemon">
  <option value="apple">
</datalist>

JS:

$('input').on('click', function() {
    $(this).attr('placeholder',$(this).val());
  $(this).val('');
});
$('input').on('mouseleave', function() {
  if ($(this).val() == '') {
    $(this).val($(this).attr('placeholder'));
  }
});

【讨论】:

    【解决方案3】:

    上面的解决方案很好,但是如果用户自然只是在输入框内点击占位符值旁边,打算保留并继续它,它将完全被删除。

    所以基于上面的解决方案,我为我做了以下解决方案:

    HTML:

    <input id="other" list="values" value="<?php echo $val; ?>">
     <datalist id="values">
      <option value="orange">
      <option value="banana">
     </datalist>
    

    JS:

    jQuery(document).ready(function ($) {
        function putValueBackFromPlaceholder() {
            var $this = $('#other');
            if ($this.val() === '') {
                $this.val($this.attr('placeholder'));
                $this.attr('placeholder','');
            }
        }
    
        $('#other')
            .on('click', function(e) {
                var $this = $(this);
                var inpLeft = $this.offset().left;
                var inpWidth = $this.width();
                var clickedLeft = e.clientX;
                var clickedInInpLeft = clickedLeft - inpLeft;
                var arrowBtnWidth = 12;
                if ((inpWidth - clickedInInpLeft) < arrowBtnWidth ) {
                    $this.attr('placeholder',$this.val());
                    $this.val('');
                }
                else {
                    putValueBackFromPlaceholder();
                }
            })
            .on('mouseleave', putValueBackFromPlaceholder);
    });
    

    对我来说,页面上有很多输入框,我只希望这个有这种行为,所以我使用 id 并将其设置为“个人”。如果您希望将其更改为更通用的函数,则必须将 putValueBackFromPlaceholder 与发生点击的元素和事件本身绑定。

    【讨论】:

    • 正是我想要的。加上一个小修复 if ((inpWidth - clickedInInpLeft)
    • @andre719mv,谢谢你,我认为改变不是必须的——如果它是空的,它只会有空的占位符。或者你看到其他改变它的理由?
    • 我认为这是必须的,如果您不想通过第二次单击箭头而丢失所选值。重现步骤: 1. 选择一些值 2. 单击箭头 3. 第二次单击箭头 - 您的值和占位符将变为空。这是固定版本jsfiddle.net/7sugxf2v
    【解决方案4】:

    另一个选项,基于建议的解决方案,保留以前的值或选择的新值。

    // Global variable to store current value
    var oldValue = '';
    // Blank value when click to activate all options
    $('input').on('click', function() {
      oldValue = $(this).val();
      $(this).val('');
    });
    // Restore current value after click
    $('input').on('mouseleave', function() {
      if ($(this).val() == '') {
        $(this).val(oldValue);
      }
    });
    

    https://jsfiddle.net/jpussacq/7Ldbc013/

    【讨论】:

      【解决方案5】:

      最干净的选项可能是Mozilla.org 推荐的选项。

      input.onfocus = function () {
        datalist.style.display = 'block';
      }
      
      input.onblur = function () {
        datalist.style.display = 'none';
      }
      
      
      
      for (let option of datalist.options) {
        option.onclick = function () {
          input.value = this.value;
          datalist.style.display = 'none';
        }
      }
      
      datalist.style.width = input.offsetWidth + 'px';
      datalist.style.left = input.offsetLeft + 'px';
      datalist.style.top = input.offsetTop + input.offsetHeight + 'px';
      datalist {
        position: absolute;
        background-color: lightgrey;
        font-family: sans-serif;
        font-size: 0.8rem;
      }
      
      option {
        background-color: #bbb;
        padding: 4px;
        margin-bottom: 1px;
        cursor: pointer;
      }
      <input
        list=""
        name="option"
        id="input"
        autocomplete="off"
      >
      
      <datalist id="datalist">
        <option>Carrots</option>
        <option>Peas</option>
        <option>Beans</option>
      </datalist>

      【讨论】:

      • 这对我不起作用,直到我将 300 毫秒超时设置为 onblur (否则它会过早隐藏数据列表以使 onclick 触发): setTimeout(function(){ datalist.style.display = '无'; }, 300);
      【解决方案6】:

      function InputDropList_Focus(elementID)
          {//input must have value and valuetemp attributes 
              
              const el=document.getElementById(elementID);
              el.setAttribute("valuetemp", el.value);
              el.value="";        
          }
      
      function InputDropList_FocusOut(elementID)
          {       
              const el=document.getElementById(elementID);
          if(el.value !== el.getAttribute("valuetemp"))
                  el.value=el.getAttribute("valuetemp");
          }
        
        function InputDropList_OnChange(elementID, action)
          {       
              const el=document.getElementById(elementID);
              el.setAttribute("valuetemp", el.value);
          
          el.blur();   
              
              if(action != null)
                  action();
          }
        
        
      function DoSmthOnChange(elementID)
      {
          const el=document.getElementById(elementID);
          console.log("new value: " + el.value);
      }
      <input id="mylist" list="mylistOptions" value="apple" 
      valuetemp="apple"
      onfocus="InputDropList_Focus('mylist')"
      onfocusout="InputDropList_FocusOut('mylist')"
      onchange="InputDropList_OnChange('mylist', DoSmthOnChange('mylist'))"
      >
      <datalist id="mylistOptions">
        <option value="apple">
        <option value="orange">
        <option value="banana">
      </datalist>

      【讨论】:

      • 欢迎来到 Stack Overflow。当代码附有解释时,它会更有帮助。 Stack Overflow 是关于学习的,而不是提供 sn-ps 来盲目复制和粘贴。请编辑您的问题并解释它如何回答所提出的具体问题。
      【解决方案7】:

      我发现使用 click 和 mouseleave 事件并不理想,因为它们无法使用 键盘控件。

      所以我想出了这个辅助函数:

      keepDatalistOptions('.keepDatalist');
      
      function keepDatalistOptions(selector='') {
        // select all input fields by datalist attribute or by class/id
        selector = !selector ? "input[list]" : selector;
        let datalistInputs = document.querySelectorAll(selector);
        if (datalistInputs.length) {
          for (let i = 0; i < datalistInputs.length; i++) {
            let input = datalistInputs[i];
            input.addEventListener("change", function (e) {
              e.target.setAttribute("placeholder", e.target.value);
            });
            input.addEventListener("focus", function (e) {
              e.target.setAttribute("placeholder", e.target.value);
              e.target.value = "";
            });
            input.addEventListener("blur", function (e) {
              e.target.value = e.target.getAttribute("placeholder");
            });
          }
        }
      }
      <input class="keepDatalist" type="text" list="data" value="apple">
      <datalist id="data">
        <option value="apple">
        <option value="orange">
        <option value="banana">
      </datalist>
      
      <input  type="text" list="browser" value="">
      <datalist id="browser">
        <option value="firefox">
        <option value="opera">
        <option value="safari">
      </datalist>

      主要概念基本相同:

      1. 将当前输入值保存到占位符属性中
      2. 重置焦点值以显示所有数据列表选项
      3. 在模糊时用占位符交换实际输入值

      此功能还会在更改事件时更新当前值 - 否则您会在通过 tab 键导航到下一个输入后丢失当前值。

      【讨论】:

        【解决方案8】:

        这是herrstriezel's answer(在es6中)的改进版

        function keepDatalistOptions(selector = 'input[list]') {
          // select all input fields by datalist attribute or by class/id
          document.querySelectorAll(selector).forEach(dataListInput => {
            let dataListValue = dataListInput.value
            dataListInput.addEventListener('focus', () => {
              dataListValue = datalistInput.value
              dataListInput.value = ''
            })
            dataListInput.addEventListener('change', () => {
              dataListValue = dataListInput.value
            })
            dataListInput.addEventListener('blur', () => {
              if (dataListInput.value === '') {
                dataListInput.value = dataListValue
              }
            })
          })
        }
        

        【讨论】:

          【解决方案9】:

          只需在输入标签中粘贴所需的默认值即可。无需额外的 JavaScript 编码!

                  <input list="skills" value="DBA">
          
                    <datalist name="skills" id="skills">
          
                        <option value="PHP">Zend PHP</option>
                        <option value="DBA">ORACLE DBA</option>
                        <option value="APEX">APEX 5.1</option>
                        <option value="ANGULAR">ANGULAR JS</option>
          
                    </datalist>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-21
            • 2017-03-18
            • 1970-01-01
            • 1970-01-01
            • 2019-08-03
            • 2013-09-16
            相关资源
            最近更新 更多