Equals vs Strictly Equals (== vs ===)

Pop Quiz:


alert(2 == '2');   // true or false?
If you answered false, well… sorry. You'd be wrong. How about this:
function Steve()
{
  this.toString = function() { return 'Steve is cool!'; };
}

var s = new Steve();
alert(s == 'Steve is cool!');   // true or false?

False? Actually, no, it's true.

Kind of puzzling isn't it?

Read on to find out what's going on here.

Continue reading Equals vs Strictly Equals (== vs ===)

Fixing IE's .attachEvent(..) failures

Welcome to another addition of Beating IE into submission!

It's a well know fact that IE's proprietary .attachEvent(..) function fails with regards to a number of W3C recommendations:

  1. Fails to honor the 'this' keyword when wiring up events to DOM objects.
  2. Fails to enforce just one function wired to a given event for a given object.
  3. Fails to name events appropriately, that is: without prefixing event names with the word 'on'.
  4. Fails to accept a 3rd parameter, useCapture, which would allow for event capture instead of event bubbling.

In this blog entry, I'm going to look at how to solve the first 3 of these issues (the 4th is more complicated is beyond the scope of this entry).

Before continuing, you may want to review one of my previous entries: The .call(..) and the .apply(..) functions. Understanding these functions will be helpful in understading the techniques we're going to use to fix IE's .attachEvent(..) failures.

Read on to learn more.

Continue reading Fixing IE's .attachEvent(..) failures

Converting to Pixels with javascript

A few entries back, I wrote about CSS Computed Style. In that blog entry, I discussed a cross-browser javascript function to retrieve the computed style of a DOM element on the page.

If you need a quick refresher… javascript doesn't allow you to access arbitrary style properties of a DOM element via .style unless you've previously set that property using javascript OR if you've defined the style using an inline style attribute of the DOM element.

This is where CSS Computed Style can really come in handy. By retrieving an element's computed style, you can retrieve style properties just as they were when you defined them in your CSS file (regardless of whether or not you've ever set them in javascript).

But there's a gotcha (isn't there always). If you remember, IE doesn't really support computed style. Instead, IE offers .currentStyle which, while similar, is most definitely NOT the same thing.

Perhaps the most inconvenient shortcoming of .currentStyle is the fact that it fails to normalize all units to pixels, as the W3C recommends.

In this blog entry, I'm going to explain how to write a function that will convert these non-pixel values to pixels for you.

Read on to learn more.

Continue reading Converting to Pixels with javascript

The IE Resize Bug (revisited)

To see the resize demo in action, browse to the revised Resize Demo Page.

In my last blog entry, I talked about an IE reisze issue (IE failing to properly distinguish between a resize that happens to the <body> element and one that happens to the window (or viewport)).

In that blog entry, I proposed a solution for getting around this issue by ditching IE's built-in resize event entirely and writing some custom code to manage it instead. Specifically, the technique centered around an absolutely positioned DIV whose CSS instructed it to fill the viewport. We then used a bit of javascript (executed at regular intervals) to monitor the size of the DIV.

While this technique worked in my sample page, it failed when put to the test in a real world scenerio. The major problem I ran into was that if the <body> element were manually made smaller or larger any time during the resize logic (something you might want to do to manage scrollbars and page layout) some strange behavior would ensue.

Given that my technique turned out to be less robust that I would have liked, I went back to the drawing board to try to come up with a better design.

What I ended up with was a similar technique, but one that didn't require any CSS (which is a plus) and which centered around a getViewportSize(..) function courtesy of James Edwards (aka Brothercake) and Cameron Adams (highly recommend picking up their book: "The Javascript Anthology").

So enough of my babbling. Let's take a look at the revised sample:


<!DOCTYPE html PUBLIC "-W3CDTD XHTML 1.0 TransitionalEN" "http:www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

  <head>
    <script type = "text/javascript">
   function resize()
   {
    var currentSize = getViewportSize();
    if (currentSize[0] != g_prevSize[0] || currentSize[1] != g_prevSize[1])
    {
     g_prevSize = currentSize;
     debug.value = 'the window was resized: ' +
                   document.documentElement.clientWidth + ', ' +
                   document.documentElement.clientHeight;
    }
   }

   function init()
   {
    window.debug = document.getElementById('debug');
    window.g_prevSize = getViewportSize();
    setInterval(resize, 100);
   }

   function grow()
   {
    var p = document.createElement('p');
    p.appendChild(document.createTextNode('This is a paragraph'));
    document.body.appendChild(p);
   }


   function getViewportSize()
   {
    var size = [0, 0];
    if (typeof window.innerWidth != 'undefined')
    {
     size = [ window.innerWidth, window.innerHeight ];
    }
    else if (typeof document.documentElement != 'undefined' &amp;&amp;
             typeof document.documentElement.clientWidth != 'undefined' &amp;&amp;
             document.documentElement.clientWidth != 0)
    {
     size = [ document.documentElement.clientWidth, document.documentElement.clientHeight ];
    }
    else
    {
     size = [ document.getElementsByTagName('body')[0].clientWidth,
              document.getElementsByTagName('body')[0].clientHeight ];
    }

    return size;
   }
  </script>

  <style type = "text/css">
   body { border: 2px solid red; }
  </style>
 </head>

 <div id = "resizer"></div>
 <body onload = "init()">

  <input id = "debug" type = "text" size = "80" /><br />


  <button id = "btn" onclick = "grow()">Grow</button>
 </body>

</html>

The conept here is pretty simple. Like the technique used in the previous blog entry, once again we create a global reference to the previous viewport size (g_prevSize) when the page initially loads and then call setInterval(resize, 100); to monitor that viewport size at 100ms intervals.

In the resize(..) function itself, we determine the current viewport size (currentSize) and compare that against g_prevSize. If the width of currentSize (represented by index 0 in the array returned by the getViewportSize(..) function) is [i]different[/i] from the width of g_prevSize OR if the height of currentSize (represented by index 1) is different from the height of g_prevSize, then we know that the viewport size has changed, and hence, the window must have been resized.

Once we've determined that a resize has occurred, we simply update the value of g_prevSize and then go ahead with our resize logic.

If your resize logic is complicated and consists of many lines of code (or perhaps even if it doesn't) you may want to consider calling a separate function for it. In a real-world scenerio for example, after I determine that a resize needs to take place, I call a function, doResize(..).

I find this to be a bit cleaner than stuffing the resize detection and the resize logic all in one function.

So I think this is pretty straight-forward and not tremendously different from the technique used in my previous blog entry (though hopefully a bit more robust).

Comments welcome.

Beating the IE Resize Bug

So it turns out that there are actually a number of problems with the solution I've proposed in this blog entry. It seems to work for my sample page, but when put to the test in a real world scenerio, it failed miserably.

An updated solution has been posted: Beating the IE Resize Bug (revisited).

And you can see this updated solution in action here.

There is a bug (at least I consider it a bug) in IE (versions 6 and 7) in which the clarity between window.onresize and body.onresize is muddied. This can cause quite a problem for developers and even render the client's browser unresponsive (throttling the CPU to near 100%) if you're not very careful.

I've discussed this with numerous members of the IE development team, and I was able to gain some valuable insight. The general feeling was that this behavior is by design. It may be (and I can understand the motivation to do this), but I'm still not so sure I agree with it (it just doesn't feel logical to me).

After quite a bit of back-and-forth, I finally got in touch with one developer who seemed to think that this is the wrong behavior (in strict mode). Personally, I feel that this behavior is undesirable in either strict mode or transitional, but I guess just having the issue acknowledged is a good start.

The problem remains though, because this bug affects developers today, and it won't be addressed for quite some time (if I'm not mistaken, the official IE7 release is not going to address it).

So in this blog entry, my goal is to introduce a work-around that I've come up with for dealing with this issue.

Read on to learn more.

Continue reading Beating the IE Resize Bug

Mutual Exclusion with minimal javascript

With toilet cleaner becoming so popular for building web applications (oh c'mon, toilet cleaner — it's not that hard to figure out), it's not at all uncommon to run into a scenario in which you need to make one option, among a list of options, appear to be selected without doing any sort of page refresh or linking to another page.

Often, only one of these options can appear selected at a time, so one might call these options mutually exclusive (see wikipedia for an in-depth explanation of what mutual exclusion means in the world of programming).

Now, there's a good way to accomplish this and there's a bad way; an easy way and a tedious way; an elegant way and an ugly way. And if you're anything like most poeple, you probably tend towards the latter approach.

In this blog entry, I hope to illustrate how to accomplish mutual exclusive link selection (visually) with an astonishingly small amount of Javascript code.

Continue reading Mutual Exclusion with minimal javascript

NaN (and what it means to javascript)

Not surprisingly, NaN in Javascript repesents "Not a number." You probably knew that, but here's something you may not have known.

NaN is a 'number'! Well, sort of.

Actually, it's typeof NaN that yields 'number', which, if you ask me, is little bizarre, though not completely illogical (depending on my mood).

Continue reading NaN (and what it means to javascript)

The javascript ternary operator

Pop Quiz: Do you understand the Javascript ternary operator?

You said "yes" didn't you? Alright hotshot. See if you can analyze these statements correctly:


var x = 'steve_' + 10 == 10 ? 'A' : 'B';
alert(x);

If you answered 'steve_A', you'd be wrong.

How about:


var y = 'steve_' + (10 == 10) ? 'C' : 'D';
alert(y);

You think the answer is 'steve_C'? Wrong again.

How about:


var z = 'steve_' + (10 == 10 ? 'E' : 'F');
alert(z);

'steve_E'? Ok, that one was easy.

But what about the first two examples? Why aren't they yielding the obvious answer? Read on to find out.

Continue reading The javascript ternary operator