MediaWiki:Common.js: Unterschied zwischen den Versionen

Aus ElaWiki
Zur Navigation springenZur Suche springen
Zeile 1: Zeile 1:
mw.loader.load('//he.wikipedia.org/w/index.php?title=Mediawiki:Gadget-ime.js&action=raw&ctype=text/javascript');
+
/*
 +
modified by [[user:קיפודנחש]]
 +
 +
original script by Peter Schlömer, can be found on
 +
https://tools.wmflabs.org/imagemapedit/ime.js,
 +
and contains the following copyright notice:
 +
=========== original license ================
 +
Copyright (c) 2007-2013 Peter Schlömer
 +
 
 +
Released under the following licenses (to make reuse in other Wikis
 +
easier):
 +
 
 +
GNU General Public License (GPL), version 2
 +
GNU Free Documentatin Licence (GFDL), version 1.2 or later
 +
Creative Commons Attribution ShareAlike (CC-by-sa), version 2 or later
 +
=============================================
 +
*/
 +
 
 +
if (mw.config.get('wgNamespaceNumber') == 6 && mw.config.get('wgAction') == 'view')
 +
$(function() {
 +
// avoid multiple activation, e.g. when [[m:Special:MyPage/global.js]] activates the script
 +
// and it's also activated on the wiki
 +
 
 +
if (window.mw_ime_running) return;
 +
window.mw_ime_running = true;
 +
 
 +
var ime_translations = { error_imagenotfound: 'ImageMapEdit: Could not find image in page structure.' };
 +
var ime_areas = Array();
 +
var ime_currentlyEditing = -1;
 +
var ime_width;
 +
var ime_height;
 +
var ime_scale;
 +
var img;
 +
var $img;
 +
var context;
 +
var jcanvas;
 +
var imageProperties;
 +
var currentClicks = {};
 +
var ime_templateHtml;
 +
var listenToMouse = false;
 +
var selectArea;
 +
 
 +
if (document.getElementById('file')) {
 +
ime_init1();
 +
}
 +
 
 +
function ime_htmlNewDiv(id) {
 +
var div = document.createElement('div');
 +
if (id) div.id = id;
 +
return div;
 +
}
 +
 
 +
/*
 +
Initialization, part 1: Tries to find image and uses a XMLHttpRequest
 +
to download information about the image. When this is done (it's an
 +
asynchronous request) show a link to load the rest of ImageMapEdit
 +
using ime_init2().
 +
*/
 +
function ime_init1() {
 +
var divFile = document.getElementById('file');
 +
if (!divFile) {
 +
ime_error(ime_translations['error_imagenotfound'] + ' (ime_init1,divFile=null)');
 +
return;
 +
}
 +
 
 +
var a = ime_findATag(divFile);
 +
if (!a) {
 +
ime_error(ime_translations['error_imagenotfound'] + ' (ime_init1,a=null)');
 +
return;
 +
}
 +
 
 +
var img = a.firstChild;
 +
if (!img) {
 +
ime_error(ime_translations['error_imagenotfound'] + ' (ime_init1,img=null)');
 +
return;
 +
}
 +
 
 +
var url = mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=imageinfo&iiprop=size&titles=' + mw.config.get('wgPageName');
 +
 
 +
$.get(url, function(data) {
 +
 
 +
if( typeof data.query.pages != "undefined" ) {
 +
        imageProperties = data.query.pages[Object.keys(data.query.pages)[0]];
 +
            var imageInfo = imageProperties.imageinfo;
 +
            if (imageInfo) {
 +
                ime_width = imageInfo[0].width;
 +
                ime_height = imageInfo[0].height;
 +
                ime_scale = img.width/ime_width;
 +
 
 +
                // Show 'show ImageMapEdit' button now
 +
                $('<a>', { id: 'imeLink'})
 +
                    .css({ display: 'block' })
 +
                    .text('ImageMapEdit >')
 +
                    .click( function(e) {
 +
                        e.preventDefault();
 +
                        ime_init2();
 +
                    })
 +
                    .appendTo('#file');
 +
            }
 +
}
 +
});
 +
}
 +
 
 +
/*
 +
Initialization, part 2: Triggered by an external link. Does some moving
 +
around of the image in the logical structure of the page, then hides the
 +
link and finally puts the HTML code in place.
 +
*/
 +
 +
function ime_init2() {
 +
 
 +
// Remove UI that might interfere with this code
 +
ime_removeOtherUIElements();
 +
 
 +
var divFile = document.getElementById('file');
 +
var tempNode = divFile.firstChild;
 +
var a = ime_findATag(tempNode);
 +
var divImeContainer = ime_htmlNewDiv('imeContainer');
 +
img = a.firstChild,
 +
$img = $(img);
 +
 +
divImeContainer.style.position = 'relative';
 +
 
 +
// Move image from within link to outside
 +
a.removeChild(img);
 +
divFile.insertBefore(divImeContainer,tempNode);
 +
divFile.removeChild(tempNode);
 +
divFile.style.direction = 'ltr';
 +
img.id = 'imeImg';
 +
img.style.border = 'none';
 +
img.oncontextmenu = function(e){e.preventDefault();e.stopPropagation();};
 +
 
 +
// Internet Explorer needs this differently
 +
if (typeof(navigator.userAgent) != 'undefined' && navigator.userAgent.match('/MSIE/')) {
 +
divImeContainer.style.overflow = 'none';
 +
}
 +
else {
 +
divImeContainer.style.overflow = 'auto';
 +
}
 +
 
 +
divImeContainer.appendChild(img);
 +
 +
jcanvas = $('<canvas>')
 +
.css( {
 +
position: 'absolute',
 +
width: $img.width() + 'px',
 +
height: $img.height() + 'px',
 +
border: 0,
 +
top:0,
 +
left:0
 +
})
 +
.attr({width: $img.width(), height: $img.height()})
 +
.appendTo(divImeContainer)
 +
context = jcanvas[0].getContext("2d");
 +
$.extend(context,  {
 +
fillStyle: 'rgba(255,255,0,0.4)',
 +
strokeStyle: 'red',
 +
lineJoin: 'round',
 +
lineWidth: 1.5/ime_scale}
 +
);
 +
context.scale(ime_scale, ime_scale);
 +
jcanvas.mousedown(onmousedown);
 +
jcanvas.click(function(e){e.preventDefault();e.stopPropagation();})
 +
jcanvas[0].oncontextmenu = img.oncontextmenu = function(e){e.preventDefault();e.stopPropagation();};
 +
 +
var divIme = ime_htmlNewDiv('ime');
 +
divFile.appendChild(divIme);
 +
 
 +
// Hide the link now
 +
document.getElementById('imeLink').style.display = 'none';
 +
 
 +
// Disable image context menu so right click can be used for events
 +
img.oncontextmenu = ime_eventDummy;
 +
 
 +
$(divIme).html(ime_templateHtml);
 +
 +
attachTemplate();
 +
 
 +
// Translate texts
 +
ime_translate();
 +
}
 +
 
 +
function ime_translate() {
 +
var allt = [ime_translations, window.ime_translations];
 +
while (allt.length) {
 +
var trans = allt.shift();
 +
if (trans)
 +
for (var key in trans)
 +
$('.ime_t_' + key).text(trans[key]);
 +
}
 +
}
 +
 
 +
/*
 +
Finds all elements in the current document with the specified class.
 +
*/
 +
function ime_getElementsByClassName(className) {
 +
// Hopefully the browser supports this natively
 +
if (document.getElementsByClassName) {
 +
return document.getElementsByClassName(className);
 +
}
 +
 
 +
// Otherwise use the function defined by MediaWiki
 +
return getElementsByClassName(document,'*',className)
 +
}
 +
 
 +
/*
 +
Display an error message, either by putting it on the page or - if the
 +
place to put it does not exist - by showing an alert box.
 +
*/
 +
function ime_error(message) {
 +
var jqFile = $('#file');
 +
var jqIme = $('#ime');
 +
 
 +
if (jqFile.length !== 0) {
 +
var jqImeError = $('<p>')
 +
.css({
 +
'color' : 'darkred',
 +
'background' : 'white',
 +
'border' : '1px solid darkred',
 +
'padding' : '1ex'
 +
})
 +
.text(message)
 +
 
 +
if (jqIme !== 0) {
 +
jqIme.before(jqImeError);
 +
} else {
 +
jqImeError.appendTo(jqFile);
 +
}
 +
}
 +
else {
 +
window.alert(message);
 +
}
 +
}
 +
 
 +
/*
 +
Dummy function to intercept events
 +
*/
 +
function ime_eventDummy(e) {
 +
e.cancelBubble = true;
 +
return false;
 +
}
 +
 
 +
 
 +
/*
 +
Function to define an object storing info on a clickable area for the
 +
imagemap.
 +
*/
 +
 
 +
/*
 +
Browser invariant function to get the event "behind" the object passed
 +
to event handlers.
 +
*/
 +
function ime_eventGetButton(e) {
 +
if (typeof(e.which)!='undefined') {
 +
return e.which;
 +
}
 +
else {
 +
return e.button;
 +
}
 +
}
 +
 
 +
function onmousedown(event) {
 +
if (!listenToMouse) return;
 +
event.preventDefault();
 +
event.stopPropagation();
 +
var isLeftButton = event.which == 1, isRightButton = event.which > 1;
 +
var offset = $('#imeImg').offset();
 +
var x = event.pageX - offset.left;
 +
var y = event.pageY - offset.top;
 +
var position = { x: parseInt( x / ime_scale ), y:  parseInt( y / ime_scale ) };
 +
if (isLeftButton) {
 +
currentClicks.left = position;
 +
}
 +
if (isRightButton) {
 +
currentClicks.right = position;
 +
}
 +
ime_saveArea(isLeftButton);
 +
}
 +
 +
function ime_mouseEventClear() {
 +
listenToMouse = false;
 +
currentClicks = {};
 +
jcanvas.css({ cursor: '' });
 +
}
 +
 
 +
function ime_mouseEventSet() {
 +
listenToMouse = true;
 +
jcanvas.css({ cursor: 'crosshair' });
 +
}
 +
 
 +
function ime_newArea(shape) {
 +
ime_mouseEventSet();
 +
ime_areas.push( { shape: shape, coords: [], link: '' } );
 +
ime_currentlyEditing = ime_areas.length-1;
 +
ime_updateAreas();
 +
return currentArea();
 +
}
 +
 
 +
function ime_updateAreas() {
 +
ime_updateSelectArea();
 +
ime_editArea(ime_currentlyEditing);
 +
ime_updateResult();
 +
}
 +
 
 +
function ime_updateResult() {
 +
var arr = document.ime.imageDescriptionPos;
 +
var imageDescriptionPos = arr[0].value;
 +
for (var i=1; i<arr.length; i++) {
 +
if (arr[i].checked) {
 +
imageDescriptionPos = arr[i].value;
 +
break;
 +
}
 +
}
 +
 
 +
var result = Array();
 +
result.push('<imagemap>');
 +
result.push(mw.config.get('wgPageName') + '|' + document.ime.imageDescription.value);
 +
result.push('');
 +
for (var i=0; i<ime_areas.length; i++) {
 +
var s = ime_areas[i].shape +
 +
' ' +
 +
ime_areas[i].coords.join(' ') +
 +
' [[' +
 +
ime_areas[i].link +
 +
(ime_areas[i].title ? '|' + ime_areas[i].title : '') +
 +
']]';
 +
 +
result.push(s);
 +
}
 +
result.push('');
 +
result.push('desc ' + imageDescriptionPos);
 +
result.push('</imagemap>');
 +
 
 +
var preResult = document.getElementById('imeResult');
 +
 
 +
while (preResult.lastChild) {
 +
preResult.removeChild(preResult.lastChild);
 +
}
 +
 
 +
for (var i=0; i<result.length; i++) {
 +
preResult.appendChild(document.createTextNode(result[i]));
 +
preResult.appendChild(document.createElement('br'));
 +
}
 +
ime_updateSelectArea();
 +
}
 +
 
 +
function drawAreas() { // this is where the magic is done.
 +
 +
function markPoint(point, color) {
 +
if (point) {
 +
context.beginPath();
 +
var arm = 8 / ime_scale;
 +
context.moveTo(point.x + arm, point.y);
 +
context.lineTo(point.x - arm, point.y);
 +
context.moveTo(point.x, point.y + arm);
 +
context.lineTo(point.x, point.y - arm);
 +
context.strokeStyle = color;
 +
context.stroke();
 +
context.closePath();
 +
}
 +
}
 +
 +
function drawPoly(coords) {
 +
coords = coords.slice();
 +
context.moveTo(coords.shift(), coords.shift());
 +
while (coords.length)
 +
context.lineTo(coords.shift(), coords.shift());
 +
}
 +
 +
context.clearRect(0, 0, context.canvas.width/ime_scale, context.canvas.height/ime_scale); // prepare for a new day.
 +
for (var ind in ime_areas) {
 +
var current = ind == ime_currentlyEditing;
 +
context.fillStyle = current ? 'rgba(255,255,0,0.4)' : 'rgba(255,0,0,0.4)';
 +
var area = ime_areas[ind];
 +
var coords = area.coords;
 +
context.beginPath();
 +
switch (area.shape) {
 +
case 'rect':
 +
var complete = true;
 +
for (var i = 0; i < 4; i++) complete = complete && coords[i];
 +
if (complete)
 +
drawPoly([coords[0], coords[1], coords[0], coords[3], coords[2], coords[3], coords[2], coords[1]]); break;
 +
case 'circle': if (coords.length == 3) {
 +
context.arc(coords[0],coords[1],coords[2],0,Math.PI*2);
 +
}
 +
break;//x,y,r,startAngle,endAngle
 +
case 'poly': drawPoly(coords);
 +
break;
 +
}
 +
context.closePath();
 +
context.fill();
 +
if (current) {
 +
context.strokeStyle = 'red';
 +
context.stroke();
 +
}
 +
}
 +
markPoint(currentClicks.left, 'red');
 +
if (currentArea().shape != 'poly') markPoint(currentClicks.right, 'yellow');
 +
}
 +
 
 +
function ime_updateSelectArea() {
 +
 
 +
selectArea.children().remove();
 +
 +
for (var i=0; i<ime_areas.length; i++) {
 +
var area = ime_areas[i],
 +
title = (area.title || area.link || '') + ' [' + area.shape + ']';
 +
$('<option>', { value: i })
 +
.text(title)
 +
.prop({ selected: i == ime_currentlyEditing } )
 +
.appendTo(selectArea);
 +
}
 +
selectArea.prop('selectedIndex', ime_currentlyEditing);
 +
}
 +
 
 +
function ime_editArea(index) {
 +
$('#imeProps').toggle(false);
 +
 
 +
var area = ime_areas[index];
 +
currentClicks = area.clicks || {};
 +
 
 +
 
 +
if (area) {
 +
ime_currentlyEditing = index;
 +
 
 +
$('#imeProps').toggle(true);
 +
$('.ime-prop').toggle(false);
 +
$('.ime-prop-' + area.shape).toggle(true);
 +
 +
ime_mouseEventSet();
 +
updateInputs();
 +
}
 +
drawAreas();
 +
}
 +
 
 +
function ime_deleteArea() {
 +
ime_mouseEventClear();
 +
 
 +
// Remove element from ime_areas array
 +
ime_areas.splice(ime_currentlyEditing,1);
 +
 
 +
if (ime_currentlyEditing>=ime_areas.length) {
 +
ime_currentlyEditing = ime_areas.length-1;
 +
}
 +
 
 +
ime_updateAreas();
 +
if (ime_currentlyEditing >= 0) {
 +
ime_editArea(ime_currentlyEditing);
 +
}
 +
}
 +
 +
function updateInputs(fromAreas) {
 +
 +
function updateRectInputs(coords) {
 +
var lx = $('#ime_areaRectLeft'),
 +
ly = $('#ime_areaRectTop'),
 +
rx = $('#ime_areaRectRight'),
 +
ry = $('#ime_areaRectBottom');
 +
 +
lx.val(coords && coords[0] || '');
 +
ly.val(coords && coords[1] || '');
 +
rx.val(coords && coords[2] || '');
 +
ry.val(coords && coords[3] || '');
 +
}
 +
 +
function updateCircInputs(coords) {
 +
var x = $('#ime_areaCircleX'),
 +
y = $('#ime_areaCircleY'),
 +
radius = $('#ime_areaCircleRadius')
 +
 +
x.val(coords && coords[0] || '');
 +
y.val(coords && coords[1] || '');
 +
radius.val(coords && coords[2] || '');
 +
}
 +
 +
function updatePolyInputs(coords) {
 +
$('#imePropsPolyCoords').val(coords.join(', '));
 +
}
 +
 +
 +
var area = currentArea();
 +
var coords = area.coords;
 +
switch (area.shape) {
 +
case 'rect'  : updateRectInputs(coords); break;
 +
case 'circle': updateCircInputs(coords); break;
 +
case 'poly' : updatePolyInputs(coords); break;
 +
}
 +
$('#ime_areaLink').val(area.link || '');
 +
$('#ime_areaTitle').val(area.title || '');
 +
}
 +
 
 +
function currentArea() {
 +
return ime_areas[ime_currentlyEditing];
 +
}
 +
 +
function ime_saveArea(leftClick) {
 +
var area = currentArea();
 +
area.link = document.ime.areaLink.value;
 +
area.title = document.ime.areaTitle.value;
 +
var d = area.clicks = $.extend({}, currentClicks);
 +
 +
var full = d.left && d.right;
 +
switch (area.shape) {
 +
case 'rect':
 +
if (d.left) {
 +
area.coords[0] = d.left.x; area.coords[1] = d.left.y;
 +
}
 +
if (d.right) {
 +
area.coords[2] = d.right.x; area.coords[3] = d.right.y;
 +
}
 +
break;
 +
case 'circle':
 +
if (leftClick) {
 +
area.coords[0] = d.left.x; area.coords[1] = d.left.y;
 +
}
 +
if (full) {
 +
var dx = d.left.x - d.right.x,
 +
dy = d.left.y - d.right.y;
 +
area.coords[2] = parseInt(Math.sqrt(dx*dx + dy*dy));
 +
}
 +
break;
 +
case 'poly':
 +
if (leftClick && d.left) {
 +
area.coords.push(d.left.x, d.left.y);
 +
}
 +
break;
 +
}
 +
updateInputs(full || area.shape == 'poly');
 +
ime_updateAreas();
 +
}
 +
 
 +
/*
 +
Remove all UI elements that might interfere with ImageMapEdit.
 +
*/
 +
function ime_removeOtherUIElements() {
 +
// Remove all UI elements of the 'annotations' feature used on Wikimedia
 +
// Commons.
 +
$('#ImageAnnotationAddButton').remove();
 +
}
 +
 
 +
/*
 +
Try to find an <a> tag within the specified HTML document node.
 +
*/
 +
 
 +
function ime_findATag(node) {
 +
// We just look at the first child until there is none or it is an <a> tag
 +
var a = node;
 +
while (a != null && a.nodeName.toUpperCase() != 'A') {
 +
a = a.firstChild;
 +
}
 +
return a;
 +
}
 +
 +
function ime_importLines(toclear) {
 +
var text = document.ime.importText.value;
 +
var lines = text.split("\n");
 +
 
 +
if (toclear) {
 +
ime_areas = [];
 +
}
 +
 +
for (var i=0; i<lines.length; i++) {
 +
var rectMatch = /^rect +(\d+) +(\d+) +(\d+) +(\d+) +\[\[([^|]*)(|(.*))?\]\]/i;
 +
var circleMatch = /^circle +(\d+) +(\d+) +(\d+) +\[\[([^|]*)(|(.*))?\]\]/i;
 +
var polyMatch = /^poly +(.*?) +\[\[([^|]*)(|(.*))?\]\]/i;
 +
 
 +
var line = lines[i];
 +
 
 +
if (rectMatch.test(line)) {
 +
var results = rectMatch.exec(line);
 +
var area = ime_newArea("rect");
 +
area.coords = results.slice(1, 5);
 +
area.link = results[5];
 +
if (results[6]) area.title = results[6].substring(1);
 +
}
 +
else if (circleMatch.test(line)) {
 +
var results = circleMatch.exec(line);
 +
var area = ime_newArea("circle");
 +
area.coords = results.slice(1, 4);
 +
area.link = results[4];
 +
if (results[5]) area.title = results[5].substring(1);
 +
}
 +
else if (polyMatch.test(line)) {
 +
var results = polyMatch.exec(line);
 +
var area = ime_newArea("poly");
 +
area.coords = results[1].split(/\s/);
 +
area.link = results[2];
 +
if (results[3]) area.title = results[3].substring(1);
 +
}
 +
}
 +
ime_updateAreas();
 +
}
 +
 
 +
function ime_showImport() {
 +
$('#imeImport').show();
 +
$('#imeImportShow').hide();
 +
$('#imeImportHide').show();
 +
}
 +
 
 +
function ime_hideImport() {
 +
$('#imeImport').hide();
 +
$('#imeImportShow').show();
 +
$('#imeImportHide').hide();
 +
}
 +
 
 +
function attachTemplate() {
 +
$('.ime_t_rect').click(function(e) { e.preventDefault(); ime_newArea('rect'); } );
 +
$('.ime_t_circle').click(function(e) { e.preventDefault(); ime_newArea('circle'); } );
 +
$('.ime_t_poly').click(function(e) { e.preventDefault(); ime_newArea('poly'); } );
 +
$('#ime_areaselector').change(function(e) { ime_editArea($(this).prop('selectedIndex')); });
 +
$('.ime_t_deletearea').click(function(e) { e.preventDefault(); ime_deleteArea();});
 +
$('#imeImportShow').click(function(e) { e.preventDefault(); ime_showImport();});
 +
$('#imeImportHide').click(function(e) { e.preventDefault(); ime_hideImport();});
 +
$('.ime_t_import').click(function(e) { e.preventDefault(); ime_importLines();});
 +
$('.ime_t_replace').click(function(e) { e.preventDefault(); ime_importLines(true);});
 +
$('.ime_saveonchange').change(ime_saveArea);
 +
$('.ime-updateresultsonchange').change(ime_updateResult);
 +
$('#ime_areaLink').change(function() { currentArea().link = $(this).val(); ime_updateResult();});
 +
$('#ime_areaTitle').change(function() { currentArea().title = $(this).val(); ime_updateResult();});
 +
$('.ime_t_deletecoordinates').click(function(e) {
 +
e.preventDefault();
 +
currentArea().coords = [];
 +
currentClicks = {};
 +
ime_saveArea();
 +
} );
 +
selectArea = $('#ime_areaselector');
 +
$('.ime-savepolyonout').focusout(function() {
 +
var val = $(this).val();
 +
var area = currentArea();
 +
var coords = val.split(/,/g).map(x => parseInt(x)).filter(x => !isNaN(x));
 +
if (coords && coords.length && coords.length % 2 === 0) {
 +
area.coords = coords;
 +
}
 +
ime_saveArea();
 +
});
 +
 +
$('.ime-saveonchange').focusout(function() {
 +
var input = $(this);
 +
var ind = input.data('coord');
 +
var val = parseInt(input.val());
 +
var area = currentArea();
 +
var coords = area && area.coords;
 +
 
 +
if (coords && typeof(ind) == 'number' && typeof(val) == 'number' && ! isNaN(val)) {
 +
coords[ind] = val;
 +
currentClicks = {};
 +
ime_saveArea();
 +
}
 +
});
 +
mw.loader.using(['mediawiki.api', 'jquery.ui']).done(function() {
 +
$('#ime_areaLink').autocomplete({
 +
    source: function( request, response ) {
 +
new mw.Api().get( {
 +
            action: 'opensearch',
 +
            search: request.term,
 +
            namespace: 0,
 +
limit:10
 +
        }).done(function( data ) {
 +
if ( data && data.length > 1 )
 +
response( data[1] );
 +
        }); // done
 +
    } // source
 +
}); // autocomplete
 +
}); // using
 +
}
 +
 +
 
 +
// this is the one-(very long)-line version of the template, since mw linger does not allow use multiline delimiter (ascii 96), not even in the comment...
 +
// formatted version in comment below.
 +
// original can be found at https://imagemapedit.toolforge.org/template.php.
 +
ime_templateHtml = '<form name="ime" action="" ><fieldset style="margin:0.5ex;padding:0 1ex 1ex"><legend>ImageMapEdit</legend><fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex"><legend style="padding:0 0.5ex" class="ime_t_newarea">Create new area</legend><a style="padding:1px;background:white;color:darkblue" class="ime_t_rect">rect(angle)</a><br /><a style="padding:1px;background:white;color:darkblue" class="ime_t_circle">circle</a><br /><a style="padding:1px;background:white;color:darkblue" class="ime_t_poly">poly(gon)</a></fieldset><fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex"><legend style="padding:0 0.5ex" class="ime_t_editarea">Edit area</legend><select id="ime_areaselector" size="10" style="float:left;height:10em;margin:0.5ex;width:auto;min-width:18em;overflow:auto;" ></select><div id="imeProps" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><div style="float:left;margin:0.5ex;padding:0 1ex 1ex"><label for="ime_areaLink" class="ime_t_linktarget">Link target</label><br /><input id="ime_areaLink" name="areaLink" style="width:10em" class="ime-saveonchange" /><br /><label for="ime_areaTitle"><span class="ime_t_linktitle">Link title</span> (<span class="ime_t_optional">optional</span>)</label><br /><input id="ime_areaTitle" name="areaTitle" style="width:10em" class="ime-saveonchange" /></div><div id="imePropsRect" class="ime-prop ime-prop-rect" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><label for="ime_areaRectLeft" class="ime_t_rectleft">First corner</label><br /><input id="ime_areaRectLeft" name="areaRectLeft" data-coord=0 class="ime-saveonchange" style="width:4em" /><input id="ime_areaRectTop" name="areaRectTop" data-coord=1 style="width:4em" class="ime-saveonchange" /><span class="ime_t_rectchoose1">Select with left mouse button</span><br/><label for="ime_areaRectRight" class="ime_t_rectright">Second corner</label><br /><input id="ime_areaRectRight" name="areaRectRight" data-coord=2 style="width:4em" class="ime-saveonchange" /><input id="ime_areaRectBottom" name="areaRectBottom" data-coord=3 style="width:4em" class="ime-saveonchange" /><span class="ime_t_rectchoose2">Select with right mouse button</span></div><div id="imePropsCircle" class="ime-prop ime-prop-circle" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><label class="ime_t_position">Position</label><br /><input name="areaCircleX" id="ime_areaCircleX" class="ime-saveonchange" data-coord=0 style="width:4em" /><input name="areaCircleY" id="ime_areaCircleY" style="width:4em" data-coord=1 class="ime-saveonchange" /><span class="ime_t_circlechoose1">Select with left mouse button</span><br /><label for="ime_areaCircleRadius" class="ime_t_radius">Radius</label><br /><input id="ime_areaCircleRadius" name="areaCircleRadius" data-coord=2 style="width:4em" class="ime-saveonchange" /><span class="ime_t_circlechoose2">Select with right mouse button</span></div><div id="imePropsPoly" class="ime-prop ime-prop-poly" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><label class="ime_t_coordinates">Coordinates</label><br /><textarea id="imePropsPolyCoords" style="font-size:0.8em;max-width:20em;height:8em"class="ime-savepolyonout"></textarea><a style="padding:1px;background:white;color:darkblue" class="ime_t_deletecoordinates">Delete all coordinates</a><br /><span class="ime_t_polychoose">Add new corner with left mouse button</span></div><div style="clear:both"></div><a style="padding:1px;background:white;color:darkblue" class="ime_t_deletearea">Delete selected area</a></div><div style="clear:both"></div></fieldset><div style="clear:both"></div><fieldset style="margin:0 0.5ex 0.5ex;padding:0 1ex 1ex"><legend class="ime_t_preferences">General preferences</legend><div style="float:left;margin-right:1em;"><label for="ime_imageDescription" class="ime_t_imagedescription">Image description</label><br /><input id="ime_imageDescription" name="imageDescription" class="ime-updateresultsonchange" /></div><div style="float:left"><label style="display:block" class="ime_t_infolinkposition">Position of information link</label><div style="float:left"><input type="radio" name="imageDescriptionPos" value="bottom-left" class="ime-updateresultsonchange" checked="checked" id="ime_imageDescriptionPos_bottomleft" /><label for="ime_imageDescriptionPos_bottomleft"><span class="ime_t_bottomleft">Bottom left</span> (<span class="ime_t_default">default</span>)</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="bottom-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_bottomright" /><label for="ime_imageDescriptionPos_bottomright" class="ime_t_bottomright">Bottom right</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="top-left" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topleft" /><label for="ime_imageDescriptionPos_topleft" class="ime_t_topleft">Top left</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="top-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topright" /><label for="ime_imageDescriptionPos_topright" class="ime_t_topright">Top right</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="none" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_none" /><label for="ime_imageDescriptionPos_none" class="ime_t_nolink">No link</label></div></div><div style="clear:both"></div></fieldset><fieldset style="margin:0.5ex;padding:0 1ex 1ex"><legend class="ime_t_importareas">Import areas from wikicode</legend><a style="padding:1px;background:white;color:darkblue" id="imeImportShow"><span class="ime_t_showtextbox">Show text box</span> &gt;</a><a style="padding:1px;background:white;color:darkblue;display:none" id="imeImportHide"><span class="ime_t_hidetextbox">Hide text box</span> &lt;</a><div id="imeImport" style="display:none"><textarea name="importText" style="width:100%;margin:0;height:10em;display:block"></textarea><a style="padding:0 2em;background:white;color:darkblue" class="ime_t_import">Import</a><a style="padding:0 2em;background:white;color:darkblue" class="ime_t_replace">Replace</a></div></fieldset><fieldset style="margin:0.5ex;padding:0 1ex 1ex"><legend class="ime_t_generatedwikicode">Generated wikicode</legend><div><code id="imeResult" style="display:block;line-height:1.2em"></code></div></fieldset></fieldset></form>';
 +
});
 +
