In HTML, what should happen to a selected, disabled option element? - html

In my specific example, I'm dealing with a drop-down, e.g.:
<select name="foo" id="bar">
<option disabled="disabled" selected="selected">Select an item:</option>
<option>an item</option>
<option>another item</option>
</select>
Of course, that's pretty nonsensical, but I'm wondering whether any strict behaviour is defined. Opera effectively rejects the 'selected' attribute and selects the next item in the list. All other browsers appear to allow it, and it remains selected.
Update: To clarify, I'm specifically interested in the initial selection. I'm dealing with one of those 'Select an item:'-type drop-downs, in which case the first option is really a label, and an action occurs onchange(). This is fairly well 'progressively enhanced', in that a submit button is present, and only removed via JavaScript. If the "select..." option were removed, whatever then were to become the first item would not be selectable. Are we just ruling out onchange drop downs altogether, or should the "select..." option be selectable, just with no effect?

The HTML specs are a bit vague (ie. completely lacking) with regard to this odd combination. They do say that a form element with the disabled attribute set should not be successful, so it really can't be selected.
The browser may well render it so that it looks selected, but it shouldn't show up in the POSTed data. Looks like Opera's got it right to me.

The HTML specs state that both selected & disabled are available options for the <option> element, but doesn't specify what should happen in case of a conflict. In the section on disabled controls it says
When set, the disabled attribute has
the following effects on an element:
Disabled controls do not receive focus.
Disabled controls are skipped in tabbing navigation.
Disabled controls cannot be successful.
it also says
How disabled elements are rendered depends on the user agent. For example, some user agents "gray out" disabled menu items, button labels, etc. In this example, the INPUT element is disabled. Therefore, it cannot receive user input nor will its value be submitted with the form.
While this specific case isn't specified, my reading of this says that the actual rendering of a 'selected' 'disabled' element is left up to the browser. As long as the user cannot select it then it's working as standard. It does say that a script can act upon the element, so it is possible for Javascript to set a disabled option as selected (or disable a selected option). This isn't contrary to the standards, but on form submission, that option's value couldn't be the selected value. The select list would (I assume) have to have an empty value in this case.

In reply to the update in the question, I would say that the 'label' option should be selectable but either make it do nothing on submission or via JavaScript, don't allow the form to be submitted without a value being selected (assuming it's a required field).
From a usablilty point of view I'd suggest doing both, that way all bases are covered.

