设置默认值时,如何使浏览器显示所有数据列表选项?

Posted

技术标签:

【中文标题】设置默认值时,如何使浏览器显示所有数据列表选项?【英文标题】: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'。有没有办法避免这种情况,或者浏览器是否修复了这种行为?

【问题讨论】:

你的问题不清楚。 请解释一下这个问题是怎么不清楚的。 【参考方案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>

主要概念基本相同:

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

此功能还会在更改事件时更新当前值 - 否则您会在通过 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>

【讨论】:

以上是关于设置默认值时,如何使浏览器显示所有数据列表选项?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC DropdownList 设置默认值时未选择任何内容

如何使游戏对象列表消失动画? (或如何在设置 alpha 值时解决奇怪的行为)

android studio怎么实时预览布局界面

设置颜色时,如何使组合框显示像 VS' 这样的选项卡控件?

下拉搜索列表无法使变量等于所选选项

如何使列表框的一个选项将数据添加到新字段