Wednesday 30 January 2013

Writing Cross-Browser Code


Same Markup: Writing Cross-Browser Code

I recently presented a session at MIX10 covering the topic of cross-browser best practices. The key focus of the session was not on a particular feature, but on how web developers can reliably write code that adapts to cross-browser differences.
IE9 reduces these differences and enables developers to use the same markup across browsers. Enabling the same markup means supporting the right features to make the same HTML, JavaScript, and CSS "just work". Yet enabling the same markup on the web is an n-way street. Each browser must provide the right features, but developers also need to properly detect and use those features when they are available.
With respect to properly detecting features I'll share examples of issues and best practices I've seen on the web. Most importantly I'll offer patterns that can help you rewrite similar code to take advantage of the same markup. For now I'll focus on more basic examples to illustrate the core concepts, but future posts will cover more complex examples in greater detail. Let me start by sharing a set of guidelines:

Same Markup: Core Guidelines

  • DO
    • Feature Detection
      Test whether a browser supports a feature before using it.
    • Behavior Detection
      Test for known issues before applying a workaround.
  • DON'T
    • Detect Specific Browsers
      Also known as browser detection. Don't use the identity of a browser (e.g. navigator.userAgent) to alter page behavior.
    • Assume Unrelated Features
      Don't perform feature detection for one feature, and then proceed to use a different feature.
These guidelines are important because most web pages today are a hybrid of code meant for multiple different browsers. Mixed in with this code are the tests for choosing what runs where. The conditions used in such tests determine how a page adapts to run on different browsers. From script at least, these tests generally take the following form:
if( condition ) {
    // Primary Code
} else {
    // Alternate Code
}
The conditions used in such tests are often not based on whether a given feature is available, but rather on which browser is in use. Therein lies the problem: altering code based on a specific browser limits the adaptability of web pages. The end result can be as serious as the page breaking when a new browser is released. Other times a legacy workaround continues to be used, even when that workaround is no longer needed.

DON'T: Detect Specific Browsers - Event Registration Example

You can easily test the effects yourself. The code below switches between event models based on the detected browser (a bad practice). Running this in IE9 illustrates that addEventListener doesn't get used, even though it's supported.
// [TR] Different listeners added for illustration
function f1() { document.write("addEventListener was used"); }
function f2() { document.write("attachEvent was used"); }

// DON'T USE THIS: Detecting specific browsers
if(navigator.userAgent.indexOf("MSIE") == -1) {
    window.addEventListener("load", f1, false);
} else {
    window.attachEvent("onload", f2);
}
Try It!
IE9 Output: attachEvent was used

DO: Feature Detection - Event Registration Example

The following code shows how to switch between event models correctly using feature detection. Instead of checking for IE, it checks for the availability of addEventListener itself. This code will continue to fallback correctly in legacy browsers without addEventListener, but more importantly will now ALWAYS use addEventListener when it is available. In short, this approach enables running the same markup in IE9 and other browsers.
// [TR] Different listeners added for illustration
function f1() { document.write("addEventListener was used"); }
function f2() { document.write("attachEvent was used"); }

// Use this: Feature Detection
if(window.addEventListener) {
    window.addEventListener("load", f1, false);
} else if(window.attachEvent) {
    window.attachEvent("onload", f2);
}
Try It!
IE9 Output: addEventListener was used
The challenge of getting the right code to run in the right browser is why feature detection has been seeing increased adoption in pages and frameworks. Feature detection enables cross-browser code to "just work" without requiring you to know the capabilities of each and every browser ahead of time. One framework which relies almost entirely on feature detection is jQuery. In fact the jQuery.support documentation details how you can use jQuery's feature detection in your own site.

DO: Behavior Detection - getElementById Example from jQuery

In addition to straight feature detection, jQuery also makes extensive use of behavior detection. It does this by running a tests for known issues to determine if certain workarounds are needed. Below is a slightly modified snippet from the jQuery source code that tests whether getElementById includes elements with "name" attributes. This is a legacy IE bug that was fixed in IE8.
// We're going to inject a fake input element with a specified name
var form = document.createElement("div"),
id = "script" + (new Date).getTime();
form.innerHTML = "<a name='" + id + "'/>";

// Inject it into the root element, check its status, and remove it quickly
var root = document.documentElement;
root.insertBefore( form, root.firstChild );

// The workaround has to do additional checks after a getElementById
// Which slows things down for other browsers (hence the branching)
if ( document.getElementById( id ) ) { 
    // ... Workaround code ...
  
    // [TR] Added for illustration
    document.write("getElementById workaround was used");
}
// [TR] Added for illustration
else document.write("No workaround was used");

root.removeChild( form );
Try It!
IE9 Output: No workaround was used

DON'T: Assume Unrelated Features - Real-World Example

