Connecting Tech Pros Worldwide Forums | Help | Site Map

Mouse event capture failing in Firefox?

Mobius Evalon's Avatar
Newbie
 
Join Date: Feb 2007
Location: Wisconsin, USA
Posts: 4
#1: Feb 25 '07
I'm trying to make this thing work in Firefox, because I know the client my game is on is pondering switching to Gecko (they're currently using something very similar to IE4 for browser windows launched in the client). This tooltip script works fine in IE, and the coordinates are apparently being read and changed in Firefox (I tossed in a div for debug), but I keep getting an "ev has no properties" error in Firefox and the tooltip div fails to appear.

Following is the entirety of the document I'm working on:

Expand|Select|Wrap|Line Numbers
  1. <head>
  2.     <style type="text/css">
  3.         #tooltip_div
  4.         {
  5.             position: absolute;
  6.             visibility: hidden;
  7.             z-index: 20;
  8.             top: 0px;
  9.             left: 0px;            
  10.         }
  11.         .tooltip_table
  12.         {
  13.             border: 0px;
  14.             width: 250px;
  15.             height: 80px;
  16.             margin: 0px;
  17.             padding: 0px;
  18.             background-color: #404040;
  19.             background: url('table_bg.PNG');
  20.             color: #aaaaaa;
  21.         }
  22.         .tooltip_head
  23.         {
  24.             border: 0px;
  25.             text-align: center;
  26.             vertical-align: middle;
  27.             height: 10px;
  28.             font-family: verdana,sans-serif;
  29.             font-size: 10px;
  30.             background: url('title_bg.PNG');
  31.             background-color: #808080;
  32.             color: #aaaaaa;
  33.         }
  34.         .tooltip_content
  35.         {
  36.             border: 0px;
  37.             margin: 0px;
  38.             text-align: center;
  39.             vertical-align: middle;
  40.             font-family: verdana,sans-serif;
  41.             font-size: 10px;
  42.             color: #aaaaaa;
  43.         }
  44.     </style>
  45.     <script type="text/javascript">
  46.         if(!document.all) document.captureEvents(Event.MOUSEMOVE);
  47.         document.onmousemove = realign_tooltip;
  48.  
  49.         var body_width = 0;
  50.         var body_height = 0;
  51.         var tooltip_x_offset = 15;
  52.         var tooltip_y_offset = 15;
  53.         var tooltip_div;
  54.  
  55.         function init_tooltip()
  56.         {
  57.             if(document.all)
  58.             {
  59.                 body_width = document.body.clientWidth;
  60.                 body_height = document.body.clientHeight;
  61.             }
  62.             else
  63.             {
  64.                 body_width = window.innerWidth;
  65.                 body_height = window.innerHeight;
  66.             }
  67.         }
  68.         function show_tooltip(title,content)
  69.         {
  70.             tooltip_div = document.getElementById('tooltip_div');
  71.             tooltip_div.innerHTML = ('<table class="tooltip_table"><tr><td class="tooltip_head">'+title+'</td></tr><tr><td class="tooltip_content">'+content+'</td></tr></table>');
  72.             realign_tooltip();
  73.             tooltip_div.style.visibility = 'visible';
  74.         }
  75.         function hide_tooltip()
  76.         {
  77.             tooltip_div.style.visibility = 'hidden';
  78.             tooltip_div = null;
  79.         }
  80.         function realign_tooltip(ev)
  81.         {
  82.             ev = (ev || window.event);
  83.             init_tooltip();
  84.             if(tooltip_div)
  85.             {
  86.                 if(document.all)
  87.                 {
  88.                     tooltip_div.style.left = ((((ev.clientX+tooltip_x_offset+tooltip_div.clientWidth) <= body_width) ? (ev.clientX+tooltip_x_offset) : (body_width-tooltip_div.clientWidth))+'px');
  89.                     tooltip_div.style.top = ((((ev.clientY+tooltip_y_offset+tooltip_div.clientHeight) <= body_height) ? (ev.clientY+tooltip_y_offset) : (body_height-tooltip_div.clientHeight))+'px');
  90.                 }
  91.                 else
  92.                 {
  93.                     tooltip_div.style.left = ((((ev.pageX+tooltip_x_offset+tooltip_div.clientWidth) <= body_width) ? (ev.pageX+tooltip_x_offset) : (body_width-tooltip_div.clientWidth))+'px');
  94.                     tooltip_div.style.top = ((((ev.pageY+tooltip_y_offset+tooltip_div.clientHeight) <= body_height) ? (ev.pageY+tooltip_y_offset) : (body_height-tooltip_div.clientHeight))+'px');
  95.                 }
  96.                 document.getElementById('debug').innerHTML = (''+body_width+'x'+body_height+'<br>'+tooltip_div.style.left+', '+tooltip_div.style.top);
  97.             }
  98.         }
  99.     </script>
  100. </head>
  101. <body onload="init_tooltip();">
  102.     <a href="#" onmouseover="show_tooltip('Total mutes','This is the total number of automated mutes currently being applied. This number does not include mutes by staff or those who have logged out before an auto-mute expired.');" onmouseout="hide_tooltip();">blah</a>
  103.     <br><br><br><br><a href="#" onmouseover="show_tooltip('lol','More text');" onmouseout="hide_tooltip();">lol</a>
  104.     <br><br><br><br><div id="tooltip_div">&nbsp;</div>
  105.     <div id="debug">0,0</div>

Expert
 
Join Date: Nov 2006
Posts: 392
#2: Feb 26 '07

re: Mouse event capture failing in Firefox?


Quote:

Originally Posted by Mobius Evalon

I'm trying to make this thing work in Firefox, because I know the client my game is on is pondering switching to Gecko (they're currently using something very similar to IE4 for browser windows launched in the client). This tooltip script works fine in IE, and the coordinates are apparently being read and changed in Firefox (I tossed in a div for debug), but I keep getting an "ev has no properties" error in Firefox and the tooltip div fails to appear.

Following is the entirety of the document I'm working on:

Expand|Select|Wrap|Line Numbers
  1. <head>
  2.     <style type="text/css">
  3.         #tooltip_div
  4.         {
  5.             position: absolute;
  6.             visibility: hidden;
  7.             z-index: 20;
  8.             top: 0px;
  9.             left: 0px;            
  10.         }
  11.         .tooltip_table
  12.         {
  13.             border: 0px;
  14.             width: 250px;
  15.             height: 80px;
  16.             margin: 0px;
  17.             padding: 0px;
  18.             background-color: #404040;
  19.             background: url('table_bg.PNG');
  20.             color: #aaaaaa;
  21.         }
  22.         .tooltip_head
  23.         {
  24.             border: 0px;
  25.             text-align: center;
  26.             vertical-align: middle;
  27.             height: 10px;
  28.             font-family: verdana,sans-serif;
  29.             font-size: 10px;
  30.             background: url('title_bg.PNG');
  31.             background-color: #808080;
  32.             color: #aaaaaa;
  33.         }
  34.         .tooltip_content
  35.         {
  36.             border: 0px;
  37.             margin: 0px;
  38.             text-align: center;
  39.             vertical-align: middle;
  40.             font-family: verdana,sans-serif;
  41.             font-size: 10px;
  42.             color: #aaaaaa;
  43.         }
  44.     </style>
  45.     <script type="text/javascript">
  46.         if(!document.all) document.captureEvents(Event.MOUSEMOVE);
  47.         document.onmousemove = realign_tooltip;
  48.  
  49.         var body_width = 0;
  50.         var body_height = 0;
  51.         var tooltip_x_offset = 15;
  52.         var tooltip_y_offset = 15;
  53.         var tooltip_div;
  54.  
  55.         function init_tooltip()
  56.         {
  57.             if(document.all)
  58.             {
  59.                 body_width = document.body.clientWidth;
  60.                 body_height = document.body.clientHeight;
  61.             }
  62.             else
  63.             {
  64.                 body_width = window.innerWidth;
  65.                 body_height = window.innerHeight;
  66.             }
  67.         }
  68.         function show_tooltip(title,content)
  69.         {
  70.             tooltip_div = document.getElementById('tooltip_div');
  71.             tooltip_div.innerHTML = ('<table class="tooltip_table"><tr><td class="tooltip_head">'+title+'</td></tr><tr><td class="tooltip_content">'+content+'</td></tr></table>');
  72.             realign_tooltip();
  73.             tooltip_div.style.visibility = 'visible';
  74.         }
  75.         function hide_tooltip()
  76.         {
  77.             tooltip_div.style.visibility = 'hidden';
  78.             tooltip_div = null;
  79.         }
  80.         function realign_tooltip(ev)
  81.         {
  82.             ev = (ev || window.event);
  83.             init_tooltip();
  84.             if(tooltip_div)
  85.             {
  86.                 if(document.all)
  87.                 {
  88.                     tooltip_div.style.left = ((((ev.clientX+tooltip_x_offset+tooltip_div.clientWidth) <= body_width) ? (ev.clientX+tooltip_x_offset) : (body_width-tooltip_div.clientWidth))+'px');
  89.                     tooltip_div.style.top = ((((ev.clientY+tooltip_y_offset+tooltip_div.clientHeight) <= body_height) ? (ev.clientY+tooltip_y_offset) : (body_height-tooltip_div.clientHeight))+'px');
  90.                 }
  91.                 else
  92.                 {
  93.                     tooltip_div.style.left = ((((ev.pageX+tooltip_x_offset+tooltip_div.clientWidth) <= body_width) ? (ev.pageX+tooltip_x_offset) : (body_width-tooltip_div.clientWidth))+'px');
  94.                     tooltip_div.style.top = ((((ev.pageY+tooltip_y_offset+tooltip_div.clientHeight) <= body_height) ? (ev.pageY+tooltip_y_offset) : (body_height-tooltip_div.clientHeight))+'px');
  95.                 }
  96.                 document.getElementById('debug').innerHTML = (''+body_width+'x'+body_height+'<br>'+tooltip_div.style.left+', '+tooltip_div.style.top);
  97.             }
  98.         }
  99.     </script>
  100. </head>
  101. <body onload="init_tooltip();">
  102.     <a href="#" onmouseover="show_tooltip('Total mutes','This is the total number of automated mutes currently being applied. This number does not include mutes by staff or those who have logged out before an auto-mute expired.');" onmouseout="hide_tooltip();">blah</a>
  103.     <br><br><br><br><a href="#" onmouseover="show_tooltip('lol','More text');" onmouseout="hide_tooltip();">lol</a>
  104.     <br><br><br><br><div id="tooltip_div">&nbsp;</div>
  105.     <div id="debug">0,0</div>


