Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Rhinorhino on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tooltip without external js file 2

Status
Not open for further replies.

kylebellamy

Programmer
Joined
Jan 24, 2002
Messages
398
Location
US
I'm working in a CMS for a company that doesn't allow a lot of things. However, they will set up a special template with the JS that I need in it to create tooltips in an image map for the project that I am working on.

The question is this:
Can I take the code from a .js file and place it in the head of a page? There are a thousand sites in Google that use the external method but I cannot use it and I need all that functionality (ie links in the tooltip) and would like it to be a bit stylish (drop shadow would be nice but not necessary).

 
The question is this:
Can I take the code from a .js file and place it in the head of a page?

Yes.

-kaht

[small] <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <.</B>[/small]
[banghead] [small](He's back)[/small]
 
I assume that it will slow page loading

That is correct. Since the .js file would normally be cached, that is additional data that will have to be transfered with the page.

-kaht

[small] <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <B> <P> <.</B>[/small]
[banghead] [small](He's back)[/small]
 
kb, why can you not use the .js file approach?
Is it just not working when you try it or is there some other limitation?

If it is just not working when you try it, it may be the folder that you are trying to do the include from.
You should be able to store the .js file in your HTML folder and use a command like:
<script type="text/javascript" src="myfile.js"></script>

If you CAN use the .js file you are much better off since any change to the tooltip code would have to be replicated on every single page you had included the code directly into rather than in a single place.



Stamp out, eliminate and abolish redundancy!
 
The way things are setup, all JS has to be in the page and only if the admins set it up ahead of time for me. As such, I have no way to place a .js file on the server or even know where it is to reference it. This limits me to the parameters stated above.

So, I'm now trying to find one that isn't loaded with a thousand options and then figure out how to get it to function. *wipes forehead*

 
Here is some code I finagled together a long time back.
It was based I THINK on someone else's calendar code to position an on-page calendar. I stripped out all the calendar code and tweaked the positioning routines to use it for positioning tool tips.
I THINK this version is setup to even adjust the tip so that it shifts itself to the side to prevent it from flowing offscreen if too close to the left or right sides of the screen.

Give it a test and see if it will work for you. It's pretty easy to setup. It does not do drop shadows but you may be able to take care of that in CSS.

The script uses a single DIV tag to define the window to display and will automatically position that box directly below the item you have called it from. Additionally, if the width of the display window based on the position of the controlling element would put the box past the edge of the current window, the box will adjust itself to the left to compensate.

This is very easy to integrate into your own pages.

Position this text in the Head of your page.
NOTE: You CAN put this style inline with the DIV tag. It is important though that the Width parameter in the DIV tag remain there and not be moved or replicated in the Style block. IE has trouble reading the values stored in the Style block and so the code is setup to read this value from the DIV tag so that it will know how to calculate screen position.
<STYLE>
<!--
#tipbox {position: absolute; z-index: 100;border: 1pt black solid; background: #FFFFD0; visibility: hidden; font-size:8pt; font-family: "verdana, arial"; color:#000000 }
-->
</STYLE>
<script language="JavaScript" type="text/JavaScript">
<!--

function showObject(outtxt)
{
var el = window.event.srcElement;
el.style.cursor='hand';
var tip = document.all["tipbox"];
tip.innerHTML = outtxt;
setPosition(tip);
tip.style.visibility = "Visible";
}

function hideObject()
{
var el = window.event.srcElement;
el.style.cursor='auto';
document.all['tipbox'].style.visibility = "hidden";
}

function setPosition(el)
{
// Set the position of an element
// The pixelLeft attribute is modified to move the box to the left in order to prevent it from scrolling off the
// right side of the screen and is shortened an additional 10 pixels for aesthetics.
var src = window.event.srcElement;
var srcleft = getOffset(src, "Left");
var swidth = document.body.scrollWidth -10; // The -10 keeps the box from reaching the edge of the screen.
var myElem = document.getElementById("tipbox");
var myStyle = myElem.style;
var boxwidthval = myStyle.width;
var boxwidth = boxwidthval.substring(0,boxwidthval.length-2); // The width set for the tipBox
var newval = srcleft + (boxwidth-0);
if (newval > swidth)
srcleft = srcleft - (newval - swidth);
if (srcleft < 0)
srcleft = 0;
el.style.pixelTop = getOffset(src, "Top");
el.style.pixelLeft = srcleft;
}

function getOffset(el, which)
{
// Calculates and returns the screen top and left position of an element.
var amount = el["offset"+which];
if (which=="Top")
amount+=el.offsetHeight;
el = el.offsetParent;
while (el!=null)
{
amount+=el["offset"+which];
el = el.offsetParent;
}
return amount;
}
//-->
</script>

Place the below DIV tag somewhere in the body of your page. The Width parameter can be changed to whatever size you require.
<DIV ID='tipbox' Style="width: 520"></div>

Use an event such as onmouseover or onclick to call the showObject function and another event to call the hideObject function.
In my example I used the onmouseover and onmouseoff events within cells of a table. I placed these events inside the TD tag rather than inside the cell so that the entire cell would act as a trigger rather than just the text. You can set it up any way you like. You can also leave, modify or remove the events I setup for changing background color or the cursor. These were just done for visual effect on my page.
NOTE: Microsoft IE events bubble up to the parent so the event would apply to all child nodes as well. What this means is that in my example below I have the onmouseover event setup in the TD tag. Below the TD tag are the child elements FONT and the text stored inside the TD.
Passing the mouse over these areas trigger the onmouseover event so the event has three potential triggers instead of just one. This is fine in this case since the text and cell locations are pretty much identical and the FONT element is not going to cause us any problems with the event but if you had a more complex table setup you could potentially end up with some odd results as child objects unexpectedly trigger the parent objects events.

<table width="100%" border="1">
<tr>
<td id="one" bgcolor="#FFFFFF" align='left' onmouseover="showObject('This is the long description for #1'); this.style.background = '#FFFFD0'" onmouseout="hideObject(); this.style.background = 'white'"><font size='1' face='Verdana, Arial, Helvetica'>Short description #1</font></td>
<td></td>
<td id="two" bgcolor="#FFFFFF" align='left' onmouseover="showObject('This is the long description for #2'); this.style.background = '#FFFFD0'" onmouseout="hideObject(); this.style.background = 'white'"><font size='1' face='Verdana, Arial, Helvetica'>Short description #2</font></td>
<td></td>
<td id="three" bgcolor="#FFFFFF" align='left' onmouseover="showObject('This is the long description for #3'); this.style.background = '#FFFFD0'" onmouseout="hideObject(); this.style.background = 'white'"><font size='1' face='Verdana, Arial, Helvetica'>Short description #3</font></td>
</tr>
</table>


Stamp out, eliminate and abolish redundancy!
 
It has been a long time since I played with that code and I do not know if I ever tested it with all the changes in various browsers. If you are an IE only shop like mine it should be fine but it should be tested for FireFox, Netscape, etc if there might be variation on other pages.

The styles can be converted into a regular stylesheet also, I just did not know anything about CSS at the time.

One upgrade I might do at a later date is to build in a Tips On/Off feature (should be simple to implement) so people can turn the help on or off as they please.

I use the same code for pop-up calendars. Rather than popping up the calendar in a new window this allows it to pop up on the same page and it set's itself relative to the field it was called from automatically. Works nicely.

I have seen other tool-tip scripts and some may be better in many ways but I had never seen one that not only sets the position relative to the element it is related to but also adjusts that position to keep it from going off-screen.
I should track down where the original positioning code came from before I modified it and send a thank you to the author but I cannot remember where it came from. I may have even picked it up here at work somewhere.

In any event, I take credit for the specific tool-tip application of the code and the piece that determines current screen size and adjusts position to stay on-screen but the bulk was done by someone else.

Have fun.

Stamp out, eliminate and abolish redundancy!
 
The script is perfect for my IE only office. What I need to do now is to make the tooltip stay in place until the mouse goes out of it. That way I can put links in the tip to lead to sub-sections.

Turns out that the bosses liked it so much that they wanted more functionality. lol BTW, if you want credit for all this, thenightowl, email me and I'll put your data into the code. Seems fair to me.

 
Eh??? It should stay there until the mouse moves off.
In any event, you are in luck.
I got intrigued by the task and started playing with it again after my original post above. Turns out the original code does not work in FireFox and probably not anything else other than IE so I began streamlining it and making it work in other browsers.

Borrowing ideas from other tool tip code I have seen I added in a few more features. The new code uses timers so that when you mouseoff it has a short delay before the box disappears but if you mouseover something else before the timer finishes it cancels the timer immediately.
I have also been playing with fading the box up it makes a more interesting transition and was about to begin working on fading it out again. The code as it exists is a conglomeration of several different code sources though it has all been modified quite a bit.

Try this out, it works in IE AND FireFox. It is still a work in progress and I have not tested it in other browsers.
The one annoying thing is that when you place the onmouseover event inside a TD tag it applies to children of that tag so when you mouseover the table cell the box pops up but when the mouse goes over the text inside the cell the box shifts it's position a few pixels for the text and gives it a bit of a flicker effect.
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE></TITLE>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<STYLE>
  <!--
  #tipbox {position: absolute; z-index: 100;border: 1pt black solid; background: #FFFFD0; visibility: hidden; font-size:8pt; font-family: "verdana, arial"; color:#000000 }
  -->
</STYLE>
<SCRIPT type=text/JavaScript>
<!--
var tID;
var opacityID;

  function showObject(e,outtxt)
  {
    if (window.tID) clearTimeout(tID); //Clear any existing timer.

    if ( window.opacityID ) {
      clearTimeout(opacityID);
    }


    // Get the object based on browser implementation.
    if (!e) var e = window.event;
    if (e.target) var obj = e.target;
    else if (e.srcElement) var obj = e.srcElement;
    if (obj.nodeType == 3) var obj = obj.parentNode; // for Safari bug
    obj.style.cursor='pointer';
    var tipBox = document.getElementById('tipbox');
    setPosition(obj,tipBox);
    tipBox.innerHTML = outtxt;
    tipBox.style.visibility = "Visible";

    tipBox.style.opacity = '.1';
    tipFade(10);
  }

  function setPosition(obj,tipBox)
  {
    var scrWidth = document.body.scrollWidth -10;  // The -10 keeps the box from reaching the edge of the screen.
    var lftOffset = getOffset(obj, "Left");
    var boxWidth = tipBox.style.width.substring(0,tipBox.style.width.length-2); // The width set for the tipBox
    var totWidth = lftOffset + (boxWidth-0);
    if (totWidth > scrWidth) lftOffset = lftOffset - (totWidth - scrWidth); //Subtracts pixels to keep box 10px within right of window.
    if (lftOffset < 0) lftOffset = 0;
    if (document.captureEvents) {
      tipBox.style.left = lftOffset;
      tipBox.style.top = getOffset(obj, "Top");
    }
    else if ( window.event.clientX ) {
      tipBox.style.pixelLeft = lftOffset;
      tipBox.style.pixelTop = getOffset(obj, "Top");
    }
  }

  function getOffset(obj,which) { // Calculate and return the top and left position of an element relative to window.
    var amount = obj["offset"+which];
    if (which=="Top") amount+=obj.offsetHeight;
    obj = obj.offsetParent;
    while (obj!=null) {
      amount+=obj["offset"+which];
      obj = obj.offsetParent;
    }
    return amount;
  }

  function hideObject() {
    document.getElementById('tipbox').style.visibility = "hidden";
  }

  function closeTip() {
    tID = window.setTimeout("hideObject()",500);
  }

  function tipFade(opac) {
    var passed = parseInt(opac);
    var newOpac = parseInt(passed+10);
    var tipBox = document.getElementById('tipbox');
    if (newOpac < 80) {
      tipBox.style.opacity = '.'+newOpac;
      tipBox.style.filter = "alpha(opacity:"+newOpac+")";
      opacityID = window.setTimeout("tipFade('"+newOpac+"')",20);
    }
    else {
      tipBox.style.opacity = '.80';
      tipBox.style.filter = "alpha(opacity:80)";
    }
  }

//-->
</SCRIPT>
<!-- <DIV ID='tipbox' Style="width: 520"></div> -->
<DIV id=tipbox style="VISIBILITY: hidden"></DIV><B>Table cells</B><BR>
<TABLE width="100%" border=1>
  <TR>
    <TD id="one" onmouseover="showObject(event,'This is the long description for #1'); this.style.background = '#FFFFD0'" onmouseout="closeTip(); this.style.background = 'white'" align=left bgColor=#ffffff><FONT face="Verdana, Arial, Helvetica" size=1>Short description #1</FONT></TD>
    <TD id="two" onmouseover="showObject(event,'This is the long description for #2'); this.style.background = '#FFFFD0'" onmouseout="closeTip(); this.style.background = 'white'" align=left bgColor=#ffffff><FONT face="Verdana, Arial, Helvetica" size=1>Short description #2</FONT></TD>
    <TD id=three onmouseover="showObject(event,'This is the long description for #3'); this.style.background = '#FFFFD0'" onmouseout="closeTip(); this.style.background = 'white'" align=left bgColor=#ffffff><FONT face="Verdana, Arial, Helvetica" size=1>Short description #3</FONT></TD>
  </TR>
</TABLE>
<BR><BR>
<B>Text within a span tag</B>
<BR>
<SPAN onmouseover="showObject(event,'This is the long description for #1');" onmouseout=closeTip();>Short description #1</SPAN><BR><BR>
<SPAN onmouseover="showObject(event,'This is the long description for #2');" onmouseout=closeTip();>Short description #2</SPAN><BR><BR>
<SPAN onmouseover="showObject(event,'This is the long description for #3');" onmouseout=closeTip();>Short description #3</SPAN><BR><BR>
<BR><BR>
<B>Links</B><BR><A onmouseover="showObject(event,'This is the long description for #1');" onmouseout=closeTip(); href="#">Short description #1</A><BR><BR>
<A onmouseover="showObject(event,'This is the long description for #2');" onmouseout=closeTip(); href="#">Short description #2</A><BR><BR>
<A onmouseover="showObject(event,'This is the long description for #3');" onmouseout=closeTip(); href="#">Short description #3</A><BR><BR>
</BODY>
</HTML>


Paranoid? ME?? Who wants to know????
 
It's fun, isn't it? *laughing*

This is becoming my crash course in javascript. I had some knowledge of it before but with all that they have begun looking for, I'm getting a ton of learning in.

Thanks for looking into this further, I do appreciate it.

 
I found what I'm looking for but there is a problem... lol

Check this script out:

The problem is that all I want is the Sticky one that allows the close button and the links. I tried looking through the js file to see if I could find the section I wanted and port it out but this thing is a monster maze of code.

 
What I need to do now is to make the tooltip stay in place until the mouse goes out of it. That way I can put links in the tip to lead to sub-sections.

Oh, I see what you want. You mis-stated it above and said the reverse of what you meant.

You could just not put an onmouseout event in the field and the box would not go away. Inside the text you use an HTML link for Close and set that link to execute the closeTip function. Same effect.

One thing to consider though is that the script currently only uses a single DIV so if you had a sticky one on screen and you moused over another tag that calls it the sticky one would go away and the new one would come up. That could be taken care of by dynamically creating a div specific to each field as the showobject function is called.


Paranoid? ME?? Who wants to know????
 
Actually, in the beginning, they wanted just the tooltips. Upon seing them function, somebody got the great idea to use them as navigation tools too and that brought me back here with a different set of parameters.

You have to love it when the non-technical leaders have an idea...

 
Well it is easy enough to put links inside the display div as it is. I just hope they do not want to turn it into a full blown navigation system. For that there are plenty of DHTML nav menu scripts out there.

There is a timer delay set on the mouseoff event so that when you leave the link the link stays open briefly. This prevents accidental drifting off the link from causing it to close and then reopen. Makes the whole things smoother and if you were trying to move to click on a link inside the tool tip it will not disappear on you if you drift just off the edge making you go back to open it up again.

I have to consider the best way to make sticky's work.
You could leave them up until close is pressed, until a timer expires or until another link is hovered over.
But to support more than one tool tip on the screen at once then you need to have multiple divs which means either having a defined div for every tip on the page and passing the div name to show/hide functions or having code that will dynamically create/destroy the div as needed. It all depends on how you wanted it to function.

If I had the time I could modify my auto form validation code to do the job. Then all you would have to do is put a comment tag on the page with the name of the field it should associate with and the text to populate into it and I could handle it all dynamically. You could put in all the tags you wanted in a couple minutes without editing your fields, just inserting comments. I might actually work on something like that for a future revision.

In any event do you really want the sticky to remain until they press close or would you prefer it ran on a timer so if they did not click it in about 5 seconds after the mouse left it it would close automatically? And would you want it to disappear instantly if the mouse moved over a different tag with a tool tip?


Paranoid? ME?? Who wants to know????
 
Here is the code I am now working with. It does basically what I want except that it does not hide itself when another mouseover event happens. I'm trying to figure out how to tell the new popUp event to check and see if any others are visible and if so to close them.
Code:
<HTML>
<HEAD> 
<script language='javascript'>
function popUp(evt, currElem) {
  popUpWin = eval("document.all." + currElem + ".style");
  popUpWin.top = parseInt(evt.y);
  popUpWin.left = parseInt(evt.x);
  popUpWin.visibility = "visible";
  popUpWin.status = "";
}

function popDown(evt,currElem) {
 eval("document.all." + currElem + ".style").visibility = "hidden";
}
</script>
<style>
a:link {
  color: #0000FF; 
  text-decoration: none; 
  }
a:visited {
  color: #0000FF; 
  text-decoration: none; 
  }
.popUpStyle {
	BORDER-RIGHT: #000000 1px solid; font-family:Verdana, Arial, Helvetica, sans-serif; PADDING-RIGHT: 3px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 3px; FONT-SIZE: 11px; VISIBILITY: hidden; PADDING-BOTTOM: 3px; BORDER-LEFT: #000000 1px solid; WIDTH: 200px; PADDING-TOP: 3px; BORDER-BOTTOM: #000000 1px solid; POSITION: absolute; BACKGROUND-COLOR: #ffff99; layer-background-color: #FFFFcc;
}  
</style>
</HEAD>
<BODY>
<img src="east.jpg" width="400" height="370" border="0" usemap="#Map">
<DIV class=popUpStyle id=dvEurope><b>European Region</b><br><a href="#">Regional Team</a><br><a href="#">Current Initiatives</a><br><a href="#">Home Page</a><br><br><a href="#" onClick="popDown(event,'dvEurope');">Close</a></DIV>
<DIV class=popUpStyle id=dvRussia><b>Russian Region</b><br><a href="#">Regional Team</a><br><a href="#">Current Initiatives</a><br><a href="#">Home Page</a><br><br><a href="#" onClick="popDown(event,'dvRussia');">Close</a></DIV>
<DIV class=popUpStyle id=dvAfrica><b>African Region</b><br><a href="#">Regional Team</a><br><a href="#">Current Initiatives</a><br><a href="#">Home Page</a><br><br><a href="#" onClick="popDown(event,'dvAfrica');">Close</a></DIV>
<DIV class=popUpStyle id=dvAsia><b>Asian Region</b><br><a href="#">Regional Team</a><br><a href="#">Current Initiatives</a><br><a href="#">Home Page</a><br><br><a href="#" onClick="popDown(event,'dvAsia');">Close</a></DIV>
<map name="Map">
  <area shape="rect" coords="35,84,50,102" href="#" onMouseOver="popUp(event,'dvEurope');return true;">
  <area shape="rect" coords="186,78,206,96" href="#" onMouseOver="popUp(event,'dvRussia');return true;">
  <area shape="rect" coords="88,189,106,204" href="#" onMouseOver="popUp(event,'dvAfrica');return true;">
  <area shape="rect" coords="230,154,246,169" href="#" onMouseOver="popUp(event,'dvAsia');return true;">
</map>
</BODY>
</HTML>

 
Like this: Add the lines in Red.

Code:
[COLOR=red]var oldElem="";[/color]
function popUp(evt, currElem) {
[COLOR=red]  if (oldElem != "" && oldElem != currElem) {
    document.all(oldElem).style.visibility = "hidden";
  }[/color]
  popUpWin = eval("document.all." + currElem + ".style");
  popUpWin.top = parseInt(evt.y);
  popUpWin.left = parseInt(evt.x);
  popUpWin.visibility = "visible";
  popUpWin.status = "";
[COLOR=red]  oldElem = currElem;[/color]
}

First it sets a global value to store the last element that was popped up. Then it tests to make certain that oldElem is not blank (first time the function is called) and if it is not blank is it different than the currElem (in case they browsed back over the same one this prevents it from closing it and opening back up again). Then it hides the last element, displays the new element and then updates the oldElem value with the one just displayed.



Paranoid? ME?? Who wants to know????
 
BTW, what CMS are you using?
We use Vignette StoryServer and you can do includes with it, they just store them differently than the rest of the template pages.



Paranoid? ME?? Who wants to know????
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top