пятница, 13 марта 2009 г.

Site Compatibility and IE8

Original: Site Compatibility and IE8

Reports of broken sites are an important part of the feedback the IE team receives from the community. When we receive a report of a broken site, we take it and identify the core issue causing the problem. A number of these issues end up being side effects of changes we deliberately made in IE8, but even these are useful. They help us identify which IE8 changes have the broadest compatibility impact. In this post I'll share some of these issues with you so you can quickly identify problems affecting your site when migrating from IE7 to IE8.

Differences between IE8 Compatibility View and IE7

We strive to make Compatibility View behave as much like IE7 as possible, but we do make exceptions. Many of these exceptions enable improved security and accessibility features immediately, even for sites that have not yet migrated to IE8 Standards Mode.

Cross Document Communication

Hacks enabling cross-domain, cross-document communication have been disabled for security reasons. SOLUTION: Use Cross Document Messaging (XDM) to work around this change.

Extending the Event Object

IE exposes new properties for certain AJAX features such as Cross Document Messaging (XDM), even in Compatibility View. Adding custom properties to the Event object can conflict with these new properties, such as "source". SOLUTION: Change the names of conflicting custom properties to avoid collision.

event.source = myObject; // Read-only in IE8

event.mySource = myObject;

Attribute Ordering

The ordering of attributes has changed, affecting the attributes collection as well as the values of innerHTML and outerHTML. Pages depending on a specific attribute ordering may break. SOLUTION: Reference attributes by name as opposed to their position within the attributes collection.

attr = elm.attributes[1]; // May differ in IE8

attr = elm.attributes["id"];

Setting Unsupported CSS Values

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. SOLUTION: Short of version detection, this is a difficult issue to work around. If this behavior is essential to a page, updating the page to run in IE8 Standards Mode may be the best approach.

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

Differences Between IE8 Standards Mode and IE8 Compatibility View

We see the majority of compatibility issues in IE8 Standards Mode. Most of these occur when sites expect legacy behavior that no longer exists in IE8 Standards Mode. Upgrading your site to run in IE8 Standards Mode is the best option in the long run, but in the interim you can quickly fix these types of issues by running your site in Compatibility Mode. This is described in Jefferson's post on the EmulateIE7 meta tag. In addition to the issues mentioned above, here's what you should be aware of.

Version Detection

While other changes are typically the root cause, version detection is where pages often go wrong. This is largely because making the right decision before a browser exists can be next to impossible. Nevertheless, incorrect version detection in conditional comments, script, and on the server side can easily break a page in IE8. This is especially true for conditional comments. They are used by a number of pages to apply fix-up CSS that IE8 no longer needs. SOLUTION: Update pages to make appropriate version decisions. When possible, use object detection instead.

<!--[if IE]
    <link rel="stylesheet" type="text/css" src="ie.css" />
[endif]-->

<!--[if lte IE 7]
    <link rel="stylesheet" type="text/css" src="ie.css" />
[endif]-->

Object Detection

Object detection works great when used correctly. However some pages assume the existence of one feature based upon the presence of another, leading to problems when both features are not implemented in the same release. SOLUTION: Perform proper object-detection for each feature used.

if(window.postMessage) {
    window.addEventListener(
        "load",
        myHandler,
        false
    );
}

if(window.addEventListener) {
    window.addEventListener(
        "load",
        myHandler,
        false
    );
}

Malformed HTML

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. SOLUTION: Ensure your markup is well-formed and valid.

<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>

<ul>
    <li>1.1
        <ul>
            <li>1.1.1</li>
    <!-- </li> -->
            <li>1.1.2</li>
        </ul>
    </li>
</ul&g

Working with an Element's Class

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. SOLUTION: Use the standardized name, "class", instead of "className".

return elm.getAttribute("className");

return elm.getAttribute("class");

GetElementById

The method getElementById is now case-sensitive and no longer searches name attributes. SOLUTION: Ensure case-correctness and use getElementsByName when searching name attributes.

<div id="Test"></div>
<script type="text/javascript">
    // No element is found because of case difference
    var test = document.getElementById("test");
</script>

<div id="Test"></div>
<script type="text/javascript">
    // Element Test is found
    var test = document.getElementById("Test")
</script>

Generic CSS Prefix Selectors

Generic CSS prefix selectors are no longer supported in IE8 Standards Mode in order to provide standards-compliant CSS parsing. Most often, this affects pages trying to use CSS to attach behaviors to VML elements. This can cause a script error if set dynamically, or a silent failure when hard-coded into the CSS of a page. Ultimately the rule is not applied, leading to effects such as VML not displaying on a page. SOLUTION: Explicitly specify each tag name you want to match when using CSS prefix selectors.

v\:* {
    behavior: url(#default#VML);
}

v\:polyline,
v\:line {
    behavior: url(#default#VML);
}

CSS Expressions

Support for CSS Expressions has been removed in IE8 Standards Mode. SOLUTION: Refactor to utilize either improved CSS support or DHTML logic.

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

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

Native JSON Object

IE8 now has a native JSON object, compliant with the JSON support described in the ES3.1 Proposal Working Draft. Some pages detect the native JSON object, then use it in a non-standard way. This typically results in a script error and breaks handling of AJAX requests. SOLUTION: Define a custom JSON object when using a non-standard syntax or alter the rest of the code to use the standardized syntax.

if(!window.JSON) JSON = myJSON;
JSON.encode(obj); // Not part of the standard

JSON = myJSON;
JSON.encode(obj);

Initial CSS Property Values

Unset properties on the currentStyle object now return their initial value. Relying on the old initial values for CSS properties such as z-index can cause problems. This is the root cause of issues with the ASP.NET menu control. SOLUTION: Perform a check for both the backwards compatible value and the standardized initial value.

var zIndex = elm.currentStyle.zIndex;
if(zIndex == 0) {
    // custom code
}

var zIndex = elm.currentStyle.zIndex;
if(zIndex == 0 || zIndex == "auto") {
    // custom code
}

Unspecified CSS Property Values

Unset properties on the style object now return the empty string for improved compliance with the DOM Level 2 Style Specification. Expecting CSS properties such as z-index to have a value when they have not been explicitly set can lead to problems. SOLUTION: Perform a check for both the backwards compatible value and the empty string.

var zIndex = elm.style.zIndex;
if(zIndex === 0) {
    // custom code
}

var zIndex = elm.style.zIndex;
if(zIndex === 0 || zIndex === "") {
    // custom code
}

Attributes Collection

The attributes collection no longer contains all possible attributes recognized by IE, but only those that have been explicitly set. Scripts can fail if they depend on natively supported attributes always being present as they were in IE7. SOLUTION: Do not assume an attribute will be in the attributes collection. Check for existence first.

var attr = elm.attributes["checked"];
// Potential script error in IE8
return attr.specified;

var attr = elm.attributes["checked"];
if(attr) return attr.specified;
else return false;

That's all I have for now. If you encounter anything else you feel should be on the list, please add it to the comments to help others out.

Tony Ross
Program Manager

Комментариев нет: