HTML5 datalist value vs. inner-text - html

I have an issue that is manifesting between Chrome and Firefox's handling of the HTML5 datalist element.
I may be abusing it, which Firefox is handling the way I expect, but Chrome is not. I have not tried it on Opera. This is for an in-house page, so I can control the browser being used.
I set a value, as well as the inner-text, as in:
<input list="Names" placeholder="Enter Name or ID" name="txtSearchValue" autocomplete="off"/>
<datalist id="Names"><%=OptionsList%></datalist>
The server-side value "OptionsList" gets built dynamically from a database query. The end result looks, approximately, like this:
<option value="123">Sam's Fresh Sandwiches</option>
<option value="234">Sawatdee</option>
etc.
On Firefox, I can type the letters "S" then "A" (case insensitive) and both of the above entries will appear. As soon as I type a "W" or select Sawatdee with the mouse, the text box is populated with 234. This is what I desire to have happen - as I want 234 sent back to the server and not Sawatdee. It also works if I type "A" then "T".
On Chrome, I can type all the letters I want, but nothing will appear in the list. However, if I type a 2, only the second entry will appear; but in the list it will show a 2 followed by Sawatdee.
Am I over-using/abusing the datalist or does Chrome have a problem with it? Or is Chrome handling it as it is technically supposed to and I've found a Firefox bug?

I'm trying to do something similar. I think the issue is the datalist isn't spec'ed to work like a dropdown option list. One work around is that you generate both an <%=OptionsList%> and then an array <%=OptionListValues %>...so once you get the text value in your input, you can use javascript to look for it's key in the OptionListValues and send the key instead of the description back to the server. Pain in the rear and adds an extra data load on the client side, though I guess you could do this server side as well (send the text in the input and then lookup the text and get the key on the server side).
Too bad Chrome doesn't work like FF on this, maybe in the future the browsers will work like Mozilla on this.
Or you can do something like this. Say you have the following input/datalist
<input id="datalisttestinput" list="stuff" ></input>
<datalist id="stuff">
<option id="3" value="Collin" >
<option id="5" value="Carl">
<option id="1" value="Amy" >
<option id="2" value="Kristal">
</datalist>
You can use jQuery (or plain javascript) to dig out the id value...here is my example, I'm sure this could be optimized a bit.
function GetValue() {
var x = $('#datalisttestinput').val();
var z = $('#stuff');
var val = $(z).find('option[value="' + x + '"]');
var endval = val.attr('id');
alert(endval);
}
That should get you going.

Slightly modifying infocyde's answer to use a hidden field to contain the value which ultimately gets sent to the server.
$('#inputStates').change(function(){
var c = $('#inputStates').val();
$('#inputStates').val(getTextValue());
$('#statesHidden').val(c);
});
function getTextValue(){
var val = $('#inputStates').val();
var states = $('#states');
var endVal = $(states).find('option[value="' + val + '"]');
//depending on your logic, if endVal is empty it means the value wasn't found in the datalist, you can take some action here
return endVal.text();
}

Related

Best accessible way to show a default for a form field

