MediaWiki:Gadget-tooltips.js
After saving, you may need to bypass your browser's cache to see the changes. For further information, see Wikipedia:Bypass your cache.
- In most Windows and Linux browsers: Hold down Ctrl and press F5.
- In Safari: Hold down ⇧ Shift and click the Reload button.
- In Chrome and Firefox for Mac: Hold down both ⌘ Cmd+⇧ Shift and press R.
/* JavaScript tooltips
usage:
recommended usage: see [[Template:Tooltip]] and [[Template:Tooltip text]], or [[Module:Tooltip]] for module interface
raw usage:
Place this where you want the button to appear:
<span class="hidden js-tooltip-click" style="display:none;" data-tooltip-name="test">clickable</span>
place this elsewhere to define the content of the tooltip:
<div class="hidden js-tooltip-wrapper" style="display:none;" data-tooltip-for="test" data-tooltip-arrow="yes" data-tooltip-arrow-size="10" data-tooltip-style="custom style"><div class="js-tooltip-text">Content</div></div>
span.js-tooltip-click - required
attribute: data-tooltip-name - links to the corresponding divl; can have many with the same name
content: the clickable thing, defaults to ?
div.js-tooltip-wrapper - required
attributes:
data-tooltip-for - required; links this to spans with the data-tooltip-name equal to this
data-tooltip-arrow - optional; yes for arrow, no/default for no arrow
data-tooltip-arrow-size - optional; yes for arrow, no/default for no arrow
data-tooltip-style - optional; the width of the arrow (height=2width) in px; also defines the gap between the tooltip and the span. defaults to 10
content: div.js-tooltip-text
div.js-tooltip-text - required
contains: text/html to display inside tooltip
*/
$(function () {
if (!($('.js-tooltip-wrapper').length && $('.js-tooltip-click').length)) {
return;
}
// every tooltip wrapper on the page considered separately
// remove excess tooltip wrappers for the same name - can cause issues
(function(){
var forarr = {}, forarrv, key, first;
$('.js-tooltip-wrapper').each(function(){
forarr[$(this).attr('data-tooltip-for')] = true;
});
for (key in forarr) {
first = $('.js-tooltip-wrapper[data-tooltip-for="'+key+'"]').first();
$('.js-tooltip-wrapper[data-tooltip-for="'+key+'"]').not(first).remove();
}
})();
$('.js-tooltip-wrapper').each(function () {
var $span,
$text,
$arrow,
$wrapper,
$close,
resizeEvent,
hasArrow = true,
arrpos,
style,
styles,
parsed_styles,
name,
size,
limitwidth = false,
$currspan = $(null);
// setup vars
$wrapper = $(this);
name = $wrapper.attr('data-tooltip-for');
if ($wrapper.attr('data-tooltip-arrow')) {
hasArrow = $wrapper.attr('data-tooltip-arrow').toLowerCase() == 'yes';
}
if ($wrapper.attr('data-tooltip-limit-width')) {
limitwidth = $wrapper.attr('data-tooltip-limit-width').toLowerCase() == 'yes';
}
style = $wrapper.attr('data-tooltip-style');
size = parseInt($wrapper.attr('data-tooltip-arrow-size'), 10);
if (typeof size !== 'number' || isNaN(size)) {
size = 10;
}
$text = $wrapper.find('.js-tooltip-text');
// setup wrapper css for movement
$wrapper.removeClass('hidden')
.on('js-tooltip-close', function () {
$wrapper.hide();
$currspan.removeAttr('data-is-currspan');
$currspan = $(null);
});
// setup span css
$span = $('span.js-tooltip-click[data-tooltip-name="' + name + '"]');
$span.removeClass('hidden')
.attr('title', 'Click for explanation, click again to close');
if ($span.html() === '') {
$span.text('?');
}
// setup arrow
$arrow = $('<div>');
$arrow.addClass('js-tooltip-arrow')
.css({
top: ($wrapper.outerHeight() * 0.3) + 'px',
left: ('-' + (size+2) + 'px'), // width of arrow + width of text div border
'margin-top': ('-' + (size/2) + 'px'),
'border-width': size + 'px', //actual width of the arrow
});
arrpos = '-' + (size+2) + 'px';
// easiest way to deal with arrow is to just not add it if it isn't specified
if (hasArrow) {
$wrapper.prepend($arrow);
}
// setup close button
$close = $('<button>');
$close.html('<img src="/images/Close-x-white.svg?1ccac" />')
.addClass('close js-tooltip-close')
.click(function(){
$wrapper.trigger('js-tooltip-close');
});
$text.prepend($close);
// setup resize event for repositioning tooltips
resizeEvent = function () {
if ($currspan.length === 0) {
return;
}
var offset, position, width, $body, $mwtext;
offset = $currspan.offset();
position = $currspan.position();
width = $currspan.outerWidth();
$body = $('body');
$mwtext = $('#mw-content-text');
$wrapper.css({
top: (offset.top - $wrapper.outerHeight()*0.3) + 'px',
});
$arrow.css({
top: ($wrapper.outerHeight() * 0.3) + 'px',
});
if ((!limitwidth && offset.left > 0.5 * $body.width())
|| (limitwidth && position.left > 0.5 * $mwtext.width())) {
$wrapper.css({
right: (($body.width() - offset.left) - 5 + size) + 'px',
left: '', // remove other pos to prevent overspecification
});
$arrow.removeClass('js-tooltip-arrow-pointleft').addClass('js-tooltip-arrow-pointright').css({
left: '', // remove other pos to prevent overspecification
right: arrpos,
'border-left-width': size + 'px',
'border-right-width': 0,
});
if (limitwidth) {
$wrapper.css({
'max-width': '500px',
});
}
} else {
$wrapper.css({
left: (offset.left + width - 5 + size) + 'px',
right: '', // remove other pos to prevent overspecification
});
$arrow.removeClass('js-tooltip-arrow-pointright').addClass('js-tooltip-arrow-pointleft').css({
right: '', // remove other pos to prevent overspecification
left: arrpos,
'border-right-width': size + 'px',
'border-left-width': 0,
});
if (limitwidth) {
$wrapper.css({
'max-width': '500px',
});
}
}
};
// attach resize event
$(window).resize(resizeEvent);
// attach click event to span
$span.click(function (event) {
//no bubbles
event.preventDefault();
event.stopPropagation();
$this = $(event.currentTarget);
if ($this.attr('data-is-currspan') == 'true') {
// if the current span is clicked while the popup is open, close the popup
$this.removeAttr('data-is-currspan');
$currspan = $(null);
$wrapper.trigger('js-tooltip-close');
} else {
// else move and show the currently open popup
$currspan = $this;
$('.js-tooltip-wrapper').not($wrapper).trigger('js-tooltip-close');
$this.attr('data-is-currspan', true);
$wrapper.show();
resizeEvent();
}
});
// add custom style
if (typeof style === 'string' && style !== '') {
styles = style.split(';');
styles_parsed = {};
styles.forEach(function(v) {
if (typeof v === 'string') {
var arr = v.split(':');
if (typeof arr[1] === 'string' && arr[1].trim() !== '') {
styles_parsed[arr[0].trim()] = arr[1].trim();
}
}
});
$wrapper.css(styles_parsed);
}
// finish up
$wrapper.hide();
$span.show();
$wrapper.appendTo($('body'));
});
// close tooltip if clicked outside of
$(document).click(function (event) {
if ($('.js-tooltip-wrapper:visible').length && !$(event.target).closest('.js-tooltip-wrapper, .js-tooltip-click').length) {
$('.js-tooltip-wrapper').trigger('js-tooltip-close');
}
});
})