The final piece I want to touch on is assuming unrelated features. This is something we saw a number of examples of as we did compatibility testing for IE8. Sites suffering from this problem would perform feature detection for one feature, then continue to use a variety of other features without testing whether they were supported. The following modified example illustrates a case where a site was using the postMessage and addEventListener APIs, but was only testing for the former. Support for postMessage was added in IE8, butaddEventListener was not added until IE9. If you run this example unmodified in IE8, it results in a script error, preventing any following script from executing.
// [TR] Try-catch block added to trap the script error in IE8
try { 
    function fn() {}

    if(window.postMessage) {
        window.addEventListener("message", fn, false);
 
        // [TR] Added for illustration
        document.write("Message listener registered successfully");
    } else {
        // ... workaround for when postMessage is unavailable ...
  
        // [TR] Added for illustration
        document.write("postMessage is not supported, using workaround");
    }
 
} catch(e) {
    document.write("Message listener registration FAILED");
}
Try It!
IE7 Output: postMessage is not supported, using workaround
IE8 Output: Message listener registration FAILED
IE9 Output: Message listener registered successfully

DO: Feature Detection - Test for Unrelated Features Independently

A corrected version of the above example is provided below. It checks for BOTH postMessage and addEventListener before using them.
function fn() {}

if(window.postMessage) {
    if(window.addEventListener) {
        window.addEventListener("message", fn, false);
    } else if(window.attachEvent) {
        window.attachEvent("onmessage", fn);
    }
 
    // [TR] Added for illustration
    document.write("Message listener registered successfully");
} else {
    // ... workaround for when postMessage is unavailable ...
    // [TR] Added for illustration
    document.write("postMessage is not supported, using workaround");
}
Try It!
IE7 Output: postMessage is not supported, using workaround
IE8 Output: Message listener registered successfully
IE9 Output: Message listener registered successfully

Moving Forward

I've outlined the benefits of using feature and behavior detection over detecting specific browsers, but my intent is for this to be the start of a conversation, not the end of it. Watch for future posts covering more detailed examples of issues we've seen on the web and how they can be coded to work correctly across all browsers. We'll also be examining our own sites and encouraging them to update to follow these practices. Please feel free to ask questions and share insights, especially around specific issues you've encountered while developing your own pages.
Tony Ross
Program Manager
  • #
    Again, just switch to webkit. Concentrate your efforts in the user interface.
    The wheel ( decent engine that support near 100% of old and modern web standards ) was invented years ago and it is rolling.
    Just my 2 cents.
  • #
    On IE there exists "navigator.plugins" but it is always empty.
  • #
    @Menace,
    "Being a web programmer, having to support, now with the coming of IE9, 4 browsers separatedly, make my work a bit dull and boring while fixing the entire site for IE, but I happily code once for standards browsers like Firefox and Chrome."
    What 4 browsers separately? IE6 is horrible, IE7 is bad, sure, but IE8 is mostly not requiring any specific fixes. So you just code once, and it mostly works across Firefox, IE8, and Chrome. I have spent countless hours to fix webpages for IE6 and IE7, but I don't remember spending much time fixing webpages for IE8 at all.
    For today's web developers, you can treat IE8 and IE9 as "standards browsers" most of the time already, unlike IE6 and IE7.
    As far as I see, you can just code once, and expect it to work all okay in Firefox, Chrome, Opera, Safari, and IE9. Then you may need to fix some minor things with just under minutes for IE8. It's the IE6 and IE7 specific problems that mostly always take hours upon hours to fix.
  • #
    »With the new features that Internet Explorer 4.0 provides, it may be desirable for both client-side and server-side scripts to determine the browser version, so that a Web application can either take advantage of new functionality, or degrade gracefully, depending on the version of the currently-running browser.«
  • #
    @carlos
    Which webkit should they use? Browsers based on webkit all render differently and support different features.  Especially the mobile versions of webkit.
    Besides they can do better if they want.
  • #
  • #
    @wechrome
    IE8 does not work well at all if there is javascript on the page. We have so many problems with getting our sites to work with IE8 that it takes up about 20% of our development time and sometimes it is impossible to make IE8 work within the allotted resource allowances so we just turn the advanced features off.
    The necessity to do that disgusts me, but until IE dies or Microsoft grows a conscience or a soul we are stuck with having to hack our sites for the benefit of the uninformed users that use IE8 (or even worse IE6 or IE7).
    Yes I likewise wish that MS dumped their core and adopt Webkit or Gecko (or even Presto)  and dress them up. MS can indeed build a nice interface and GUI.
  • #
    i just stick to a css framework (960 grid) and js library (jquery), so i've got little or no problems with cross-browser compatibility.
    let the guys at jquery handle the headaches :D
  • #
    Thanks for a good article.
    Would all the whiners here rather have Microsoft NOT telling web developers to use good programming?
  • #
    @Menace, I'm talking about real world production site, not some flashy bleeding-edge experimental sites.
    And yes IE8 still lacks some nice visual effects, but those are not needed. Unlike IE6/7 that can usually makes a site completely a mess, with IE8 it's easy to degrade gracefully, so those people with Opera/Chrome can see a flashy site, while those with IE8 sees a non-flashy, but still very much functional site.
    If we give browser scores, and Opera/Chrome get 100 points, Firefox gets 95 point, then I'd say IE8 gets 80 points, compared to IE7 at 40 points, IE6 at 20 points.
    If you insist on making the whole site flashy and pixel-perfect in all browsers, then yes IE8 can cost you some time, but IE6 would cost you exponentially more time. But if you aim for a functional site for everyone and give those with Opera/Chrome some extra nice effects (which is what most real world web developer are doing nowadays, as trying to implement those same effects in IE6 is simply practically impossible), then IE8 hardly cost you any extra work. It's the IE6 and IE7 that are the big pain, you mostly don't need IE8 specific hacks and the site is still quite functional.
    And what part of CSS2.1 is IE8 poor at? IE8 is poor at CCS3 for sure, but its CSS2.1 implementation is mostly quite okay.
    @vmajor, if you put 20% development for IE8 specific problems, I'd wonder how much time you put for IE7 and IE6? I'd say IE7 would cost 10 times more development time, and IE6 100 times more time, than IE8.
    Really, if you want some super advanced and complex Javascript features, then reserve them for Opera/Chrome, and turn them off for IE versions less than 9.
    Again turning off some advanced effects is easy, as compared to fixing a complete mess from the ground up.
    Like I said, it's quite easy to do graceful degradation with IE8, usually taking just minutes. Not supporting some advanced features and technology (IE8) is one thing, doing some basic things the wrong way (IE6/7) is another completely different, and exponentially more severe, problem.
  • #
    @Menance - I guess the question for you si what kind of developer world do you live in? No browser is perfect, especially when it comes to javascript. It's our job as developers to work within the constraints of all browsers, aiming for progressive enhancement enables people on up to date browsers to enjoy a rich user experience, while people on older browsers can still access the content. Don't forget it is the content people want, not just a pretty picture. If you can't get a site to work it's time to check in with the design teamand make amends there.
    Of course you'll spend some time on IE6 but this shouldn't be a lot, mostly with layout and checking for script errors - the latter a very good use of the browser. Again, a few more checks and fixes for IE7 but never really any that warrent an IE7 specific stylesheet. IE8, once you're familiar with it, throws up as many problems as a firefox or safari - it's a good browser with great CSS2.1 support.
    IE9 is looking amazing and we should really be thanking the team to embracing the developer communities rather than bashing them every time they post on this blog. Are you feeding back to the working groups MS are now part of? This is how you, as a developer, can make a difference. IE6 is really starting to fade away and it's amazing to be part of another round of browser wars/advances that are really pushing web development forward in a way not seen for the last few years.
  • #
    Or you could just do:
    <!IE < 9 cond comment>
     <script src="legacyIEHacks.js"></script>
    <!end legacy IE hacks-->
    then do all your normal code using standards based calls.
    Call document.getElementById(id) and it just works.  Use jQuery's $('#id') and it just works.
    I have no intention of littering my code with hacks and tests to handle legacy bugs in IE6, IE7, & IE8.
  • #
    Thanks for this article. The info is quite helpful.
  • #
    Actually, I think the "DONT" postMessage example is a relatively legitimate one. The event model is a pretty integral part of anything you do with the DOM, so... not supporting it sucks for the ones not supporting it.
    If this was authored before IE8 was out, I hereby grant absolution to the developer responsible.
    If this was authored when IE8 was out... well then I guess it's between god and the dev.
    It's obviously hitting some of the wrong guys (the MS devs cleaning up after the mess), but ya took tha job, ya know? My sympathy is limited.
  • #
    @carlos and vmajor: In what specific way would Webkit (in place of Trident 5) improve IE9?
  • #
    @Tony Ross [MSFT]
    First of all, your post is entirely about javascript and javascript code (browser forking). In my opinion, it has nothing to do with markup or same markup (repeated 7 times in your post).
    Checking the capability and support of an object is one thing but checking it for the correct object is as equally important. E.g. When Opera 7 came out, it had support for addEventListener but only for DOM nodes, not for the window object. This sort of situation can happen. It's always better, best and more reliable to test support on the object which is going to be used. Your post does not explicitly mention this. You mentioned the guideline of same method or same feature but not same object or same DOM node.
    I have always avoided to register the load event to the window because document and window are loaded asynchronuously. In my opinion, it always better to register the load event on the body element, not the window, in other to do whatever script you want.
    Coding manners
    ==============
    var form = document.createElement("div")
    is quite awkward and counter-intuitive. Why not
    var objDiv = document.createElement("div")
    ? or even a more semantic variable name serving the purpose of the code?
    form.innerHTML = "<a name='" + id + "'/>";
    Can you create a minimized anchor in HTML5? Why create an empty anchor in any HTML document to begin with?
    Why create and try to DOM-insert an empty anchor before the document root element? This does not seem coherent, logical or even possible to begin with. (FWIW, the script fails in Konqueror 4.4.2.)
    If all this is allowed in HTML5, then it certainly is weird looking to me.
    Other references
    ===============
    Your post is very silent on what other browser manufacturers' documentation have been provided during years.
    Object detection
    at Apple
    Towards capability detection at Opera
    Developing Cross Browser/Cross Platform Pages
    A Strategy That Works: Object/Feature Detecting from comp.lang.javascript FAQ
    > We'll also be examining our own sites and encouraging them to update to follow these practices.
    Yes. That is very very important to do this. Utterly important. The X-UA-compatible meta-tag system would not have been any useful if Microsoft/MSDN had started to explain how to detect support for method or feature in objects or DOM nodes years ago.
    regards, Gérard
  • #
    Why create and try to DOM-insert an empty anchor before the document root element?
    root.insertBefore( form, root.firstChild );
    Correction. The code inserts it before the root's first child which is the <head> node. It is definitely not a good example. I do not understand how this can work without javascript errors...
    regards, Gérard
  • #
    I don't know how Microsoft can even dare to lecture web developers about proper web standard practices when their browser doesn't even follow the correct standards! It is like being told to use your umbrella during a flood.
    I have to use browser detection because some versions of IE, especially IE6, don't render some of my layouts correctly.  In that way, an alternative layout can be displayed to those users (along with a message telling them to get a proper browser!)
    Maybe when you start to show a proper commitment to web standards, people will take note of what you are saying here.
  • #
    <<The X-UA-compatible meta-tag system would not have been any useful if Microsoft/MSDN had started to explain how to detect support for method or feature in objects or DOM nodes years ago.>>
    Pure, unsubstantiated fantasy, yet again.
    MSDN documentation does not magically make for better web code. MSDN documentation *plainly* stated that STRICT mode would result in new behavior in new browser versions, and yet (surprise, surprise) there was shock and dismay from the web community when this happened in IE7 and begging for the "UA-Compatible" system which was eventually introduced.
    Rather than wasting your time rewriting history in the IEBlog comments, how about you start your own blog evangelizing best practices, and try to find some way to get readers to follow your guidance? They're clearly not following the best-practices listed on MSDN for the last decade.
  • #
    @Victoria: I hope you are not using JavaScript for this.
  • #
    @wechrome
    > If we give browser scores, and Opera/Chrome get 100 points, Firefox gets 95 point, then I'd say IE8 gets 80 points, compared to IE7 at 40 points, IE6 at 20 points.
    On which topic are those scores about or coming from? Ease of developing a web-standards-compliant website? I may agree with you on those scores... but you did not define on what topic or perspective such scores apply to.
    > what part of CSS2.1 is IE8 poor at?
    Margin collapsing, clearance, integer implementation (for z-index, orphans and widows), border-style: hidden, min- and max- properties, cursor parsing, visibility, etc.
    @Wurst
    > "navigator.plugins" but it is always empty.
    Many people reported this already, including in IE Blog in 2009.
    regards, Gérard
  • #
    > We'll also be examining our own sites and encouraging them to update to follow these practices.
    That's great. You may want to start with the browser ballot page (http://www.browserchoice.eu/BrowserChoice/browserchoice_en.htm ) - I already created an improved version for you:http://crisp.tweakblogs.net/blog/3751/the-ms-browser-ballot-page-analyzed.html ;)
  • #
    tino, the "ballot" page was obviously designed by eu-government lawyers.
  • #
    @Wurst re: the KB link
    "APPLIES TO
       * Microsoft Internet Explorer 3.0
       * Microsoft Internet Explorer 3.01
       * Microsoft Internet Explorer 3.02
       * Microsoft Internet Explorer 4.0 128-Bit Edition"
    I *really* hope you don't support those...
  • #
    @Will Peavy
    "@carlos and vmajor: In what specific way would Webkit (in place of Trident 5) improve IE9?"
    For example, IE will instantly scalate from 28% to 88% of SVG support (*)
  • #
    Since when has a scripting language suddenly changed to a markup language?
    HTML -> Markup
    ECMA/JavaScript -> Scripting.
    Clue is in the name really.
  • #
    @graham I deal with QUALITY online, semantic HTML coding and EYECANDY for the prospects/clietns of my clients, I use 960.gs, I use jquery 1.4.2, I use Flash for somethings Javascript is too slow to do, and have a lot of clients, and been doing web for a lot of time. Don't come pointing fingers.
  • #
    @Menace: while I can't fault you for using jQuery, and I applaud your quest for quality, you haven't done "real" JS coding if you haven't tried doing object detection without standing on the shoulders of giants.
    But still, there is a difference to be made, right now.
    CSS support and DOM support.
    While CSS support improved a LOT between IE 6 and IE 8 (IE 8 is, indeed, almost painless to synchronize with other browsers while IE 6 actually REQUIRES a few kb of CSS fixes - IE 7 fixes most of these, but also has its own quirks and regressions), the DOM saw very little improvement between the 3 versions.
    If I must take a very simple example where object detection fails, or gets VERY difficult, is with innerHTML: if you check that it is supported, it IS supported. If you try to run it as a write property, it works.
    If you try to use it as a write property on a table or table body, you get a fatal error of 'unknown' origin.
    And that's in IE 6/7/8 only.
  • #
    This is all very good advice.  There's far too much code out there doing browser sniffing rather than behavior detection.  And the "assuming unrelated features" problem will undoubtedly cause real issues once IE9 is released with addEventListener() and more.  Thanks for making this post.
  • #
    @Mitch 74:
    ... you haven't done "real" JS coding if you haven't tried doing object detection without standing on the shoulders of giants ...
    Really? Seriously? So if someone wrote an implementation of a linked list in Javascript, or say, a large LOB application using ExtJs/JQuery/a.n.other framework, or any other number of complex things, they still wouldn't have done "real" javascript coding? I guess if the definition of doing "real" javascript coding is "doing object detection", you're utterly correct. In this instance though, I think you're quite far from there. If that's the case, perhaps we should all go back to coding in assembly? ;)
  • #
    @Rob: I wasn't being derogatory; I just wanted to emphasize how, using libraries like jQuery, which abstract all this stuff of "object detection and quirks workaround" in a browser, hides away the trouble that people that develop for a browser without these libraries (for performance and/or size reasons, or simply because they actually MAKE those libraries) may encounter.
    That does NOT detract from the actual skill of the programmer; however, since the topic at hand is object detection, I'll say, and I stand by what I say, developing something from A to Z for all browsers is a PAIN. If you're doing ECMAscript on top of jQuery, then it means you NEED each and every user to download 24 Kb of jQuery libraries (that's the current, already gzipped, code-packed version) on top of your own code. If you're programming for internal use, you don't have too many visitors, alright; if you have thousands of visitors a day, then it means megabytes of bandwidth.
    If I take my own situation, object detection code FOR MY OWN USE requires, compressed and packed, around 3K. Total code stands at 10 K. If I had used jQuery, I would have needed 30 K total (some, but not all, of my non-detection code would probably not be required with jQuery).
    With 10 000 visitors/month, most of them unique (no caching)  and not including bots, that would have meant 200 Mbytes/month extra traffic. Just for jQuery. Bandwidth ain't cheap, and I have a tight budget.
  • #
    Mitch, Google would be happy to host JQuery on their ultra-fast CDN for you, with long-lived cache headers. Since it's shared cross-site, chances are good it's already in the end-user's cache anyway.
  • #
    @Mitch: Also, where are you hosting? I get 400gigs/month for $27 bucks. So, in your example, the marginal bandwidth cost is about 1.3 cents. Which is less than most programmers make per minute.
  • #
    @Mitch 74 well, there's something called cache and exist for solely a reason. When you control your cache the way you want, you won't have any bandwidth problems over the major benefit it brings. If you know how to create a gzip/custom headers/packaging proxy in PHP, you wouldn't be questioning about bandwidth.
    I always coded using "vanilla" Javascript, since 1998, until I first met jQuery in 2007. The main reason I stuck with it is the cross-browser facility. If IE wouldn't exist anymore, I think I would just be using querySelector/All and still plain vanilla javascript. The fancy flashy stuff is flash's job (until canvas and svg is par to it).
  • #
    @Matt - not in today's economy :-)
  • #
    @Jack
    > Would all the whiners here rather have Microsoft NOT telling web developers to use good programming?
    Oject/method support detection has been proposed and recommended many years ago (july 26 2004) in this blog and many years before that. In 2008, Scott Dickens [MSFT] continued to promote user agent string detection in Code Focus magazine. MSDN has never stopped promoting, explaining, examplifying user agent string detection and has been silent about object/method support detection.
    comp.lang.javascript newsgroup FAQ notes and Peter-Paul Koch quirksmode site were promoting and explaining about object/method support detection a lot sooner than 2004. Again, IE Team/Microsoft/MSDN have been promoting user agent string detection for probably over 10 years.
    The work on IE7 and IE8 (2005 to 2008) was in no way whatsoever preventing IE Team/MSDN to update their documentation and tutorials and in no way whatsoever preventing Microsoft/MSDN from upgrading their coding techniques and practices. We have excellent reasons to state and claim that IE Team/MSDN/Microsoft controlled websites are not what they should be.
    Gérard Talbot
  • #
    Gerard: Have you noticed that the problem with lying on the internet is that it's so easy to get caught?
    Scott's 2008 article simply explained what user-agent string IE8 sent, and it in *no way suggested* that sites should be writing code that depends upon it.
    As for MSDN, yes, there are decade-old articles about IE4 that are clearly marked as "retired" and not updated. On the other hand, the most popular article "Detecting Internet Explorer" explicitly says: "It is not recommended that you block access to content based on the user-agent string of the browser." and "Serving content based solely on the user-agent string is often an unreliable way to detect the full capabilities of the browser."
    So, I say again, rather than wasting your time rewriting history in the IEBlog comments, how about you start your own blog evangelizing best practices, and try to find some way to get readers to follow your guidance? They're clearly not following the best-practices listed on MSDN for the last decade.
  • #
    @Menace: as I said, I get thousands of UNIQUE visitors to my websites (different IPs and all). As such, caching is useless - so I plainly deactivated caching in some cases, because otherwise I'd get nags from people using stale copies (for some reasons, IE sometimes refuses to check if the server copy is newer - oh, right, "auto" caching is so efficient). And, I also mentioned that my JS libraries were already packed and compressed.
    I could simply link to the jQuery website and use THEIR bandwidth for jQuery. I'd rather not, it's rude.
    @Luke: while there are, indeed, rather recent articles that promote object detection, sadly I have to side with Gérard here. Many many MANY MSDN articles still promote UA detection.
    And there's one good reason for it: you can try and perform object detection as much as you want, the fact is that many objects are claimed as supported by IE - but are so quirky you need to check that they work properly before you use them.
    Case in point, to use document.getElementById, should you check:
    - that it merely is supported?
    Or should you also check that it returns:
    - a collection if several elements share the same ID?
    - an element that has the required value, but for its 'name' property?
    - an ID with a different case?
    Answer:
    - IE 6 returns a collection if several elements have the same ID. This is erroneous: only one element should have a given ID. So, getElementById should NEVER return a collection.
    - IE 7 looks at name and ID for that property. It's completely wrong: several elements may have the same name (think select-one), and name != ID
    - IE 7 is case insensitive on attribute values: that is completely wrong.
    And, right there, MSDN defines that (I cite):
    "Returns the first object with the specified ID or NAME."
    Title: Defining Document Compatibility
    I cite the second line of the first Jscript example in that page:
    if (window.navigator.appName == "Microsoft Internet Explorer")
    What's wrong with that, let's see... First, it uses a lax comparison (==) instead of a strict one (both are supposed to be strings, thus you should use === to ensure there is no unwanted type conversion happening). Second, it detects the user agent's name.
    Yay object detection in MSDN.
  • #
    <<(for some reasons, IE sometimes refuses to check if the server copy is newer)>>
    There are no known issues with over-aggressive caching when the server sends proper cache directives. To understand how HTTP caching works, please see http://www.enhanceie.com/redir/?id=httpperf.
    <<I could simply link to the jQuery website and use THEIR bandwidth for jQuery.>>
    I believe John actually takes technical measures to prevent that, or has in the past.
  • #
    Regarding jQuery hosting, it's not only acceptable, but encouraged to use the copy hosted on Google's CDN.  They put it (and other libraries) there specifically for that very reason.
    My recent research has shown that a surprisingly high number of the Alexa top 100,000 are using it too.  So, you do have a good chance of a cache hit primed by another site, even if you don't have any repeat users of your own.
  • #
    Here is an interesting feature test to try
       if (typeof (google) == 'object')
       { sAns = 'Yes'; }
       else
       { sAns = 'No'; }
       document.writeln("<p><span>Google Gears - " + sAns + "</span></p>");
       if (typeof (chromium) == 'object')
       { sAns = 'Yes'; }
       else
       { sAns = 'No'; }
       document.writeln("<p><span>Google Chromium - " + sAns + "</span></p>");
    Try this on a page loaded in Chromium or in IE8 where Google Gears has been installed.
  • #
    @Dave Ward
    Microsoft is also hosting jQuery:
  • #
    Hallo, will IE9 include a download manager to be able to pause downloads and maybe with container file and Torrent File support?
    How about including an option to save a browser session maybe even saving it to a file or some kind of hibernation for IE9?
    Why don't You plan an IE9 GDI Version for Windows XP?
    Thanks.
    Sincerely Jelges
  • #
    Why not Microsoft, Mozilla, Apple, Google, Opera etc get together and develop a common standard?
    In this way, developers will have to write one single code for all browsers and it will be less work for you as well.
  • #
    @Jelges: Even if the devs wanted to support XP they'd have to get it past the Microsoft lawyers.
  • #
    @Adi: that's what the W3C is, basically. Sadly, it took 6 years for MS to remember they were members, and then 4 more years to remember that, "oh, right - we should also implement what is studied there". Or something. Gross, biased oversimplification on my part - the IE team started implementing stuff anew in IE 7, and started doing it correctly in 8. And 9 is getting mightily interesting.
    @EricLaw: no known issue with aggressive caching? Well then, how comes that my host defines "Expires" at 1981, and I still get caching?
    @Matt: your hosting budget is ten times mine. Literally. Yes, my boss is Scrooge's spiritual heir. And the host disabled caching, and compression, and... whatever. Making saving a byte wherever possible, a priority. If I could manually gzip my files and send them with appropriate headers, I'd do it too (I tried: headers are overwritten).
  • #
    Just to re-iterate my previous comment to another post, it would be great to be able to opt into IE9's script engine only.  With IE8 you have to run in IE8 standards mode to access the new scripting features, meaning you have to target multiple versions of IE using different CSS which can be quite awkward and time consuming.
    PS EricLaw did respond to that comment and I think he missed my point of opting into the scripting engine, I totally understand forcing the scripting engine might break old sites but if I were given the choice with a particular command (or meta tag) it wouldn't be a problem.
  • #
    @Andy: the problem isn't so much with the scripting engine itself (it is actually shipped separately from IE) than it is with IE's DOM support (the objects that IE supports can be manipulated with Jscript)...
  • #
    I think I.E needs his own automatic update, a lof of people doesnt run windows update so there browser is obsolete.
  • #
    <<<a lof of people doesnt run windows update >>>
    I'm not sure where you get your information, mrx-- you're not exactly in a position to know this.
    If users aren't keeping the rest of Windows up-to-date, they're insecure anyway.
  • #
    @Andy: No, I didn't miss your point; as I replied to your original comment, I simply agree with Mitch.
    @Mitch: Pretend I'm from Missouri-- please provide a repro URL or network capture (www.fiddlercap.com). Keep in mind that HTTP Cache-Control headers override the Expires header. Who is your hosting provider, by the way?
    @Hoink: I'm not sure what you're implying?
  • #
    @Mitch: Compression header overwritten? I knew that transparent proxies used for information control purposes (censoring) would do that, but hosting providers?!
  • #
    OT: IE Testing Center has a faulty test according to Mozilla devs: https://bugzilla.mozilla.org/show_bug.cgi?id=554016
  • #
    @EricLaw[MSFT]:
    I was just guessing. From the blog of another MS employee:
    « Although the XmlLite developers wanted to provide a redistributable for Windows XP, they never managed to get it past the Microsoft lawyers. »
  • #
    @Hoink: IE8 on XP uses XMLLite. "Redistributable" means that 3rd parties may ship it.
  • #
    Microsoft has completely abandoned Windows XP by not supporting IE9. This is the worst kiss-off to any Microsoft product I've ever seen, and one'd think MS would show a little more respect to its best-selling OS of all time. But the reality is, Microsoft is looking ahead to new revenue and not behind to money that's already in the bank. And hundreds of millions of people will be running XP for years to come, despite Microsoft's best efforts at selling them a later Windows version. This flies in the face of its publicly-stated life cycle support plans.
  • #
    @EricLaw: headers...
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Provider: Nuxit (yes, in France)
    Sample URL: see above... Alright, I don't update it THAT often any more. It's very unsettling when I do update the thing and test it "live", and all browsers happily chug along with refreshing the cache, ...but IE. And I mean IE 5,6,7 and 8 (actually, since I deactivated scripting for IE6-, I get trouble with 7, 8 and 9DP1).
    @Wurst: inexpensive hosts on shared servers will save resources by disabling compression. But, since you have stuff like CMS that try to enable it by forcibly defining HTTP headers, you may need (in order to prevent an HTTP 500 error) to prevent said headers from being sent. "Rewriting" is too strong a word, sorry - it's more a header restriction.
  • #
    <<This flies in the face of its publicly-stated life cycle support plans.>>
    No, it absolutely does not.
    And for those keeping score, Win7 is by far the fastest selling OS of all time.
  • #
    @Mitch74: By "link above" do you mean the MoneyShop.fr link?
    If so, I'm rather confused. Your homepage is GZIP compressed, while you earlier said you wasn't allowed?
    On the homepage itself, I do see the no-cache directives, including the bogus "pre-check=0" and "post-check=0" directives added by PHP for no reason (http://blogs.msdn.com/ieinternals/archive/2009/07/20/Using-post_2D00_check-and-pre_2D00_check-cache-directives.aspx).
    However, on the resources (images,script,css) your page uses, I see no caching directives at all, which permits their future reuse without validation.
    I don't see any caching of your homepage itself; on every visit, I see a new request for the content. It's not even a conditional request, because the homepage itself provides neither an ETAG nor a Last-Modified time.
  • #
    @EricLaw: OK, now I get it: I investigated more. And I can confirm one thing: it's only text/html content that allows (and even forces) compression. Any other content (application/xhtml+xml, text/x-javascript, text/css) will not be compressed - even if required through htaccess or in file header modifications.
    And, silly me, I send application/xhtml+xml MIMEtypes to those browsers (meaning, Firefox, Safari, Chrome(ium), Opera, IE 9) that explicitly support it (yeah, well, it helps me detect mistakes in my mark-up faster).
    And I must admit, I program in Firefox first (which shows me headers with a key press) and test in IE last (which requires me starting a VM, then load Fiddler, then open IE, then look at page headers... impractical).
    Now, about the CSS and Javascript being cacheable: well, I hardly can put META http-equiv elements in it, can I... And since the cache headers are pretty much frozen by my host (I can add extra headers, but not modify existing ones), well, tough for me.
    Note that when I test a new version of my code, I usually make use of Ctrl+F5 (same thing in IE and Fx, it bypasses the cache) - but even when I do that, I sometimes get "stale" code in IE 8. Never in Fx or other browsers.
    Thinking harder about it, and 'logging' how I test my code updates, it may be that the peeve I have against IE's cache is that Ctrl+F5 is less reliable in it than in Fx.
    Considering that a debug session may have me press that combo a hundred times a day, it becomes a bit of a blur. Still, would you mind having a harder look at Ctrl+F5's behaviour in IE 9?
    Note: suggestions to disable the cache in developer tools will be ignored. I need to see if my customers may get a mere annoyance or a complete break (so switching back'n'forth ain't a solution, while a working Ctrl+F5 would be).
  • #
    @Mitch: I'm sorry to hear your web host isn't working well for you. I'm not sure whether they have any local competition which might offer you a better experience.
    As for the browser issues, I spend a LOT of time looking at Internet Explorer's network behavior, and I've never seen the behavior you describe. I've never seen CTRL+F5 fail to unconditionally re-request resources, for instance.
    Does your ISP perhaps have a transparent proxy which is doing overaggressive and illegal caching?
  • #
    @EricLaw: AFAIK, no proxy - and if it were the case, it would affect all browsers, not IE alone (except if they set up the proxy to rat on IE...). I can usually solve IE's problem with hitting Ctrl+F5 twice, but not always.
    There recently was a time when I had to open developer tools, flush the cache, close IE 8, then reopen it and open again to see the actual files; this occurred even on my development machine, and the only thing between the server and IE 8 was the virtual machine's NAT (and Windows' proxy)
    It could have been a matter of having two tabs with the website open, and refreshing one didn't work as the other (thus, with stale copies) was already loaded.
    Maybe I'm the odd one out there, as I develop on a LAMP physical machine (without a proxy nor cache), and test in a VM'ed Windows. I don't see how that would affect the results, though - but I could be that one-in-a-million person affected by that Shroedinbug. Or could it come from my webpages' size? I try to keep them small (under 32K), maybe I trigger something... Frankly, I don't know.
  • #
    > it would affect all browsers
    You mentioned that you were sending XHTML to the other browsers and HTML to IE. That could well explain the difference in a network intermediary's behavior.
    If you ever manage to get a network capture of bad behavior (e.g. with Ethereal, Charles, Fiddler, etc), I'd love to have a look-- just mail it to me.  Thanks.
  • #
    « Does your ISP perhaps have a transparent proxy which is doing overaggressive and illegal caching? »
    I heard about 3G ISPs using similar stupid and page-breaking methods.
  • #
    @EricLaw: I will, for sure.
    If I can catch it, that is...
    @Wurst: I've heard about stuff like that. But as far as I know, my dev machine doesn't have a proxy.
  • #
    @Gérard Talbot,
    "On which topic are those scores about or coming from? Ease of developing a web-standards-compliant website? I may agree with you on those scores... but you did not define on what topic or perspective such scores apply to."
    Since the topic I was talking about was developing a functional site across different browsers, the scores are obvious about the ease of developing a functional site (not necessarily a fully W3C-validated site) across those browsers, and how much trouble (or the lack thereof) they have given me in the past.
    For the past two months, I have encountered about a couple dozen problems in my current project, and ALL of them are IE6 and IE7 specific. Especially IE6, it's just frustrating that perfectly valid markup can result in IE6 RANDOMLY show or hide a part of the page at each refresh, and after two days of fruitless attempts at fixing the problem, putting one extra useless div around another existing div at some completely unrelated place somehow fixes the problem O_o
    And it's not even any complex site at all, all simple effects, no flashy stuff, that I haven't encounter a single IE8 problem for those same couple months. It just works with IE8 like it does with Firefox/Opera/Chrome. the existence of IE6 and IE7 is the sole reason that I'm currently four days behind my schedule *_*
    It's those kind of illogical, at times seemingly random, problems from IE6 and IE7 that frustrate the most.
    "Margin collapsing, clearance, integer implementation (for z-index, orphans and widows), border-style: hidden, min- and max- properties, cursor parsing, visibility, etc."
    All browsers have some quirky CSS2.1 implementation, and I'd say IE8 is NOT poorer than any other standards-compliant browser out there at CSS2.1
    And it surely doesn't cost me much time as a normal web developer, I'll be fully happy if only IE6 and IE7 disappear.
  • #
    @wechrome: I disabled all Javascript and advanced (level 2/2.1) CSS on my websites at the start of the month for IE 6 and lower. Interestingly, and although I had extensively tested my websites under IE6 (and even IE 5), my efficiency and conversion ratios have _increased_ ever since. That does include IE 6 users.
    My current recommendation is thus:
    Develop for an "IE 8" feature level:
    - it's not too hard having CSS that works cross-browser with that version
    - you don't need TOO MANY IE7 hacks and workaround to make IE7 usable
    - its DOM support is still awful and, again, supporting IE 7 (and 6) isn't too difficult
    Then, create a "handheld/limited" profile:
    - with limited CSS, which would fit a small screen better anyway,
    - with limited/disabled Javascript, which should always be considered possible: NoScript is VERY popular on Firefox, and anyway there are many 'basic' HTML 4.01 and CSS features that can replace a bunch of JS code and still remain quite user-friendly.
    Not that both parts are not necessarily codependent.
    I'll cite, for example, on CSS alone:
    - using :hover
    - using display:none
    - using :before and :after with 'content'
    - using overflow (and even overflow-x/y, which although not standard are pretty well supported)
    In HTML, you may:
    - use all lower case, and use the same term for id and name
    - use 'title' extensively
    - use ID'ed DIV's that you then position with CSS (handhelds can't deal with tables well, and when they do, they do so inconsistently)
    - use HTML tags such as sub, sup, pre, address, cite, abbr, fieldset etc. with their intended use. Interestingly, once you're done with pushing 'pure' HTML use, you may notice that your page doesn't look half bad, and is already quite easy to use.
    - do NOT rely upon HTML automatisms, such as list elements or paragraphs closing: always specify where they should end, and don't play cute with block and inline elements: a paragraph should NOT contain a table (eventhough IE 7 and lower will gladly accept an inlined table), so close your paragraphs before you run into another block level element. If you want to position a table next to a paragraph, don't forget that:
    * a table can have a CAPTION
    * positioning falls into the 'style' category: deal with it with CSS.
    And, last but not least, VALIDATE YOUR CODE! While browsers fly off the handle on erroneous markup, even IE 5/6 can behave in an almost predictable fashion if you feed them valid code.
  • #
    Mitch: While your strategy seems reasonable, you shouldn't believe the hype... NoScript is not "VERY popular". A single digit percentage of firefox users actually have it (and a smaller portion have it turned on correctly). Giorgio would have you believe otherwise and presents misleading stats. For instance, he counts every update as a "download" but he updates the thing nearly every other day, meaning the download count is hundreds or thousands of times higher than the user count.

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...