/*
 +
<form name="ime" action="">
 +
    <fieldset style="margin:0.5ex;padding:0 1ex 1ex">
 +
        <legend>ImageMapEdit</legend>
 +
        <fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex">
 +
            <legend style="padding:0 0.5ex" class="ime_t_newarea">Create new area</legend>
 +
            <a style="padding:1px;background:white;color:darkblue" class="ime_t_rect">rect(angle)</a>
 +
            <br />
 +
            <a style="padding:1px;background:white;color:darkblue" class="ime_t_circle">circle</a>
 +
 
 +
            <br />
 +
            <a style="padding:1px;background:white;color:darkblue" class="ime_t_poly">poly(gon)</a>
 +
        </fieldset>
 +
        <fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex">
 +
            <legend style="padding:0 0.5ex" class="ime_t_editarea">Edit area</legend>
 +
            <select id="ime_areaselector" size="10" style="float:left;height:10em;margin:0.5ex;width:auto;min-width:18em;overflow:auto;" ></select>
 +
 
 +
            <div id="imeProps" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
 +
                <div style="float:left;margin:0.5ex;padding:0 1ex 1ex">
 +
 
 +
                        <label for="ime_areaLink" class="ime_t_linktarget">Link target</label>
 +
                        <br />
 +
                        <input id="ime_areaLink" name="areaLink" style="width:10em" class="ime-saveonchange" />
 +
                        <br />
 +
                        <label for="ime_areaTitle"><span class="ime_t_linktitle">Link title</span> (<span class="ime_t_optional">optional</span>)</label>
 +
                        <br />
 +
 
 +
                        <input id="ime_areaTitle" name="areaTitle" style="width:10em" class="ime-saveonchange" />
 +
                </div>
 +
                <div id="imePropsRect" class="ime-prop ime-prop-rect" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
 +
                    <label for="ime_areaRectLeft" class="ime_t_rectleft">First corner</label>
 +
                    <br />
 +
                    <input id="ime_areaRectLeft" name="areaRectLeft"  data-coord=0 class="ime-saveonchange" style="width:4em" />
 +
                    <input id="ime_areaRectTop" name="areaRectTop"  data-coord=1 style="width:4em" class="ime-saveonchange" />
 +
 
 +
                    <span class="ime_t_rectchoose1">Select with left mouse button</span>
 +
                    <br/>
 +
                    <label for="ime_areaRectRight" class="ime_t_rectright">Second corner</label>
 +
                    <br />
 +
                    <input id="ime_areaRectRight" name="areaRectRight"  data-coord=2 style="width:4em" class="ime-saveonchange" />
 +
                    <input id="ime_areaRectBottom" name="areaRectBottom"  data-coord=3 style="width:4em" class="ime-saveonchange" />
 +
                    <span class="ime_t_rectchoose2">Select with right mouse button</span>
 +
 
 +
                </div>
 +
                <div id="imePropsCircle" class="ime-prop ime-prop-circle" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
 +
                    <label class="ime_t_position">Position</label>
 +
                    <br />
 +
                    <input name="areaCircleX" id="ime_areaCircleX" class="ime-saveonchange" data-coord=0 style="width:4em" />
 +
                    <input name="areaCircleY" id="ime_areaCircleY" style="width:4em"  data-coord=1 class="ime-saveonchange" />
 +
                    <span class="ime_t_circlechoose1">Select with left mouse button</span>
 +
                    <br />
 +
 
 +
                    <label for="ime_areaCircleRadius" class="ime_t_radius">Radius</label>
 +
                    <br />
 +
                    <input id="ime_areaCircleRadius" name="areaCircleRadius" data-coord=2 style="width:4em" class="ime-saveonchange" />
 +
                    <span class="ime_t_circlechoose2">Select with right mouse button</span>
 +
                </div>
 +
                <div id="imePropsPoly" class="ime-prop ime-prop-poly" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
 +
                    <label class="ime_t_coordinates">Coordinates</label>
 +
 
 +
                    <br />
 +
                    <textarea id="imePropsPolyCoords" style="font-size:0.8em;max-width:20em;;height:8em" class="ime-savepolyonout"></textarea>
 +
                    <a style="padding:1px;background:white;color:darkblue" class="ime_t_deletecoordinates">Delete all coordinates</a>
 +
                    <br />
 +
                    <span class="ime_t_polychoose">Add new corner with left mouse button</span>
 +
                </div>
 +
                <div style="clear:both"></div>
 +
                <a style="padding:1px;background:white;color:darkblue" class="ime_t_deletearea">Delete selected area</a>
 +
 
 +
            </div>
 +
            <div style="clear:both"></div>
 +
        </fieldset>
 +
        <div style="clear:both"></div>
 +
        <fieldset style="margin:0 0.5ex 0.5ex;padding:0 1ex 1ex">
 +
            <legend class="ime_t_preferences">General preferences</legend>
 +
            <div style="float:left;margin-right:1em;">
 +
                <label for="ime_imageDescription" class="ime_t_imagedescription">Image description</label>
 +
 
 +
                <br />
 +
                <input id="ime_imageDescription" name="imageDescription" class="ime-updateresultsonchange" />
 +
            </div>
 +
            <div style="float:left">
 +
                <label style="display:block" class="ime_t_infolinkposition">Position of information link</label>
 +
                <div style="float:left">
 +
                    <input type="radio" name="imageDescriptionPos" value="bottom-left" class="ime-updateresultsonchange" checked="checked" id="ime_imageDescriptionPos_bottomleft" /><label for="ime_imageDescriptionPos_bottomleft"><span class="ime_t_bottomleft">Bottom left</span> (<span class="ime_t_default">default</span>)</label>
 +
 
 +
                </div>
 +
                <div style="float:left">
 +
                    <input type="radio" name="imageDescriptionPos" value="bottom-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_bottomright" /><label for="ime_imageDescriptionPos_bottomright" class="ime_t_bottomright">Bottom right</label>
 +
                </div>
 +
                <div style="float:left">
 +
                    <input type="radio" name="imageDescriptionPos" value="top-left" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topleft" /><label for="ime_imageDescriptionPos_topleft" class="ime_t_topleft">Top left</label>
 +
                </div>
 +
                <div style="float:left">
 +
 
 +
                    <input type="radio" name="imageDescriptionPos" value="top-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topright" /><label for="ime_imageDescriptionPos_topright" class="ime_t_topright">Top right</label>
 +
                </div>
 +
                <div style="float:left">
 +
                    <input type="radio" name="imageDescriptionPos" value="none" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_none" /><label for="ime_imageDescriptionPos_none" class="ime_t_nolink">No link</label>
 +
                </div>
 +
            </div>
 +
            <div style="clear:both"></div>
 +
        </fieldset>
 +
 
 +
        <fieldset style="margin:0.5ex;padding:0 1ex 1ex">
 +
            <legend class="ime_t_importareas">Import areas from wikicode</legend>
 +
            <a style="padding:1px;background:white;color:darkblue" id="imeImportShow"><span class="ime_t_showtextbox">Show text box</span> &gt;</a>
 +
            <a style="padding:1px;background:white;color:darkblue;display:none" id="imeImportHide"><span class="ime_t_hidetextbox">Hide text box</span> &lt;</a>
 +
            <div id="imeImport" style="display:none">
 +
                <textarea name="importText" style="width:100%;margin:0;height:10em;display:block"></textarea>
 +
 
 +
                <a style="padding:0 2em;background:white;color:darkblue" class="ime_t_import">Import</a>
 +
                <a style="padding:0 2em;background:white;color:darkblue" class="ime_t_replace">Replace</a>
 +
            </div>
 +
        </fieldset>
 +
        <fieldset style="margin:0.5ex;padding:0 1ex 1ex">
 +
            <legend class="ime_t_generatedwikicode">Generated wikicode</legend>
 +
            <div>
 +
                <code id="imeResult" style="display:block;line-height:1.2em"></code>
 +
            </div>
 +
 
 +
        </fieldset>
 +
    </fieldset>
 +
</form>
 +
`;
 +
 +
});
 +
*/

Version vom 27. November 2024, 22:25 Uhr

/*
	modified by [[user:קיפודנחש]]
	
	original script by Peter Schlömer, can be found on 
	https://tools.wmflabs.org/imagemapedit/ime.js, 
	and contains the following copyright notice:
=========== original license ================
			Copyright (c) 2007-2013 Peter Schlömer

			Released under the following licenses (to make reuse in other Wikis
			easier):

			GNU General Public License (GPL), version 2
			GNU Free Documentatin Licence (GFDL), version 1.2 or later
			Creative Commons Attribution ShareAlike (CC-by-sa), version 2 or later
=============================================			
*/

if (mw.config.get('wgNamespaceNumber') == 6 && mw.config.get('wgAction') == 'view') 
$(function() {
	// avoid multiple activation, e.g. when [[m:Special:MyPage/global.js]] activates the script
	// and it's also activated on the wiki

if (window.mw_ime_running) return;
window.mw_ime_running = true;

var ime_translations = { error_imagenotfound: 'ImageMapEdit: Could not find image in page structure.' };
var ime_areas = Array();
var ime_currentlyEditing = -1;
var ime_width;
var ime_height;
var ime_scale;
var img;
var $img;
var context;
var jcanvas;
var imageProperties;
var currentClicks = {};
var ime_templateHtml;
var listenToMouse = false;
var selectArea;

if (document.getElementById('file')) {
	ime_init1();
}

function ime_htmlNewDiv(id) {
	var div = document.createElement('div');
	if (id) div.id = id;
	return div;
}

/*
	Initialization, part 1: Tries to find image and uses a XMLHttpRequest
	to download information about the image. When this is done (it's an
	asynchronous request) show a link to load the rest of ImageMapEdit
	using ime_init2().
*/
function ime_init1() {
	var divFile = document.getElementById('file');
	if (!divFile) {
		ime_error(ime_translations['error_imagenotfound'] + ' (ime_init1,divFile=null)');
		return;
	}

	var a = ime_findATag(divFile);
	if (!a) {
		ime_error(ime_translations['error_imagenotfound'] + ' (ime_init1,a=null)');
		return;
	}

	var img = a.firstChild;
	if (!img) {
		ime_error(ime_translations['error_imagenotfound'] + ' (ime_init1,img=null)');
		return;
	}

	var url = mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=imageinfo&iiprop=size&titles=' + mw.config.get('wgPageName');

	$.get(url, function(data) {

		if( typeof data.query.pages != "undefined" ) {
	        imageProperties = data.query.pages[Object.keys(data.query.pages)[0]];
            var imageInfo = imageProperties.imageinfo;
            if (imageInfo) {
                ime_width = imageInfo[0].width;
                ime_height = imageInfo[0].height;
                ime_scale = img.width/ime_width;

                // Show 'show ImageMapEdit' button now
                $('<a>', { id: 'imeLink'})
                    .css({ display: 'block' })
                    .text('ImageMapEdit >')
                    .click( function(e) {
                        e.preventDefault();
                        ime_init2();
                    })
                    .appendTo('#file');
            }
		}
	});
}

/*
	Initialization, part 2: Triggered by an external link. Does some moving
	around of the image in the logical structure of the page, then hides the
	link and finally puts the HTML code in place.
*/
	
function ime_init2() {

	// Remove UI that might interfere with this code
	ime_removeOtherUIElements();

	var divFile = document.getElementById('file');
	var tempNode = divFile.firstChild;
	var a = ime_findATag(tempNode);
	var divImeContainer = ime_htmlNewDiv('imeContainer');
	img = a.firstChild,
		$img = $(img);
	
	divImeContainer.style.position = 'relative';

	// Move image from within link to outside
	a.removeChild(img);
	divFile.insertBefore(divImeContainer,tempNode);
	divFile.removeChild(tempNode);
	divFile.style.direction = 'ltr';
	img.id = 'imeImg';
	img.style.border = 'none';
	img.oncontextmenu = function(e){e.preventDefault();e.stopPropagation();};

	// Internet Explorer needs this differently
	if (typeof(navigator.userAgent) != 'undefined' && navigator.userAgent.match('/MSIE/')) {
		divImeContainer.style.overflow = 'none';
	}
	else {
		divImeContainer.style.overflow = 'auto';
	}

	divImeContainer.appendChild(img);
	
	jcanvas = $('<canvas>')
		.css( {
			position: 'absolute', 
			width: $img.width() + 'px', 
			height: $img.height() + 'px', 
			border: 0, 
			top:0, 
			left:0			
		})
		.attr({width: $img.width(), height: $img.height()})
		.appendTo(divImeContainer)
	context = jcanvas[0].getContext("2d");
	$.extend(context,  {
		fillStyle: 'rgba(255,255,0,0.4)', 
		strokeStyle: 'red', 
		lineJoin: 'round', 
		lineWidth: 1.5/ime_scale}
		);
	context.scale(ime_scale, ime_scale);
	jcanvas.mousedown(onmousedown);
	jcanvas.click(function(e){e.preventDefault();e.stopPropagation();})
	jcanvas[0].oncontextmenu = img.oncontextmenu = function(e){e.preventDefault();e.stopPropagation();};
	
	var divIme = ime_htmlNewDiv('ime');
	divFile.appendChild(divIme);

	// Hide the link now
	document.getElementById('imeLink').style.display = 'none';

	// Disable image context menu so right click can be used for events
	img.oncontextmenu = ime_eventDummy;

	$(divIme).html(ime_templateHtml);
	
	attachTemplate();

	// Translate texts
	ime_translate();
}

function ime_translate() {
	var allt = [ime_translations, window.ime_translations];
	while (allt.length) {
		var trans = allt.shift();
		if (trans) 
			for (var key in trans) 
				$('.ime_t_' + key).text(trans[key]);
	}
}

/*
	Finds all elements in the current document with the specified class.
*/
function ime_getElementsByClassName(className) {
	// Hopefully the browser supports this natively
	if (document.getElementsByClassName) {
		return document.getElementsByClassName(className);
	}

	// Otherwise use the function defined by MediaWiki
	return getElementsByClassName(document,'*',className)
}

/*
	Display an error message, either by putting it on the page or - if the
	place to put it does not exist - by showing an alert box.
*/
function ime_error(message) {
	var jqFile = $('#file');
	var jqIme = $('#ime');

	if (jqFile.length !== 0) {
		var jqImeError = $('<p>')
		.css({
			'color' : 'darkred',
			'background' : 'white',
			'border' : '1px solid darkred',
			'padding' : '1ex'
		})
		.text(message)

		if (jqIme !== 0) {
			jqIme.before(jqImeError);
		} else {
			jqImeError.appendTo(jqFile);
		}
	}
	else {
		window.alert(message);
	}
}

/*
	Dummy function to intercept events
*/
function ime_eventDummy(e) {
	e.cancelBubble = true;
	return false;
}


/*
	Function to define an object storing info on a clickable area for the
	imagemap.
*/

/*
	Browser invariant function to get the event "behind" the object passed
	to event handlers.
*/
function ime_eventGetButton(e) {
	if (typeof(e.which)!='undefined') {
		return e.which;
	}
	else {
		return e.button;
	}
}

function onmousedown(event)	{
	if (!listenToMouse) return;
	event.preventDefault();
	event.stopPropagation();
	var isLeftButton = event.which == 1, isRightButton = event.which > 1;
	var offset = $('#imeImg').offset();
	var x = event.pageX - offset.left;
	var y = event.pageY - offset.top;
	var position = { x: parseInt( x / ime_scale ), y:  parseInt( y / ime_scale ) };
	if (isLeftButton) {
		currentClicks.left = position;
	}
	if (isRightButton) {
		currentClicks.right = position;
	}
	ime_saveArea(isLeftButton);
}
	
function ime_mouseEventClear() {
	listenToMouse = false;
	currentClicks = {};
	jcanvas.css({ cursor: '' });
}

function ime_mouseEventSet() {
	listenToMouse = true;
	jcanvas.css({ cursor: 'crosshair' });
}

function ime_newArea(shape) {
	ime_mouseEventSet();
	ime_areas.push( { shape: shape, coords: [], link: '' } );
	ime_currentlyEditing = ime_areas.length-1;
	ime_updateAreas();
	return currentArea();
}

function ime_updateAreas() {
	ime_updateSelectArea();
	ime_editArea(ime_currentlyEditing);
	ime_updateResult();
}

function ime_updateResult() {
	var arr = document.ime.imageDescriptionPos;
	var imageDescriptionPos = arr[0].value;
	for (var i=1; i<arr.length; i++) {
		if (arr[i].checked) {
			imageDescriptionPos = arr[i].value;
			break;
		}
	}

	var result = Array();
	result.push('<imagemap>');
	result.push(mw.config.get('wgPageName') + '|' + document.ime.imageDescription.value);
	result.push('');
	for (var i=0; i<ime_areas.length; i++) {
		var s = ime_areas[i].shape + 
					' ' + 
					ime_areas[i].coords.join(' ') + 
					' [[' + 
					ime_areas[i].link + 
					(ime_areas[i].title ? '|' + ime_areas[i].title : '') + 
					']]';
		
		result.push(s);
	}
	result.push('');
	result.push('desc ' + imageDescriptionPos);
	result.push('</imagemap>');

	var preResult = document.getElementById('imeResult');

	while (preResult.lastChild) {
		preResult.removeChild(preResult.lastChild);
	}

	for (var i=0; i<result.length; i++) {
		preResult.appendChild(document.createTextNode(result[i]));
		preResult.appendChild(document.createElement('br'));
	}
	ime_updateSelectArea();
}

function drawAreas() { // this is where the magic is done.
	
	function markPoint(point, color) {
		if (point) {
			context.beginPath();
			var arm = 8 / ime_scale;
			context.moveTo(point.x + arm, point.y);
			context.lineTo(point.x - arm, point.y);
			context.moveTo(point.x, point.y + arm);
			context.lineTo(point.x, point.y - arm);
			context.strokeStyle = color;
			context.stroke();
			context.closePath();
		}
	}
		
	function drawPoly(coords) {
		coords = coords.slice();
		context.moveTo(coords.shift(), coords.shift());
		while (coords.length)
			context.lineTo(coords.shift(), coords.shift());
	}
	
	context.clearRect(0, 0, context.canvas.width/ime_scale, context.canvas.height/ime_scale); // prepare for a new day.
	for (var ind in ime_areas) {
		var current = ind == ime_currentlyEditing;
		context.fillStyle = current ? 'rgba(255,255,0,0.4)' : 'rgba(255,0,0,0.4)';
		var area = ime_areas[ind];
		var coords = area.coords;
		context.beginPath();
		switch (area.shape) {
			case 'rect': 
				var complete = true;
				for (var i = 0; i < 4; i++) complete = complete && coords[i];
				if (complete)
					drawPoly([coords[0], coords[1], coords[0], coords[3], coords[2], coords[3], coords[2], coords[1]]); break;
			case 'circle': if (coords.length == 3) {
					context.arc(coords[0],coords[1],coords[2],0,Math.PI*2); 
				}
				break;//x,y,r,startAngle,endAngle
			case 'poly': drawPoly(coords); 
				break;
		}
		context.closePath();
		context.fill();
		if (current) {
			context.strokeStyle = 'red';
			context.stroke();
		}
	}
	markPoint(currentClicks.left, 'red');
	if (currentArea().shape != 'poly') markPoint(currentClicks.right, 'yellow');
}

function ime_updateSelectArea() {

	selectArea.children().remove();
	
	for (var i=0; i<ime_areas.length; i++) {
		var area = ime_areas[i],
			title = (area.title || area.link || '') + ' [' + area.shape + ']';
		$('<option>', { value: i })
			.text(title)
			.prop({ selected: i == ime_currentlyEditing } )
			.appendTo(selectArea);
	}
	selectArea.prop('selectedIndex', ime_currentlyEditing);
}

function ime_editArea(index) {
	$('#imeProps').toggle(false);

	var area = ime_areas[index];
	currentClicks = area.clicks || {};


	if (area) {
		ime_currentlyEditing = index;

		$('#imeProps').toggle(true);
		$('.ime-prop').toggle(false);
		$('.ime-prop-' + area.shape).toggle(true);
		
		ime_mouseEventSet();
		updateInputs();
	}
	drawAreas();
}

function ime_deleteArea() {
	ime_mouseEventClear();

	// Remove element from ime_areas array
	ime_areas.splice(ime_currentlyEditing,1);

	if (ime_currentlyEditing>=ime_areas.length) {
		ime_currentlyEditing = ime_areas.length-1;
	}

	ime_updateAreas();
	if (ime_currentlyEditing >= 0) {
		ime_editArea(ime_currentlyEditing);
	}
}
	
function updateInputs(fromAreas) {
	
	function updateRectInputs(coords) {
		var lx = $('#ime_areaRectLeft'), 
			ly = $('#ime_areaRectTop'), 
			rx = $('#ime_areaRectRight'), 
			ry = $('#ime_areaRectBottom');
			
		lx.val(coords && coords[0] || '');
		ly.val(coords && coords[1] || '');
		rx.val(coords && coords[2] || '');
		ry.val(coords && coords[3] || '');
	}
	
	function updateCircInputs(coords) {
		var x = $('#ime_areaCircleX'), 
			y = $('#ime_areaCircleY'), 
			radius = $('#ime_areaCircleRadius')
			
		x.val(coords && coords[0] || '');
		y.val(coords && coords[1] || '');
		radius.val(coords && coords[2] || '');
	}
	
	function updatePolyInputs(coords) {
		$('#imePropsPolyCoords').val(coords.join(', '));
	}
	
	
	var area = currentArea();
	var coords = area.coords;
	switch (area.shape) {
		case 'rect'  : updateRectInputs(coords); break;
		case 'circle': updateCircInputs(coords); break;
		case 'poly'	 : updatePolyInputs(coords); break;
	}
	$('#ime_areaLink').val(area.link || '');
	$('#ime_areaTitle').val(area.title || '');
}

function currentArea() {
	return ime_areas[ime_currentlyEditing];
}	
	
function ime_saveArea(leftClick) {
	var area = currentArea();
	area.link = document.ime.areaLink.value;
	area.title = document.ime.areaTitle.value;
	var d = area.clicks = $.extend({}, currentClicks);
	
	var full = d.left && d.right;
	switch (area.shape) {
		case 'rect':
			 if (d.left) {
				 area.coords[0] = d.left.x; area.coords[1] = d.left.y;
			 }
			 if (d.right) {
				 area.coords[2] = d.right.x; area.coords[3] = d.right.y;
			 }
			break;
		case 'circle':
			if (leftClick) {
				area.coords[0] = d.left.x; area.coords[1] = d.left.y; 
			}
			if (full) {
				var dx = d.left.x - d.right.x,
					dy = d.left.y - d.right.y;
				area.coords[2] = parseInt(Math.sqrt(dx*dx + dy*dy));
			}
			break;
		case 'poly': 
			if (leftClick && d.left) {
				area.coords.push(d.left.x, d.left.y);
			}
			break;
	}
	updateInputs(full || area.shape == 'poly');
	ime_updateAreas();
}

/*
	Remove all UI elements that might interfere with ImageMapEdit.
*/
function ime_removeOtherUIElements() {
	// Remove all UI elements of the 'annotations' feature used on Wikimedia
	// Commons.
	$('#ImageAnnotationAddButton').remove();
}

/*
	Try to find an <a> tag within the specified HTML document node.
*/

function ime_findATag(node) {
	// We just look at the first child until there is none or it is an <a> tag
	var a = node;
	while (a != null && a.nodeName.toUpperCase() != 'A') {
		a = a.firstChild;
	}
	return a;
}
	
function ime_importLines(toclear) {
	var text = document.ime.importText.value;
	var lines = text.split("\n");

	if (toclear) {
		ime_areas = [];
	}
	
	for (var i=0; i<lines.length; i++) {
		var rectMatch = /^rect +(\d+) +(\d+) +(\d+) +(\d+) +\[\[([^|]*)(|(.*))?\]\]/i;
		var circleMatch = /^circle +(\d+) +(\d+) +(\d+) +\[\[([^|]*)(|(.*))?\]\]/i;
		var polyMatch = /^poly +(.*?) +\[\[([^|]*)(|(.*))?\]\]/i;

		var line = lines[i];

		if (rectMatch.test(line)) {
			var results = rectMatch.exec(line);
			var area = ime_newArea("rect");
			area.coords = results.slice(1, 5);
			area.link = results[5];
			if (results[6]) area.title = results[6].substring(1);
		}
		else if (circleMatch.test(line)) {
			var results = circleMatch.exec(line);
			var area = ime_newArea("circle");
			area.coords = results.slice(1, 4);
			area.link = results[4];
			if (results[5]) area.title = results[5].substring(1);
		}
		else if (polyMatch.test(line)) {
			var results = polyMatch.exec(line);
			var area = ime_newArea("poly");
			area.coords = results[1].split(/\s/);
			area.link = results[2];
			if (results[3]) area.title = results[3].substring(1);
		}
	}
	ime_updateAreas();
}

function ime_showImport() {
	$('#imeImport').show();
	$('#imeImportShow').hide();
	$('#imeImportHide').show();
}

function ime_hideImport() {
	$('#imeImport').hide();
	$('#imeImportShow').show();
	$('#imeImportHide').hide();
}

function attachTemplate() {
	$('.ime_t_rect').click(function(e) { e.preventDefault(); ime_newArea('rect'); } );
	$('.ime_t_circle').click(function(e) { e.preventDefault(); ime_newArea('circle'); } );
	$('.ime_t_poly').click(function(e) { e.preventDefault(); ime_newArea('poly'); } );
	$('#ime_areaselector').change(function(e) { ime_editArea($(this).prop('selectedIndex')); });
	$('.ime_t_deletearea').click(function(e) { e.preventDefault(); ime_deleteArea();});
	$('#imeImportShow').click(function(e) { e.preventDefault(); ime_showImport();});
	$('#imeImportHide').click(function(e) { e.preventDefault(); ime_hideImport();});
	$('.ime_t_import').click(function(e) { e.preventDefault(); ime_importLines();});
	$('.ime_t_replace').click(function(e) { e.preventDefault(); ime_importLines(true);});
	$('.ime_saveonchange').change(ime_saveArea);
	$('.ime-updateresultsonchange').change(ime_updateResult);
	$('#ime_areaLink').change(function() { currentArea().link = $(this).val(); ime_updateResult();});
	$('#ime_areaTitle').change(function() { currentArea().title = $(this).val(); ime_updateResult();});
	$('.ime_t_deletecoordinates').click(function(e) { 
			e.preventDefault(); 
			currentArea().coords = [];
			currentClicks = {};
			ime_saveArea();
		} );
	selectArea = $('#ime_areaselector');
	$('.ime-savepolyonout').focusout(function() {
		var val = $(this).val();
		var area = currentArea();
		var coords = val.split(/,/g).map(x => parseInt(x)).filter(x => !isNaN(x));
		if (coords && coords.length && coords.length % 2 === 0) {
			area.coords = coords;
		}
		ime_saveArea();
	});
	
	$('.ime-saveonchange').focusout(function() {
		var input = $(this);
		var ind = input.data('coord');
		var val = parseInt(input.val());
		var area = currentArea();
		var coords = area && area.coords;

		if (coords && typeof(ind) == 'number' && typeof(val) == 'number' && ! isNaN(val)) {
			coords[ind] = val;
			currentClicks = {};
			ime_saveArea();
		}
	});
	mw.loader.using(['mediawiki.api', 'jquery.ui']).done(function() {
		$('#ime_areaLink').autocomplete({
    		source: function( request, response ) {
				new mw.Api().get( {
	            	action: 'opensearch',
	            	search: request.term,
	            	namespace: 0,
					limit:10
	        	}).done(function( data ) {
					if ( data && data.length > 1 ) 
						response( data[1] );
	        	}); // done
    		} // source
		}); // autocomplete
	}); // using
}
	

// this is the one-(very long)-line version of the template, since mw linger does not allow use multiline delimiter (ascii 96), not even in the comment... 
// formatted version in comment below.
// original can be found at https://imagemapedit.toolforge.org/template.php.
ime_templateHtml = '<form name="ime" action="" ><fieldset style="margin:0.5ex;padding:0 1ex 1ex"><legend>ImageMapEdit</legend><fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex"><legend style="padding:0 0.5ex" class="ime_t_newarea">Create new area</legend><a style="padding:1px;background:white;color:darkblue" class="ime_t_rect">rect(angle)</a><br /><a style="padding:1px;background:white;color:darkblue" class="ime_t_circle">circle</a><br /><a style="padding:1px;background:white;color:darkblue" class="ime_t_poly">poly(gon)</a></fieldset><fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex"><legend style="padding:0 0.5ex" class="ime_t_editarea">Edit area</legend><select id="ime_areaselector" size="10" style="float:left;height:10em;margin:0.5ex;width:auto;min-width:18em;overflow:auto;" ></select><div id="imeProps" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><div style="float:left;margin:0.5ex;padding:0 1ex 1ex"><label for="ime_areaLink" class="ime_t_linktarget">Link target</label><br /><input id="ime_areaLink" name="areaLink" style="width:10em" class="ime-saveonchange" /><br /><label for="ime_areaTitle"><span class="ime_t_linktitle">Link title</span> (<span class="ime_t_optional">optional</span>)</label><br /><input id="ime_areaTitle" name="areaTitle" style="width:10em" class="ime-saveonchange" /></div><div id="imePropsRect" class="ime-prop ime-prop-rect" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><label for="ime_areaRectLeft" class="ime_t_rectleft">First corner</label><br /><input id="ime_areaRectLeft" name="areaRectLeft" data-coord=0 class="ime-saveonchange" style="width:4em" /><input id="ime_areaRectTop" name="areaRectTop" data-coord=1 style="width:4em" class="ime-saveonchange" /><span class="ime_t_rectchoose1">Select with left mouse button</span><br/><label for="ime_areaRectRight" class="ime_t_rectright">Second corner</label><br /><input id="ime_areaRectRight" name="areaRectRight" data-coord=2 style="width:4em" class="ime-saveonchange" /><input id="ime_areaRectBottom" name="areaRectBottom" data-coord=3 style="width:4em" class="ime-saveonchange" /><span class="ime_t_rectchoose2">Select with right mouse button</span></div><div id="imePropsCircle" class="ime-prop ime-prop-circle" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><label class="ime_t_position">Position</label><br /><input name="areaCircleX" id="ime_areaCircleX" class="ime-saveonchange" data-coord=0 style="width:4em" /><input name="areaCircleY" id="ime_areaCircleY" style="width:4em" data-coord=1 class="ime-saveonchange" /><span class="ime_t_circlechoose1">Select with left mouse button</span><br /><label for="ime_areaCircleRadius" class="ime_t_radius">Radius</label><br /><input id="ime_areaCircleRadius" name="areaCircleRadius" data-coord=2 style="width:4em" class="ime-saveonchange" /><span class="ime_t_circlechoose2">Select with right mouse button</span></div><div id="imePropsPoly" class="ime-prop ime-prop-poly" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none"><label class="ime_t_coordinates">Coordinates</label><br /><textarea id="imePropsPolyCoords" style="font-size:0.8em;max-width:20em;height:8em"class="ime-savepolyonout"></textarea><a style="padding:1px;background:white;color:darkblue" class="ime_t_deletecoordinates">Delete all coordinates</a><br /><span class="ime_t_polychoose">Add new corner with left mouse button</span></div><div style="clear:both"></div><a style="padding:1px;background:white;color:darkblue" class="ime_t_deletearea">Delete selected area</a></div><div style="clear:both"></div></fieldset><div style="clear:both"></div><fieldset style="margin:0 0.5ex 0.5ex;padding:0 1ex 1ex"><legend class="ime_t_preferences">General preferences</legend><div style="float:left;margin-right:1em;"><label for="ime_imageDescription" class="ime_t_imagedescription">Image description</label><br /><input id="ime_imageDescription" name="imageDescription" class="ime-updateresultsonchange" /></div><div style="float:left"><label style="display:block" class="ime_t_infolinkposition">Position of information link</label><div style="float:left"><input type="radio" name="imageDescriptionPos" value="bottom-left" class="ime-updateresultsonchange" checked="checked" id="ime_imageDescriptionPos_bottomleft" /><label for="ime_imageDescriptionPos_bottomleft"><span class="ime_t_bottomleft">Bottom left</span> (<span class="ime_t_default">default</span>)</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="bottom-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_bottomright" /><label for="ime_imageDescriptionPos_bottomright" class="ime_t_bottomright">Bottom right</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="top-left" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topleft" /><label for="ime_imageDescriptionPos_topleft" class="ime_t_topleft">Top left</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="top-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topright" /><label for="ime_imageDescriptionPos_topright" class="ime_t_topright">Top right</label></div><div style="float:left"><input type="radio" name="imageDescriptionPos" value="none" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_none" /><label for="ime_imageDescriptionPos_none" class="ime_t_nolink">No link</label></div></div><div style="clear:both"></div></fieldset><fieldset style="margin:0.5ex;padding:0 1ex 1ex"><legend class="ime_t_importareas">Import areas from wikicode</legend><a style="padding:1px;background:white;color:darkblue" id="imeImportShow"><span class="ime_t_showtextbox">Show text box</span> &gt;</a><a style="padding:1px;background:white;color:darkblue;display:none" id="imeImportHide"><span class="ime_t_hidetextbox">Hide text box</span> &lt;</a><div id="imeImport" style="display:none"><textarea name="importText" style="width:100%;margin:0;height:10em;display:block"></textarea><a style="padding:0 2em;background:white;color:darkblue" class="ime_t_import">Import</a><a style="padding:0 2em;background:white;color:darkblue" class="ime_t_replace">Replace</a></div></fieldset><fieldset style="margin:0.5ex;padding:0 1ex 1ex"><legend class="ime_t_generatedwikicode">Generated wikicode</legend><div><code id="imeResult" style="display:block;line-height:1.2em"></code></div></fieldset></fieldset></form>';
});
/* 
<form name="ime" action="">
    <fieldset style="margin:0.5ex;padding:0 1ex 1ex">
        <legend>ImageMapEdit</legend>
        <fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex">
            <legend style="padding:0 0.5ex" class="ime_t_newarea">Create new area</legend>
            <a style="padding:1px;background:white;color:darkblue" class="ime_t_rect">rect(angle)</a>
            <br />
            <a style="padding:1px;background:white;color:darkblue" class="ime_t_circle">circle</a>

            <br />
            <a style="padding:1px;background:white;color:darkblue" class="ime_t_poly">poly(gon)</a>
        </fieldset>
        <fieldset style="float:left;margin:0 0.5ex 0.5ex;padding:0 1ex 1ex">
            <legend style="padding:0 0.5ex" class="ime_t_editarea">Edit area</legend>
            <select id="ime_areaselector" size="10" style="float:left;height:10em;margin:0.5ex;width:auto;min-width:18em;overflow:auto;" ></select>

            <div id="imeProps" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
                <div style="float:left;margin:0.5ex;padding:0 1ex 1ex">

                        <label for="ime_areaLink" class="ime_t_linktarget">Link target</label>
                        <br />
                        <input id="ime_areaLink" name="areaLink" style="width:10em" class="ime-saveonchange" />
                        <br />
                        <label for="ime_areaTitle"><span class="ime_t_linktitle">Link title</span> (<span class="ime_t_optional">optional</span>)</label>
                        <br />

                        <input id="ime_areaTitle" name="areaTitle" style="width:10em" class="ime-saveonchange" />
                </div>
                <div id="imePropsRect" class="ime-prop ime-prop-rect" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
                    <label for="ime_areaRectLeft" class="ime_t_rectleft">First corner</label>
                    <br />
                    <input id="ime_areaRectLeft" name="areaRectLeft"  data-coord=0 class="ime-saveonchange" style="width:4em" />
                    <input id="ime_areaRectTop" name="areaRectTop"  data-coord=1 style="width:4em" class="ime-saveonchange" />

                    <span class="ime_t_rectchoose1">Select with left mouse button</span>
                    <br/>
                    <label for="ime_areaRectRight" class="ime_t_rectright">Second corner</label>
                    <br />
                    <input id="ime_areaRectRight" name="areaRectRight"  data-coord=2 style="width:4em" class="ime-saveonchange" />
                    <input id="ime_areaRectBottom" name="areaRectBottom"  data-coord=3 style="width:4em" class="ime-saveonchange" />
                    <span class="ime_t_rectchoose2">Select with right mouse button</span>

                </div>
                <div id="imePropsCircle" class="ime-prop ime-prop-circle" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
                    <label class="ime_t_position">Position</label>
                    <br />
                    <input name="areaCircleX" id="ime_areaCircleX" class="ime-saveonchange" data-coord=0 style="width:4em" />
                    <input name="areaCircleY" id="ime_areaCircleY" style="width:4em"  data-coord=1 class="ime-saveonchange" />
                    <span class="ime_t_circlechoose1">Select with left mouse button</span>
                    <br />

                    <label for="ime_areaCircleRadius" class="ime_t_radius">Radius</label>
                    <br />
                    <input id="ime_areaCircleRadius" name="areaCircleRadius" data-coord=2 style="width:4em" class="ime-saveonchange" />
                    <span class="ime_t_circlechoose2">Select with right mouse button</span>
                </div>
                <div id="imePropsPoly" class="ime-prop ime-prop-poly" style="float:left;margin:0.5ex;padding:0 1ex 1ex;display:none">
                    <label class="ime_t_coordinates">Coordinates</label>

                    <br />
                    <textarea id="imePropsPolyCoords" style="font-size:0.8em;max-width:20em;;height:8em" class="ime-savepolyonout"></textarea>
                    <a style="padding:1px;background:white;color:darkblue" class="ime_t_deletecoordinates">Delete all coordinates</a>
                    <br />
                    <span class="ime_t_polychoose">Add new corner with left mouse button</span>
                </div>
                <div style="clear:both"></div>
                <a style="padding:1px;background:white;color:darkblue" class="ime_t_deletearea">Delete selected area</a>

            </div>
            <div style="clear:both"></div>
        </fieldset>
        <div style="clear:both"></div>
        <fieldset style="margin:0 0.5ex 0.5ex;padding:0 1ex 1ex">
            <legend class="ime_t_preferences">General preferences</legend>
            <div style="float:left;margin-right:1em;">
                <label for="ime_imageDescription" class="ime_t_imagedescription">Image description</label>

                <br />
                <input id="ime_imageDescription" name="imageDescription" class="ime-updateresultsonchange" />
            </div>
            <div style="float:left">
                <label style="display:block" class="ime_t_infolinkposition">Position of information link</label>
                <div style="float:left">
                    <input type="radio" name="imageDescriptionPos" value="bottom-left" class="ime-updateresultsonchange" checked="checked" id="ime_imageDescriptionPos_bottomleft" /><label for="ime_imageDescriptionPos_bottomleft"><span class="ime_t_bottomleft">Bottom left</span> (<span class="ime_t_default">default</span>)</label>

                </div>
                <div style="float:left">
                    <input type="radio" name="imageDescriptionPos" value="bottom-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_bottomright" /><label for="ime_imageDescriptionPos_bottomright" class="ime_t_bottomright">Bottom right</label>
                </div>
                <div style="float:left">
                    <input type="radio" name="imageDescriptionPos" value="top-left" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topleft" /><label for="ime_imageDescriptionPos_topleft" class="ime_t_topleft">Top left</label>
                </div>
                <div style="float:left">

                    <input type="radio" name="imageDescriptionPos" value="top-right" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_topright" /><label for="ime_imageDescriptionPos_topright" class="ime_t_topright">Top right</label>
                </div>
                <div style="float:left">
                    <input type="radio" name="imageDescriptionPos" value="none" class="ime-updateresultsonchange" id="ime_imageDescriptionPos_none" /><label for="ime_imageDescriptionPos_none" class="ime_t_nolink">No link</label>
                </div>
            </div>
            <div style="clear:both"></div>
        </fieldset>

        <fieldset style="margin:0.5ex;padding:0 1ex 1ex">
            <legend class="ime_t_importareas">Import areas from wikicode</legend>
            <a style="padding:1px;background:white;color:darkblue" id="imeImportShow"><span class="ime_t_showtextbox">Show text box</span> &gt;</a>
            <a style="padding:1px;background:white;color:darkblue;display:none" id="imeImportHide"><span class="ime_t_hidetextbox">Hide text box</span> &lt;</a>
            <div id="imeImport" style="display:none">
                <textarea name="importText" style="width:100%;margin:0;height:10em;display:block"></textarea>

                <a style="padding:0 2em;background:white;color:darkblue" class="ime_t_import">Import</a>
                <a style="padding:0 2em;background:white;color:darkblue" class="ime_t_replace">Replace</a>
            </div>
        </fieldset>
        <fieldset style="margin:0.5ex;padding:0 1ex 1ex">
            <legend class="ime_t_generatedwikicode">Generated wikicode</legend>
            <div>
                <code id="imeResult" style="display:block;line-height:1.2em"></code>
            </div>

        </fieldset>
    </fieldset>
</form>
`;
	
});
*/