Is there any particular reason that it isn't in any of the the specs?
It seems to be supported in all browsers, (although I'll admit it doesn't work right in all of them...since you have to use libraries like innerXHTML to get it to work right thanks to Internet Explorer.
Is innerHTML in danger of disappearing from forthcoming versions of browsers? If not shouldn't they just add it already?
I'm marking this community wiki as I know I'm gonna take a beating on my rep for this...but I just wondered why...
http://dev.w3.org/html5/spec/Overview.html#innerhtml
There's absolutely no way it's in danger, thousands of applications rely on it and doing so would be a horrible idea.
I'll admit it doesn't work right in all of them...since you have to use libraries like innerXHTML to get it to work right thanks to Internet Explorer.
IE invented innerHTML; you can't really expect it to work any better than it does there.
Is there any particular reason that it isn't in any of the the specs?
It's proposed for HTML5, for what it's worth. There is certainly no danger of it disappearing in the future, though you should continue to use it only for the simple cases where you are writing straight ‘block’ or ‘inline’ element content. Special cases like tables and selects are going to continue to be troublesome.
IE, being the inventor of dynamically modifying the content has gone with it all the way - other browsers didn't!
Passing the string as innerHTML means that the string will get through a normalization process before it gets passed to the element. Meaning it will get transformed fom a string into a proper html parsing content.
Firefox implemented it wrongly. It doesn't distinguish between html:innerHTML and html:innerText and plain string:text. The difference is literally obvious for IE, but not for FF. Hence the difference in handling situations and the confusion of FF only coders when they go back to the master.
Related
In an effort to write more expressive HTML, I feel custom HTML elements are a good way for any webapp or document I may write to have good meaning gleamed from the tag name itself without the use of comments.
It appears I can define a custom HTML element with:
document.registerElement("x-el");
However it also appears that I can use a custom element before defining it:
<body>
<x-salamander>abc</x-salamander>
</body>
Or even:
<salamander>abc</salamander>
I suppose this is invalid HTML, however both Firefox and Chromium proceed to display the element without any problems or console warnings.
I can even execute the following with no complaints from the browser:
document.getElementsByTagName("salamander")[0]
Using this tag name as a selector in CSS also works fine. So, what problems might I face if I use undeclared elements in this way?
The problem with what you're trying to do is not that we can tell you it will break in some expected ways. It's that when you deviate from standards in this way, no one knows what to expect. It is, by definition, undefined, and the behavior of browsers that see it is also undefined.
That said, it might work great! Here's the things to keep in mind:
The HTMLUnknownElement interface is what you're invoking to make this work in a supported way - as far as I can tell in 5 minutes of searching, it was introduced in the HTML5 spec, so in HTML5 browsers that use it appropriately, this is no longer an undefined scenario. This is where registerElement comes into play, which can take an HTMLUnknownElement and make it known.
Browsers are typically very good at coping with unexpected markup... but it won't always result in great things (see: quirks mode).
Not all browsers are created equal. Chrome, Firefox, Safari, Opera, even IE will likely have some reliable way to handle these elements reliably (even pre-HTML5)... but I have no idea what a screen reader (Lynx) or various other esoteric, outdated, niche or even future browsers will do with it.
Everyone has said the same thing, but it's worth noting: you will fail validation. It's OK to have validation errors on your page so long as you know what they are and why they are there, and this would qualify, but you'd better have a good reason.
Browsers have a long history of taking whatever you give them and trying to do something reasonable with it, so you're likely to be OK, and if you are interested in primarily targeting HTML5 browsers, then you're very likely to be OK. As with everything HTML related, the only universal advice is to test your target demographic.
First problem I can see is that IE8 and lower will not apply your styling consistently. Even with "css resets", I get issues in IE8. It's important for the browser to know whether it's dealing with a block, inline block, list, etc, as many CSS behaviors are defined by the element type.
Second, I've never tried this, but if you use jQuery or another framework, I don't think they're built to handle non HTML tags as targets. You could create issues for your coders.
And HTML validators will probably have heart-attacks, so you lose a valuable tool.
You are re-inventing the wheel here. AngularJS has already solved the problem of adding HTML elements and attributes via what it calls directives:
Angular's HTML compiler allows the developer to teach the browser new
HTML syntax. The compiler allows you to attach behavior to any HTML
element or attribute and even create new HTML elements or attributes
with custom behavior. Angular calls these behavior extensions
directives.
The goal of Angular is broader in that it treats HTML as if HTML were a tool meant to build applications instead of just display documents. To me, this broader goal gives real meaning and purpose to the ability to extend HTML as described in your question.
You should use the namespaced version document.createElementNS instead of plain document.createElement. As you can see in the snippet below,
(...your custom element...) instanceof HTMLUnknownElement
will return false if you do that (it will be true when you do it unnamespaced)
I strongly suspect that validators won't even complain, because it's in your own namespace, and the validator (unless written by a stupid person) will (at least, really really really should) acknowledge that the 'namespaced stuff' is something it doesn't know enough about to condemn it.
New (formerly custom) elements arising in future HTML versions is a certain thing to happen, and it will happen even more often for namespaced elements compared to elements in the default namespace. And the 'HTML specs crowd' is simply not in charge of what, for example, the 'SVG spec crowd' will be doing next year or in 10. And which new namespaces will be introduced by god knows who and become common. They know they are not 'in charge of that', because they aren't stupid. For those reasons, you can bet your last shirt that you will not run into any serious problems (like errors being thrown or something of that sort) when you just go ahead and use them - it's OK if you're the first one. The worst thing that could possibly happen is that they don't look (aren't rendered) the way you'd wish, if you didn't write any CSS for them; anyway, the foremost use-case are probably invisible elements (you can be sure that display:none will work on your custom elements) and "transparent containers" (which won't effect the rest of the CSS unless you have ">" somewhere in the CSS). Philosophically, what you're doing is very much akin to jQuery using class names to better be able to transform the document in certain ways. And there is absolutely nothing wrong with jQuery doing that, and if the class in question is not referenced by some CSS, that does not make the slightest difference. In the same fashion, there is absolutely nothing wrong when you use custom elements. Just use the namespaced version. That way, you're also safe to use any names that might later be added to 'proper' HTML without causing any conflicts with how those elements later will be supposed to work.
And if - surprisingly - some validator does complain, what you should do is go on with your custom elements and ditch that validator. A validator complaining about how you use your very own namespace you just came up with is akin to a traffic cop visiting you at your home and complaining about the fashion in which you use your restroom - ditch it, got me?
bucket1 = document.getElementById('bucket1');
console1 = document.getElementById('console1');
bucket2 = document.getElementById('bucket2');
console2 = document.getElementById('console2');
chicken = document.createElement('chicken');
chicken.textContent = 'gaak';
bucket1.appendChild(chicken);
console1.appendChild(document.createTextNode([
chicken instanceof HTMLUnknownElement,
chicken.namespaceURI,
chicken.tagName
].join('\n')));
rooster = document.createElementNS('myOwnNSwhereIamKing', 'roosterConFuoco');
rooster.textContent = 'gaakarissimo multo appassionata';
bucket2.appendChild(rooster);
console2.appendChild(document.createTextNode([
rooster instanceof HTMLUnknownElement,
rooster.namespaceURI,
rooster.tagName
].join('\n')));
=====chicken=====<br>
<div id='bucket1'></div>
<pre id='console1'></pre>
=====rooster=====<br>
<div id='bucket2'></div>
<pre id='console2'></pre>
MDN article
plus, you've got almost universal browser support for createElementNS.
hmmm... just found out that if you use .createElementNS, the created elements don't have the dataset property. You can still use .setAttribute('data-foo', 'bar') but .dataset.foo='bar' would have been nicer. I almost feel like downvoting my own answer above. Anyway, I hereby frown upon the browser vendors for not putting in dataset.
I've got this example page where I'm trying to put the wmode of every youtube element inside the page to "transparent".
To do it I need to get all the "object > params" and "embed" tags in the page.
The page I link you works like charm in all the browser except for IE6 (haven't cheked the other IEs yet).
With IE6 I can't catch the "params" since document.getElementsByTagName('param') returns an empty object, but this doesn't happen with the "embed"!
It won't work with document.getElementsByTagName('object') as well
Here is the page http://dl.dropbox.com/u/4064417/provaJs.html
Any suggestion why it's not returning just the "param" tags?
Thank you in advance!
I recall some issue with <param/> tags and getElementsByTagName, but it's ages that I don't code in IE6. Instead of querying from document, trying to get the params calling getElementsByTagName from the <object /> itself and see if it helps:
var objects = document.getElementsByTagName("object");
for (var i = 0, object; object = objects[i++];) {
var params = object.getElementsByTagName("param");
alert(params.length);
}
I understand that you would like to keep your app backwards compatible, but this exercise runs counter-intuitive to the general direction of the industry and its efforts to put IE6 down to rest (even google has dropped support for IE6). Your time might be better invested if you focus on building a better web experience for pseudo-modern browsers instead of worrying about the legacy ones.
Food for thought - maybe use a browser detection script and encourage your users to upgrade so that they can experience your site in all of its modern glory :)
All that being said, ZER0's suggestion is dead-on. Find the "object" tags in the page, and then iterate through its children until you find the tag you're looking for. If you can't seem to grab the object tags with getElementsByTagName, you may very well have to iterate through the document.body.childNodes nodelist, checking for the typeof(N) or N.NodeName along the way.
If you must support browsers as old IE6, I would strongly recommend using a library such as jQuery rather than trying to access the DOM directly.
IE6 has a massive number of bugs and quirks that can break even the simplest and most innocuous of Javascript code. jQuery goes to great lengths to abstract these browser bugs and deficiencies away from the developer, allowing you to write code that works on all browsers.
For example rather than using document.getElementsByTagName('object'), you can use the jQuery code $('object'), which will give you the same end result, but will work around any bugs in whichever browser your end user is running.
jQuery does a whole lot more than just hide the browser bugs, of course, but if you're working with IE6, that alone is a good enough reason to use it.
(other libraries are of course available if you really don't like jQuery for some reason)
Consider the following code:
<html>
<head></head>
<body>
<div id='test' class='blah'>
<a href='http://somesite.com/' id='someLink'>click!</a>
</div>
</body>
</html>
So I just recently discovered that this creates a javascript object called someLink and I can for instance get the value of the href attribute with someLink.href. I tested this in the latest Chrome, FF and IE and it works.
First off, how long has this "feature" been around? I imagine probably a while, because I have known for years that IDs for html elements on a page must be unique, and if you do have more than one element sharing the same ID, the last one overwrites the previous one(s), and using for instance getElementById() will return the last one. But I never really understood why, but now, looking at it as a "this is creating an object" perspective, it makes sense. So, as far as being able to directly access it with the id-name-as-javascript object...how long has that been around? IE6 era? Earlier?
2nd...I guess this is more of a discussion point than question, but... IMO this doesn't seem like a very good "feature" to have... Isn't the whole point of having a DOM and wrapper functions like getElementById(), to give some organization and more importantly, cut down on namespace issues? I don't feel I should have to be worried about random html elements on a page overwriting my javascript variables (something that has recently happened, which is why I discovered this "feature"). Does anybody know why this is as it is, what's the logic behind it?
First off, how long has this "feature" been around?
It is a Microsoft-ism that cropped up around IE 4 if I remember correctly.
Some other browsers have added support for it in an effort to be compatible with badly written code that depends on it. Some may only support it in quirks mode.
this doesn't seem like a very good "feature" to have
Correct. Don't use it. :)
Yes, it's been around for a very long time, which is likely the only reason it exists. Removing such a "feature" will break compatibility with existing web sites, which browser vendors are very reluctant to do.
You're correct in saying that it's not a good idea. It's a profoundly bad idea and can lead to naming conflicts as well as unnecessary pollution of the global namespace.
It's an old IE feature, not recommended to use. Several browsers implement it, often as nonenumerable properties of the window object. FF, for example, does it only in quirks mode.
For further reading see duplicate Is there a spec that the id of elements should be made global variable?...
Can somebody please explain to me the internal implementation of HTML getElementById() method ?
Is it traversing whole DOM tree to find the specified element or is it intelligent enough to look for near-by elements first ?
Thank you
The implementation is entirely (er) implementation-dependent. Some browsers may use a hashmap or similar, or they may not (because although id is required to be unique, there are lots of poorly-authored pages out there that provide invalid markup with duplicated ids). Internet Explorer 6 and 7 don't even limit getElementById to id values, they conflate namespaces terribly, although Microsoft has clearly seen the light and both IE8 and IE9 improve that.
For browsers that are implemented open source, you can find out, of course. Here's a link to the WebKit source, and here's one to Mozilla's (that line number may vary a bit, if you don't land right on it, just search for GetElementById and GetElementByIdInternal). Both of those come from this related answer here on StackOverflow. (In fact, looking at that question, I think this one may be a duplicate, although as Matthew points out in a comment below, things are moving fast enough that it might justify an update...)
It depends on the browser, but most probably use a hash map from id->element. It's true that there are many invalid pages that have duplicate ids. However, the browser will still only return one element, not a collection.
I don't know what you mean by "near by elements" since the method only exists on document.
If you're interested, you can find the implementation for free software browsers such as Firefox and Chrome.
That depends. The method is implemented by each web browser vendor, so the details may be different from one to another and possibly from one version of a browser to another.
I'd suggest taking a look at the source code for a browser such as Mozilla Firefox and see if you can find the implementation.
i have built a beautiful website that works very fast in all of the latest browsers but many of the users are forced to use ie6. If i can't get around this problem. Is there anything to do to optimize some of the inefficiencies of ie6 when building my site to lessen the pain.? its an asp.net mvc site with heavy use of jquery.
You don't mention any specific issues with the site, but you can pass scripts, styles, even content just to IE6 by using conditional comments.
<!--[if IE 6]>
IE6 only stuff goes here
<![endif]-->
Apart from that, learn the many, many quirks of IE6 and the fixes for these problems. There is certainly plenty of resources on this out there, we've had to deal with it for quite some time!
If you need help with something specific, perhaps edit your question with further details.
Retroactively, i don't know if there's an exact answer other than troubleshooting the problems one at a time. The correct way would be to code proactively for all browsers until IE6 is finally put to rest as it should be :)
jQuery works pretty well with IE6, so you should be ok on that front. You will most likely run into some CSS quirks, but once you learn what to avoid it's really not bad coding for IE6. The main thing I keep running into is when you float something, you always need to put a display type of relative or absolute on it otherwise it will just disappear from the screen in many cases.
First of all, it should be considered in the beginning of a project whether IE6 needs to be supported or not. Designing for it requires a bit different approach - some things just tend to break down. My advice is you should probably make the experience on IE6 only "sufficient" and just make sure the site can be used as intended. Making it look flashy is just not going to work with any reasonable amount of effort.
Is Chrome frame an option? It could be positioned as a something similar to java which less people have a problem with.
http://code.google.com/chrome/chromeframe/