Autocomplete with datalist [duplicate] - html

Currently the HTML5 <datalist> element is supported in most major browsers (except Safari) and seems like an interesting way to add suggestions to an input.
However, there seem to be some discrepancies between the implementation of the value attribute and the inner text on the <option>. For example:
<input list="answers" name="answer">
<datalist id="answers">
<option value="42">The answer</option>
</datalist>
This is handled differently by different browsers:
Chrome and Opera:
FireFox and IE 11:
After selecting one, the input is filled with the value and not the inner text. I only want the user to see the text ("The answer") in the dropdown and in the input, but pass the value 42 on submit, like a select would.
How can I make all browsers have the dropdown list show the labels (inner text) of the <option>s, but send the value attribute when the form is submitted?

Note that datalist is not the same as a select. It allows users to enter a custom value that is not in the list, and it would be impossible to fetch an alternate value for such input without defining it first.
Possible ways to handle user input are to submit the entered value as is, submit a blank value, or prevent submitting. This answer handles only the first two options.
If you want to disallow user input entirely, maybe select would be a better choice.
To show only the text value of the option in the dropdown, we use the inner text for it and leave out the value attribute. The actual value that we want to send along is stored in a custom data-value attribute:
To submit this data-value we have to use an <input type="hidden">. In this case we leave out the name="answer" on the regular input and move it to the hidden copy.
<input list="suggestionList" id="answerInput">
<datalist id="suggestionList">
<option data-value="42">The answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">
This way, when the text in the original input changes we can use javascript to check if the text also present in the datalist and fetch its data-value. That value is inserted into the hidden input and submitted.
document.querySelector('input[list]').addEventListener('input', function(e) {
var input = e.target,
list = input.getAttribute('list'),
options = document.querySelectorAll('#' + list + ' option'),
hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden'),
inputValue = input.value;
hiddenInput.value = inputValue;
for(var i = 0; i < options.length; i++) {
var option = options[i];
if(option.innerText === inputValue) {
hiddenInput.value = option.getAttribute('data-value');
break;
}
}
});
The id answer and answer-hidden on the regular and hidden input are needed for the script to know which input belongs to which hidden version. This way it's possible to have multiple inputs on the same page with one or more datalists providing suggestions.
Any user input is submitted as is. To submit an empty value when the user input is not present in the datalist, change hiddenInput.value = inputValue to hiddenInput.value = ""
Working jsFiddle examples: plain javascript and jQuery

The solution I use is the following:
<input list="answers" id="answer">
<datalist id="answers">
<option data-value="42" value="The answer">
</datalist>
Then access the value to be sent to the server using JavaScript like this:
var shownVal = document.getElementById("answer").value;
var value2send = document.querySelector("#answers option[value='"+shownVal+"']").dataset.value;
Hope it helps.

