设置默认值时,如何使浏览器显示所有数据列表选项?
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】:<datalist>
使用自动完成功能,因此这是正常行为。
例如,如果您将输入值设置为“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/
或者你可以使用<select>
。对我来说,在这种情况下这是更好的解决方案。
【讨论】:
我意识到这种行为是正常的,但我想知道是否有办法改变它。我怀疑不是。我认为在我的情况下,解决方法是在列表中添加第二个输入元素,它会在提交时填充第一个元素,但这对于我的用例来说是非常具体的。 如果你想用纯 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 设置默认值时未选择任何内容