IE9′s Viewport Code is Broken

Internet Explorer 9 Beta sometimes gives the wrong answer when we ask for the size of the viewport (viewable area of the browser window).  On an HTML document with “X-UA compatible” set to IE=7 and Windows font DPI set to 125% or 150% with the browser window maximized, IE9 claims the viewport is a few pixels larger than it actually is.

Soon after Microsoft released IE9 Beta, we began receiving numerous tech support e-mails regarding our map page being stuck in an endless loop where the map continually refreshes.  None of our engineers were able to reproduce this problem, so we classified this as a non-issue because the problem only occurred in IE9 beta, which is not an official release.  But the tech support e-mails kept coming in, so we decided to find out exactly what was going on.  We did not know if it was a problem in our code or a bug on Microsoft’s part.

To get a better understanding of the situation, we turned to our troubled users for help.  Our first lead came from Nitin G. who mentioned that setting the display font very small cured his problem.  This helped, but we needed more information.  Mike P., another Redfin user, noticed that the problem only occurred when the browser window is maximized.  He also reported seeing scroll bars appear and disappear during the infinite loop, and the loop stopping when he opened developer tools (F12).  Not only did he provide us with screenshots, but he sent us a video capture of the bug as it was happening.  Here are a couple of the screenshots:

(Figure 1)

(Figure 2)

The first thing we wanted to do was to match his exact search and display.  We tried changing the display resolution, but with no luck.  Then we remembered Nitin’s comment about shrinking the font size, and it was clear what we needed to do to reproduce the problem.  Change the font DPI settings in Windows!

We successfully reproduced the problem by setting Window’s display text DPI to a percentage larger than standard and maximizing the window.  By simply setting the DPI to 125% or 150%, this bug caused scroll bars to appear (Figure 1) and disappear (Figure 2) on the map page, causing our map to resize, which in-turn executes a new search.  Scroll bars only appeared during a search, not when a new search is kicked-off.   So now we have a reason for the infinite loop, but what is the underlying cause?  It turns out that during a search, we lock our UI by creating an HTML element spanning the entire browser’s viewport, preventing users from searching the map as listings are being populated.  It is when we lock our UI that the scroll bars appear, and this only happens when “X-UA compatible” is set to IE=7 in the HTML document.

We use Dojo extensively in our site, and one of its uses is to obtain the browser’s viewport size by calling dojo.window.getBox(), which contains the viewport’s height and width.  These properties return values larger than the actual size of the viewport when the browser window is maximized, which cause scroll bars to appear when we call on the UI locker.  We created a reduced test case where we used dojo.window.getBox() to make a <div> that spans the entire browser viewport:

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>

<html>

<head>

<meta http-equiv=”X-UA-Compatible” content=”IE=7″ >

<title>Dojo Viewport and Popup Test</title>

<style type=”text/css”>

@import “http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/resources/dojo.css”;

@import “http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/nihilo/Dialog.css”;

@import “http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/dijit.css”;

@import “http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/nihilo/nihilo.css”

</style>

<script src=”http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js”></script>

<script>

dojo.require(“dijit.form.Button”);

dojo.require(“dijit.Dialog”);

var viewportShowing = false;

var dialog = null;

function viewportPressed() {

var viewport = dijit.getViewport();

var viewportNode = dojo.byId(“viewportID”);

if(!this.viewportShowing) {

viewportNode.style.backgroundColor = “gray”;

viewportNode.style.width = viewport.w + “px”;

viewportNode.style.height = viewport.h + “px”;

dojo.style(viewportNode, “opacity”, 1);

}

else {

viewportNode.style.backgroundColor = “white”;

viewportNode.style.width = “150px”;

viewportNode.style.height = “”;

}

this.viewportShowing = !this.viewportShowing;

}

function popupPressed() {

if(!this.dialog) {

this.dialog = new dijit.Dialog({

title: “Testing Dojo Pop-up”,

content: “test content”,

style: “width: 200px”

});

this.dialog.startup();

}

this.dialog.show();

}

</script>

</head>

<body class=”nihilo”>

<div style=”background-color:white;width:150px”>

<button dojoType=”dijit.form.Button” onClick=”viewportPressed();”>Viewport</button>

<button dojoType=”dijit.form.Button” onClick=”popupPressed();”>Pop-up</button>

</div>

</body>

</html>

Sure enough, we reproduced the problem.  This led us to believe that this is a bug with Dojo, but we needed to be certain.  Digging deeper into Dojo’s code, dojo.window.getBox() uses document.documentElement and calls on the element’s clientHeight and clientWidth properties to get the viewport dimensions.  We created another, similar reduced test case, but without Dojo:

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>

<html>

<head>

<meta http-equiv=”X-UA-Compatible” content=”IE=7″ >

<title>IE9 documentElement height/width Test</title>

<script type=”text/javascript”>

function buttonPressed() {

var docElement = document.documentElement;

var viewportNode = document.getElementById(“viewportID”);

if(!this.pressedButton) {

viewportNode.style.backgroundColor = “gray”;

viewportNode.style.width = docElement.clientWidth + “px”;

viewportNode.style.height = docElement.clientHeight + “px”;

}

else {

viewportNode.style.backgroundColor = “white”;

viewportNode.style.width = “150px”;

viewportNode.style.height = “”;

}

this.pressedButton = !this.pressedButton;

}

</script>

</head>

<body style=”margin:0px”>

<div style=”background-color:white;width:150px”>

<button onClick=”buttonPressed();”>Click me!</button>

</div>

</body>

</html>

The problem was still there!  This confirms that there is a bug with IE9’s viewport code, and not Dojo.  Although the problem is not with Dojo, we fixed this bug by modifying Dojo’s method for returning the viewport because Dojo calls on the DOM for the dimensions.  Specifically, we subtract a few pixels from the height and width.

Special thanks goes to Nitin G. and Mike P. for helping us solve the mysterious IE9 infinite loop bug.  Without their help and the help of our other avid Redfin users, this bug would have gone unnoticed.  We use and consider many feedbacks and tech support problems to improve our site time and time again.  We appreciate everyone’s help.

Discussion

  • http://www.markten-pow.ca/ Condos for sale Ajax

    I am so glad after read this fantastic and informative article.