In what authorative specification is the onChange event exhaustively defined? - html

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.

Related

Manipulate html <input>'s value retaining undo capabilities

If I have a simple <input type="text"> and never mess with its value property, I can undo (and redo) my actions at will [I mean, keyboard typing and clipboard cut and paste].
But once some event sets its value the undo stack is gone. I understand that for an arbitrary event it would be very hard (and unnatural, from user perspective) to define how the undo stack should cope with changes introduced by direct attribution to value.
But I'm thinking about edit events, like <input>'s own input and paste events (to give you some context, I'm planning to apply some field masking).
Is it possible to change the object associated with the event (InputEvent and ClipboardEvent) instead of manipulating the value property, so the stack can be preserved? Or otherwise inform "the stack" programmatically how to "undo from here"?

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;
});
});
})();

HTML Input on change of value

I have an input tag. This tag does not have the autocomplete feature turned off, thus, one does not necessarily need to release a key to change the value of this field and focus another one. My question is: how can I detect ANY value changes of this particular field, like e. g.
<input onvaluechange="//do following..." />
The JavaScript attribute onchange does not fire on change of value, only on changes like blur, focus, etc...
EDIT: It also doesn't necessarily be a key press. Due to the autocompletion, the user can simply mouse-click the autocompletion result to change the value. This would not fire an onkeydown event.
It also doesn't necessarily be a key press. Due to the autocompletion
...and many other non-key-based operations, such as right-click-cut/paste, drag and drop, undo/redo, spellchecker adjustments and so on.
HTML5 defines an oninput event to catch all direct changes.
Unfortunately browser support today isn't there (no support in IE, and there are some bugs in others), so all you can do if you really need to detect all changes to an input value earlier than onchange is to use setInterval to add a poller that constantly compares against the previous value.
Detecting "value" of input text field after a keydown event in the text field?
I had a similar problem and binding to a dozen of different events just doesn't cut it, since there are so many different ways of changing input value, as bobince noted.
So - I ended up writing dead simple jQuery monitoring plugin that's generic in nature.
With it you can monitor input value changes, textarea text changes, div content changes, etc:
https://github.com/nixd3v/monitor
Tracking div content changes:
$.monitor('add', function(){return $("div#someDiv").html()}, function(){
console.log('Div content changed');
});
Tracking input value changes:
$.monitor('add', function(){return $("#password").val()}, function(){
console.log('input value changed');
});
It also uses a loop of course, however, not through setInterval, but rather through using setTimeout along with a self-executing anonymous function:
(function(){
// do some stuff
setTimeout(arguments.callee, 100);
})();
What this does - this guarantees, that the next call is not made before your code was executed. If you use polling in your code - this is the right way of doing it.
You can use the onKeyPress attribute to monitor changes typed in by the user.
For example:
<input type='input' onKeyPress='SomeScriptMethod();'>

What is the difference between onBlur and onChange attribute in HTML?

When is one called versus the other? Is there a situation were onChange would be called but onBlur would not be called?
The onBlur event is fired when you have moved away from an object without necessarily having changed its value.
The onChange event is only called when you have changed the value of the field and it loses focus.
You might want to take a look at quirksmode's intro to events. This is a great place to get info on what's going on in your browser when you interact with it. His book is good too.
onblur fires when a field loses focus, while onchange fires when that field's value changes. These events will not always occur in the same order, however.
In Firefox, tabbing out of a changed field will fire onchange then onblur, and it will normally do the same in IE. However, if you press the enter key instead of tab, in Firefox it will fire onblur then onchange, while IE will usually fire in the original order. However, I've seen cases where IE will also fire blur first, so be careful. You can't assume that either the onblur or the onchange will happen before the other one.
An example to make things concrete. If you have a selection thus:
<select onchange="" onblur="">
<option>....
</select>
the onblur() is called when you navigate away. The onchange() is called when you select a different option from the selection - i.e. you change what it's currently selected as.
In Firefox the onchange fires only when you tab or else click outside the input field. The same is true of Onblur. The difference is that onblur will fire whether you changed anything in the field or not. It is possible that ENTER will fire one or both of these, but you wouldn't know that if you disable the ENTER in your forms to prevent unexpected submits.
I think it's important to note here that onBlur() fires regardless.
This is a helpful thread but the only thing it doesn't clarify is that onBlur() will fire every single time.
onChange() will only fire when the value is changed.
onChange is when something within a field changes eg, you write something in a text input.
onBlur is when you take focus away from a field eg, you were writing in a text input and you have clicked off it.
So really they are almost the same thing but for onChange to behave the way onBlur does something in that input needs to change.
onBluris when your focus is no longer on the field in question.
The onblur property returns the onBlur event handler code, if any, that exists on the current element.
onChange is when the value of the field changes.

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

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