What's the best/recommended way to indicate a form field will have a particular default value if you don't fill it out? I'm especially thinking about fields that are dynamic based on other fields, and wanting it to be correctly accessible.
Think a URL slug. When creating an account, if you fill the field out then that's fine. If you don't, a value will be generated based on your username. But it won't be the same as your username, just generated from it.
Actually setting the form field seems bad because it makes it less obvious you can change it yourself.
I'm not sure if placeholder text works here, but I assume not. I could do an aria-labelledby pointing to something that says "Default value: xyz" but I'm not sure if that will work, or how well it will be understood by screen readers - especially if it's changing automatically.
Cheers
The best way to do this is to populate the input and expose the fact that it was automatically filled in via the label as an extra bit of information.
Labels on inputs are read once you focus the related input.
For this reason we can generate labels "on the fly" to contain whatever we want.
As such the best option here would be to generate the label on blur of the first input that the second input depends on.
Within the label we add the instructions that explain why this input is already filled in.
We then auto populate the second input based on the input of the first.
In the below example I have appended "URL" to the first input value in order to simulate some sort of transformation from username to URL.
I also remove the explanation in parenthesis if the user has changed the second input value.
$('#iUsername, #iUserURL').on('blur', function(){
var ElUserName = $('#iUsername');
var ElUserURL = $('#iUserURL');
if(ElUserURL.val() == ""){
ElUserURL.val(ElUserName.val() + "URL");
$('label[for="iUserURL"]').text("user url (you can change this if you want, we have set it as " + $('#iUsername').val() + "URL)");
}else if(ElUserURL.val() != ElUserName.val() + "URL"){
$('label[for="iUserURL"]').text("user url");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="iUsername">User Name</label><br/>
<input id="iUsername" /><br/>
<hr/>
<label for="iUserURL">User URL</label><br/>
<input id="iUserURL" /><br/>
<hr/>
<label for="itest">I have added this third input just so you have something to tab too, it does not add anything to the fiddle</label><br/>
<input id="itest" />

How to tell Chrome form does not contain credit card fields?

Chrome is being overzealous and thinks my HTML form contains credit card information and thus proposes to fill it in with credit card information.
Are there any attributes that I can use to tell Chrome that there is no credit card information to be filled in, in this form?
The field names it is trying fill in credit card information in are:
reg_id (it puts in a CC number here)
emergency_first_name (it puts in first name here)
emergency_last_name (it puts in last name here)
I don't want to have to disable autocomplete if I don't have to.
The frustrating thing here is the Chrome 'knows better' attitude, where it ignores any value to autocomplete, including off:
<input autocomplete="off" value="" size="10" maxlength="10" id="id_reg_id" name="reg_id" type="text">
Edit: updated following answers.
try
input type="custom"
or use textarea with a single row and resize off
Your browser shouldn't remember your credit card number by default -- I can only assume that you entered into a field that had a 'generic' autocomplete value on it. You can always force your browser to forget this information by simply hitting Delete when selecting it (with the arrow keys) in the dropdown of pre-fill options.
As for preventing it appearing in certain fields, it depends on what information you want each field to hold, but there's a wide array of autocomplete values that you can use. You can use number for IDs, and the other two fields you mentioned actually come with specialised autocomplete values, given-name and family-name:
<input name="reg_id" autocomplete="number" />
<input name="emergency_first_name" autocomplete="given-name" />
<input name="emergency_last_name" autocomplete="family-name" />
If number just won't cut it, you can also make use of a JavaScript regular expression to further restrict input:
const regex = new RegExp("^[a-zA-Z]+$");
const form = document.getElementsByTagName('form')[0];
const reg_id = document.getElementsByTagName('input')[0];
form.addEventListener('click', function(e) {
e.preventDefault();
if (regex.test(reg_id)) {
this.submit();
}
});
<form>
<input name="reg_id" autocomplete="number" />
<input name="emergency_first_name" autocomplete="given-name" />
<input name="emergency_last_name" autocomplete="family-name" />
</form>
I have been banging my head against the desk for a while because of this. We have forms to enter Instruments test data, and a field called "Test Card Number", as well as "Kit (Exp. Date)". Guess what Chrome thinks these fields are for?
Needless to say, I'm pretty sure the users would be VERY upset to see chrome us trying to pull their CC information when they're inputing clinical research data.
Even autocomplete="new-password" and autocomplete="nope" are failing to do any good, here.
I tried to load the field with no label and add it dynamically in javascript. No dice. Used html entities instead of characters. Nope.
Well, after a few hours of scouring the web with no solution in sight, I figured one out: insert a few random - within each word of the offending labels. (For me, with Test Card Number, it had to be in BOTH Card and Number. Test was fine left alone).
One could easily write a javascript extension/utility function to split the html of an offending label and slap that invisible span down the middle (and one to remove it in case of needing to use the label value).
Something like this (using jQuery and old js standards because we support old browsers, with no verifications if label is missing or empty, so adapt accordingly. In fact, I'm sure a regex or some other fancy stuff could be used, but I don't have the time to fiddle around with it atm):
jQuery.fn.breakAutofill = function () {
var $lbl = $("label[for='" + this[0].id + "']"),
finalText = $lbl.html().split(" "),
foilSpan = "<span style='display:none;'>-</span>";
for (var idx in finalText) {
var textVal = finalText[idx],
midPos = Math.floor(textVal.length / 2);
finalText[idx] = textVal.substr(0, midPos) + foilSpan + textVal.substr(midPos);
}
$lbl.html(finalText.join(" "));
}
Which you can then call on document ready :
$("your_input_selector").breakAutofill();
I hope that helps someone.

HTML5 Input tag : what if max,min,step do not fit with each other

Let's say you had a job to provide the user with a <input> as this:
<input type="number" min="1" max="11" step="3" value="1"></input>
the result would be increased as this sequence : 1,4,7,10,(13).
you can never see "13" in the box because this number exceeds the maximum value it allows("11"). The max value you can get in this box is 10.
But what if the maximum number you want to show to the user is 11, as specified in your code ?
the expected sequence is like this : 1,4,7,10,11
How to make it ?
Thanks.
EDIT :
Here's a demonstration for the question.
The step attribute respects the max, but also restricts the input. If you need more flexibility, try this:
<input list="numbers">
<datalist id="numbers">
<option value="1">
<option value="4">
<option value="7">
<option value="10">
<option value="11">
</datalist>
On second thought, that's not great - I would just use the good old-fashioned select tag:
<select>
<option>1<option>
<option>4<option>
<option>7<option>
<option>10<option>
<option>11<option>
</select>
to get closer to your example. If your data set is contrived to demonstrate a point, these alternatives can be generated programmatically jsut as easy as the one in your example.
This is simply not possible using straight HTML5.
There's no HTML5 number feature that increments by 3s and switch to 1s near the last number. HTML rarely deviates from its established rules, no matter what our needs are. And step has pretty strict rules with no similar HTML5 alternatives. You will have to use Javascript or a <select> dropdown.
Easy Imperfect Solution
You can use some Javascript to make this happen. This example uses jQuery in a ready event:
$('input').change(function(){
var $input = $(this), val = $input.val();
if (val == 13) {
$input.attr("step","1");
$input.val(11);
} else if (val == 10) {
$input.attr("step","3");
} else if (val == 12) {
$input.val(11);
}
});
Demo: http://jsfiddle.net/fpm21ej2/1/
There is a flash of the incorrect number "13" right before it changes to "11". I don't know of an event that would intercept this faster though, making this solution imperfect.
Harder Better Solution
Create a custom text field to mimick this incrementing behavior, but using your special number sequence. That means take a number box, add in some up/down buttons (possibly with sprite images), use Javascript to bind them to events that increment this as expected, and validate against the user entering invalid numbers (use the HTML5 pattern attribute).
That will probably take some work, and it needs a bit more time than most of us can volunteer here at StackOverflow. But this should be possible.
Easy Better Solution
Use a <select> dropdown.

How do you implement custom autocomplete list in html?

I am trying to understand a simple auto-search result textbox.
Now, I have setup javascript events to make the ajax call and fetch the search result from the server, as the user types a string in the textbox, and store it in an array. So, I have a javascript array that contains my search result.
var searchResult = [
"Accordion Company",
"A Little Mouse",
"Another Time",
"ASIO"
];
I want to attach this list to some property(or something else) of the textbox so that my list appears as a dropdown as the user types.
Does a textbox even allow that? What HTML control/property allows the autocomplete list to appear?
Background:
1) I have worked with jQueryUI and all of this can be achieved very easily there. I am interested in learning how is the inherent property of a textbox overriden to show the autocomplete result? If I strip down everything to simple HTML and javascript how is this achieved? Or is it just an HTML/CSS trick that looks like a dropdown
2) I have looked into vCard too but couldn't figure out how will I override a vCard array with my javascript array that contains the search result.
Just trying to understand whether I can tell my INPUT type="text" control to show a custom autocomplete list.
Thanks!
There is the list attribute and the associated datalist tag
<input list="things">
<datalist id="things">
<option value="Some">
<option value="No">
<option value="Any">
</datalist>
You can take your array and build a datalist element.
datalist is html5 so support might be a problem.

Resulting request for input type="image" forms

Web developers can use <input type="image" name="name"> to present their users a graphical submit button. The w3 standard on html forms regarding input controls states that
When a pointing device is used to click on the image, the form is submitted and the click coordinates passed to the server. The x value is measured in pixels from the left of the image, and the y value in pixels from the top of the image. The submitted data includes name.x=x-value and name.y=y-value where "name" is the value of the name attribute, and x-value and y-value are the x and y coordinate values, respectively.
Now, I know that Firefox will generate a request that contains name itself, whereas Internet Explorer does not. my question, is Firefox providing additional functionality on top of the standard, does Internet Explorer not implement the full standard correctly (happened in the past …) or is the standard simply unclear regarding this aspect?
edit
It looks like Firefox creates a weird request (or it is parsed in a strange way by PHP). if the input name is an array (i.e. name[1]) the resulting $_POST variable will contain: ["name"] => array(1) { [1]=> string(2) "57" }. so the .x component is munged and the .y component is turned into the only value …
edit 2
Upon further investigation it looks like even Firefox does not send the control's name when it's of type image, even with the value attribute set …
addendum
It seems like that what I really want to know is how I can make use of <input type="image" name="el[]" /> elements when the name is an array, without messing up the POST request.