Welcome to CrankyGoblin.Com Sign in | Join | Help

Public Class GeoffAppleby

Inherits Microsoft.VisualBasic.MVP : Implements IBrainFart
Dealing With the Firefox Event Model

I'm writing some HTML at the moment that includes a dynamic pop-up menu. It's only a simple little beast, using some simple HTML and javascript.

Before the preachers start at me, yes, html popup menus are evil. I know this. But sometimes they're useful, and I think that the situation warrants it :) (Although I haven't resolved what to do if javascript is turned off on the client...)

The principles involved here are that when you click on one piece of text, a box appears directly beneath it with your 'menu'. Subsequently, clicking anywhere on the page except for the contents of the pop-up menu causes it to be hidden again.

This is the javascript client side that does it all. It's fairly simple.

<script type="text/javascript">

 

  var openMenu = null;

 

  /* Show or hide a menu.

    - Called as a result of clicking on the always visible item.

    - sMenuId is the Id of the HTML element to show/hide.

    - when a menu is shown, it's id is stored in 'openMenu' for later use

  */

  function ToggleMenu(sMenuId) {

    if ((openMenu != null) && (openMenu != sMenuId)) {

      /* a menu is currently showing, and it's not the one passed in */

      CheckMenu(openMenu);

    }

    /* get the element in question */

    var oEL = document.getElementById(sMenuId);

    if (oEL) {

      switch(oEL.style.display) {

        case 'block':

          /* it's currently visible. hide it */

          oEL.style.display = 'none';

          openMenu = null;

          if (window.event) {

            event.cancelBubble = true;

          }

          return false;

          break;

        default:

          /* it's hidden. show it. */

          oEL.style.display = 'block';

          openMenu = sMenuId;

          if (window.event) {

            event.cancelBubble = true;

          }

          return false;

      }

    }

    return true;

  }

 

  /* Hide the currently shown menu.

    - Called as a result of clicking anywhere on the page except for the menu title or the menu itself.

    - uses 'openMenu' to reference the currently shown menu.

  */

  function CheckMenu() {

    if (openMenu == null) {

      /* there's no menu visible */

      return true;

    }

    /* get the element in question */

    var oEL = document.getElementById(openMenu);

    if (oEL) {

      /* hide it */

      oEL.style.display = 'none';

      openMenu = null;

    }

  }

 

  /* global code chunk. Add a onmousedown handler to the whole document */

  if (document.attachEvent) {

    document.attachEvent('onmousedown', function(){CheckMenu();});

  }

 

</script>

There's two little tricks I've had to add to this. Firefox has no concept of 'event.cancelBubble', and so I can't call it in that case - it's wrapped in a test for window.event, which IE has but Firefox doesn't.

In the global code chunk, I've wrapped the document wide onmousedown handler in a test for document.attachEvent, again which IE has but Firefox doesn't.

Why have I done this? Well, I'm glad you asked.

As the code exists now, it works perfectly in IE, and it works perfectly in Firefox - except the document wide handler isn't called, and therefore to hide the menu again you have to click on it's title (just like showing it in the first place).

Something in the event model is screwing me up. If i enable it page wide in Firefox, when you click the menu title to show it, it shows the menu, and then the click falls through to the page, where it hides it again. It happens so fast you can't even see it flicker (I know it's happening because I stuck an alert in the CheckMenu() function, which proved it was being called.

Anyone know more about Firefox than i do and can point me in the right direction? I want to get it right, because it's for the .Text skin I'm writing. What I need is a Firefox equivalent of event.cancelBubble :)

Listening to: my poor brain - foo fighters - (3:33)
Posted: Tuesday, 8 February 2005 7:08 AM by Geoff Appleby
Filed under:

Comments

ben said:

Actually, Firefox does have the 'event' object, you just need to pass it explicitly into the event handler. Once you pass the event object in, you can cancel the bubble just like in IE. I have a little sample html page that exhibits the difference.

http://codebetter.com/blogs/images/codebetter_com/ben.reichelt/93/o_js.GIF

I'm not sure how to format the html so that I can post it in a comment, so I made a screen shot of the html, its only ~25 lines. If you want the html file, I can email it to you.

-ben


# February 8, 2005 11:35 AM

Geoff Appleby said:

That's bloddy fantastic. I'll test it now and let you know how it goes :)
# February 8, 2005 11:42 AM

Geoff Appleby said:

Didn't take long to prove the theory - it works fine in firefox now.

May I have your children? (I promise not to hurt them)
# February 8, 2005 11:48 AM

ben said:

glad it worked for you, we ran into the exact same problem at work a little bit ago

-ben
# February 8, 2005 2:07 PM

Jesse Houwing said:

On the cancelbubble thingy...

have you tried to return true when you're in Firefox? If an event handler returns true it signals the browser it has handled the event as far as I know.
# February 9, 2005 6:42 PM

Geoff Appleby said:

I'll give it a try :)
# February 9, 2005 7:19 PM

Darrell said:

Try these to cancel the event in Mozilla/Firefox:
event.returnValue=false;
event.cancel = true;
# February 10, 2005 12:44 AM

TrackBack said:

# February 12, 2005 10:00 PM

TrackBack said:

# February 13, 2005 12:46 AM

Eric said:

Perfect.
# July 22, 2006 5:04 PM

Nir said:

Thank you so much!! Very helpful!!

# July 20, 2009 8:41 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

To submit your comment, click on these pictures:
  • Geoff's tongue
  • Sleepy Geoff
  • Shocked Geoff
Gaptcha Image - No Peeking! Gaptcha Image - No Peeking! Gaptcha Image - No Peeking!
Gaptcha Image - No Peeking! Gaptcha Image - No Peeking! Gaptcha Image - No Peeking!
Gaptcha Image - No Peeking! Gaptcha Image - No Peeking! Gaptcha Image - No Peeking!
Can't recognise the people in these pictures? Look here for a quick introduction.
There's a time limit for you to get your comment submitted before this set of pictures expires. If you think it's been longer than 10 minutes, get some new pictures first (you won't lose what you've typed so far).
Get some new pictures 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS