JavaScript action inside HTML5 oninput attribute? - javascript

I have been learning HTML5. One of the examples I have encountered uses an input element of type range and an output element (this example currently only works in Chrome, Safari and Opera). The following form produces a slider with the result echoed to the output element.
<form>
<p>
<input type="range" id="slideValue" value="50"
oninput="slideCurrent.value = parseInt (slideValue.value);" />
<output id="slideCurrent">50</output>
</p>
<input type="submit" value="Send">
</form>
My question concerns the oninput attribute. The oninput attribute contains JavaScript. In pre-HTML5 JavaScript I commonly see JavaScript references to this.value. However in the above HTML5 example the references to slideCurrent and slideValue work (apparently without the need to use getElementById). I believe this is a new way for JavaScript to behave.
Is this new JavaScript method of action documented somewhere?

Code within inline event handlers is scoped to the element, as if it was in a with block.
Therefore, you can use properties of the element as global variables.
This is a little-known and dangerous feature, and is not new to HTML5.

It's a method introduced by IE, that elements' names and ids are references in the global scope. Other browsers have copied it, but it's considered as bad use. Mozilla throws a warning:
element referenced by ID/NAME in global scope. Use WC3 standard
document.getElementById() instead...
You can find lots of threads when googling for that. A good article can be found here. In the event handler you can use this
as a reference to the element, but the output element should be acessed by standard dom methods.
EDIT: Oh shit, yes, its in the spec: http://www.whatwg.org/specs/web-apps/current-work/#dom-window-nameditem. But with a big red alert:
It is possible that this will change. Browser vendors are considering limiting this behaviour to quirks mode. Read more...
See also Mozilla bugs 303420 and 602381

Related

Use onsearch on Chrome but onsubmit on non-supporting browsers?

If I have HTML along the lines of
<form onsubmit="HandleOnSubmit()">
<input type="search" id="query" onsearch="HandleOnSearch()">
</form>
... then how would I have browsers supporting onsearch (like Chrome) only use HandleOnSearch(), and non-supporting browsers (like Firefox, at the time of writing) use HandleOnSubmit()? Right now, Chrome (which doesn't need HandleOnSubmit) fires twice, first the outer, then the inner event. Thanks!
(If nothing else works, I'll do a !Chrome check in HandleOnSubmit, but I figured there might be something better I'm missing.)
Feature detection
Generally speaking, the answer to any question of the form "how do I use a feature available only in some browsers" is to use feature detection:
at runtime, your code programmatically checks for the existence of the feature, or confirms that it supports some option you need, etc
based on the results of that check, you invoke either the special behavior or some fallback behavior
There are libraries out there that do all the feature detection up-front and publish those results such that your app can get the answers easily (perhaps by looking for a CSS class on the <html> element), but a quick-and-dirty approach might be:
create an <input type="text" /> in memory
attach a search handler to it (using element.addEventListener('search', ...))
manually fire the search event on the element
your search handler sets a flag
return the value of the flag: if it was set, this browser supports onsearch; if not, the browser does not

Accessing an HTML-element by it's id DIRECTLY - What happens here?

I've discovered this behavior by accident:
I can access an HTML-element in JavaScript just by it's HTML attribute "id". Normally I used getElementById for that.
I have even write-access to it's properties.
Made this demo and tried it out in Firefox, Safari and Chrome.
It worked everywhere.
alert(test1.innerHTML);
test1.innerHTML = 'Foobar';
alert(test1.innerHTML);
<div id="test1">Demo 123</div>
So, to be honest: I'm astonished and confused because I haven't known that that's possible.
Moreover I ask myself: What sense does getElementById make when I can get and set the element directly?
Sure: I'm aware that the inventors haven't incorporated the method without some intention.
Can anyone give me some explanations why I have access to elements via id-attribute?
And why one uses getElementById nevertheless?
As far as I remember, this behaviour was introduced by Internet Explorer. After a while, other vendors picked it up. I don't think it was ever standardized and, as such, might stop functioning at any time. Also, if you have a variable test1 in your code it will override the test1 defined by the controls.
Worth mentioning, in certain IE versions, trying to create a global variable with the same name as the id of an element fails. The book "JavaScript: The Definitive Guide" by David Flanagan also says that if the variable already exists in the global scope when the element is created, then the variable will not be overwritten by the element with the same id.
More on the subject here: Is there a spec that the id of elements should be made global variable? and here: Do DOM tree elements with ids become global variables?

Referencing DOM elements in IE11 vs IE8

I have a website that contains the following HTML/javascript:
<input type="text" id="txtPhaseID" onkeypress="return onlyNumbers();" />
<a id="btnLookup" onclick="GetEventLookupData(txtPhaseID.value);this.blur();return false;" href="javascript:void(0);" class="btn"><span>Lookup</span></a>
The reference to txtPhaseID.value in the onclick event works in IE8 but fails in IE11. I'd expect it to fail in both since you should have to use document.getElementById.
Why does this work in IE8?
Technically when you add an id to an element you could access it directly from the DOM with id.property - but it's always been considered very bad practice to a point that no one was ever taught that way. I can only imagine it was finally removed in Internet Explorer 11. I have no idea what this is called and I don't think it's ever been given a specific name, which means Googling will return pretty limited results. Unfortunately, if they did remove it there probably isn't anything saying so.
Here are some other resources from stackoverflow for more information:
Do DOM tree elements with ids become global variables?
Why don't we just use element IDs as identifiers in JavaScript?

addEventListener() without getElementById reference success?

Check out this fiddle (partial code snippet below): http://jsfiddle.net/QJJb8/
<button id='mybutton'>MY BUTTON</button>
mybutton.addEventListener('click', mybuttonClick, false);
function mybuttonClick(e){
alert(e.target.textContent+' WAS CLICKED!');
}
Note how I'm not using getElementById() to get a reference to the button. Why does it still work? (Tested in Firefox, Chrome and IE9 & 10.)
Is it bad-practice/quirk, or is it built in functionality for button elements? If the latter, that's an awesome perk/shortcut when using button elements! Or perhaps I've just been over-using getElementById() all this time?
//ANSWER UPDATE//////////////////////////////////////////////////////////////////////
After some research it seems the behavior discussed above is in fact part of the HTML5 spec. In addition to RobG's answer below, see also the following links for more insight:
http://tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/
https://stackoverflow.com/a/3434388/2434324 (link supplied by yoelp)
http://jsperf.com/named-access-on-the-window-object
Because way back at the begining of browser scripting, IE decided to make element names and IDs global variables that referenced the element. Everyone else thought that was a bad idea (it was) and didn't do it.
However, IE grabbed about 95% of the browser market and developers developed for IE's quirks, so other browsers implemented the same behaviour but didn't advertise it (same with support for document.all). So now all browsers do it, but (almost) no one uses it.
Except when someone stumbles across it…
So where you have:
<button id='mybutton' ...>
browsers create a global mybutton variable that references the element.
This works on all DOM elements, not only buttons, Its probably a bad practice since any one may change mybutton to something else (ie.mybutton = "BLABLA") then your code breaks
also see this

Setting an attribute named "required" and any value, with JQuery, doesn't work

This doesn't work:
$("#elementId").attr("required", "true");
In both Chrome and Firefox, the DOM produces either required as the attribute (no value) or required="" (empty value).
And it doesn't matter that the value in this example is "true". If you try "asdf" the same thing happens.
What's odd is that I believe this used to work because this new code is part of a large project that's been ongoing for several years.
The only thing I can think of is that my Chrome (v10) and Firefox (v4) are now both sufficiently advanced that they're recognizing the required attribute as an HTML5 reserved keyword. I added the novalidate attribute, thinking that that might turn off any form-related HTML5-ness. No such luck.
Thoughts?
Edit:
To clarify, this only happens with JQuery. If I say this, it works:
$("#elementId")[0].setAttribute("required", "true");
Is there a bug in JQuery? Any idea why this only happens with JQuery? Our development team likes all code to go through JQuery where possible. I can use the straight setAttribute JavaScript method, but would rather use a JQuery solution that works.
Edit 2:
The crux of the matter is this...
Why does using JQuery's attr() method not work when the regular setAttribute() method does? Doesn't the attr() method call setAttribute() at some point lower down?
That is what is so confusing. Chrome and Firefox are perfectly fine setting required="true" if you use setAttribute().
You can use prop to achieve this:
$("#elementId").prop("required", true);
Corresponding documentation: http://jquery.com/upgrade-guide/1.9/#attr-versus-prop-
It is indeed browser related. I checked in IE8 and it will apply whatever string value you set to the required attribute.
Since you don't need any value (only the attribute must be present), this won't affect default behavior. If you are abusing the attribute value for javascript hooks, that's another thing :)
<input required> is the same as <input required=""> and <input required="honky-tonk">
Since IE8 doesn't support html5, it's just like setting a made-up attribute, so you could set $("input").attr("derp", "derty") and it would assign it to the element.
My guess is that jquery uses the required="" for folks who wish to use this in XHTML strict syntax, while still conforming to HTML5 standards.
http://dev.w3.org/html5/spec/Overview.html#the-required-attribute
http://dev.w3.org/html5/spec/Overview.html#boolean-attribute
The way I got this working was to implement the following good old javascript in place of any jQuery:
document.getElementById("inputid").required = true;
or, (obviously)
document.getElementById("inputid").required = false;
depending on requirements.
The source of my solution is here.
I have read through .attr() and .prop() pages on the jQuery API, and there seems to be no support for the "required" attribute - but I am open to correction.
I use this fairly often and I haven't noticed any problems with it.
$("#elementId").attr("required", "required");
Note: I have try this but I could NOT get it working:
$("#elementId").attr("required");
Even though required is now a boolean attribute, simply adding the attribute name (without the value) does not appear to be too compatible with different versions of different browsers. Stick with my original example above and you should be fine.
For input required, it works much better if you remove the attribute vs. setting it to false
$('#elementId').removeAttr('required');

Categories

Resources