I realize this may be a bit late, but I stumbled upon this and was wondering how to handle situations with multiple identical values, but different keys (as per bigbearzhu's comment).
So I modified Stephan Muller's answer slightly:
A datalist with non-unique values:
<input list="answers" name="answer" id="answerInput">
<datalist id="answers">
<option value="42">The answer</option>
<option value="43">The answer</option>
<option value="44">Another Answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">
When the user selects an option, the browser replaces input.value with the value of the datalist option instead of the innerText.
The following code then checks for an option with that value, pushes that into the hidden field and replaces the input.value with the innerText.
document.querySelector('#answerInput').addEventListener('input', function(e) {
var input = e.target,
list = input.getAttribute('list'),
options = document.querySelectorAll('#' + list + ' option[value="'+input.value+'"]'),
hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden');
if (options.length > 0) {
hiddenInput.value = input.value;
input.value = options[0].innerText;
}
});
As a consequence the user sees whatever the option's innerText says, but the unique id from option.value is available upon form submit.
Demo jsFiddle

When clicking on the button for search you can find it without a loop.
Just add to the option an attribute with the value you need (like id) and search for it specific.
$('#search_wrapper button').on('click', function(){
console.log($('option[value="'+
$('#autocomplete_input').val() +'"]').data('value'));
})

to get text() instead of val() try:
$("#datalistid option[value='" + $('#inputid').val() + "']").text();

Using PHP i've found a quite simple way to do this. Guys, Just Use something like this
<input list="customers" name="customer_id" required class="form-control" placeholder="Customer Name">
<datalist id="customers">
<?php
$querySnamex = "SELECT * FROM `customer` WHERE fname!='' AND lname!='' order by customer_id ASC";
$resultSnamex = mysqli_query($con,$querySnamex) or die(mysql_error());
while ($row_this = mysqli_fetch_array($resultSnamex)) {
echo '<option data-value="'.$row_this['customer_id'].'">'.$row_this['fname'].' '.$row_this['lname'].'</option>
<input type="hidden" name="customer_id_real" value="'.$row_this['customer_id'].'" id="answerInput-hidden">';
}
?>
</datalist>
The Code Above lets the form carry the id of the option also selected.

Related

Not able to display user input date in datalist

I have an input field called creation date where user can enter date information. When user enter a date, that date should be listed in <datalist> automatically. But i am not getting expected result.
Creation Date <input type="text" list="cdate" id="cdate" class="tb1">
<datalist id="cdate">
<option value="<%= new SimpleDateFormat("dd-MM-yyyy").format(new java.util.Date())%>">UNIT 1</option>
</datalist>
<datalist> represents a set of options and need to be hooked to control element (<input> in this case). There is an id conflict between <datalist> and <input>. That's why the code snippet does not work.
However, even if the id conflict is fixed, this code may not work as you expected (if my understanding is right) -- The final result is: <input> element is able to select value from <datalist> options. The <datalist> content will not change dynamically due to <input> interaction.
you gave same ID cdate to input and datalist which is incorrect.
this is working example with javascript.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Creation Date <input type="text" list="cdate" class="tb1">
<datalist id="cdate">
</datalist>
<script>
(function() {
var todaysDate = new Date();
$('#cdate').append("<option value='" + todaysDate + "'>");
})();
</script>
As mentioned above. changed code as
Creation Date <input type="date" name="cdate" id="cdate" class="inp" value="<%= new SimpleDateFormat("dd-MM-yyyy").format(new java.util.Date())%>"><br><br></p><br><br>
So that it will receive date from users also

How to prevent a user from entering negative values in Html input

I am using the following html input element for collecting the product quantity in Html page but the user can still go ahead and manually enter negative value. For example: I selected the the textbox and entered -100 and input field took it without complaining about it.
How can I prevent user from entering 0 and non-negative values in Html input element?
<input type="number" id="qty" value="" size="3" min="1" />
Due to the <input type="number"> still not being widely well supported, you are still better off using a text input. Preventively you could disallow any characters which are not numbers with the keypress event and e.preventDefault(). However be sure that if you want to support legacy browsers (IE8-), there are a number of inconsistencies to take into account regarding returned key codes/ char codes. If you also want to disallow pasting non-number content, you can do so with the paste event and e.clipboardData.getData('plain/text') (for a complete implementation see here)
Test with the code below:
var myInput = document.getElementsByTagName('input')[0];
myInput.addEventListener('keypress', function(e) {
var key = !isNaN(e.charCode) ? e.charCode : e.keyCode;
function keyAllowed() {
var keys = [8,9,13,16,17,18,19,20,27,46,48,49,50,
51,52,53,54,55,56,57,91,92,93];
if (key && keys.indexOf(key) === -1)
return false;
else
return true;
}
if (!keyAllowed())
e.preventDefault();
}, false);
// EDIT: Disallow pasting non-number content
myInput.addEventListener('paste', function(e) {
var pasteData = e.clipboardData.getData('text/plain');
if (pasteData.match(/[^0-9]/))
e.preventDefault();
}, false);
<input type="text">
You can validate the value with regex with the pattern attribute:
<input type="number" pattern="^[1-9]\d*$" name="qty">
You can use the built-in form validation validity.valid, user won't be able to enter or paste negative values. Also user won't be able enter decimals. More info here
<input type="number" min="1" oninput="validity.valid||(value='');"/>
try this :
<input type="number" min="0">

How do I get the text and not the value of an Option?

I have a form, which is generated by a ticket system, but I have to customize it.
In this form there is a select part with different options, each option got a value with a number and a text (between the tags). I can't change the value because the ticket system need it when you send the form to it. Now I have a function which collects some inputs and place it into a text field (which is also in the form) but, I need the text from the option tag not the value:
<select id="selectfield" bla bla bla>
<option value="1"> something </option>
<option value="2"> something different </option>
<option value="3"> complete other text </option>
</select>
so when I try it with selectfield.value I get the value parameter, but I need the text. Is there any way I can get this text and let the value be still a number?
I think you might be looking for innerHTML have a look at, http://www.w3schools.com/jsref/prop_html_innerhtml.asp
You would need to assign an id to each option like:
<option id="option-1" value="1">Inner text</option>
...
<script>
var innerText = document.getElementById('option-1').innerHTML;
</script>
That answer above it a little tricky, so here's what i did:
<script>
function test() {
var x = document.getElementById('selectfield').selectedIndex;
alert(x);
}
</script>
and the HTML:
<select id="selectfield" onChange="test()">
<option value="0"></option>
<option value="1"> something </option>
<option value="2"> something different </option>
<option value="3"> complete other text </option>
</select>
Notice a few differences here. First, in the javascript, a DOM command called '.selectedIndex' which gets the option selected in the box.
Now for what I did to the HTML, Notice a couple of things. First, you have an event Handler called onChange which calls the function i created called test(). I also added a blank option so that if someone wanted to choose the first one they could, and not have to click the second option and then the first to get that particular choice. Honestly, those value="" attributes are not necessary now.
If you run the code, you might notice that instead of returning text, it returns a number. "A number?" you might ask, "I wanted the text!". Here is a solution I have for you:
var option_Array = [];
option_Array[0] = "";
option_Array[1] = "something";
option_Array[2] = "something different";
option_Array[3] = "complete other text";
Suppose you had an array of the options, now all you would have to do is use the variable x as the index number of the array like so:
option = option_Array[x];
Now the new variable option is equal to whatever item you clicked!
I hope this fully answers your question. I would appreciate any feedback on this answer, as it is 1:10 AM and I'm not perfect.
Just as a side note, it might be a good idea to put a parseInt() around
var x = parseInt(document.getElementById('selectfield').selectedIndex); just in case it returns x as a string instead of a real integer.

Not send GET variable on submit if dropwdown not selected

I have a form that I used to filter search results that consist of only dropdowns. I use GET rather then post so that the results can easily be shared with the URL.
<form action="" name='filter' method="GET">
<select name="Make" id="Make">
<option selected="selected" value ="nothing">All</option>
<option value="Toyota">Toyota</option>
<option value="Honda">Honda</option>
</select>
<input type="submit" value="Filter">
</form>
As it is right now if It will submit the value "nothing" for the get variable Make if the user doesn't change the selection. They're are multiple drop downs identical as this one for model year etc.
Is it possible for the Make variable to not show up in the URL if it isn't used?
As it is now if that code is submited it will say website.com/?Make=nothing. I tried removing the value and then it says website.com/?Make=All. I do not want make to show up in the URL if "All" is selected. Is this possible?
You don't have a submit button :)
you can add a JS that runs on submit and checks the value of "Make" and in case it's "nothing" just do a simple redirect instead of submitting the form. Something like:
var e = document.getElementById("Make");
var val = e.options[e.selectedIndex].value;
if (val === 'nothing'){
window.location = "http://www.google.com/"
}

Do checkbox inputs only post data if they're checked?

Is it standard behaviour for browsers to only send the checkbox input value data if it is checked upon form submission?
And if no value data is supplied, is the default value always "on"?
Assuming the above is correct, is this consistent behaviour across all browsers?
Yes, standard behaviour is the value is only sent if the checkbox is checked. This typically means you need to have a way of remembering what checkboxes you are expecting on the server side since not all the data comes back from the form.
The default value is always "on", this should be consistent across browsers.
This is covered in the W3C HTML 4 recommendation:
Checkboxes (and radio buttons) are on/off switches that may be toggled
by the user. A switch is "on" when the control element's checked
attribute is set. When a form is submitted, only "on" checkbox
controls can become successful.
In HTML, each <input /> element is associated with a single (but not unique) name and value pair. This pair is sent in the subsequent request (in this case, a POST request body) only if the <input /> is "successful".
So if you have these inputs in your <form> DOM:
<input type="text" name="one" value="foo" />
<input type="text" name="two" value="bar" disabled="disabled" />
<input type="text" name="three" value="first" />
<input type="text" name="three" value="second" />
<input type="checkbox" name="four" value="baz" />
<input type="checkbox" name="five" value="baz" checked="checked" />
<input type="checkbox" name="six" value="qux" checked="checked" disabled="disabled" />
<input type="checkbox" name="" value="seven" checked="checked" />
<input type="radio" name="eight" value="corge" />
<input type="radio" name="eight" value="grault" checked="checked" />
<input type="radio" name="eight" value="garply" />
Will generate these name+value pairs which will be submitted to the server:
one=foo
three=first
three=second
five=baz
eight=grault
Notice that:
two and six were excluded because they had the disabled attribute set.
three was sent twice because it had two valid inputs with the same name.
four was not sent because it is a checkbox that was not checked
six was not sent despite being checked because the disabled attribute has a higher precedence.
seven does not have a name="" attribute sent, so it is not submitted.
With respect to your question: you can see that a checkbox that is not checked will therefore not have its name+value pair sent to the server - but other inputs that share the same name will be sent with it.
Frameworks like ASP.NET MVC work around this by (surreptitiously) pairing every checkbox input with a hidden input in the rendered HTML, like so:
#Html.CheckBoxFor( m => m.SomeBooleanProperty )
Renders:
<input type="checkbox" name="SomeBooleanProperty" value="true" />
<input type="hidden" name="SomeBooleanProperty" value="false" />
If the user does not check the checkbox, then the following will be sent to the server:
SomeBooleanProperty=false
If the user does check the checkbox, then both will be sent:
SomeBooleanProperty=true
SomeBooleanProperty=false
But the server will ignore the =false version because it sees the =true version, and so if it does not see =true it can determine that the checkbox was rendered and that the user did not check it - as opposed to the SomeBooleanProperty inputs not being rendered at all.
If checkbox isn't checked then it doesn't contribute to the data sent on form submission.
HTML5 section 4.10.22.4 Constructing the form data set describes the way form data is constructed:
If any of the following conditions are met, then skip these substeps
for this element:
[...]
The field element is an input element whose type
attribute is in the Checkbox state and whose checkedness is false.
and then the default valued on is specified if value is missing:
Otherwise, if the field element is an input element whose type attribute is in the Checkbox state or the Radio Button state, then run these further nested substeps:
If the field element has a value attribute specified, then let value be the value of that attribute; otherwise, let value be the string "on".
Thus unchecked checkboxes are skipped during form data construction.
Similar behavior is required under HTML4. It's reasonable to expect this behavior from all compliant browsers.
Checkboxes are posting value 'on' if and only if the checkbox is checked. Insted of catching checkbox value you can use hidden inputs
JS:
var chk = $('input[type="checkbox"]');
chk.each(function(){
var v = $(this).attr('checked') == 'checked'?1:0;
$(this).after('<input type="hidden" name="'+$(this).attr('rel')+'" value="'+v+'" />');
});
chk.change(function(){
var v = $(this).is(':checked')?1:0;
$(this).next('input[type="hidden"]').val(v);
});
HTML:
<label>Active</label><input rel="active" type="checkbox" />
Is it standard behaviour for browsers to only send the checkbox input
value data if it is checked upon form submission?
Yes, because otherwise there'd be no solid way of determining if the checkbox was actually checked or not (if it changed the value, the case may exist when your desired value if it were checked would be the same as the one that it was swapped to).
And if no value data is supplied, is the default value always "on"?
Other answers confirm that "on" is the default. However, if you are not interested in the value, just use:
if (isset($_POST['the_checkbox'])){
// name="the_checkbox" is checked
}
None of the above answers satisfied me.
I found the best solution is to include a hidden input before each checkbox input with the same name.
<input type="hidden" name="foo[]" value="off"/>
<input type="checkbox" name="foo[]"/>
Then on the server side, using a little algorithm you can get something more like HTML should provide.
function checkboxHack(array $checkbox_input): array
{
$foo = [];
foreach($checkbox_input as $value) {
if($value === 'on') {
array_pop($foo);
}
$foo[] = $value;
}
return $foo;
}
This will be the raw input
array (
0 => 'off',
1 => 'on',
2 => 'off',
3 => 'off',
4 => 'on',
5 => 'off',
6 => 'on',
),
And the function will return
array (
0 => 'on',
1 => 'off',
2 => 'on',
3 => 'on',
)
input type="hidden" name="is_main" value="0"
input type="checkbox" name="is_main" value="1"
so you can control like this as I did in the application.
if it checks then send value 1 otherwise 0
From HTML 4 spec, which should be consistent across almost all browsers:
http://www.w3.org/TR/html401/interact/forms.html#checkbox
Checkboxes (and radio buttons) are on/off switches that may be toggled
by the user. A switch is "on" when the control element's checked
attribute is set. When a form is submitted, only "on" checkbox
controls can become successful.
Successful is defined as follows:
A successful control is "valid" for submission. Every successful
control has its control name paired with its current value as part of
the submitted form data set. A successful control must be defined
within a FORM element and must have a control name.
I have a page (form) that dynamically generates checkbox so these answers have been a great help. My solution is very similar to many here but I can't help thinking it is easier to implement.
First I put a hidden input box in line with my checkbox , i.e.
<td><input class = "chkhide" type="hidden" name="delete_milestone[]" value="off"/><input type="checkbox" name="delete_milestone[]" class="chk_milestone" ></td>
Now if all the checkboxes are un-selected then values returned by the hidden field will all be off.
For example, here with five dynamically inserted checkboxes, the form POSTS the following values:
'delete_milestone' =>
array (size=7)
0 => string 'off' (length=3)
1 => string 'off' (length=3)
2 => string 'off' (length=3)
3 => string 'on' (length=2)
4 => string 'off' (length=3)
5 => string 'on' (length=2)
6 => string 'off' (length=3)
This shows that only the 3rd and 4th checkboxes are on or checked.
In essence the dummy or hidden input field just indicates that everything is off unless there is an "on" below the off index, which then gives you the index you need without a single line of client side code.
.
Just like ASP.NET variant, except put the hidden input with the same name before the actual checkbox (of the same name). Only last values will be sent. This way if a box is checked then its name and value "on" is sent, whereas if it's unchecked then the name of the corresponding hidden input and whatever value you might like to give it will be sent. In the end you will get the $_POST array to read, with all checked and unchecked elements in it, "on" and "false" values, no duplicate keys. Easy to process in PHP.
Having the same problem with unchecked checkboxes that will not be send on forms submit, I came out with a another solution than mirror the checkbox items.
Getting all unchecked checkboxes with
var checkboxQueryString;
$form.find ("input[type=\"checkbox\"]:not( \":checked\")" ).each(function( i, e ) {
checkboxQueryString += "&" + $( e ).attr( "name" ) + "=N"
});
in your post
'your_field': your_field.is(':checked'),
I resolved the problem with this code:
HTML Form
<input type="checkbox" id="is-business" name="is-business" value="off" onclick="changeValueCheckbox(this)" >
<label for="is-business">Soy empresa</label>
and the javascript function by change the checkbox value form:
//change value of checkbox element
function changeValueCheckbox(element){
if(element.checked){
element.value='on';
}else{
element.value='off';
}
}
and the server checked if the data post is "on" or "off". I used playframework java
final Map<String, String[]> data = request().body().asFormUrlEncoded();
if (data.get("is-business")[0].equals('on')) {
login.setType(new MasterValue(Login.BUSINESS_TYPE));
} else {
login.setType(new MasterValue(Login.USER_TYPE));
}