Testing for HTML5 attribute support

R

RobG

HTML5 introduces the placeholder attribute[1] for elements that allow
user input. This replaces the common script solution that uses focus
and blur events to put a hint in empty inputs and textarea elements.
To detect support for placeholder (and aovid attaching unnecessary
listeners), I've come across the following code:

var placeholderSupported = (function() {
var el = document.createElement('input');
el.type = 'text';
return 'placeholder' in el;
}());

While it "works" in all the browsers I've tested (IE (no support),
Safari (desktop and mobile), Firefox (with and witout support), Opera
(with and without support) and Chrome), it doesn't seem reasonable to
me to expect DOM elements to be given a property for every default
attribute that they support. Am I wrong about that? Is it reasonable
to expect that for an element created by createElement, if <property>
in <element> returns true that the browser supports that HTML
attribute?

1. <URL: http://dev.w3.org/html5/spec/Overview.html#the-placeholder-attribute
 
J

Jukka K. Korpela

RobG said:
HTML5 introduces the placeholder attribute[1] for elements that allow
user input. This replaces the common script solution that uses focus
and blur events to put a hint in empty inputs and textarea elements.

I would rather say that it is meant to replace the use of value="..."
attributes in <input> elements and the use of <textarea> content for the
purposes of giving users some instructions or hints, as such texts are
supposed to be meaningful default content. The use of Javascipt to wipe out
the instructions or hints when the user tries to enter some text is just an
attempt to reduce the problems caused by the practice.
To detect support for placeholder (and aovid attaching unnecessary
listeners), I've come across the following code:

var placeholderSupported = (function() {
var el = document.createElement('input');
el.type = 'text';
return 'placeholder' in el;
}());

Such an approach is commonly described in material on HTML5, but note that
in this case you would only be testing whether the attribute is supported
for <input type="text">. This does not tell you whether it is supported for
<input type="search" for example.

On the other hand, in many common situations, where you just want to use the
attribute in a single field, you don't need to create a dummy element. You
can just have the element in markup and test the expression 'placeholder' in
.... for it. I guess you would then typically place a copy of the text into
the value property of the element and associate with an onfocus event (which
removes the text) with the element.
While it "works" in all the browsers I've tested [...]
it doesn't seem reasonable to
me to expect DOM elements to be given a property for every default
attribute that they support.

Testing for support isn't an exact science. We can just hope that
a) browsers aren't so mean that they would recognize the property without
actually trying to support it as per HTML5
b) browsers won't accidentally recognize a property with that name in some
different meaning.
These are reasonable expectations. Regarding b), we can expect that authors
of HTML5 have avoided using such names for new attributes and properties
that might clash with existing vendor-specific extensions unless they are
reasonably compatible with the new meanings.

I don't understand the word "default" in "default attribute" in your text.

But it is reasonable to expect that when a support to a new attribute
defined in HTML5 is added to a browser, a corresponding property is added to
the HTMLElement interface, as that's what the HTML5 "specifications" require
and that's how HTML5 works - it is primary defined in DOM terms, with
conventional markup notations defined just as fairly uninteresting
serializations.

The risk of finding a browser that happens to recognize 'placeholder' in ...
by accident is extremely small, and so is the risk of false negative (i.e.,
a browser that evaluates 'placeholder' in ... to false despite actually
supporting the new attribute). But the risk of finding a browser that
evaluates 'placeholder' in ... to true and has support to the attribute but
fails to support it "by the book" (the HTML5 "specifications") is quite
real - HTML5 is a moving target and may change at any moment without prior
notice, and it is relatively complex to implement, so accidental errors
(bugs) and partial implementations of features are quite possible.

I wouldn't be particularly worried about the placeholder="..." attribute,
though. It is fairly simple, so I'd expect browsers to either support it "by
the book" or not support it at all.
 
R

Ry Nohryb

HTML5 introduces the placeholder attribute[1] for elements that allow
user input. This replaces the common script solution that uses focus
and blur events to put a hint in empty inputs and textarea elements.
To detect support for placeholder (and aovid attaching unnecessary
listeners), I've come across the following code:

  var placeholderSupported = (function() {
    var el = document.createElement('input');
    el.type = 'text';
    return 'placeholder' in el;
  }());

While it "works" in all the browsers I've tested (IE (no support),
Safari (desktop and mobile), Firefox (with and witout support), Opera
(with and without support) and Chrome), it doesn't seem reasonable to
me to expect DOM elements to be given a property for every default
attribute that they support. Am I wrong about that? Is it reasonable
to expect that for an element created by createElement, if <property>
in <element> returns true that the browser supports that HTML
attribute?

1. <URL:http://dev.w3.org/html5/spec/Overview.html#the-placeholder-attribute

My understanding is that supported attributes should reflect as
properties, so if set as a property, it should be reflected in
getAttribute and even in its outerHTML.

e = document.createElement('input');
e.type = 'text';
e.placeholder= 'test';
e.kk= 'unsupported';

e.getAttribute('placeholder')
-> 'test'

e.getAttribute('kk')
-> ''

e.outerHTML
-> '<input placeholder="test" type=​"text">'
 
S

Scott Sauyet

Ry said:
My understanding is that supported attributes should reflect as
properties, so if set as a property, it should be reflected in
getAttribute and even in its outerHTML.

e = document.createElement('input');
e.type = 'text';
e.placeholder= 'test';
e.kk= 'unsupported';

e.outerHTML
-> '<input placeholder="test" type=​"text">'

Really? So are you talking about any supported attribute, or only
'placeholder'?

Would you expect the equivalent code to include a blank value for
'alt' on the outerHTML for an IMG tag?

Besides, I think you're missing the point of the question. It's not
whether a property you set will be there, but whether the property
will be there by default even though you don't set it. Since I don't
have any answer to that question, I'll shut up now. :)

-- Scott
 
R

RobG

RobG wrote: [...]
To detect support for placeholder (and aovid attaching unnecessary
listeners), I've come across the following code:
 var placeholderSupported = (function() {
   var el = document.createElement('input');
   el.type = 'text';
   return 'placeholder' in el;
 }());

Such an approach is commonly described in material on HTML5, but note that
in this case you would only be testing whether the attribute is supported
for <input type="text">. This does not tell you whether it is supportedfor
<input type="search" for example.

Fair enough, I suppose all elements on which placeholder support is
required should be tested.
On the other hand, in many common situations, where you just want to use the
attribute in a single field, you don't need to create a dummy element. You
can just have the element in markup and test the expression 'placeholder'in
... for it. I guess you would then typically place a copy of the text into
the value property of the element and associate with an onfocus event (which
removes the text) with the element.
While it "works" in all the browsers I've tested [...]
it doesn't seem reasonable to
me to expect DOM elements to be given a property for every default
attribute that they support.

Testing for support isn't an exact science. We can just hope that
a) browsers aren't so mean that they would recognize the property without
actually trying to support it as per HTML5
b) browsers won't accidentally recognize a property with that name in some
different meaning.

My concern was mostly that if..in would return a false negative, but I
suppose that really isn't much of an issue if the fallback is designed
to be general. It just means that browser will get the listener
version instead (which should include removing the attribute if it has
been added in the source).

[...]
I don't understand the word "default" in "default attribute" in your text..

I meant attributes defined in the specification (or whatever we are
supposed to call the living HTML5 document - it's not an as-built,
more a might-be-built).
But it is reasonable to expect that when a support to a new attribute
defined in HTML5 is added to a browser, a corresponding property is addedto
the HTMLElement interface, as that's what the HTML5 "specifications" require
and that's how HTML5 works - it is primary defined in DOM terms, with
conventional markup notations defined just as fairly uninteresting
serializations.

Thanks, are you referring to the Web IDL?

<URL: http://www.w3.org/TR/WebIDL/#named-properties >


[...]
I wouldn't be particularly worried about the placeholder="..." attribute,
though. It is fairly simple, so I'd expect browsers to either support it "by
the book" or not support it at all.

Yes, the consequences aren't particularly dire either way, but it's
good to know that there is some support other than "it has been
observed".
 
J

Jukka K. Korpela

Scott said:
Really? So are you talking about any supported attribute, or only
'placeholder'?