You need to have something link realign_tooltip(event) as a method call instead of realign_tooltip(); You are not passing any event to the function for Firefox to get data from.
Newbie
 
Join Date: Feb 2007
Location: Alabama, USA
Posts: 19
#3: Feb 26 '07

re: Mouse event capture failing in Firefox?


Hi Mobius,

These are some things that I've wanted to say in response to a lot of different people's questions.

When you get an error like this, start using 'alerts' and look at the values of certain variables. realign_tooltip expects ev to be an event object, but adding "alert(ev);" as the first line in realign_tooltip shows that ev is not an event object - it is 'undefined'. So we look to see from where the function is called 'from' and we see that it is called from show_tooltip and no arguments are passed. show_tooltip is the function which we call the event handler (or 'listener') because it is called directly by the system when the event occurs. So show_tooltip needs to pass the event object to realign_tooltip. How does show_tooltip receive the event object? In IE (DOM0) you use 'window.event'. In DOM2 browsers the event object is passed as an argument to the event listener.

There are many general patterns and 'best practices' we can use when developing our applications. I will discuss a few of them in the following.

1. No Javascript in HTML.

For example, we want this:
Expand|Select|Wrap|Line Numbers
  1. <a href="#" onmouseover="show_tooltip('lol','More text');" onmouseout="hide_tooltip();">
  2.  
to look more like this:
Expand|Select|Wrap|Line Numbers
  1. <a class="tt1" href="#">text</a>
  2.  
