Friday, September 5, 2008

Line 0 Object Required Internet Explorer Javascript error - aka the dangers of using CSS Expressions

One of my favorite mechanisms to do IE-specific CSS is to use the so-called dynamic properties available to IE5+ browsers. Firefox and Opera ignore these tags, so if, for instance you need a div of id "foo" to be 110 pixels in IE and 100 pixels in all other browsers, you would just do this:

#foo {
width: 100px;
width: expression('110px');
}

I spent the better part of the day trying to track down a Line 0. Object Required Javascript bug that, when hit, required me to close IE using Task Manager. I could not figure this one out and finally resorted to reconstructing the entire page, line-by-line until I found the problem.

I finally determined it occurred only when I added a <textarea> tag to the page. My current project is a Ruby on Rails app, which necessarily indludes the Prototype Library, so I initally wrote off this weirdity to the vagaries of Prototype and its many tens of thousands of lines of code.

In this context, an input type=text tag would do fine, so I switched to that and moved on.

Quite by accident, I stumbled across this section in my CSS file:

.WordBubble textarea {
overflow:hidden;
border:solid 1px lightBlue;
height:30px;
width:expression(document.getElementById('WordBubble').offsetWidth-66);
}

And WHALA, the answer!

Thinking to reuse a WordBalloon construct I had developed, I had modified this CSS to play off of .WordBubble the className vs the original #WordBubble the ID. Therefore, when I used the original:

<div id="WordBubble" class="WordBubble">
<textarea>
</div>

things worked as expected.

However, when using:

<div id="AnotherWordBubble" class="WordBubble">
<textarea>
</div>

The CSS, when evaluating the dynamic property, could not find "WordBubble" as it did not exist.

Although I realize this posting is somewhat confusing (I barely understand it myself), what I am trying to say is "When you get a Line 0, Object Expected" Javascript error and can't figure out where it comes from, check your CSS for Expression use.

Shannon

Tuesday, March 18, 2008

parseInt Bug in Firefox, IE6 and IE7

Quick Entry:

There is a bug in shipping versions of Internet Explorer and Firefox wherein if you attempt to use parseInt on a number with leading zeros, the value returned will be incorrect for "08" and for "09" due to the Javascript interpreter thinking these are, in fact, Octal numbers (and there being no "Octal" value greater than 7, the value returned is "0").

Try it.  Copy/Paste the following Javascript into your browser's url:

javascript:alert(parseInt("08"))

Anyway, a somewhat esoteric bug perhaps but it did cause an infinite loop today when I was attempting to scan over a date range where the dates were stored with leading zeroes.

The fix?

USE parseInt( var, 10) instead.

The second parameter ensures that the parseInt operation will be done using base10

Tuesday, March 11, 2008

fetchNVPValue - routine to extract a value from a querystring

There are probably more efficient - and more bullet-proof - ways to do this, but figured I had better capture this before I forgot that I wrote it.

Shannon Norrell

////////////////////////////////////////////////////////////////////////////////
//
// fetchNVPValue( string aNVPName, string aURL )
//           Extracts the value of a Named Value Pair (NVP) from a URL
//       eg: fetchNVPValue( "name", "http://mypage.com?id=123&name=Shannon&foo=bar" ) returns "Shannon"
//
////////////////////////////////////////////////////////////////////////////////
function fetchNVPValue( aNVPName, aURL ) {
  var retVal = "";
  var bItsInThereSomeWhere = (aURL.toLowerCase().indexOf(aNVPName) > -1);
  // If we have a URL, a name to look for and it's in there somewhere ...
  if ( aNVPName && aURL && bItsInThereSomeWhere ) {
    var theURL = aURL.toLowerCase().replace(/\+/g, ' ');    // Turn all '+' signs back into spaces, if applicable
    var args = theURL.split("&");
    for (var i=0;i<args.length;i++) {
      var nvp = args[i].split("="); // Break out each argument out into a NVP
      var name  = unescape(nvp[0]);
      if (name==aNVPName) {
        retVal = nvp[1];
        break;
      }
    }
  }
  // If we still haven't extracted it and it's in there somewhere, the Named value follows a "?" in the URL, rather than a &
  if (( retVal == "") && bItsInThereSomeWhere) {
    if (aURL.toLowerCase().indexOf("?" + aNVPName) > -1) {
      retVal = aURL.split("?")[1].split("=")[1];
    }
  }
  return retVal;
}