Dynamically added AJAX content with wrong markup - javascript

i am using jQuery to dynamically add content
$("#articles").prepend('<article><header><p>info</p><h2>You are using Internet Explorer</h2></header><p>It is recommended that you use a modern browser like Firefox, Chrome or install Google Chrome Frame to experience better performance and advanced HTML5 and CSS3 features.</p></article>');
but the HTML i got was
notice the />

jQuery is using innerHTML, which doesn't always work with HTML5 elements even when the normal ‘shiv’ is in use. You would need another extra workaround hack, eg this.
I really don't think the proposed new HTML5 elements are ready for real-world use. They get you no practical gain yet, aren't even finalised, and cause a bunch of problems (working around which can be fragile and cost performance).
They don't really add anything semantic to your warning markup, and you're only ever showing it to IE anyway—the browser that can handle them least well of all.

Related

What repercussions do I get by using an undefined HTML element?

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.

Is there a reliable, cross-browser way to use polyfills with knockout?

We have a site that is driven pretty much entirely out of knockout and we need to support all major browsers, including Internet Explorer back to IE7 (not IE6).
Chrome already supports almost all of the HTML 5 features that we actually care about, and Modernizr handles the CSS hacks like a champ. But there are times when we still have to resort to polyfills, two notable examples being the placeholder attribute and more recently the <details> element.
Most of the polyfills are or rely on jQuery plugins, which is great in theory. Unfortunately, they also tend to be ineffective at dealing with dynamically loaded content - which there's a ton of when you use knockout (or any templating engine, really). Further complicating matters is that we're using knockout as true MVVM, so there's no decent place to shoehorn in a bunch of JS hacks to reload the plugins (which is probably a good thing as far as our architecture is concerned, but frustrating on this front).
We were able to come up with a semi-reliable implementation using the DOMNodeInserted event (deprecated, I know) for Firefox and IE9. Unfortunately it didn't work in IE8, because legacy IE doesn't support it and it seems damn near impossible to replicate in those browsers. onreadystatechange seemed promising at first but the event tends to fire too early - even if readyState is explicitly checked - and the polyfills miss their targets, so to speak.
The only option we tried that actually worked reliably in IE7/IE8 was using a repeating timeout to rerun the polyfills every 50 ms. Unfortunately, that also consumed an entire CPU constantly, and bumping it up to even 100 ms caused a too-noticeable delay in the UI, so not really suitable for production use.
So: Is there any reliable way of combining traditional polyfill techniques with dynamic content and templating engines like knockoutjs, that works in every major browser down to at least IE7?
(FWIW, we did eventually manage a workaround using knockout's afterRender binding, but that kind of takes the "poly" out of "polyfill". I'm hoping for something that we can write once and then forget about.)
The way I solved the same problem was to wrap most of my jQuery plugins, and behaviors in general, in knockout bindings (http://knockoutjs.com/documentation/custom-bindings.html). So I had, for example, a placeholder "binding" that I used on each input like <input data-bind="placeholder:'Some Placeholder Text'"/> that either simply set the placeholder attribute or did some IE hack depending on the need.
A broader solution would be to augment knockouts binding provider (http://www.knockmeout.net/2011/09/ko-13-preview-part-2-custom-binding.html). The binding provider is the thing that traverses the DOM (both on load and when dynamically loaded) and identifies bindings. By default, that essentially means it's just looking for data-bind attributes and ko comments, but you can change this to also find attributes like placeholder, input types for date or number inputs, etc, and add your IE hacks.

Most common use cases for the HTML5 shiv/shim JS script

I often see people suggesting I include the HTML5 shiv JS script to make HTML5 work in Internet Explorer but I can't find a clear explanation for the most common use cases this will cover.
Might someone give common scenarios of why one would need this JS script?
Also, does it need to be in the <head> or can I put it with the rest of my JS at the bottom of the <body> tag such that it doesn't block the UI thread?
Internet Explorer prior to version 9 refuses to apply any CSS styling to HTML elements it does not recognise, this includes the new elements brought in by HTML5. By creating the elements through the JavaScript DOM it suddenly and magically realises that the elements should indeed be styled.
You can write a naive and simple script that loops over an array of HTML5 tag names you want calling document.createElement(tagName). This may work for you in most cases, however, printing HTML5 pages in IE and adding HTML5 content through innerHTML will cause you further problems at which point it would be an idea to switch to the shiv.
HTML5 shiv can, to my best knowledge, be placed in the head or after the body tag if you prefer. I would recommend using conditional comments so that only IE loads it.

Javascript IE6 getElementsByTagName not working

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)

What are the likely main reasons my website is very slow on IE?

I need to know what can be the main reasons (apart from the basics like grouping CSS selectors, reducing image size, using image sprite etc.) which makes a website slow on Internet Explorer, because my website works fine on the others like FF, chrome etc.
Is it the huge use of Javascript framework (ie. jQuery, extjs, prototype)?
Is it because of the use of plugins based on JS framework?
Should I use core javascript and remove the use of any js framework?
Should I try to avoid using jQuery(document).ready()? in case of jQuery framework?
Above some of the questions which I know and please answer the questions which I couldn't ask because of lesser knowledge about these.
I need to make my website perform well on IE (6,7,8) also please suggest.
Thanks
It has nothing to do with jQuery. The plugins however are hit or miss, and may not be well tested in IE. I'd use at your own risk.
DOM manipulation is very slow in IE. using appendChild (or insertRow) to add multiple nodes (say, 100+ for a long list) is much slower than building a string and doing one innerHTML.
You also want to be careful how you access nodes. Devs tend to rely upon jQuery too much and search for nodes via their class names, like:
$(".evenRows").hover(doSomething);
IE doesn't have a native way of getting a node by class name, so JQ is looping through the entire document and every single element and checking its class name... which needs to be checked via RegExp because it may look like:
class="evenRows yellow foo bar"
Finally, in spite of its improvements, IE8 is still using an old rendering engine - the same as IE6. Don't go crazy with the animations, and don't expect miracles.
As MSIE has a default-limit of 2 simultaneous connections you should minimize the number of requests that are required for building the page(use css-sprites, merge js-and css-files into a single file)
While you need to speed things up in IE, you can still use Firebug to look for places, that consume resources.
Install Yslow and see what it tells you
Run the site under profiler (Yslow or Firebug have one) and look for a bottleneck
It is very difficult to answer general questions like this, but jQuery is unlikely to be the one slowing everything down, just remember to
Use IDs as selectors wherever possible — they are the fastest, i.e. $('#myid')
Avoid using .class selectors without tagname, i.e. $('div.myclass') can be ten times faster than $('.myclass').
and so on
More tips for using jQuery to achieve better performance.
Earlier versions of IE will, in general, run JavaScript slower than later versions of IE, because there have been advances in JavaScript compilation speed since then.

Categories