In principle, each markup (HTML) attribute, or "content attribute" in HTML5
parlance, is defined separately so that it by definition "reflects" a DOM
property/attribute, or "IDL attribute", and "reflect" is defined at
http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#reflect
Note the statement "In general, [...] on setting, if the content attribute
is not present, it must first be added."
Would you expect the equivalent code to include a blank value for
'alt' on the outerHTML for an IMG tag?

It depends on the meaning of "equivalent", but if you mean that there's an
assignment like e.alt = "...", even e.alt="", then yes, alt="..." should
appear in outerHTML, and browsers that support outerHTML seem to conform.
Besides, I think you're missing the point of the question. It's not
whether a property you set will be there, but whether the property
will be there by default even though you don't set it.

"In general, on getting, if the content attribute is not present, the IDL
attribute must act as if the content attribute's value is the empty string".

So if the markup is <input> and if the JavaScript code tests for the
placeholder property, it should see the property as defined, with the empty
string as its value, on conforming browsers.
 
R

Ry Nohryb


Yes :)
So are you talking about any supported attribute, or only
'placeholder'?

All supported attributes should reflect like that.
Would you expect the equivalent code to include a blank value for
'alt' on the outerHTML for an IMG tag?

What equivalent code do you mean ?

If you set the alt property on an img, its value should be reflected
in getAttribute and in .outerHTML, because alt is a supported
attribute for imgs.
Besides, I think you're missing the point of the question.  It's not
whether a property you set will be there, but whether the property
will be there by default even though you don't set it.

I don't think that was the question. I think RobG wants to know
whether the browser it's running in supports an attribute or not, if
it supports it, it should reflect as 'placeholader/test' above, if it
does not support it, it won't reflect as 'kk/unsupported' above.
Since I don't
have any answer to that question, I'll shut up now.  :)

:)

Cheers,
-
Jorge.
 
V

VK

While it "works" in all the browsers I've tested (IE (no support),
Safari (desktop and mobile), Firefox (with and witout support), Opera
(with and without support) and Chrome), it doesn't seem reasonable to
me to expect DOM elements to be given a property for every default
attribute that they support. Am I wrong about that? Is it reasonable
to expect that for an element created by createElement, if <property>
in <element> returns true that the browser supports that HTML
attribute?

No, it is not if by "browser supports" you mean "has it and can be
used as documented with the documented result".
if ('property' in object)
check tells you one thing only: that 'property' is presented by
default and isEnumerable. Most of the time it is not enough for a
reliable code deployment and requires separate per UA and OS checks
with possible additional per UA/OS workarounds. Practically the
negative outcomes to be ready for are:

1) ('property' in object) == true but 'property' is just a loophole
left by the producer because it is planned to implement in some future
release or is not planned to implement at all but used to mimic some
other UA in order to cheat on feature testing. For instance Opera 9.x
(and up till now I believe) didn't support XPCOM yet provided a full
set of loophole XPCOM methods for whatever reasons. They were just
void functions so say for my application launcher I had to use rather
cryptic at the first look approach:
if ((window &&netscape && netscape.security &&
netscape.security.PrivilegeManager) && (typeof window.opera !=
'object'))

2) ('property' in object) == true but 'property' functionality differs
or completely different from what standards say or even what browser
producer docs say.
The same Opera used to have dysfunctional CSS properties for <svg>
canvas. It had 'left' and 'top' properties, one could set it and read
it back with proper values: but for 'position:absolute' visually they
where silently ignored and <svg> was placed as for 'left:0; top:0'. So
it was necessary to detect Opera first and to use <div> outer
container for positioning.

3) ('property' in object) == false because it is not enumerable yet
can be addressed directly. That applies to many additional interfaces
on Gecko for instance.

4) ('property' in object) == false because it is intentionally hidden
to mimic some other UA or to prevent undesirable branching. For
instance Gecko in quirk mode reports document.all as missing (so to
cheat on if(document.all) checks) yet has it functional (so to use IE-
specific scripts w/o rewriting).

So
if ('property' in object)
is definitely a reliable *starting* point. With positive match next
steps are (1) and (2) for all currently prominent UAs by all currently
prominent OS. With negative match next steps are (3) and (4) for all
currently prominent UAs by all currently prominent OS.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,983
Messages
2,570,187
Members
46,747
Latest member
jojoBizaroo

Latest Threads

Top