MediaWiki:ImageMapHighlight.js
Jump to navigation
Jump to search
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* ImageMapHighlight for Standalone MediaWiki installations
* Bypasses Fandom i18n hooks to ensure it runs universally.
*/
mw.hook('wikipage.content').add(function($content) {
// Only run if there is at least one highlighter div and the browser supports canvas
if (!$('.imageMapHighlighter').length || !window.CanvasRenderingContext2D) return;
window.imagemap = window.imagemap || {};
var artifactClass = 'imageMapHighlighterArtifact',
defaultAreaHighlight = {
fillStyle: window.imagemap.hightlightfill || 'rgba(0, 0, 0, 0.35)',
strokeStyle: window.imagemap.hightlightcolor || '#FFC500',
lineJoin: 'round',
lineWidth: window.imagemap.hightlightstrokewidth || 2
};
// Convert ImageMap area(s) to highlights on the canvas
function drawMarker(context, areas) {
function drawPoly(coords) {
context.moveTo(coords.shift(), coords.shift());
while (coords.length)
context.lineTo(coords.shift(), coords.shift());
}
for (var i in areas) {
var coords = areas[i].coords.split(',');
context.beginPath();
switch (areas[i].shape) {
case 'rect': drawPoly([coords[0], coords[1], coords[0], coords[3], coords[2], coords[3], coords[2], coords[1]]); break;
case 'circle': context.arc(coords[0], coords[1], coords[2], 0, Math.PI * 2); break;
case 'poly': drawPoly(coords); break;
}
context.closePath();
context.stroke();
context.fill();
}
}
// Add highlighting on hover
function mouseAction(e) {
var $this = $(this),
activate = e.type == 'mouseover',
caption = $this.text(),
ol = $this.parent(),
context = ol.data('context'),
areaHighlight = ol.data('area-highlight');
$this.toggleClass('liHighlighting', activate);
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
ol.find('li').each(function() {
var $li = $(this);
var licap = $li.text();
if (activate && licap === caption) {
$.extend(context, areaHighlight || defaultAreaHighlight);
drawMarker(context, $li.data('areas'));
}
});
}
// Add highlighting to an ImageMap
function handleOneMap() {
var img = $(this),
w = img.width(),
h = img.height(),
dims = { position: 'absolute', width: w + 'px', height: h + 'px', border: 0, top: 0, left: 0 },
parentMarker = img.closest('.imageMapHighlighter'),
liClasses = parentMarker.data('list-classes'),
map = img.siblings('map:first'),
defaultLink = false;
if (!map.length) {
map = img.parent().siblings('map:first');
defaultLink = true;
}
if (!$('area', map).length) return;
img.addClass('highlighted');
$(img).closest('div.noresize').css({ height: '', width: '' });
var jcanvas = $('<canvas>', { 'class': artifactClass })
.css(dims)
.attr({ width: w, height: h });
var bgimg = $('<img>', { 'class': artifactClass, src: img.attr('src') })
.css(dims)
.prop('alt', '').prop('ariaHidden', true);
var areaHighlight = $.extend({}, defaultAreaHighlight, {
fillStyle: parentMarker.data('fill') || parentMarker.css('--imagemaphighlight-fill'),
strokeStyle: parentMarker.data('stroke') || parentMarker.css('--imagemaphighlight-stroke'),
lineWidth: parentMarker.data('line-width') || parentMarker.css('--imagemaphighlight-stroke-width')
});
var context = $.extend(jcanvas[0].getContext('2d'), areaHighlight);
var div = $('<div>').css({ position: 'relative', width: w + 'px', height: h + 'px' });
(defaultLink ? img.parent() : img).before(div);
div.append(bgimg).append(jcanvas).append(defaultLink ? img.parent() : img);
img.fadeTo(1, 0);
var ol = $('<ol>', { 'class': artifactClass })
.css({ maxWidth: w + 'px' })
.data('area-highlight', areaHighlight)
.data('context', context);
// Simple visibility check for legend toggle
if ([0, false, 'no'].includes(parentMarker.data('legend'))) {
ol.css('display', 'none');
}
var figure = parentMarker.find('figure');
var figcaption = figure.children('figcaption');
figcaption.addClass('imageMapHighlighterLegend');
figcaption.empty().append(ol);
var lis = {};
var someli;
$('area', map).each(function() {
var text = this.title;
var li = lis[text];
if (!li) {
var href = this.href;
lis[text] = li = $('<li>', { 'class': artifactClass })
.append($('<a>', { href: href }).html(mw.html.escape(this.title)))
.on('mouseover mouseout', mouseAction)
.data('areas', [])
.addClass(liClasses && (liClasses[text] || liClasses['default']))
.appendTo(ol);
}
li.data('areas').push(this);
someli = li;
$(this).on('mouseover mouseout', function(e) {
li.trigger(e.type);
});
});
if (someli) someli.trigger('mouseout');
}
// Process maps found on load or dynamic injection
var selector = '.imageMapHighlighter img[usemap]:not(.highlighted)';
$content.find(selector).each(handleOneMap);
});