/*
Astro Tooltips
@dylang, created May 17 2011
------------------------------------------------------------------
Recommended Usage: Data attribute.
data-tooltip="optional selector for the tip"
data-tooltip-html="If
data-tooltip
is empty then data-tooltip-html
is required"
data-tooltip-style="optional className" //defaults to showing tip above content, "side" will show the tip to the left or right
data-tooltip-disable //disables the tooltip
data-tooltip-offset="2" //px distance from trigger
------------------------------------------------------------------
Optional Usage: jQuery Plugin
// You should never need this. Adding the data attributes should be enough.
$(triggerElement).tooltip({
selector: 'optional selector or jquery object',
style: 'optional className',
html: 'optional html if content is not used'
offset: 2 //px distance from trigger
});
// Show a tooltip, should never be needed
$(triggerElement).tooltip({action: 'show'});
// Hide a tooltip, should never be needed
$(triggerElement).tooltip({action: 'hide'});
// Enable/Disable the tooltip
$(triggerElement).tooltip({action: 'enable|disable'});
------------------------------------------------------------------
Tips and Examples
The trigger element always gets the class "highlight" while the tooltip is active.
Tooltips activate on mouse hover and keyboard focus.
The selector can be a child of the trigger or an element elsewhere in the DOM.
Child:
DOM: Tooltip in DOM
Inline:
*/
(function($){
//Tooltip container and pointer is shared for all tips
var $container = $(''),
$pointer = $container.find('.tooltip-pointer'),
$pointerBorder = $container.find('.tooltip-pointer-border');
// For active element
var $activeTrigger, // The element that the user hovered over
$activeContent, // The specific tooltip content
activeStyle, // Current style being used
hide_timer; // Timer for hiding the tooltip
// Constants
var MILLISECONDS_BEFORE_TIP_HIDES = 30,
POINTER_OFFSET = 19,
DEFAULT_OFFSET = 2;
var $window = $(window);
function hide() {
hide_timer = setTimeout(function() {
$container.fadeOut('fast');
if ($activeTrigger) { $activeTrigger.removeClass('highlight'); }
}, MILLISECONDS_BEFORE_TIP_HIDES);
}
function positionPointer(direction, side) {
$container.removeClass('tooltip-left tooltip-right tooltip-down tooltip-up');
var containerHeight = $container.height();
if (side) {
// container is left or right of the trigger
$pointerBorder.css({top: containerHeight/2});
$pointer.css({top: containerHeight/2 + 3}); //move pointer up three so there is room for the border
} else {
// Container is above or below the trigger
//Remove modifications from other style of tooltips
$pointerBorder.css({top: ''});
$pointer.css({top: ''});
}
$container.addClass('tooltip-' + direction);
}
function position($trigger, side) {
var top,
left,
direction; //up/down/left/right
var offset = POINTER_OFFSET + $trigger.data('tooltip-offset');
var containerSize = {
width: $container.outerWidth(),
height: $container.outerHeight()
};
var triggerSize = {
width: $trigger.outerWidth(),
height: $trigger.outerHeight()
};
var triggerPosition = $trigger.offset();
if (side) {
//show tip to the left or right side
top = triggerPosition.top - (containerSize.height/2 - triggerSize.height/2);
left = triggerPosition.left - containerSize.width - offset;
direction = 'right';
if (left < 0) {
left = triggerPosition.left + triggerSize.width + offset;
direction = 'left';
}
} else {
//show tip above unless there isn't enough room then show below
top = triggerPosition.top - containerSize.height - offset;
left = triggerPosition.left + (triggerSize.width/2 - containerSize.width/2);
direction = 'down';
if (top < $window.scrollTop()) {
top = triggerPosition.top + triggerSize.height + offset;
direction = 'up';
}
}
return {
top: top,
left: left,
direction: direction
}
}
function show($trigger, $content, style){
clearTimeout(hide_timer);
// Hide previous tooltip if it's still showing
if ($activeTrigger) { $activeTrigger.removeClass('highlight'); }
if ($activeContent) { $activeContent.hide(); }
if (activeStyle) { $container.removeClass(activeStyle); }
$trigger.addClass('highlight');
// show this tip content
$content.show();
var containerPosition = position($trigger, style === 'side');
$container
.stop() //stop the fade if it was fading
.addClass(style)
.show()
.css({
top: containerPosition.top,
left: containerPosition.left,
opacity: 1, //fade in fully
zoom: '', //fix IE6/7 bug that would crop the pointer
filter: '' //fix IE6/7 bug that would crop the pointer
});
positionPointer(containerPosition.direction, style === 'side');
$activeTrigger = $trigger;
$activeContent = $content;
activeStyle = style;
}
$.fn.tooltip = function(options) {
options = options || {};
return this.each(function() {
var $trigger = $(this),
tooltipSelector = options.selector || $trigger.data('tooltip'),
tooltipHTML = options.html || $trigger.data('tooltip-html'),
style = options.style || $trigger.data('tooltip-style'),
offset = options.offset || $trigger.data('tooltip-offset') || DEFAULT_OFFSET,
$content = $trigger.data('$tooltip-content'); //might be cached;
if (!$content) {
if (tooltipSelector) {
$content = $trigger.find(tooltipSelector); //child of trigger
// didn't find, it, look on the whole page
if (!$content.length) {
//absolute selector
$content = $(tooltipSelector);
}
tooltipHTML = $content.html();
}
if (tooltipHTML) {
$content = $('')
.hide()
.html(tooltipHTML)
.appendTo($container);
// cache it
$trigger.data('$tooltip-content', $content);
}
}
$trigger.data('tooltip-offset', offset);
switch (options.action) {
case 'show':
if (!$trigger.is('[data-tooltip-disable]')) {
show($trigger, $content, style);
}
break;
case 'hide':
hide();
break;
case 'disable':
$trigger.attr('data-tooltip-disable', '');
break;
case 'enable':
$trigger.removeAttr('data-tooltip-disable');
break;
default:
break;
}
// If the jquery plugin is used this enables the delegate to work
if (!$trigger.attr('data-tooltip')){
$trigger.attr('data-tooltip', '');
}
});
};
$(function(){
$container
.hide()
.hover(function(){
// Keep the tooltip up if the user hovers over it
clearTimeout(hide_timer);
}, function(){
// Start the hiding if the user leaves the tooltip
hide();
})
.appendTo('body');
});
$.doc.delegate('[data-tooltip]', {
'mouseenter focus': function() {
$(this).tooltip({ action: 'show' });
},
'mouseleave blur': function() {
hide();
}
});
})(jQuery);