According to the HTML 4.01 Specification, disabled is a standard attribute for the option element, but behavior is probably indeterminate based on the standard (read over the information on the select element and the options elements. Here is a portion I think may shed light on Opera's reasons for their implementation:
When set, the disabled attribute has the following effects on an element:
* Disabled controls do not receive focus.
* Disabled controls are skipped in tabbing navigation.
* Disabled controls cannot be successful.
So, it is very likely that this is just one of those things where the spec is vague enough to allow for both interpretations. This is the kind of idiosyncrasy that makes programming for the web so fun and rewarding. :P

Are we just ruling out 'onchange' drop
downs altogether, or should the
"select..." option be selectable, just
with no effect?
"onchange" drop-downs are frowned upon by more standards-obsessed types.
I would typically do some client-side validation. "Please select an item from the drop down" kind of thing. i.e.
should the "select..." option be selectable, just with no effect?
So I just said "Yes" to your A or B question. :/ Sorry!

unfortunately it doesn't really matter what should happen, because IE doesn't support the disabled attribute on options period.
http://webbugtrack.blogspot.com/2007/11/bug-293-cant-disable-options-in-ie.html

Related

Disable browsers Form inputs prefill/autofill feature when hitting "back" button

I want to "prevent browsers from prefilling form inputs when hitting the "back" button". Indeed, I want the initial values to be filled in (added via jsp), not the browser's (cached) values.
Solution 1: I found out that this can be done by disabling the browser caching for the current page. This seems a rather extreme solution considering that I "only" want to disable this prefill feature for a "form" (hence disable caching for the form only, not the whole page).
Solution 2: Then, the obvious next solution is to use javascript: that is, store the initial value in a data-* attribute, then, on page load, replace the input value by the initial value if they differ.
Both solutions seem rather unperfect (these are rather work arounds) I turn to you guys hoping to hear of a better one.
Resources:
How does SO's form remember previous input values?
Disable Firefox's Auto-fill
Pressing back prefills inputs with value from right before submit
HTML form values and 'Back' button
The first thing that comes to my mind is to use a <input type="reset"> button. These aren't seen often nowadays because the user rarely actually wants to reset the form, but here it might just be what you need.
You could also do it in javascript on page load with form.reset(); instead of providing a button for the user.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement.reset
This is similar to your solution 2 and thus still a workaround of the browser behavior, but it is a(n old) part of standard forms and I think it'll do the trick with very little additional code (no need for data-* attributes), so wanted to throw it out there.

In what authorative specification is the onChange event exhaustively defined?

I was slightly surprised to find out that the onChange event in an html document is fired on a text input or textarea not at the very moment when its value actually changes, but only when focus leaves the element (if its value has changed, of course).
So I was looking for the specification that states that, and I can't find it. I can find millions of tutorials explaining that, including W3Schools' ones, but I can't find the standard that defines when the event is expected to be fired.
In the HTML5 specification itself, the event's name is listed but nothing is said about it:
http://www.w3.org/html/wg/drafts/html/master/
In this other spec, "DOM level 3 Events Specification", it is not even mentioned:
http://www.w3.org/TR/DOM-Level-3-Events/
So what is the standard that defines it?
It's briefly mentioned in the Intrinsic events section of the W3C 4.01 specification:
"The onchange event occurs when a control loses the input focus and its
value has been modified since gaining focus".
It's also mentioned a little more extensively on MSDN:
"This event is fired when the contents are committed and not while the
value is changing. For example, on a text box, this event is not fired
while the user is typing, but rather when the user commits the change
by leaving the text box that has focus.
In addition, this event is executed before the code specified by onblur when the control is also
losing the focus."
Finally, on the MDN:
Depending on the kind of the form element being changed and the way
the user interacts with the element, the change event fires at a
different moment:
When the element is activated (by clicking or using the keyboard) for <input type="radio"> and <input type="checkbox">;
When the user commits the change explicitly (e.g. by selecting a value from a <select>'s dropdown with a mouse click, by selecting a date from a date pickier for <input type="date">, by selecting a file
in the file picker for <input type="file">, etc.);
When the element loses focus after its value was changed, but not committed (e.g. after editing the value of <textarea> or <input type="text">).
Another potentially useful link - WhatWg - specification - change event.

How do I create fully accessible nested dropdown lists using WAI-ARIA?

A few days ago, I have started searching on the Internet for tutorials and documentation about WAI-ARIA for just about any kind of AJAX requests.
I am used to coding nested dropdown lists using jQuery and AJAX. It works pretty well but is not natively accessible. We need to use WAI-ARIA specific tags to "enable" accessibility for all kind of dynamic stuffs like AJAX, for instance.
One of my requirements is the following:
Let's say I have a State dropdown that updates a Region dropdown using the onchange event. How can I interact with the screen reader using WAI-ARIA and jQuery in order to tell the user that the Region dropdown list has been updated?
My 2c is that aria-controls may be a better fit here.
The UI you are describing here sounds very similar to the Country/State selects that you often find when purchasing a product online. A typical pattern for these is:
<label for="country">Country:</label>
<select id="country" aria-controls="state">
<option value="">Select a country...</option>
<option value="Andorra">Andorra</option>
<option value="Belgium">Belgium</option>
...
</select>
<br>
<label for="state">State:</label>
<select id="state">
<option value="">(Select a country first)</option>
... options here populated when country changes ...
</select>
A couple of things to note here:
I'm using 'placeholder' option entries at the start of each select. This has two benefits. First, it provides reinforcement documentation about how the user should use the UI - if they somehow end up looking at the second field first, it will direct them to the first one. Secondly, it avoids the user accidentally selecting a default value: your code can check if the default 'Select...' is the one submitted and remind the user to pick an actual value. And, additionally, it hides the fact that the contents options are changing from the user.
The main thing here, though, is that the relationship between these two selects should be clear from context in the form or page. Sighted or not, a user who encounters a form like this won't need to be explicitly told that the contents of the state select have changed, because they'll expect that from the form design, and from the context. People know that states are specific to a country (there's no "California" in Germany, for example), similarly with counties, so there's already an expectation of how these work.
Use of aria-live doesn't feel like it's appropriate here. It's really designed for areas of the page that update asynchronously, and which the user would otherwise have to poll continuously, reading back and forth, to scan for changes. Chat panels are perhaps the classic example: when a message appears from someone on the other end, you want the screenreader to read out the message when it appears, and not have to manually go hunting for it. By contrast, the UI here is more synchronous; when the country changes, the states are populated there and then(*), it's expected behavior.
ARIA does have an aria-controls="ids..." attribute, which seems to be a better fit: the spec says it's used for when one control affects the visibility or contents of another, which seems to describe what's happening here. I don't know offhand whether any screenreaders support this yet or what they would read out when its present - I may look into this and update this answer later. But in any case, the main point from earlier applies, the form's behavior and semantics should be apparent without this anyhow.
--
(*) There's still an issue that if you update the content asynchronously - eg. by getting the list of counties via ajax rather than from an array that's already loaded on the page, then there could be a delay between selecting the country and the results becoming available for use in the next select. aria-live doesn't feel like the right solution here again, since you don't want to read out the new content, you just want to let the user know that the select is now ready for use.
For this use case, I would add aria-live and aria-atomic attributes, example code:
<select id="foo" aria-live="assertive" aria-atomic="true">
<option value="nw">Northwest</option>
<option value="ne">Northeast</option>
<option value="se">Southeast</option>
<option value="sw">Southwest</option>
</select>
I think assertive is the right value for the aria-live attribute, but polite might be appropriate instead. The aria-atomic attribute is there to tell the browser/AT that region must be presented as a whole when there is a change. You might also consider using aria-disabled: true on the select initially, then switch it to false before you update it with the values associated with the State select.
Edit
OK, I've done some testing using NVDA and IE9 and Firefox 13.01. I don't have JAWS available at the moment, so it'd be great if someone could test the page with JAWS.
VoiceOver as far as I know doesn't have support for aria properties yet Just tested with Chrome + Voiceover on 10.7 (Lion) and Voiceover does indeed appear to have support for aria-live.
Test page available here.
I used a simple script that simulated loading data into the regions select (using an object):
var options = [],
regions = {
'nw': 'Northwest',
'ne': 'Northeast',
'se': 'Southeast',
'sw': 'Southwest'
}
$(document).ready(function() {
$.each(regions, function(key, value) {
options.push('<option value="'+ key +'">'+ value +'</option>');
});
$('.block').on('change, focusout', '.states', function() {
$(this).parent().children('.regions')
.attr({'disabled': false, 'aria-disabled': false})
.html(options.join(''));
});
window.setTimeout(
function() {
$('#speak').text('assertive!');
},
3000
);
});
Some observations after playing with this a bit (I'm certainly no expert when it comes to screen readers, so if I missed something let me know)...
Using the HTML disabled attribute is not advised as you really don't want to load the region data until the state select is focused out and since the associated region select is disabled at the time of the focusout it is skipped when tabbing to the next control (you can hear this in the recordings below.) Strangely, Firefox announces the value of the region select even though it doesn't focus it.
I saw no difference in behavior between polite and assertive, or for that matter in the example without the aria-live attribute. I thought that both FF13 and IE9 had support for aria-live, but from the last but of code ($('#speak')...) it appears that IE9 doesn't?
Perhaps a delay to simulate loading via AJAX would be a good thing to add.
You can listen to the recordings: IE9, Firefox 13

Does the handling of hidden form controls in HTML5 make sense?

HTML5 added in the ability to better define client-side validation in forms without needing to use JavaScript. The concept already existed with attributes such as "maxlength" and "minlength". It's been extended with attributes such as "required" and "pattern". However, HTML5 has also defined limits on these attributes and WebKit browsers have implemented these restrictions (likely with Firefox and Opera not far behind).
The restrictions in question have to do with a form control's visibility when hidden by CSS / JavaScript using the display: none or visibility: hidden CSS rules. The restrictions are defined as:
4.10.7.1.1 Hidden state
When an input element's type attribute is in the Hidden state [...] The input element represents a value that is not intended to be examined or manipulated by the user.
[Also,]
The value IDL attribute applies to this element and is in mode default.
The following content attributes must not be specified and do not apply to the element: accept, alt, autocomplete, checked, dirname, formaction, formenctype, formmethod, formnovalidate, formtarget, height, list, max, maxlength, min, multiple, pattern, placeholder, readonly, required, size, src, step, and width.
The following IDL attributes and methods do not apply to the element: checked, files, list, selectedOption, selectionStart, selectionEnd, selectionDirection, valueAsDate, and valueAsNumber IDL attributes; select(), setSelectionRange(), stepDown(), and stepUp() methods.
The input and change events do not apply.
At first glance, it makes sense to say that validation shouldn't need to be performed on form controls that the user has no control over. And, for form's built using default form control elements, these make sense. But now, an issue has arisen with building remote form controls.
Neither HTML5 nor CSS3 (nor the major browsers) has made it much easier to style form controls. <select> elements are still greatly restricted in terms of styling and both <input> and <button> elements have annoyingly different styling rules (and for non-IE browsers, near impossible CSS browser-targeting). As such, when my designers want "pretty" form controls, they may need to be rebuilt using HTML, CSS, and JavaScript. The simulated control will remotely control the real control which is hidden by CSS. This applies to <select>, <input type="checkbox"> and <input type="radio"> elements for me, all of which cause an issue in WebKit browsers when given the required attribute.
Since the HTML5 specification states that certain attributes, such as required, cannot exist on hidden form controls, browsers will be required to respond to invalid attributes. WebKit browsers are responding by not submitting the form at all (and not triggering JavaScript's submit event). I am running into the error right now with a <select> element.
Chrome fails with this error to the console:
An invalid form control with name='element-name' is not focusable.
Safari fails by showing a grey bar at the bottom of the window with the message:
Please select an item in the list
So, my concern is whether HTML5 is too restricting or I am approaching this issue incorrectly. Either:
HTML5's specification is flawed and adds an extra restriction without another solution. HTML5 assumes that if a form control is not visible, the user should not be able to interact with it. This prevents developers from utilizing HTML5's validation attributes for elements that we control remotely while leaving the original form control hidden. We still don't have the ability to create our custom controls using only CSS which requires that we still build them ourselves.
I am handling remote form controls incorrectly. as I am using an "old" technique to solve a problem that very well may have been redefined, it's possible that my approach is outdated. It's also possible that, since WebKit are the only one handling this restriction at the moment, WebKit has a workaround for this that I haven't found yet.
The only workarounds that I can think of at the moment are to
Remove the restricted attributes whenever I dynamically hide a form control with JavaScript, which would mean that I sacrifice HTML5's validation,
Temporarily display and immediately hide the offending form controls, though I'm unsure when this would be done since the submit event is never fired and it's possible to submit a form without firing the click event on the submission button, or
Use the novalidate attribute, though I'd still lose the HTML5 validation.
So am I looking at this correctly or am I missing something?
First you do mix up two things. If the HTML5 specification says hidden state, the specification only means an input element with an type attribute set to the value "hidden". In this case, the input is not validated, which means, the input can not be invalid. And the browser does not abort form submission.
Your problem is another one. You have a true invalid element, which is only visually hidden (using display: none) and replaced by another element (or by a set of other elements). In your case the problem is the following: By specification in case of interactive form validation the browser has to focus the first invalid element and show at least for this element a validation message.
The problem is that a browser can neither focus a hidden element nor show a validation message below this element. Which means that the browser stops form submission, but has an odd UI to show the validation problems.
Now to your question: Does this make sense? Yes, it does! If you change the UI of an form element you have to implement also UI for the validation message. (If you want to customize something, you have customize everything you want to use). HTML5 gives you an API to achieve exactly this.
You have to bind the invalid event of your select element, then prevent the default action (if it's the first invalid event of the form) and place your own validation tooltip to styled select element.
In my HTML5 form polyfill (webshims library), I'm already using code to link a native element (with API) with another element + generating simply validation tooltips.
I have created a simple jsfiddle, which mimics a select-replacement and shows how to achieve HTML5 form validation with custom form controls. You can find the example here and below:
HTML
<form class="example">
<div>
<select name="test" required>
<option value="">empty </option>
<option>sdadsa</option>
</select>
</div>
<div>
<input type="submit" />
</div>
</form>
<p>uses the webhsims library
JavaScript
(function() {
"use strict";
webshims.polyfill('forms dom-support');
$(function() {
$('select').each(function(){
var visualReplacement = $('<span tabinde="0">replaced select</select>');
$(this).after(visualReplacement).hide();
// Bind the visual element to the API element
webshims.addShadowDom(this, visualReplacement);
});
$('form').on('firstinvalid', function(e){
webshims.validityAlert.showFor(e.target);
// Remove native validation
return false;
});
});
})();

Help in select tag in for html

<select onchange ="----">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
I want to write this small piece of code wherien if a person selects any item, then it should move to the next html page showing what value is being selected..
How can i do that..
Hope my doubt is clear
Any suggestions here would be appreciated...
Thanks..
All form fields have a form property that you can use to easily access the form element to submit it.
You also need a name attribute in your select tag, or it will not work.
<select name="item" onchange="this.form.submit();">
Alternatively, you can go to another page by setting the location of the window, adding the value in the query string:
<select onchange="window.location.href='NextPage.html?item='+this.options[this.selectedIndex].value;">
<select onchange="document.forms[0].submit();">
assuming it's the first form on the page (which it usually is). If not you can alter the index to the correct form.
A good reference is Introduction to Forms.
You can of course do it using a library like jQuery (my preferred option) but that is strictly optional as it can be done fairly easily with stock standard Javascript.
Are you looking for Javascript running on the user's browser, or some server-side solution? You only tagged this as "html" so it's not clear what programming language the "small piece of code" should be in...
The onChange attribute will accept a javascript expression or function. Therefore, it depends on exactly what you want to do. If you need the value of the dropdown in the same page, you can access it using a Javascript snippet.
If however, you want the value to be available on the subsequent page (to which the form action attribute points), then you will need to submit the form in the change event. In this case, you can something similar to what #Cletus has pointed out.
<select onChange="redirect(this)">
<option value="html1.html" selected>1</option>
<option value="html2.html">2</option>
<option value="html3.html">3</option>
</select>
<script type="text/javascript">
function redirect(selSelectObject)
{
if (selSelectObject.options[selSelectObject.selectedIndex].value != "")
{
location.href=selSelectObject.options[selSelectObject.selectedIndex].value
}
}
</script>
I hope it will help you.
I would suggest that for cross-browser compatibility you think about combining the dropdown with a button to invoke the "go to" action. Some browsers, especially when used with accessibility technology, will fire an onchange for a select when that item is scrolled over. Having the onchange event itself do a postback in this scenario would be counterproductive. Even though the user experience may not be quite as nice, the select with a button degrades more gracefully both when the user does not have javascript and when the user is using accessibility technology. Were you loading the content via AJAX this would be less important since the select, presumably, would still be there to interact with. Doing a full postback to a different page, however, will frustrate users who experience this problem.
You could do inline Javascript using onchange in the select element ... but inline JS is a bad habit, and should be avoided. Markup, i.e. (X)HTML, should be minimal and semantic, without any inline CSS or Javascript. It's good to separate your markup (HTML) from your layout (CSS) and your behaviour (Javascript) as much as you can.
Keep your Javascript within the document head, or, even better, as an external script called in the head. This has advantages both in keeping your markup clean and minimal, and centralising and externalising your Javascript, which promotes code reuse and ease of maintenance.
A Javascript framework like jQuery will make things much simpler and more robust, too, if you're not experienced with Javascript.
Also, be aware that this approach (onchange on a select) is a poor one for accessibility (despite the fact that you see it everywhere on the web). For instance, many keyboard-only users (and that includes a whole lot of mobiles) are faced with the horrible situation where they choose a different option by moving up/down the list one option at a time... so your Javascript is kicked off over and over again, once for each option between the initial option and the newly desired one. Ugly - and if you're actually submitting the html form with the onchange JS, potentially a complete showstopper for those users.
Regardless, you really should have have a separate submit button (for users without Javascript, search bots etc) anyway; there might be some value in onchange JS triggering some Ajax, but don't rely on it to be the only way a user can submit the selection.