Corey Trager
Corey Trager

Reputation: 23133

How do I constrain the size of a tooltip/popup-style DIV so that it doesn't trigger scrollbars on the page

The mouse hovers over an element and a tip appears. The tip overflows the page, triggering a scrollbar, which changes the layout just enough so that the underlying element that triggered the tip is no longer under the mouse pointer, so the tip goes away.

The tip goes away, so the scrollbar goes away, and now the mouse is again over the element.

Wash, rinse, repeat.

If I could make sure that tip isn't too big so as to trigger scrollbars, that would solve my problem.

EDIT: After reading comments, some things to clarify: The div contains text which can vary. If I can, I want to show all the text. The div's location needs to be near the element the mouse's tip is over. So the key is, I need to know whether to truncate the text.

I did find this link:
http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
which contains this piece of the puzzle, figuring out how big the browser window is:

function alertSize() {
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  window.alert( 'Width = ' + myWidth );
  window.alert( 'Height = ' + myHeight );
}

Upvotes: 5

Views: 4952

Answers (9)

Corey Trager
Corey Trager

Reputation: 23133

Here is the code that I ended up using, and it seems to be working.

function display_popup(s)
{ 

    var popup = document.getElementById("popup");
    popup.innerHTML = s

    //viewport_height = $(document).height()  doesn't work
    viewport_height = get_viewport_size()[1] // does this factor in scrollbar?

    mytop = $(current_element).offset().top + $(current_element).height() + 4
    scroll_offset_y = $(document).scrollTop()
    y_in_viewport = mytop - scroll_offset_y

    if (y_in_viewport < viewport_height) // are we even visible?
    {
        // Display the popup, but truncate it if it overflows   
        // to prevent scrollbar, which shifts element under mouse
        // which leads to flicker...

        popup.style.height= ""
        popup.style.display = "block";

        if (y_in_viewport + popup.offsetHeight > viewport_height)
        {
            overflow = (y_in_viewport + popup.offsetHeight) - viewport_height

            newh = popup.offsetHeight -  overflow
            newh -= 10 // not sure why i need the margin..

            if (newh > 0)
            {
                popup.style.height = newh 
            }
            else
            {
                popup.style.display = "none";
            }
        }
        popup.style.left = $(current_element).offset().left + 40
        popup.style.top = mytop
    }
}


function get_viewport_size()
{
  var myWidth = 0, myHeight = 0;

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

  return [myWidth, myHeight];
}

Upvotes: 1

buti-oxa
buti-oxa

Reputation: 11431

A better idea may be to place the tooltip to the left or to the right of the element depending on which side of the page is closer. I have width of my tooltip fixed, fill it with content and make it visible when needed, and then position it depending on mouse position. Here's the key part of onmousemove event handler when tooltip is enabled:

if (!e) var e = window.event;
if(e) {
    var posx = 0;
    var posy = 0;

    if (e.pageX || e.pageY) {
        posx = e.pageX;
        posy = e.pageY;
    }
    else if (e.clientX || e.clientY) {
        posx = e.clientX + document.body.scrollLeft
            + document.documentElement.scrollLeft;
        posy = e.clientY + document.body.scrollTop
            + document.documentElement.scrollTop;
    }

    var overflowX = (document.body.clientWidth + document.body.scrollLeft + document.documentElement.scrollLeft) - (posx + 25+ tooltip.clientWidth);
    if(overflowX < 0) posx -= 25+ (tooltip.clientWidth);

    var overflowY = (document.body.clientHeight + document.body.scrollTop + document.documentElement.scrollTop) - (posy + 15+ tooltip.clientHeight);
    if(overflowY < 0) posy += overflowY;

    tooltip.style.left=(10+posx);
    tooltip.style.top=(10+posy);
}

Upvotes: 0

Zachary Yates
Zachary Yates

Reputation: 13386

