Category Archives: IE

Checked attribute of checkboxes- IE versus FireFox

In FireFox, <input type="checkbox" name="checkme" value="ok" "checked"> results in the checkbox being checked by default. In IE (version 7 – haven’t tried 8), it does not. This is one of the few times FireFox is more liberal than IE, and wrong. The correct code is: <input type="checkbox" name="checkme" value="ok" checked="checked">

See this W3C specification.

It’s a bit difficult to find the rule on this page, but if you scroll down to section 17.4 The INPUT element you’ll see this text for the checked attribute:

checked (checked) #IMPLIED — for radio buttons and check boxes —

Even then, it’s still confusing, because if you click the link for the ‘checked’ attribute, you’ll see it referred to as ‘this boolean attribute’. While it’s correct that it is a switch – either “checked” or nothing, it’s not a true boolean – either ‘true’ or ‘false’. Anyway, this one bit me because I wrote some markup with checkboxes and only tested the page in FireFox. In my test, all the checkboxes were checked, by default, which is what I wanted. The IE users got a different result altogether.

Update: Chrome also requires that you use the correct (strict) syntax.

How To Create A Global Event Object For Both IE and FireFox

How To Create A Global Event Object For FireFox and IE

Disconnecting Behaviour from Content

Recent articles on Javascript recommend separating content from behaviour, much the same way as you should separate content (HTML) from layout (CSS). This means registering event handlers for page elements at the script level rather than attaching code to specific elements. This is a great idea, and one which all of us Javascript coders should adopt. Also, your scripts should be cross-browser compliant, at least for IE and FireFox. This post explains how to handle events that are attached to specific events in a manner that provides IE and FireFox compliance with minimal changes to your script.

Here’s an example of a behaviour that is too closely tied to content:

  <input type="test" name="phone1" onclick="editphone();">

To separate content from behaviour you can code this inside the <head> portion of your page:

<script>
// Use this instead of <body onload="init();"> :
window.attachEvent('onload', init);

function init()
{
  document.getElementById('phone').attachEvent('onclick',doSomething);

}
</script>

Then, the input tag looks like this (sans the onclick attribute):

	<input type="test" name="phone"  id="phone" >

(this is IE compliant code – see Quirksmode Advanced Event Handling for cross-browser solutions).

You can also add an event handler for your entire document, so you can trap a given event such as click for any element on your page:

 document.attachEvent('onclick',  dosomething);

The dosomething function can then check the element on which the event occurred, and take appropriate action, like so:

function dosomething(e)
{
// get handle to object event occurred on:
  var EventObj = window.event.srcElement;
  if (EventOjb.id == 'phone') alert('You clicked on the phone number');
  // etc...
}

This is also an IE-specific solution, and PPK explains in detail how to code for both FireFox and IE.

Unobtrusive Solution For Existing Closely Linked Presentation-Behaviour Markup

This is all well and good if you use advanced event handlers as described above. But what if you have a bunch of legacy HTML and script that uses event handlers that are attached directly to the content? It turns out this presents problems for FireFox. First, I’ll show the problem, then present a solution that works for both.

The Problem

For example:

<a  id="link1' onClick="youclickedme('newpopup1');">Click me!</a>

In this case, the function “youclickedme” is supposed to be a function that can be called by any number of elements on the page. It expects a parameter that is unrelated to the link itself. So what if you want to know what element the onclick event happened for? Consider this script:

function youclickedme(parm1)
{
 if window.event.srcElement.id = "link1"   // do something.
}

Here we are able to detect the object the event occurred on because IE has a global variable called event that is available anywhere in your code. FireFox, on the other hand, has no such global variable. Instead, it uses a local event variable (e) that is populated when an event that is registered is triggered. So, borrowing from PPK at Quirksmode, here’s a cross-browser function to detect the type of an event:

function doSomething(e) {
 if (!e) var e = window.event;
 alert(e.type);
}

This function checks to see if a local event object has been created and passed to the event handler, which it will be in FireFox. If e is not defined, then the function assumes the IE global event variable window.event exists.

The lack of existence of the global variable window.event means the “youclickedme” script will fail in FireFox. Also, there is no easy way to get the event without major restructuring of code. However, there’s a relatively simple and elegant solution that creates a global event variable for FireFox that emulates the widow.event variable.

Using FireFox’s Event Capturing Model

FireFox uses an event capturing model that percolates events down from the containing element to contained ones. (IE uses event bubbling. Again, see Quirksmode for a detailed explanation). The event-capture model lets us attach an event handler at the document level and unobtrusively perform some function.

Creating A Global Event Variable For FireFox and IE

Because this happens before element-specific events, it means we can use this model to set a global variable that serves the same purpose as IE’s window.event variable.
It then becomes a simple matter of substituting that variable for window.event throughout our script in order to make element-specific event-handlers work. Here’s cross-browser compliant code:

// Attach an on-click event handler at the document level:
xl_AttachEvent(document, "click", xl_FFEventhandler);

// Event handler for any onclick:
function xl_FFEventhandler(e)
{
 // Declare a global variable to trap events in FireFox or IE
 ff_event  = null;
 ff_event = xl_GetEvent(e);

}

That’s it! Here are the helper functions, from PPK’s work at Quirksmode.

function xl_GetEvent(e)
{
 // e gives access to the event in all browsers
 if (!e) var e = window.event;

 return e;
}

function xl_AttachEvent(obj, evType, fn, useCapture)
{
 if (!useCapture) var useCapture = true;
 if (obj.addEventListener){
  obj.addEventListener(evType, fn, useCapture);
  return true;
 } else if (obj.attachEvent){
  var r = obj.attachEvent("on"+evType, fn);
  return r;
 } else {
  return false;
 }
}

Change “youclickedme” function to be cross-browser compliant

This is all we need to do to change function “youclickedme”, our event handler that is attached via the onlcik property of the element:

 if ff_event.srcElement.id = "link1"   // do something.

Well – not quite, since srcElement is IE-only, while FireFox uses target instead. But you get the idea. For example, here’s a cross-browser function to return a handle to the element the event occured on- a modified version of PPK’s using this technique:

function xl_eventTarg()
{
 var targ = null;

 if (xl_event().target) targ = xl_event().target;
 else if (xl_event().srcElement) targ = xl_event().srcElement;
 if (targ.nodeType == 3) // defeat Safari bug
  targ = targ.parentNode;
 return targ;

}

And here’s a function that uses our cross-browser event object if we are not in IE:

// By default, use window.event so we don't depend on attaching an event handler at the document level.
// Otherwise, use the cross-browser event object.
function xl_event()
{
  if (window.event) return window.event;
  else return ff_event;

}

Now we can write this:

	if xl_eventtarg.id = "link1";   // works in IE and FireFox.

I recommend you create a library of functions for this sort of cross-browser stuff. In this case, you can place:

  • xl_AttachEvent
  • xl_FFEventHandler
  • xl_event
  • xl_GetEvent
  • xl_eventTarg

in a library.

And, in order to use the global event variable, you’ll need this line of code (and one for each event type you want to trap) in the top of your script:

xl_AttachEvent(document, "click", xl_FFEventhandler);

As noted in several places of this post, I’ve relied heavily on PPK and his quirksmode.org site for help in understanding the various event models, etc. I’ve just ordered his book, and recommend anyone else who is serious about writing quality Javascript code do the same. Thanks, Peter.