Smart Hover Box for Mootools 1.2

- Troy

v0.11

Update: we have released a new version of smart hover box!

Update: thanks to some feedback, found and fixed an IE bug that threw an error the first time you hovered over an element.

Smart Hover Box is a simple Mootools 1.2 function that spun off of mootime, my mootools 1.2 javascript timepicker. I liked the smart positioning, so decided to take the idea a bit further. With the Smart Hover Box you can add a hover html elements to any other element by adding a single id.

Imagine your web design has a single set of instructions that you want to hover:

  • create your hover control and give it the id “instructions”
  • then add the id “instructions_smarthbox” to a div containing the instructions.

That is all you have to do. Just add the id “id_suffix” to the element you want to hover, where “id” is the id of the control element. You can even define your own suffix to match your css style.

Demo

Check out a live demo of the Smart Hover Box v0.1 here.

Features

  • create a hover box out of any html element
  • smart positioning will always show hover box in window quadrant with the most space
  • optional close button by adding a user defined class to any element
  • user defined x and y hover element offset
  • user defined timeout after mouseleave event

Installation

Install mootools 1.2, then copy and paste the code before the </head> tag in your html file, or save it as a .js and pull it in.

  1. Download mootools 1.2, in my opinion, the best javascript library around.
  2. Upload the Smart Hover Box code between script tags (<script type=”text/javascript”> </script>), before the end of the head tag in your html (or)
  3. Save the javascript code below as smarthoverbox.js (or whatever you like) and link to in the head tag (<script src=”/js/smarthoverbox.js” type=”text/javascript”>)

Configuration

Javascript

To add hover boxes to your website, all you have to do is call the Smart Hover Box function, and define the following parameters: delay, x offset, y offset, the smart box suffix, the close button class name.

Here is the Smart Hover Box javascript:

var smartHoverBox = function(boxTimer, xOffset, yOffset, smartBoxSuffix, smartBoxClose) {
	var smartBoxes = $(document.body).getElements('[id$=' + smartBoxSuffix + ']');
	var closeElem = $(document.body).getElements('.' + smartBoxClose);  
	var closeBoxes = function() { smartBoxes.setStyle('display', 'none'); };
	closeElem.addEvent('click', function(){ closeBoxes() }).setStyle('cursor', 'pointer');
	var closeBoxesTimer = 0;	
	smartBoxes.each(function(item){	
		var currentBox = item.getProperty('id');
		currentBox = currentBox.replace('' + smartBoxSuffix + '', '');	 
 
		$(currentBox).addEvent('mouseleave', function(){
			closeBoxesTimer = closeBoxes.delay(boxTimer);									  
		});	
 
		item.addEvent('mouseleave', function(){
			closeBoxesTimer = closeBoxes.delay(boxTimer);								  
		});	
 
		$(currentBox).addEvent('mouseenter', function(){ 
			if($defined(closeBoxesTimer)) $clear(closeBoxesTimer); 
		});
 
		item.addEvent('mouseenter', function(){
			if($defined(closeBoxesTimer)) $clear(closeBoxesTimer);
		});  
 
 
 
		item.setStyle('margin', '0'); 
		$(currentBox).addEvent('mouseenter', function(){					 
				smartBoxes.setStyle('display', 'none');
				item.setStyles({ display: 'block', position: 'absolute' }).setStyle('z-index', '1000000'); 
 
				//coordinates and size vars and math 
				var windowSize = $(window).getSize();
				var windowScroll = $(window).getScroll();
				var halfWindowY = windowSize.y / 2;
				var halfWindowX = windowSize.x / 2;
				var boxSize = item.getSize();
				var inputPOS = $(currentBox).getCoordinates();
				var inputCOOR = $(currentBox).getPosition();
				var inputSize = $(currentBox).getSize(); 
				var inputBottomPOS = inputPOS.top + inputSize.y; 
				var inputBottomPOSAdjust = inputBottomPOS - windowScroll.y
				var inputLeftPOS = inputPOS.left + xOffset;
				var inputRightPOS = inputPOS.right;
				var leftOffset = inputCOOR.x + xOffset;  
 
				if(halfWindowY < inputBottomPOSAdjust) {
					item.setStyle('top', inputPOS.top - boxSize.y - yOffset);
					if (inputLeftPOS < halfWindowX) { item.setStyle('left', leftOffset); }
					else { item.setStyle('left', (inputPOS.right - boxSize.x) - xOffset); }; 
				}
				else {
					item.setStyle('top', inputBottomPOS + yOffset);
					if (inputLeftPOS < halfWindowX) { item.setStyle('left', leftOffset); } 
					else { item.setStyle('left', (inputPOS.right - boxSize.x) - xOffset); };
				};
		}).setStyle('cursor', 'pointer');	
	});
};