I had this same problem earlier this year. The way I fixed it:

  1. I assumed vertical scrolling is ok, but horizonal scrolling is not. (There was always enough room so that the vertical scrollbar didn't affect my layout)
  2. I fixed the relative vertical position of the tooltip with regards to the target. (The top of the tooltip was always 5px below the bottom of the anchor)
  3. The left side of the tooltip was set with regard to the size of the screen. If the whole tooltip could fit on one line, cool. Otherwise, I constrained the max width and made it wrap.

One thing that helped me implement it this was was Quirksmode's Find Position article.

My solution might not be exactly what you're looking for, but at least have a look at the Quirksmode link, its good.

Hope that helps!

Upvotes: 0

pkaeding
pkaeding

Reputation: 37643

You could try determining where the pointer is, and if it is in the right 1/4 (or whatever area you determine) of the viewport, put the tool tip on the left of the pointer, otherwise put it to the right.

You mentioned that the text can vary, but is it possible it will grow very large? Could it take up an entire screen itself? Most likely, there is a maximum size it will be, so take that into account when deciding what threshold to use to decide if the tip should be on the right or the left.

Then, absolutely position your tip div, and to be safe, give it a max-height and max-width attribute. If the text does grow larger than that, give it overflow: scroll in the CSS.

Upvotes: 0

Thevs
Thevs

Reputation: 3253

It could be possible to setup a ghost transparent DIV exactly of you whole page/viewport size. Then you can 'stick' a tooltip DIV within it, providing CSS float:right attribute. That would give you correct top/left tooltip's corner measures for a final tooltip rendering.

Edit: this should be done only for the case of 'edge situations'.

Upvotes: 0

Steven A. Lowe
Steven A. Lowe

Reputation: 61233

you can use a hidden DIV positioned at 0,0 with width and height set to 100% as a 'yardstick' to measure the client area of the screen

if you know the size of your tooltip window, you can clip it to the client window, or change the display position to shift it so that it stays within the boundaries

some code below (untested, ripped from another project and renamed inline)

var toolTipDiv; //this is your tooltip div element
//call AdjustToolTipPosition(window.event);
function AdjustToolTipPosition(e)
{
    var cpos = getPosition(e);
    mouseX = cpos.x;
    mouseY = cpos.y;

    //Depending on IE/Firefox, find out what 
    //object to use to find mouse position

    toolTipDiv.style.visibility = "visible";

    //backdrop 'yardstick' for client area measurement
    var backdropDiv = document.getElementById("divBackdrop");

    //make sure floating box doesn't leave the screen
    //we know box is 200x200 plus margins, say 215x215
    if ((cpos.y + 215) > backdropDiv.offsetHeight)
    {
        cpos.y = backdropDiv.offsetHeight - 215;
    }
    if ((cpos.x + 215) > backdropDiv.offsetWidth)
    {
        cpos.x = backdropDiv.offsetWidth - 215;
    }
    toolTipDiv.style.left = cpos.x + "px";
    toolTipDiv.style.top = cpos.y + "px";
}
//this function courtesy of 
//http://hartshorne.ca/2006/01/23/javascript_cursor_position/
function getPosition(e) 
{
    e = e || window.event;
    var cursor = {x:0, y:0};
    if (e.pageX || e.pageY) 
    {
        cursor.x = e.pageX;
        cursor.y = e.pageY;
    }
    else 
    {
        var de = document.documentElement;
        var b = document.body;
        cursor.x = e.clientX + 
            (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0);
        cursor.y = e.clientY + 
            (de.scrollTop || b.scrollTop) - (de.clientTop || 0);
    }
    return cursor;
}

Upvotes: 1

Owen
Owen

Reputation: 84513

edit: in response to the comments, it sounds like you're trying to have the tooltip appear, without affecting the positioning of existing elements (and thus causing the scrollbar on the main window).

if that's the case, you want to define your tooltip's position as absolute, as this will remove it from the flow of elements (so when it appears it won't push the rest of the page down).

for example, you could start it hidden:

#tooltip {
  position: absolute;
  height: 100px;
  width: 200px;
  border: 1px solid #444444;
  background-color: #EEEEEE;
  display: none;
}

then, on your mouseover event (or whatever it's called on), set the top and left css of the #tooltip to where ever you want it, and switch the display to block. as it's positioned absolutely, it won't cause the flicker.

Upvotes: 1

kender
kender

Reputation: 87171

Seems to me that what you need is cursor position within the client browser window. Then you can do your calculations to place the tooltip so it doesn't cross the border.

What I found on the web is a short article discussing this in diffrent browsers: Mouse Cursor Position. Maybe this could help you fix your problem?

And some more info about browser size can be found here.

Hope it helps.

Upvotes: 0

andyk
andyk

Reputation: 10008

CSS : specify the tooltip's width and height, add overflow: hidden or overflow: scroll to it.

position: absolute works fine too, but of course, then you'll have to specify the top and left position of the tooltip.

Upvotes: 1

Related Questions