of course we might like to put tooltips on 'any' element:
Expand|Select|Wrap|Line Numbers
  1. <span class="tt2">text</span>
  2.  

2. No HTML in Javascript.

For example, the HTML in this string:
Expand|Select|Wrap|Line Numbers
  1. '<table class="tooltip_table"><tr><td class="tooltip_head">'+title+'</td></tr><tr><td class="tooltip_content">'+content+'</td></tr></table>';
  2.  
should be in the HTML:
Expand|Select|Wrap|Line Numbers
  1. <div id="tooltip_div">
  2. <table id="tooltip_table">
  3. <tr><td id="tooltip_title"></td></tr>
  4. <tr><td id="tooltip_content"></td></tr>
  5. </table>
  6. </div>
  7.  
I would not use a table but that's a personal choice.


3. Register event listeners in script instead of HTML attributes.

Elements are not available to script (as we say 'in the DOM') until after the 'onload' event. So let's register an onload listener and do all our initialization there (much more could be said about 'onload' techniques).
Expand|Select|Wrap|Line Numbers
  1. window.onload = winOnLoad;
  2.  
  3. function winOnLoad()
  4. {
  5.   initTooltips();
  6.   // initialize other things needed by the app
  7. }
  8.  
  9. function initTooltips()
  10. {
  11. }
  12.  

3. Using ID and CLASS for script access to elements.

Using ID and CLASS are not the only ways to access elements and this suggestion is more specific to the tooltip app.

Notice in the above HTML how I've used ID and CLASS attributes. I used ID where there could be only one of that type of object, and I used CLASS where there could be more than one.

I'm using class 'tt1' to associate any element with a specific tooltip. Class 'tt2' is a different tooltip, etc.

Let's store the tooltip titles and text in arrays:
Expand|Select|Wrap|Line Numbers
  1. var tt_title = [
  2. "title 1",
  3. "title 2",
  4. "title 3"
  5. ];
  6.  
  7. var tt_content = [
  8. "text 1",
  9. "text 2",
  10. "text 3"
  11. ];
  12.  
Now let's finish the initialization function. We want to find all elements that have classes 'tt1', 'tt2', 'tt3', etc. and for each element we will register mouseover and mouseout listeners. Also, for each element we will add a new property 'tooltipIndex' which is an index into the tt_title and tt_content arrays. Note that there could be any number of elements with class 'tt1' - and likewise for 'tt2' etc.

I'm going to use my function xGetElementsByClassName but you can use anyone's version of this. As long as it returns an array of elements, all of which have a certain className.
Expand|Select|Wrap|Line Numbers
  1. window.onload = winOnLoad;
  2.  
  3. function winOnLoad()
  4. {
  5.   initTooltips();
  6.   // initialize other things needed by the app
  7. }
  8.  
  9. function initTooltips()
  10. {
  11.   var a, i, tti = 1;
  12.   a = xGetElementsByClassName('tt' + tti);
  13.   while (a.length) {
  14.     for (i = 0; i < a.length; ++i) {
  15.       a[i].tooltipIndex = tti;
  16.       a[i].onmouseover = ttOnMouseover;
  17.       a[i].onmouseout = ttOnMouseout;
  18.     }
  19.     ++tti;
  20.     a = xGetElementsByClassName('tt' + tti);
  21.   }
  22. }
  23.  
  24. function ttOnMouseover(e)
  25. {
  26.   // "this" points to the element moused over
  27.   var e = document.getElementById('tooltip_title');
  28.   if (e) e.innerHTML = tt_title[this.tooltipIndex];
  29.   e = document.getElementById('tooltip_content');
  30.   if (e) e.innerHTML = tt_content[this.tooltipIndex];
  31.   // now position and show 'tooltip_div' 
  32.   // here you could register a mousemove listener
  33. }
  34.  
  35. function ttOnMouseout(e)
  36. {
  37.   // hide 'tooltip_div'
  38.   // remove mousemove listener
  39. }
  40.  
Reply


Similar JavaScript / Ajax / DHTML bytes