To add the function to your web page:

window.addEvent('domready', function() {
	smartHoverBox(
             1000, //delay before vanishing
             30, //x offset
             0,  //y offset
             '_smarthbox', //smart hover box suffix
             'smarthbox_close' //hover box close class
       );
});

HTML

<span id="instructions">instructions</span>
 
<div id="instructions_smarthbox">
 
<ul>
 
	<li>Step one</li>
 
 
	<li>Step two</li>
 
 
	<li>Step three</li>
 
</ul>
 
</div>

Download

Download Smart Hover Box

*Including the mootools 1.2 core, the ‘Smart Hover Box’ javascript file, and a simple html file.

Notes

You may have to set body {margin:0} for the offset to register correctly in IE (a bug in IE’s position reporting).

If you have any problem with flickering boxes on reload, try setting the boxes to display: none in the css.

Currently, only a single instance of the function is supported, though you may have as many hover boxes with the same parameters as you like.

You can use this however you like, and please drop me a comment letting me know if you use it in your web development project and what you think. I also welcome any suggestions on how to make it easier to use, as well as feature requests.

Thanks and I hope you find it useful.

Creative Commons License
This work is dedicated to the Public Domain.

Bookmark and Share

Comments (25) Trackbacks (2)
  1. yukon


    Nice...

    Have you heard or seen anyway of getting a "thought bubble" effect where an arrow points to what you are hovering over and dynamically moves depending on the direction of the hoverbox?
  2. Troy


    hmm... I'm not sure if i follow exactly what you mean. Could you point to an example?
  3. HÃ¥vard


    sad it's not working with smoothscroll (mootools) activated..
  4. Troy


    Bummer, I never tried it in combination with smoothscroll. Do you have an example set up so I can take a look?
  5. Tai Nguyen


    Hey Troy,

    I think Yukon may be referring to something like this http://www.dynamicdrive.com/dynamicindex5/dhtmltooltip.htm, which is what I'm looking for as well. I'll see if I can incorporate this and let you know what I come up with. Thanks for the great bit of code.
  6. Troy


    I followed that link, it looks like that lets you add html tooltips like these, the only difference I noticed was in the implementation. Hmmm... I am thinking that Yukon was talking more about the pointer on the thought bubble moving around. Not sure though. Tai, I would love to see what you come up with, drop us a note.
  7. fornetti


    I do not believe this
  8. Troy


    Which part?
  9. don peppo


    thanks for the great script! too bad i can't get it to run alongside with mocha ui...didn't find the problem yet, the hoverboxes seem to stick at the bottom of the page, outside the viewport...
  10. Troy


    If you can provide a link i'll take a look.
  11. Tai Nguyen


    Hey Troy,

    Yeah, the implementation on that was pretty antiquated, but I just wanted to point out how the tooltip follows the cursor. Not sure if that was what Yukon was referring to but that's what I meant. Anyway, I took a crack at it, so try this out. Basically you replace the event:

    $(currentBox).addEvent('mouseover', function(){ ... }

    with the following:

    $(currentBox).addEvent('mouseover', function(event){ $(document).addEvent('mousemove', trackMouse) });
    $(currentBox).addEvent('mouseout', function(){ $(document).removeEvents('mousemove') });

    var trackMouse = function(event){
    event = new Event(event);
    smartBoxes.setStyle('display', 'none');
    item.setStyles({ display: 'block', position: 'absolute' }).setStyle('z-index', '1000000');

    // coordinates and size vars and math
    var windowSize = $(window).getSize();
    var windowScroll = $(window).getScroll();
    var boxSize = item.getSize();

    // Keep the hover box within the viewport vertically
    if (event.client.y + yOffset + boxSize.y + padding &gt; windowSize.y) {
    var top = windowSize.y + windowScroll.y - boxSize.y - padding; // abuts bottom
    } else if (event.client.y + yOffset windowSize.x) {
    var left = windowSize.x + windowScroll.x - boxSize.x - padding; // abuts right
    } else if (event.client.x + xOffset &lt; padding) {
    var left = windowScroll.x + padding; // abuts left
    } else {
    var left = event.page.x + xOffset;
    }

    item.setStyle('top', top);
    item.setStyle('left', left);
    }

    I know that I shouldn't be creating a new Event, but for some reason I couldn't get bindWithEvent working right and was lazy. Please refactor if you have the time. Also, I added an argument called padding which determines how close to the edge the hovers can go, so there is a slight change in the function call:

    smartHoverBox(
    1000, //delay before vanishing
    20, //x offset - recommend positive
    -20, //y offset
    10, //minimum padding between hoverbox and edge of screen
    '_smarthbox', //smart hover box suffix
    'smarthbox_close' //hover box close class
    );
  12. Tai Nguyen


    Hey Troy,

    I am finding an issue which probably has more to do with MooTools (and my limited experience with it) than your script but maybe you have some ideas. It seems that MooTools cannot add events to elements that don't exist yet (makes sense, right?). Using domready functions will solve this for static content by ensuring that code won't fire until after the code is rendered. However, let's say you have a function that writes some HTML out with Javascript after the page is loaded - say, on some button click - and you want smartHoverBox to register events for those new elements. Any ideas?
  13. Tai Nguyen


    Ok, answered my own question. The solution is to only call the smartHoverBox after the code which generates new elements (duh!). Unfortunately there are several points where this happens so it seems unavoidable to make that function call multiple times.
  14. Troy


    Ah, interesting. I'm sure there is a way around this. Maybe we could turn this into a class and have a "give this object hover functionality" method.
  15. John


    I keep getting a script error in IE7 on "mouseenter". The error code points to LINE: #13 CHAR: 52 saying "closeBoxesTimer" is undefined. The sample DIV element I inserted onto the page displays ok, but the error only happens when mousing in. No problems in Firefox. Obviously, I'm new to javascript so any advice would be helpful and appreciated. Did I miss a configuration setting somewhere? Here's the temp page with the test DIV. http://beseenmedia.net/
    The test DIV is in the middle-left edge under the logo. Thanks!
  16. Troy


    Hey John, I checked out the link and wasn't able to find the example or reproduce the error in IE7 either. Let me know if this is something you have fixed or if you still need some help.
  17. Troy


    @12 & 13 - Tai, you are right, the code does not feature a "add element" function. I'll make note of that for the next version, thanks.
  18. Mike


    Troy, great script, however I was viewing your demo at http://www.consideropen.com/demos/smart-hover-box/ using IE7 v7.0.5730.13 and noticed the javascript error being produced that John was talking about. Any news on this?

    Line: 13
    Char: 52
    Error: 'closeBoxesTimer' is undefined
    Code: 0
    URL: http://www.consideropen.com/demos/smart-hover-box/
  19. Troy


    I see what you are taking about, not sure how i missed that. I think what's happening is that "closeBoxTimer" just needs to be declared, i'll do some experimenting and post once I find something. Thanks all for pointing this out.
  20. Mike


    That was a quick fix...however trying to click the hyperlink in the hover box example or even holding the cursor over the div to keep the box open seems to not work as well as it did before. Any ideas, maybe just adjusting the timer?
  21. Troy


    I see what happened... again, an IE only problem. Gimme a few.

    Update: thanks all, was able to get rid of that IE error, turned out I needed to add a conditional if $defined to the clear events, as well as create the "closeBoxesTimer " var outside the each loop. Thanks much!
  22. Eddy


    I read this now I was thinking it was me because I did remove a lot code to make it work in a WYSIWYG webbuilder.

    Line: 13
    Char: 52
    Error: 'closeBoxesTimer' is undefined
    Code: 0
    URL: http://www.consideropen.com/demos/smart-hover-box/

    I did get the warning in firefox and put the word closeboxtimer in this line.

    var smartHoverBox = function(boxTimer, xOffset, yOffset, smartBoxSuffix, smartBoxClose, closeBoxesTimer) {

    Troy the new update das not hover the tooltip in webbuilder maybe you use the old code with closeboxtimer in the first line.

    Sorry I`am not a coder if I may wrong about this.

    Eddy.
  23. Troy


    Ah, that makes sense. Glad you were able to make it work :)
  24. Eddy


    People tested the old hoverbox code with( closeBoxesTimer in the first line)in IE6,avantbrowser10.5, firefox 2.0, Opera 9.5, Firefox 3, IE7,
    Avantbrowser 11.7 built 7, Firefox 2.0, Opera 9.25 and GoogleChrome 0.2.149.
    all seems ok,maybe you like to now this.
  25. Morktron


    Hi Troy, excellent work, well done and many thanks :)

    I can't seem to getting it working properly though. It all works fine except that when you first go to the page the hoverbox is not hidden. It only goes after rolling over it or refreshing the page.

    Any ideas as to what causes this? I'll upload the site if you need to see it (although I built it years ago and my old code is embarrassing ;))


Leave a Reply