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 derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tip box positioning issues

Status
Not open for further replies.

theniteowl

Programmer
May 24, 2005
1,975
US
Hi All,
This is some code I have not worked on since last April.
It places a tip box on the page in relation to the element it is attached to but it also works to ensure that it never goes off screen by calculating the current element position, size of the screen and scroll position of the viewable window. If the box will go offscreen left or right it works to adjust the position accordingly. If it will go off the bottom of the viewable window it should flip itself to x pixels above the related element instead.

I have had problems getting this to work in anything but quirks mode and have issues with Firefox reporting back numbers I can use when trying to keep the box from going off the bottom of the window.

Please, any experts take a look and tell me if you know how to overcome the issues. Otherwise it is a very nice little tipbox utility.
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<TITLE></TITLE>
<style type="text/css">
<!--
body div#tipBox { 
  position:absolute;
  z-index:1000;
  width:320px;
  background:#E5ECF9;
  border:1px solid #3366CC;
  text-align:left;
  padding:5px;
  min-height:1em;
  color:#000;
  font:11px/12px verdana,arial,sans-serif;
}
-->
</style>
<!--   #tipbox {position: absolute; z-index: 100;border: 1pt black solid; background: #FFFFD0; visibility: hidden; font-size:8pt; font-family: "verdana, arial"; color:#000000 } -->
<SCRIPT type=text/JavaScript>
<!--
/*
  Future Improvements: Allow for non-disappearing tags or timed-disappearing tags.
  Possibly change from altering length of delay for fade (set as speed) to a change in the increment of opacity and
  see if it gives a smoother transition.

  If box does not fit in either position???  Routine to allow it to stretch sideways up to max width of screen and
  then determine if it fits bottom or top?

*/
var tID;		//Global variable for delay timer.
var opacityID;		//Global variable for opacity timer.
var fadeIn = true;	//Set Fade In feature default: true=on, false=off.
var fadeOut = true;	//Set Fade Out feature default: true=on, false=off.
var fadeInSpeed = 20;	//Default Fade In speed setting.
var fadeOutSpeed = 20;	//Default Fade Out speed setting.
var tipWidth = 220;
var scrHeight;
var scrWidth;
var scrLeft=0;
var scrTop=0;

  function showObject(e,outtxt,speed,width)
  { //If speed value is passed in it overrides the fadeIn setting and applies the speed value passed in.
    //If fadeIn variable is true but no speed passed in it takes default in fadeInSpeed
    var fadeSpeed=(speed)?speed:(fadeIn && speed !=0)?fadeInSpeed:false;
    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');
    tipBox.style.width = (width)?width:tipWidth;
    tipBox.innerHTML = outtxt;
    setPosition(obj,tipBox);
    tipBox.style.visibility = "Visible";
    tipBox.style.opacity = '.1';
    tipFade('in',10,fadeSpeed);
  }

  function setPosition(obj,tipBox)
  {
    setScrSize(); // Sets the scrHeight and scrWidth values.
    scrollOffset();  //Sets the scrWT and scrWL values (number of pixels screen is scrolled from top and left).
    var elL = getOffset(obj, "Left");  //Objects number of pixels from left of screen.
    var elT = getOffset(obj, "Top");   //Objects number of pixels from top of screen.

    var boxT;   //Topmost position to set tip box.
    var boxL;   //Leftmost position to set tip box.
    var scrBL;  //Number of pixels from Left box is placed in scrolled window.

    //Set leftmost position of tip box.
    boxL = (elL <= scrWL)?scrWL:elL;
    scrBL = (elL <= scrWL)?scrWL: elL - scrWL;
    if (scrBL + tipBox.offsetWidth > scrWidth) boxL -= (scrBL + tipBox.offsetWidth) - scrWidth;
    if (boxL < scrWL) boxL = scrWL; //Never let box start before left edge of screen.

    elL = boxL;

    //Set topmost position of tip box giving preference to below element but setting above if not enough space below.
    boxT = elT+obj.offsetHeight;

//##### NOTE: Not flipping to top reliably in Firefox because FireFox is returning scrWidth/scrHeight including scrollbars.
    //Test if box will drop below screen level
    elT = (tipBox.offsetHeight+boxT-scrWT > scrHeight && boxT-obj.offsetHeight-tipBox.offsetHeight > scrWT)?boxT-obj.offsetHeight-tipBox.offsetHeight:boxT;

    if (document.captureEvents) {
      tipBox.style.left = elL;
      tipBox.style.top = elT;
    }
    else if ( window.event.clientX ) {
      tipBox.style.pixelLeft = elL;
      tipBox.style.pixelTop = elT;
    }
  }


  function setScrSizeOLD() {
    if( typeof( window.innerWidth ) == 'number' ) { //Non-IE
      scrWidth = window.innerWidth;
      scrHeight = window.innerHeight;
    } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { //IE 6+ in 'standards compliant mode'
      scrWidth = document.documentElement.clientWidth;
      scrHeight = document.documentElement.clientHeight;
    } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { //IE 4 compatible
      scrWidth = document.body.clientWidth;
      scrHeight = document.body.clientHeight;
    }
  }


  function setScrSize() {
    if (self.innerWidth) {
      scrWidth = document.documentElement.clientWidth;
      scrHeight = document.documentElement.clientHeight;
    } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
      scrWidth = document.documentElement.clientWidth;
      scrHeight = document.documentElement.clientHeight;
    } else if (document.body) {
      scrWidth = document.body.clientWidth;
      scrHeight = document.body.clientHeight;
    }

/*******  Problems.  Only working in quirks mode and the clientHeight property for Firefox returns the ENTIRE height
of the document not just the content height so it still does not bump the tag to the top of the element if it is
dipping below the window.  Might have to revert back to self.innerHeight and deal with compensating for the size
of the scrollbar.  ******/

var outstr="clientWidth:"+scrWidth+" clientHeight:"+scrHeight;
window.status = outstr;
  }


  function scrollOffset() {
    if( typeof( window.pageYOffset ) == 'number' ) {
      scrWT = window.pageYOffset; scrWL = window.pageXOffset;
    } else if( document.body ) {
      scrWT = document.body.scrollTop; scrWL = document.body.scrollLeft;
    } else if( document.documentElement ) {
      scrWT = document.documentElement.scrollTop; scrWL = document.documentElement.scrollLeft;
    }
  }

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


  function hideObject(speed) {
    if (speed) 
      tipFade('out',80,speed);
    else {
      document.getElementById('tipbox').style.visibility = "hidden";
    }
  }


  function closeTip(speed) {
    if (window.tID) clearTimeout(tID); //Clear any existing timer.
    if ( window.opacityID ) clearTimeout(opacityID);
    var fadeSpeed=(speed)?speed:(fadeOut && speed !=0)?fadeOutSpeed:false;
    tID = window.setTimeout("hideObject("+fadeSpeed+")",500);
  }

  function tipFade(fDir,opac,speed) {
    var passed = parseInt(opac);
    var newOpac = (fDir == 'in')?parseInt(passed+10):parseInt(passed-10);
    var tipBox = document.getElementById('tipbox');
    if (newOpac < 80 && newOpac > 0 && speed) {
      tipBox.style.opacity = '.'+newOpac;
      tipBox.style.filter = "alpha(opacity:"+newOpac+")";
      opacityID = window.setTimeout("tipFade('" + fDir + "','"+newOpac+"',"+speed+")",speed);
    }
    else {
      tipBox.style.opacity = (fDir == 'in')?'.80':'.00';
      tipBox.style.filter = (fDir == 'in')?"alpha(opacity:80)":"alpha(opacity:00)";
    }
  }
//-->
</SCRIPT>
</head>
<body>

<DIV id="tipbox" style="VISIBILITY: hidden"></DIV>
<B>Table cells</B><BR>

<TABLE width="100%" border=1>
  <TR>
    <TD height="100" id="one" align=left bgColor=#ffffff><FONT face="Verdana, Arial, Helvetica" size=1><div onmouseover="showObject(event,'This is the long description for #1',0);" onmouseout="closeTip(200);">Short description #1</div></FONT></TD>
    <TD height="100" id="two" onmouseover="showObject(event,'This is the long description for #2',30); 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 height="100" 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',0,300);" onmouseout=closeTip(0); href="#">Short description #2</A><BR><BR>
....................<A onmouseover="showObject(event,'This is the longest description for #3-1234567090',0,300);" onmouseout=closeTip(); href="#">Longer description for #3</A>
<br>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
<br>
<br>
<br>
<br>
<br>
</BODY>
</HTML>

At my age I still learn something new every day, but I forget two others.
 
hey buddy.

i got this working better after a good amount of work. first of all, gotta give it the doctype. then, gotta validate it against that doctype (that took about 10 minutes). your main issues is probably this line:

Code:
body div#tipBox {

which should be:

Code:
body div#tip[red]b[/red]ox {

other things i changed were:

Code:
tipBox.style.width = (width)?width[red] + "px"[/red] : tipWidth[red] + "px"[/red];

.
.
.

    if (document.captureEvents) {
      tipBox.style.left = elL[red] + "px"[/red];
      tipBox.style.top = elT[red] + "px"[/red];
    }

i also used display instead of visibility, but i'm not sure that matters much.

let me know how it goes...

cory



*cLFlaVA
----------------------------
[tt]mr. pibb + red vines = crazy delicious![/tt]

[URL unfurl="true"]http://www.coryarthus.com/[/url]
 
Nuts, got a stretched page problem here and cannot see all of your text or even all of the button to submit this reply. *Sigh*

I have tried a few different complete doctypes but was having problems. This was back in April so I do not remember all of the details and have not had time to go back and try again just yet.
I will try out your changes and then test more in Firefox to see what I get.

I thought tipbox code that stays conveniently positioned would be useful but have not yet seen any that handled all situations and browsers yet so figured I would see if I ccould come up with something better.

Thanks.

At my age I still learn something new every day, but I forget two others.
 
Hmm, when I put in a 4.01 strict or transitional doctype whenever a tipbox appears it changes the size of my table cells almost as if the box was appearing inside the cells regardless of where it shows on screen.

I have to look into it but without the doctype this does not happen???


At my age I still learn something new every day, but I forget two others.
 
i removed the "px" from the pixelLeft and pixelTop attributes, which seemed to help a little. cells still resized though.

sorry, i didn't test in ie.



*cLFlaVA
----------------------------
[tt]mr. pibb + red vines = crazy delicious![/tt]

[URL unfurl="true"]http://www.coryarthus.com/[/url]
 
Resizing is weird since the div is absolutely positioned and should not affect the table.
I will have to play around with it and see if I can figure out why the table is affected. The table is set 100% and I purposely overloaded the body with text to make it scroll wider and it looks like when the box is displayed the table jumps out to 100% of the scrollable area rather than 100% of the viewable window but since it gets rendered before the long string of text it is only sized to the display. Looks like just a quirk of IE and nothing to do with the tip box code.


At my age I still learn something new every day, but I forget two others.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top