我想创建一个带有下拉列表的文本字段,该列表允许用户选择一些预定义的值。用户还应该能够键入新值或从下拉列表中选择预定义值。我知道我可以使用两个小部件,但是在我的应用程序中,如果它在一个小部件中统一,则会更符合人体工程学。
是否有标准小部件或我是否必须使用第三方JavaScript?
浏览器可移植性如何?
答案 0 :(得分:93)
您可以使用HTML5中的<datalist>
标记来完成此操作。
<input type="text" name="product" list="productName"/>
<datalist id="productName">
<option value="Pen">Pen</option>
<option value="Pencil">Pencil</option>
<option value="Paper">Paper</option>
</datalist>
如果双击浏览器中的输入文本,将显示带有已定义选项的列表。
答案 1 :(得分:20)
这可以通过纯HTML,CSS和JQuery来实现。我创建了一个示例页面:
$(document).ready(function(){
$(".editableBox").change(function(){
$(".timeTextBox").val($(".editableBox option:selected").html());
});
});
.editableBox {
width: 75px;
height: 30px;
}
.timeTextBox {
width: 54px;
margin-left: -78px;
height: 25px;
border: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<select class="editableBox">
<option value="1">01:00</option>
<option value="2">02:00</option>
<option value="3">03:00</option>
<option value="4">04:00</option>
<option value="5">05:00</option>
<option value="6">06:00</option>
<option value="7">07:00</option>
<option value="8">08:00</option>
<option value="9">09:00</option>
<option value="10">10:00</option>
<option value="11">11:00</option>
<option value="12">12:00</option>
<option value="13">13:00</option>
<option value="14">14:00</option>
<option value="15">15:00</option>
<option value="16">16:00</option>
<option value="17">17:00</option>
<option value="18">18:00</option>
<option value="19">19:00</option>
<option value="20">20:00</option>
<option value="21">21:00</option>
<option value="22">22:00</option>
<option value="23">23:00</option>
<option value="24">24:00</option>
</select>
<input class="timeTextBox" name="timebox" maxlength="5"/>
</div>
答案 2 :(得分:15)
最好的方法是使用第三方库。
您可以在jQuery UI和dojo中实现所需的内容。 jQuery更受欢迎,但是dojo允许您以声明方式定义HTML中的小部件,这听起来更像您正在寻找的内容。
您使用哪一个取决于您的风格,但两者都是为跨浏览器工作而开发的,并且两者都会比复制和粘贴代码更频繁地更新。
答案 3 :(得分:8)
<select>
标记仅允许使用预定义的条目。您问题的典型解决方案是将一个标记为“其他”的条目和一个禁用的编辑字段(<input type="text"
)。添加一些JavaScript以仅在选择“其他”时启用编辑字段。
有可能以某种方式创建一个允许直接编辑的下拉列表,但IMO不值得付出努力。如果是这样,亚马逊,谷歌或微软都会这样做;-)只需用最简单的解决方案完成工作。它更快(你的老板可能会喜欢)并且通常更容易维护(你可能会喜欢)。
答案 4 :(得分:6)
基于CSS和一行JS代码的非常简单的实现(仅基本功能)
<div class="dropdown">
<input type="text" />
<select onchange="this.previousElementSibling.value=this.value; this.previousElementSibling.focus()">
<option>This is option 1</option>
<option>Option 2</option>
</select>
</div>
请注意:它使用不受支持的previousElementSibling in older browsers (below IE9)
.dropdown {
position: relative;
width: 200px;
}
.dropdown select
{
width: 100%;
}
.dropdown > * {
box-sizing: border-box;
height: 1.5em;
}
.dropdown select {
}
.dropdown input {
position: absolute;
width: calc(100% - 20px);
}
这是它 JSFiddle
答案 5 :(得分:3)
带有TextBox的ComboBox(用于预定义值以及用户定义的值。)
答案 6 :(得分:1)
我不确定有没有办法在没有javascript的情况下自动执行此操作。
您需要的是在浏览器端运行以在用户进行选择时将表单提交回服务器的内容 - 因此,javascript。
此外,请确保为已关闭javascript的用户提供备用方式(即提交按钮)。
一个很好的例子:Combo-Box Viewer
我昨天甚至有一个更复杂的组合框,使用这个dhtmlxCombo ,使用ajax在大量数据中检索相关值。
答案 7 :(得分:1)
答案 8 :(得分:1)
一点点CSS,你就完成了 fiddle
<div style="position: absolute;top: 32px; left: 430px;" id="outerFilterDiv">
<input name="filterTextField" type="text" id="filterTextField" tabindex="2" style="width: 140px;
position: absolute; top: 1px; left: 1px; z-index: 2;border:none;" />
<div style="position: absolute;" id="filterDropdownDiv">
<select name="filterDropDown" id="filterDropDown" tabindex="1000"
onchange="DropDownTextToBox(this,'filterTextField');" style="position: absolute;
top: 0px; left: 0px; z-index: 1; width: 165px;">
<option value="-1" selected="selected" disabled="disabled">-- Select Column Name --</option>
</select>
答案 9 :(得分:0)
HTML没有内置的可编辑下拉列表或组合框,但是我在an article中实现了大多数CSS解决方案。
您可以看到完整的演示here,但总而言之,请像这样编写HTML:
<span class="combobox withtextlist">
<input value="Fruit">
<span tabindex="-1" class="downarrow"></span>
<select size="10" class="sticky">
<option>Apple</option>
<option>Banana</option>
<option>Cherry</option>
<option>Dewberry</option>
</select>
</span>
并使用像这样的CSS对其进行样式设置(这是为具有下拉箭头▾按钮的组合框和单击时打开且可能具有不同样式的下拉菜单而设计的):
/* ------------------------------------------ */
/* ----- combobox / dropdown list styling */
/* ------------------------------------------ */
.combobox {
/* Border slightly darker than Chrome's <select>, slightly lighter than FireFox's */
border: 1px solid #999;
padding-right: 1.25em; /* leave room for ▾ */
}
.dropdown, .combobox {
/* "relative" and "inline-block" (or just "block") are needed
here so that "absolute" works correctly in children */
position: relative;
display: inline-block;
}
.combobox > .downarrow, .dropdown > .downarrow {
/* ▾ Outside normal flow, relative to container */
display: inline-block;
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 1.25em;
cursor: default;
nav-index: -1; /* nonfunctional in most browsers */
border-width: 0px; /* disable by default */
border-style: inherit; /* copy parent border */
border-color: inherit; /* copy parent border */
}
/* Add a divider before the ▾ down arrow in non-dropdown comboboxes */
.combobox:not(.dropdown) > .downarrow {
border-left-width: 1px;
}
/* Auto-down-arrow if one is not provided */
.downarrow:empty::before {
content: '▾';
}
.downarrow::before, .downarrow > *:only-child {
text-align: center;
/* vertical centering trick */
position: relative;
top: 50%;
display: block; /* transform requires block/inline-block */
transform: translateY(-50%);
}
.combobox > input {
border: 0
}
.dropdown > *:last-child,
.combobox > *:last-child {
/* Using `display:block` here has two desirable effects:
(1) Accessibility: it lets input widgets in the dropdown to
be selected with the tab key when the dropdown is closed.
(2) It lets the opacity transition work.
But it also makes the contents visible, which is undesirable
before the list drops down. To compensate, use `opacity: 0`
and disable mouse pointer events. Another side effect is that
the user can select and copy the contents of the hidden list,
but don't worry, the selected content is invisible. */
display: block;
opacity: 0;
pointer-events: none;
transition: 0.4s; /* fade out */
position: absolute;
left: 0;
top: 100%;
border: 1px solid #888;
background-color: #fff;
box-shadow: 1px 2px 4px 1px #666;
box-shadow: 1px 2px 4px 1px #4448;
z-index: 9999;
min-width: 100%;
box-sizing: border-box;
}
/* List of situations in which to show the dropdown list.
- Focus dropdown or non-last child of it => show last-child
- Focus .downarrow of combobox => show last-child
- Stay open for focus in last child, unless .less-sticky
- .sticky last child stays open on hover
- .less-sticky stays open on hover, ignores focus in last-child */
.dropdown:focus > *:last-child,
.dropdown > *:focus ~ *:last-child,
.combobox > .downarrow:focus ~ *:last-child,
.combobox > .sticky:last-child:hover,
.dropdown > .sticky:last-child:hover,
.combobox > .less-sticky:last-child:hover,
.dropdown > .less-sticky:last-child:hover,
.combobox > *:last-child:focus:not(.less-sticky),
.dropdown > *:last-child:focus:not(.less-sticky) {
display: block;
opacity: 1;
transition: 0.15s;
pointer-events: auto;
}
/* focus-within not supported by Edge/IE. Unsupported selectors cause
the entire block to be ignored, so we must repeat all styles for
focus-within separately. */
.combobox > *:last-child:focus-within:not(.less-sticky),
.dropdown > *:last-child:focus-within:not(.less-sticky) {
display: block;
opacity: 1;
transition: 0.15s;
pointer-events: auto;
}
/* detect Edge/IE and behave if though less-sticky is on for all
dropdowns (otherwise links won't be clickable) */
@supports (-ms-ime-align:auto) {
.dropdown > *:last-child:hover {
display: block;
opacity: 1;
pointer-events: auto;
}
}
/* detect IE and do the same thing. */
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
.dropdown > *:last-child:hover {
display: block;
opacity: 1;
pointer-events: auto;
}
}
.dropdown:not(.sticky) > *:not(:last-child):focus,
.downarrow:focus, .dropdown:focus {
pointer-events: none; /* Causes second click to close */
}
.downarrow:focus {
outline: 2px solid #8BF; /* Edge/IE can't do outline transparency */
outline: 2px solid #48F8;
}
/* ---------------------------------------------- */
/* Optional extra styling for combobox / dropdown */
/* ---------------------------------------------- */
*, *:before, *:after {
/* See https://css-tricks.com/international-box-sizing-awareness-day/ */
box-sizing: border-box;
}
.combobox > *:first-child {
display: inline-block;
width: 100%;
box-sizing: border-box; /* so 100% includes border & padding */
}
/* `.combobox:focus-within { outline:...}` doesn't work properly
in Firefox because the focus box is expanded to include the
(possibly hidden) drop list. As a workaround, put focus box on
the focused child. It is barely-visible so that it doesn't look
TOO ugly if the child isn't the same size as the parent. It
may be uglier if the first child is not styled as width:100% */
.combobox > *:not(:last-child):focus {
outline: 2px solid #48F8;
}
.combobox {
margin: 5px;
}
您还需要一些JavaScript才能将列表与文本框同步:
function parentComboBox(el) {
for (el = el.parentNode; el != null && Array.prototype.indexOf.call(el.classList, "combobox") <= -1;)
el = el.parentNode;
return el;
}
// Uses jQuery
$(".combobox.withtextlist > select").change(function() {
var textbox = parentComboBox(this).firstElementChild;
textbox.value = this[this.selectedIndex].text;
});
$(".combobox.withtextlist > select").keypress(function(e) {
if (e.keyCode == 13) // Enter pressed
parentComboBox(this).firstElementChild.focus(); // Closes the popup
});
答案 10 :(得分:0)
没有CSS的简单HTML + Javascript方法
function editDropBox() {
var cSelect = document.getElementById('changingList');
var optionsSavehouse = [];
if(cSelect != null) {
var optionsArray = Array.from(cSelect.options);
var arrayLength = optionsArray.length;
for (var o = 0; o < arrayLength; o++) {
var option = optionsArray[o];
var oVal = option.value;
if(oVal > 0) {
var localParams = [];
localParams.push(option.text);
localParams.push(option.value);
//localParams.push(option.selected); // if needed
optionsSavehouse.push(localParams);
}
}
}
var hidden = ("<input id='hidden_select_options' type='hidden' value='" + JSON.stringify(optionsSavehouse) + "' />");
var cSpan = document.getElementById('changingSpan');
if(cSpan != null) {
cSpan.innerHTML = (hidden + "<input size='2' type='text' id='tempInput' name='fname' onchange='restoreDropBox()'>");
}
}
function restoreDropBox() {
var cSpan = document.getElementById('changingSpan');
var cInput = document.getElementById('tempInput');
var hOptions = document.getElementById('hidden_select_options');
if(cSpan != null) {
var optionsArray = [];
if(hOptions != null) {
optionsArray = JSON.parse(hOptions.value);
}
var selectList = "<select id='changingList'>\n";
var arrayLength = optionsArray.length;
for (var o = 0; o < arrayLength; o++) {
var option = optionsArray[o];
selectList += ("<option value='" + option[1] + "'>" + option[0] + "</option>\n");
}
if(cInput != null) {
selectList += ("<option value='-1' selected>" + cInput.value + "</option>\n");
}
selectList += ("<option value='-2' onclick='editDropBox()'>- Edit -</option>\n</select>");
cSpan.innerHTML = selectList;
}
}
<span id="changingSpan">
<select id="changingList">
<option value="1">Apple</option>
<option value="2">Banana</option>
<option value="3">Cherry</option>
<option value="4">Dewberry</option>
<option onclick="editDropBox()" value="-2">- Edit -</option>
</select>
</span>