Gotchas in Internet Explorer 8

Internet Explorer 8 (IE8) is at Release Candidate 1, which means it will be released very shortly. IE8 is a brand-new browser and will represent a considerable shift from IE7/IE6; it will follow standards more closely and will offer much improved CSS 2.1 support. However, because of some of these changes, it is also widely understood that IE8 might break websites that have relied on IE-specific hacks targeted at previous versions of Internet Explorer.

To their credit, the IE development team has been very candid about the changes and have posted a number of blogs and documents aimed at helping web developers prepare for IE8. I was looking over one such page and thought I’d point out what I consider to be some of the biggest ‘gotchas’ so far.

Setting Unsupported CSS Values

Trying to detect support for a specific CSS value through a JavaScript try/catch statement will no longer generate an exception, which means you can’t rely on JavaScript to detect support for specific CSS values anymore.

Assigning CSS values that were unsupported in IE7 but are supported in IE8 Standards Mode will not generate exceptions in IE8 Compatibility View. Some sites use these exceptions to determine if a particular value for a CSS property is supported or not.


try {
   elm.style.display = "table-cell";
} catch(e) {
   // This executes in IE7,
   // but not IE8, regardless of mode
}

Malformed HTML

IE8 will not be as forgiving of malformed HTML markup. This is a great new ‘feature’ in terms of ensuring people (and software) are less sloppy with their markup, but this will certainly cause many, many problems for hundreds of thousands of old, poorly written websites.

Parser error correction for malformed HTML has changed in IE8 Standards Mode. Pages depending on the way IE7 performs error correction may encounter issues as a result.


<ul>
    <li>1.1
        <ul>
            <li>1.1.1</li>
    </li> <!-- Closes 1.1 in IE8, but not IE7 -->
            <li>1.1.2</li>
        </ul>
    </li>
</ul> 

Working with an Element’s Class

Like the malformed HTML ‘feature’, this is another great improvement in IE that will also cause many, many headaches. You see, for years IE wouldn’t let developers use the standard setAttribute("class") method for specifying a class name via JavaScript. Instead, IE required developers to use the proprietary setAttribute("className"). This means that it became commonplace for scripts to check for IE then use class for non-IE browsers and className for IE. Now, you’ll still need to make that check for older versions of IE but find a way to use class for IE8. <sarcasm>This will be fun.</sarcasm>

Don’t get me wrong — I’m excited that IE will finally behave like other browsers in this regard — but it also means that so long as IE6 and IE7 are still around, we’ll have to jump through more hoops to handle class names.

In IE7, “className” had to be used as the attribute name to set and retrieve the class of an element. This has been fixed for standards-compliance in IE8 Standards Mode. Using the old approach will create an attribute named “className” that has no affect on the actual class assigned to an element.


return elm.getAttribute("className");

SOLUTION: Use the standardized name, “class”, instead of “className”.


return elm.getAttribute("class");

CSS Expressions

One of the common hacks for IE’s shortcoming with CSS support has been to use IE’s proprietary CSS expressions, which are basically JavaScript statements embedded in place of a CSS value. While this practice has been frowned upon by most in-the-know web developers, it still wound up being heavily utilized as an ‘easy fix’ type of hack.

IE8 will no longer support CSS expressions. This will make it behave more like other browsers, but will cause problems for those who have relied on CSS expression hacks. Fortunately, it should be relatively easy to move your CSS expressions into your page’s JavaScript as suggested by Microsoft.

Support for CSS Expressions has been removed in IE8 Standards Mode.


/* CSS */
#main {
    background-color: expression(
        (new Date()).getHours()%2 ? "#000" : "#fff"
    );
}

SOLUTION: Refactor to utilize either improved CSS support or DHTML logic.


/* Script */
var elm = document.getElementById("main");
if((new Date()).getHours()%2) {
    elm.style.backgroundColor = "#000";
} else {
    elm.style.backgroundColor = "#fff";
} 

On the whole, I’m excited about the changes IE8 will bring, although it will undoubtedly require site revisions for anyone who uses JavaScript extensively in their projects.

You can read the original Microsoft blog post here.

Lazy loading excanvas.js

excanvas.js is a script that enables developers to use the canvas element in Internet Explorer; since IE doesn’t support canvas or the canvas API, the excanvas script converts (most) canvas commands to Vector Markup Language (VML), the only vector rendering language supported natively in Internet Explorer.

excanvas is designed specifically for Internet Explorer, so most people simply use a conditional comment to load it in IE and avoid loading it in other browsers:


<!--[if IE]>
<script type="text/javascript" src="/scripts/excanvas.js" src="/scripts/excanvas.js">
<![endif]-->

This works fine if you have access to the HTML file that needs to load excanvas, but what if you can’t edit the HTML? This was my predicament with a recent project; I decided to use a lazy loader approach (on-demand loading) and load excanvas.js dynamically.

I started by developing an HTML example page that used the canvas element and had the excanvas.js file hard-coded. Everything worked as planned. I then took out the hard-coded excanvas.js file and replaced it with a JavaScript-based lazy loader. Guess what? It didn’t work.

I scratched my head for a while and did some more testing. The strange thing was that excanvas.js was loading when and where it was supposed to, but the script itself wasn’t firing.

After digging around the excanvas.js source code a bit, I found the problem: the script contains an init function that only gets invoked when the document’s readystate changes. If the document is already loaded, the readystate won’t change and the init function will never fire!

A simple modification to the excanvas.js file fixed the problem:

Original code (starting at line 87 of excanvas.js)


init: function(opt_doc) {
    if (/MSIE/.test(navigator.userAgent) && !window.opera) {
        var doc = opt_doc || document;
        // Create a dummy element so that IE will allow canvas elements to be
        // recognized.
        doc.createElement('canvas');
        doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
    }
},

Modified version


init: function(opt_doc) {
    if (/MSIE/.test(navigator.userAgent) && !window.opera) {
        var doc = opt_doc || document;
        // Create a dummy element so that IE will allow canvas elements to be
        // recognized.
        doc.createElement('canvas');

        if(doc.readyState !== "complete"){

            doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));

        } else {

           this.init_(doc);

        }

    }
},

Basically all we’re doing is checking to see if the readystate is already “completed” before attempting to do attachEvent. If the state is completed, we don’t need attachEvent and can just invoke this.init_ directly.

Update: Alternate solution

January 2014. Unfortunately, the authors of ExCanvas haven’t addressed this issue yet. Since it has been over 3 years since I submitted an issue on their project site, I assume it will not be addressed. (At this point I can’t blame them, who wants to support old versions of IE anyway?)

However, there is some good news if you still need to use ExCanvas: Willis at badsyntax.co came up with a different solution that doesn’t require modifying the source code. I recommend using his technique, as it’s cleaner and allows you to use a CDN copy of ExCanvas instead of maintaining your own copy.

Font replacement techniques

Like many other web professionals, I’m tired of the limited font set we have to work with. Gee, should I use Verdana on this site or Georgia? Maybe Arial? Meh. Bor-ing.

The merits and legal implications of CSS3’s proposed @font-face are being hotly debated, which means the proposal is going nowhere fast. Unfortunately, this also means we won’t have native browser support for a wider set of fonts anytime soon. In the meantime our sites (and e-learning courses) will continue to use the same old ho-hum fonts.

Are there any other options? The answer is yes, but none of them are perfect. The most common (and cross-browser) solution is to use what’s referred to as the image-replacement technique; the basic idea is to use a program like Photoshop to create an image containing your text in a nice font, then display the image instead of the original HTML text. Since this requires making a custom image for every line of text, it’s generally only used for headings. Chris Coyier wrote a nice article on the topic about a year ago, and rounded up the most popular techniques at the time.

Some enterprising developers have come up with alternative image replacement techniques that are quite impressive. The most popular (by far) is sIFR, a Flash-based solution that can replace any specified text on your page dynamically, using small SWF files. This solution doesn’t require custom images, is cross-browser, and is extremely flexible. Alas, it also requires JavaScript and Flash Player; if used for a lot of text on the screen, you wind up with a bunch of SWFs floating around, which definitely eats up CPU cycles and slows down older computers.

