Skip to content

Instantly share code, notes, and snippets.

@yairEO
Last active February 27, 2016 18:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yairEO/df9d1642cdcdb2b253b8 to your computer and use it in GitHub Desktop.
Save yairEO/df9d1642cdcdb2b253b8 to your computer and use it in GitHub Desktop.
Tether tooltip
/*
* Tooltips using Tether
* Yair Even-Or
*/
var ttip = (function(){
var Tooltip = function(target, settings){
var defaults = {
closeBtn : false,
};
this.settings = $.extend(true, defaults, settings);
this.target = target;
// some tooltips targets might share the same tooltip
this.group = this.target.data('tooltipGroup');
this.attachment = this.settings.attachment || this.target.data('tooltipAttachment') || 'bottom center';
this.targetAttachment = this.settings.targetAttachment || this.target.data('tooltipTargetAttachment') || 'top center';
this.targetOffset = this.settings.targetOffset || this.target.data('tooltipOffset') || '10px 0';
// look if the tooltip with this group is already on the page
this.elm = $('.ttip').filter('.' + this.group);
if( this.targetAttachment == 'bottom center' && !this.target.data('tooltipOffset') ){
this.targetOffset = '-10px 0';
}
if( !this.elm[0] )
this.elm = this.generate().prependTo(document.body);
if( !this.elm )
return;
this.tether = new Tether({
element : this.elm,
target : this.target,
attachment : this.attachment,
targetAttachment : this.targetAttachment,
targetOffset : this.targetOffset,
constraints : [{
to : 'window',
attachment : 'together element'
}],
classes: {
element: [this.settings.tooltipClass || this.target.data('tooltipClass') || this.target[0].getAttribute('data-tooltipClass') || '', this.group].join(' ')
}
});
this.tether.disable();
}
Tooltip.prototype = {
generate : function(){
var content = this.settings.content || this.target[0].title || this.target.data('tooltipContent') || this.target[0].getAttribute('data-tooltipContent');
// if( !content ){
// console.warn('no tooltip content');
// return false;
// }
// clear the triggering element's title attribute (not needed anymore)
if( this.target[0].title )
this.target.prop('title','');
return $('<div>').addClass('ttip').data('ttip', this).html( content );
},
// show tooltip
show : function(checkClickOutside){
var that = this;
this.elm.prependTo(document.body);
//this.elm.focus();
this.elm[0].scrollTop;
this.tether.enable();
setTimeout(this.tether.position, 0);
clearTimeout(this.removeElmTimer);
if( checkClickOutside )
// bind a "click outside" event on the document itself (this event MUST be removed when the tooltip is removed to prevent it from being created again and not to pollute the document with events)
$(document).on('mouseup.tooltip_outside', function(e){
if( !$(e.target).closest('.ttip').length )
that.hide();
});
},
// hide tooltip
hide : function(){
// clean the "blur" event (not needed when the tooltip isn't visible)
$(document).off('mouseup.tooltip_outside');
var tether = this.tether,
that = this;
this.tether.disable();
this.removeElmTimer = setTimeout(function(){
// tether.element.style.left = '-999px';
that.elm.detach();
that.target.removeClassPrefix('tether');
}, 250);
}
}
////////////////////////////////////////////////
// callbacks
var delay = (function(){
var eventTimeout;
return function(e){
clearTimeout(eventTimeout);
if( e.type == 'mouseleave'){
event(e, ['mouseenter','mouseleave']);
return;
}
var eType = e.type;
eventTimeout = setTimeout(function(){
e.type = eType;
event(e, ['mouseenter','mouseleave']);
}, 100);
}
})();
function event(e, eventsArr, settings){
var $target = $(e.currentTarget),
eventType = e.type,
tooltip = initTooltip( $target, settings || $target.data('ttip') );
if( eventType == eventsArr[0] )
tooltip.show( eventType == 'click' );
else if( eventType == eventsArr[1] )
tooltip.hide();
}
function initTooltip(elm, settings){
var tooltip;
if( elm.data('tooltip') )
tooltip = elm.data('tooltip');
else{
tooltip = new Tooltip(elm, settings);
elm.data('tooltip', tooltip);
}
return tooltip;
}
function onEscapeKey(e){
// Prevent default keyboard action (like navigating inside the page)
if( e.keyCode == 27 )
$('.ttip.tether-enabled').remove();
}
////////////////
// Events
$(document).on('mouseenter.tooltip mouseleave.tooltip', '.hasTtip', delay)
.on('keydown.closeTooltips', onEscapeKey);
return {
init : initTooltip,
event : event,
Tooltip : Tooltip
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment