Oct
20
2006
Ajax and dynamic html tooltips - part 1
Posted by admin under
Ajax
Tooltips are not only cool - they also fill an important purpose by being able to keep information hidden until the visitor (typically by moving the mouse over a certain item) want more information.
There are a lot of libraries out there implementing tooltips by Javascript ( also pure CSS tooltips - no Javascript at all are possible), but since we are indeed moving to a Javascript world with Ajax becoming more and more popular I therefore wanted to implement a Ajax tooltip solution:
How should it work:
a) when hovering over a certain item I want to display the tooltip. However the content to display should be retrieved by using an Ajax call. Take a table of hockey players for example. When hovering the row of Peter Forsberg I want to retrieve some extra data from the database to show in the tooltip
b) I want to be able to implement "sticky" tooltips, i.e tooltips that doesn't have to go away as soon as the user moves away from the row. Ultimately I would like to offer some sort of interaction (for example clickable links) in my tooltip. And therefore - when moving the mouse to the tooltip links that mean moving out of the "Peter Forsberg" row - and the tooltip would be closed with if I used a regular onmouseout="hide(...)" implementation.
c) When retrieving data I want to show a Ajax "Working" animation. And when data is available I want the data to be updated
d) Last - I want to be able to cache the data. Meaning if the user moves away from the Peter Forsberg row and goes to Markus Naslund row (and getting his tooltip) - if going back to Peter Forsberg I don't want to retrieve the data from the server again
So, with those requirements lined that up I investigated the market and decided to use domTooltip . It allows for best customization since I can specify (initially hidden) div elements to be the tooltips - and that would allow for easiest styling. Cause I did look at overlib but found it a little too hard to style.
Anyway - lets start by looking at a "really" simple and ugly demo of domTooltip with faked Ajax call (client side timer 3 seconds):
DEMO
Keep your mouse over the first link, then go to the next, then go back to the first. The code for it is really simple, you can do "View source" to see how it's done, but I'll try to explain some of the parts:
<a href="http://www.aspcode.net/articles/l_en-US/t_default/ASP.NET/ASP.NET-2.0/Ajax/Ajax-and-dynamic-html-tooltips---part-1_article_379.aspx" onmouseover="SHShowTip(this,event,'onetooltip', '1')">Also goes back to article</a>
<div id="tooltipPool" style="display: none">
<div id="Loader" >
<div>
<nobr>Getting data...</nobr></div>
<div align="center">
<img src="images/working.gif" />
</div>
</div>
<div id="takealook">
<table border="1">
<tr><td colspan="2">
<nobr>Received data</nobr></td>
</tr>
<tr>
<td>
Data1:
</td>
<td>
125
</td>
</tr>
<tr>
<td>
Data2:
</td>
<td>
Kalle Persson
</td>
</tr>
</table>
</div>
<div id="onetooltip">
<table border="1">
<tr><td colspan="2">
<nobr>Received data</nobr></td>
</tr>
<tr>
<td>
Data1:
</td>
<td>
129
</td>
</tr>
<tr>
<td>
Data2:
</td>
<td>
Pelle Karlsson
</td>
</tr>
</table>
</div>
</div>
Basically we define the onmouseover link to call our SHShowTip function (explained later). However, the "divs" inside the div id="tooltipPool" contains the HTML we want to show in each tooltip. Here you might see the first flaw with this solution so far - we design one tooltip div for both "takealook" and "onetooltip", Those should use the same template - and our Ajax script should replace the row unique data on the fly, however we will expand this solution in next article to accomplish exactly that.
Now - lets look at the Javascript:
<script type="text/javascript">
var domTT_oneOnly = true;
var domTT_ExtLoaded = new Array()
var domTT_ExtsLoaderHTML = ''
var domTT_ExtfIsLoading = false;
function SHShowTip( a,b,sDivId, sUniqueDataId )
{
if ( domTT_ExtfIsLoading )
return;
if ( domTT_ExtLoaded[sUniqueDataId] == null )
{
if ( domTT_ExtsLoaderHTML != '' )
{
domTT_activate(a, b, 'caption', false,'content',
domTT_ExtsLoaderHTML, 'type', 'sticky', 'id', sUniqueDataId);
}
else
{
domTT_ExtsLoaderHTML = document.getElementById('Loader').innerHTML;
domTT_ExtfIsLoading = true;
domTT_activate(a, b, 'caption', false,'content',
domTT_ExtsLoaderHTML, 'type', 'sticky', 'id', sUniqueDataId);
}
setTimeout("updateCallback('" + sDivId + "','" + sUniqueDataId + "')", 3000);
}
else
{
domTT_activate(a, b, 'caption', false,'content',
document.getElementById(sDivId).innerHTML, 'type', 'sticky', 'id', sUniqueDataId);
}
}
function updateCallback(sDivId, sUniqueDataId)
{
domTT_ExtLoaded[sUniqueDataId] = "1";
domTT_ExtfIsLoading = false;
domTT_update( sUniqueDataId, document.getElementById(sDivId).innerHTML);
//domTT_update( sId, document.getElementById(sId).innerHTML );
}
</script>
In short - we flag all loaded tooltips in array Loaded[sId] - by that we are able to see if we already has loaded a tooltip. If not - we show the document.getElementById('loader') tooltip (which shows the Loading message) and spawns our "fake" Ajax call - setTimeout to function updateCallback.
In updateCallback (this should actually be our real Ajax callback function) we set the new tooltip data by calling domTT_update:
domTT_update( sUniqueDataId, document.getElementById(sDivId).innerHTML);
and also calls flags the tooltip as loaded:
domTT_ExtLoaded[sUniqueDataId] =
"1";
As I said, we will continue work on this. Right now there a lot of stupid things - and most important it doesn't work as espected - we do no Ajax call.