More recently, there have been interesting attempts at using SVG, canvas, and VML to draw fonts dynamically. One early implementation of this was typeface.js [link no longer available], which appeared to be a great idea but was difficult to use. More recently, Cufon has been getting a lot of buzz. I think it’s very nice and is easy to use, but it also has a few drawbacks, namely what happens if CSS is disabled in the browser:

cufon-screenshot

Image: Cufon in action, but with CSS disabled. Cufon-generated text is blue, the original text is black.

Any text generated by Cufon (and some similar scripts) is treated as an inline image — canvas elements are functional equivalents to images. The original text is hidden using CSS. If CSS is disabled, the original text shows up side-by-side with the generated text. This causes all sorts of problems.

Another drawback is selectability; Cufon and other canvas/VML-based systems have problems making text selectable in all browsers. To be fair, this is a problem with just about every image replacement technique except sIFR, which uses the power of the Flash Player plugin to get around the issue.

I’d like to be able to harness the creative possibilities of typography in my e-learning courses but really wish I didn’t have to jump through all these hoops to do it. Which system will I wind up using? Probably a combination of old-school static images created in Photoshop and sIFR. I feel that sIFR is the best option for my projects because of its greater accessibility and flexibility, but only when I know my target audience has Flash Player. I’m also very impressed by Cufon and hope they manage to take it to the next level to be on-par with sIFR.

The pipwerks forum is dead, long live the new eLearning Technology and Development Google Group!

A year ago this week, I launched the not-for-profit and ad-free pipwerks E-Learning Development Forum. It was mostly intended to be a way for me to answer questions about some of my projects, such as the SCORM API wrapper, SCORM ActionScript classes, and my many Captivate hacks. The forum wasn’t a vanity project so much as an attempt to avoid email… I’d rather post answers online where everyone can see them than reply to individual emails. I had also hoped other people in the e-learning community would get involved and ask/answer questions beyond the scope of my pipwerks projects.

Now that a year has passed, I decided to step back and evaluate the success of the forum. The numbers aren’t bad: over 200 members, over 550 posts. Of course, it isn’t about the numbers, but about helping people; I’d like to think that most of those 200 people found the answers they were looking for. This is great, and makes me happy. If I helped even one person, the forum can be considered a success.

However, I also noticed a considerable lack of participation from others. Aside from a few helpful folks, I wound up answering most of the questions myself. This means it wasn’t so much a forum as an “Ask Philip” column. Not exactly what I had in mind.

When combined with the effort it takes to maintain a website (security patches, compatibility issues, styling, etc.), the forum started to feel more like a weight on my shoulders than anything else. So, as of today, I have closed down the forum and moved over to a Google Group: the eLearning Technology and Development group.

I’ve been using Google Groups for over a year with the SWFObject Google Group and Aaron Silvers’ Flash For Learning Google Group (no longer online). It isn’t a perfect system, but I’ve learned to enjoy its simplicity. It’s also free and relieves me of administrative hassles such as applying updates and backing up data. Sweet. Plus you can use Google Groups via email, which means you never even need to visit the site. Bonus.

I’d like to say thank you to all the people who posted in the pipwerks forum, and invite you to join me in the new eLearning Technology and Development group.

I’d also like to ask anyone and everyone who develops e-learning to drop by and sign up for the eLearning Technology and Development group. Ask questions — lots of questions — and let’s see if we can get a good community going!

PS: If you’re wondering why I bothered creating a new group considering there are many other discussions groups/forums out there, the answer is simple: no product favoritism and no advertising. Product forums by vendors such as Adobe and Articulate are focused solely on their products, while bulletin boards by organizations such as the eLearning Guild tend to have a ton of ads and a focus on their events and sponsors. I’d like less clutter in my life, and a simple Google Group (even with the AdSense ads) is a nice clean way to handle discussions. Hope you agree!

Image-Free Progress Bar using MooTools and Canvas

As part of my ongoing experiments with <canvas>, I decided to convert an image-based progress bar to an image-free canvas-based system. I just finished whipping up a proof-of-concept; it uses MooTools to generate the canvas and CSS code. No images were harmed in the making of this progress bar.

More info later (time permitting)