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:
-
<a href="#" onmouseover="show_tooltip('lol','More text');" onmouseout="hide_tooltip();">
-
to look more like this:
-
<a class="tt1" href="#">text</a>
-
of course we might like to put tooltips on 'any' element:
-
<span class="tt2">text</span>
-
2. No HTML in Javascript.
For example, the HTML in this string:
-
'<table class="tooltip_table"><tr><td class="tooltip_head">'+title+'</td></tr><tr><td class="tooltip_content">'+content+'</td></tr></table>';
-
should be in the HTML:
-
<div id="tooltip_div">
-
<table id="tooltip_table">
-
<tr><td id="tooltip_title"></td></tr>
-
<tr><td id="tooltip_content"></td></tr>
-
</table>
-
</div>
-
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).
-
window.onload = winOnLoad;
-
-
function winOnLoad()
-
{
-
initTooltips();
-
// initialize other things needed by the app
-
}
-
-
function initTooltips()
-
{
-
}
-
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:
-
var tt_title = [
-
"title 1",
-
"title 2",
-
"title 3"
-
];
-
-
var tt_content = [
-
"text 1",
-
"text 2",
-
"text 3"
-
];
-
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.
-
window.onload = winOnLoad;
-
-
function winOnLoad()
-
{
-
initTooltips();
-
// initialize other things needed by the app
-
}
-
-
function initTooltips()
-
{
-
var a, i, tti = 1;
-
a = xGetElementsByClassName('tt' + tti);
-
while (a.length) {
-
for (i = 0; i < a.length; ++i) {
-
a[i].tooltipIndex = tti;
-
a[i].onmouseover = ttOnMouseover;
-
a[i].onmouseout = ttOnMouseout;
-
}
-
++tti;
-
a = xGetElementsByClassName('tt' + tti);
-
}
-
}
-
-
function ttOnMouseover(e)
-
{
-
// "this" points to the element moused over
-
var e = document.getElementById('tooltip_title');
-
if (e) e.innerHTML = tt_title[this.tooltipIndex];
-
e = document.getElementById('tooltip_content');
-
if (e) e.innerHTML = tt_content[this.tooltipIndex];
-
// now position and show 'tooltip_div'
-
// here you could register a mousemove listener
-
}
-
-
function ttOnMouseout(e)
-
{
-
// hide 'tooltip_div'
-
// remove mousemove listener
-
}
-