Jump to content

User:Bernanke's Crossbow/ModifiedIME.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Bernanke's Crossbow (talk | contribs) at 03:30, 14 August 2022 (Typos). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*  Coordinatizing an HTML
	image map can be hard for you.  
	What vision is made from numbers?  
	This script lets you see as you do.  
    
	Version as of eight/thirteen/twenty-two.  
	Original script by Peter Schlömer 
	modified by	[[:he:user:קיפודנחש]]
	and also Bernanke's Crossbow.  
	
	The original script
	displays a copyright warning.  
	
	It says: (https://tools.wmflabs.org/imagemapedit/ime.js)
		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
*/

//<nowiki>
/*jshint esversion: 6 */
if (mw.config.get('wgNamespaceNumber') == 6 &&
	mw.config.get('wgAction') == 'view')
	$(function () {
		"use strict";
		//Ensure idempotence, in case (eg)
		//[[m:Special:MyPage/global.js]] and main wiki both activate the script
		if (window.mw_ime_running) return;
		window.mw_ime_running = true;

		//General utilities
		const util = {
			//Localize error messages to your favorite language
			translations: {
				error_imagenotfound:
					'ImageMapEdit: Could not find image in page structure.'
			},
			//Translate texts
			translate() {
				for (const trans of [
					this.translations,
					window.ime_translations
				])
					if (trans) for (const key in trans)
						$('.ime_t_' + key).text(trans[key]);
			},
			std_handler(fct) {
				return e => {
					e.preventDefault();
					fct(e);
				};
			},
			displayErr(message) {
				//First try on screen
				const jqFile = $('#file'); if (jqFile.length !== 0) {
					const errBox =
						$('<p>')
							.css({
								'color': 'darkred',
								'background': 'white',
								'border': '1px solid darkred',
								'padding': '1ex'
							})
							.text(message);
					const jqIme = $('#ime');
					if (jqIme !== 0) jqIme.before(errBox);
					else errBox.appendTo(jqFile);
				}
				//Can't find a good location
				else window.alert(message);
			},
			makeDiv(id) {
				const div = document.createElement('div');
				if (id) div.id = id;
				return div;
			},
			//Try to find an <a> tag within the specified HTML document node.
			findHyperlink(node) {
				//Look at the first child until it is none or <a>
				let a = node;
				while (a && a.nodeName.toUpperCase() != 'A')
					a = a.firstChild;
				return a;
			},
			all(arr) { return arr.reduce((a, b) => a && b); }
		};
		//Keep track of recent clicks
		const mouse = {
			listening: false,
			currentClicks: {},
			relax() {
				this.listening = false;
				this.currentClicks = {};
				ime.jcanvas.css({ cursor: '' });
			},
			listen() {
				this.listening = true;
				ime.jcanvas.css({ cursor: 'crosshair' });
			},
			fired(event) {
				if (!this.listening) return;
				event.preventDefault();
				event.stopPropagation();
				const offset = $('#imeImg').offset();
				const
					x = event.pageX - offset.left,
					y = event.pageY - offset.top;
				const position = {
					x: parseInt(x / ime.scale),
					y: parseInt(y / ime.scale)
				};
				const dblClick = event.detail > 1;
				if (dblClick) this.currentClicks.left = position;
				else this.currentClicks.right = position;
				ime.store(dblClick);
			}
		};
		//Highlighted areas
		const areas = Array();
		areas.current = function () { return this[this.currentlyEditing]; };
		areas.make = function (shape) {
			mouse.listen();
			this.push({ shape: shape, coords: [], link: '' });
			this.currentlyEditing = this.length - 1;
			this.update();
			return areas.current();
		};
		areas.update = function () {
			this.updateSelection();
			this.edit(this.currentlyEditing);
			updateResult();
		};
		areas.updateSelection = function () {
			this.selection.children().remove();
			for (let i = 0; i < this.length; i++) {
				const area = this[i],
					title = (area.title || area.link || '') +
						' [' + area.shape + ']';
				$('<option>', { value: i })
					.text(title)
					.prop({ selected: i == this.currentlyEditing })
					.appendTo(this.selection);
			}
			this.selection.prop('selectedIndex', this.currentlyEditing);
		};
		areas.edit = function (index) {
			$('#imeProps').toggle(false);

			const area = this[index];
			mouse.currentClicks = (area || {}).clicks || {};
			if (area) {
				this.currentlyEditing = index;

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

				mouse.listen();
				updateInputs();
			}
			this.draw();
		};
		areas.remove = function () {
			mouse.relax();
			// Remove element from this array
			this.splice(this.currentlyEditing, 1);
			if (this.currentlyEditing >= this.length)
				this.currentlyEditing = this.length - 1;
			this.update();
			if (this.currentlyEditing >= 0)
				this.edit(this.currentlyEditing);
		};
		areas.draw = function () { // this is where the magic is done.
			function markPoint(point, color) {
				if (point) {
					ime.context.beginPath();
					const arm = 8 / ime.scale;
					ime.context.moveTo(point.x + arm, point.y);
					ime.context.lineTo(point.x - arm, point.y);
					ime.context.moveTo(point.x, point.y + arm);
					ime.context.lineTo(point.x, point.y - arm);
					ime.context.strokeStyle = color;
					ime.context.stroke();
					ime.context.closePath();
				}
			}

			function drawPoly(coords) {
				coords = coords.slice();
				ime.context.moveTo(coords.shift(), coords.shift());
				while (coords.length)
					ime.context.lineTo(coords.shift(), coords.shift());
			}

			// prepare for a new day.
			ime.context.clearRect(0, 0,
				ime.context.canvas.width / ime.scale,
				ime.context.canvas.height / ime.scale);
			for (let ind = 0; ind < this.length; ++ind) {
				const current = (ind == this.currentlyEditing);
				ime.context.fillStyle =
					current ? 'rgba(255,255,0,0.4)' : 'rgba(255,0,0,0.4)';
				const area = this[ind];
				const coords = area.coords;
				ime.context.beginPath();
				switch (area.shape) {
					case 'rect':
						 //Ignore spurious clicks outside
						if (coords.length && util.all(coords))
							drawPoly([
								coords[0], coords[1],
								coords[0], coords[3],
								coords[2], coords[3],
								coords[2], coords[1]
							]);
						break;
					case 'circle':
						if (coords.length && util.all(coords))
							//x,y,r,startAngle,endAngle
							ime.context.arc(coords[0], coords[1], coords[2],
								0, Math.PI * 2);
						break;
					case 'poly':
						drawPoly(coords);
						break;
				}
				ime.context.closePath();
				ime.context.fill();
				if (current) {
					ime.context.strokeStyle = 'red';
					ime.context.stroke();
				}
			}
			markPoint(mouse.currentClicks.left, 'red');
			if (this.current() && this.current().shape != 'poly')
				markPoint(mouse.currentClicks.right, 'yellow');
		};

		const ime = {
			//Remove UI elements that might interfere 
			//(Wikimedia Commons 'annotations' feature)
			trimUI() { $('#ImageAnnotationAddButton').remove(); },
			store(leftClick) {
				const area = areas.current();
				area.link = document.ime.areaLink.value;
				area.title = document.ime.areaTitle.value;
				const d = area.clicks = $.extend({}, mouse.currentClicks);

				const 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');
				areas.update();
			},
			imports: {
				make() {
					for (const line of
						document.ime.importText.value.split("\n")) {
						const detect = {
							rect: /^rect +(\d+) +(\d+) +(\d+) +(\d+) +\[\[([^|]*)(|(.*))?\]\]/i,
							circ: /^circle +(\d+) +(\d+) +(\d+) +\[\[([^|]*)(|(.*))?\]\]/i,
							poly: /^poly +(.*?) +\[\[([^|]*)(|(.*))?\]\]/i
						};

						let results;
						if (results = detect.rect.exec(line)) {
							const area = areas.make("rect");
							area.coords = results.slice(1, 5);
							area.link = results[5];
							if (results[6])
								area.title = results[6].substring(1);
						}
						else if (results = detect.circ.exec(line)) {
							const area = areas.make("circle");
							area.coords = results.slice(1, 4);
							area.link = results[4];
							if (results[5])
								area.title = results[5].substring(1);
						}
						else if (results = detect.poly.exec(line)) {
							const area = areas.make("poly");
							area.coords = results[1].split(/\s+/);
							area.link = results[2];
							if (results[3])
								area.title = results[3].substring(1);
						}
					}
					areas.update();
					this.hide();
				},
				show() {
					$('#imeImport').show();
					$('#imeImportShow').hide();
					$('#imeImportHide').show();
				},
				hide() {
					$('#imeImport').hide();
					$('#imeImportShow').show();
					$('#imeImportHide').hide();
				}
			}
		};

		/*
			Initialization, part 1: 
				-Find image and
				-Download info async via XMLHttpRequest.  When complete...
				-...show a link to load the rest of ImageMapEdit (continuance)
		*/
		{
			const divFile = document.getElementById('file');
			if (divFile) try {
				const a = util.findHyperlink(divFile);
				if (!a) throw 'a';
				const img = a.firstChild;
				if (!img) throw 'img';
				const url =
					mw.config.get('wgScriptPath') +
					'/api.php?format=json&action=query&prop=imageinfo&' +
					'iiprop=size&titles=' + mw.config.get('wgPageName');
				$.get(url, data => {
					if (typeof data.query.pages != "undefined") {
						const imageProperties =
							data.query.pages[Object.keys(data.query.pages)[0]];
						const 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('⟨Start ImageMapEdit⟩')
								.click(util.std_handler(continuance))
								.appendTo('#file');
						}
					}
				});
			} catch (e) {
				util.displayErr(
					'ImageMapEdit initialization failed: "' +
					e + '" was missing');
			}
		}

		/*
			Initialization, part 2 (triggered by link):
				-Move the image in the logical structure of the page, then
				-Hides the link and finally 
				-Adds the ImageMapEdit HTML.
		*/
		function continuance() {
			ime.trimUI();

			const divFile = document.getElementById('file'),
				tempNode = divFile.firstChild,
				a = util.findHyperlink(tempNode),
				img = a.firstChild,
				$img = $(img),
				divImeContainer = util.makeDiv('imeContainer');

			divImeContainer.style.position = 'relative';

			// Move image from within link to outside
			a.removeChild(img);

			divFile.insertBefore(divImeContainer, tempNode);
			divFile.removeChild(tempNode);
			// Fix for rtl wikis, thanks to hewiki user "קיפודנחש"
			divFile.style.direction = 'ltr';

			img.id = 'imeImg';
			img.style.border = 'none';
			const handler = util.std_handler(e => e.stopPropagation());
			img.oncontextmenu = handler;

			// Internet Explorer needs this differently
			divImeContainer.style.overflow =
				(typeof (navigator.userAgent) != 'undefined' &&
					navigator.userAgent.match('/MSIE/')) ?
					'none' : 'auto';
			divImeContainer.appendChild(img);

			ime.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);
			ime.context = ime.jcanvas[0].getContext("2d");
			$.extend(ime.context, {
				fillStyle: 'rgba(255,255,0,0.4)',
				strokeStyle: 'red',
				lineJoin: 'round',
				lineWidth: 1.5 / ime.scale
			}
			);
			ime.context.scale(ime.scale, ime.scale);
			ime.jcanvas.click(mouse.fired.bind(mouse));
			ime.jcanvas.click(handler);
			ime.jcanvas[0].oncontextmenu = img.oncontextmenu = handler;

			const divIme = util.makeDiv('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 = e => ((e.cancelBubble = true), false);

			$(divIme).html(ime.templateHtml);
			attachTemplate();
			util.translate();
		}

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

			const results = Array().concat(
				['<imagemap>',
					mw.config.get('wgPageName') + '|' +
					document.ime.imageDescription.value,
					''],
				areas.map(area =>
					area.shape + ' ' + area.coords.join(' ') +
					' [[' + area.link +
					(area.title ? '|' + area.title : '') + ']]'),
				['',
					'desc ' + imageDescriptionPos,
					'</imagemap>']
			);

			const preResult = document.getElementById('imeResult');
			while (preResult.lastChild)
				preResult.removeChild(preResult.lastChild);

			for (const result of results) {
				preResult.appendChild(document.createTextNode(result));
				preResult.appendChild(document.createElement('br'));
			}
			areas.updateSelection();
		}

		function updateInputs(fromAreas) {
			function updateShape(selectors, coords) {
				for (let index = 0; index < selectors.length; ++index)
					$(selectors[index]).val(coords && coords[index] || '');
			}

			function updatePolyInputs(coords) {
				$('#imePropsPolyCoords').text(coords.join(', '));
			}

			const area = areas.current(), coords = area.coords;
			switch (area.shape) {
				case 'rect':
					updateShape([
						'#ime_areaRectLeft',
						'#ime_areaRectTop',
						'#ime_areaRectRight',
						'#ime_areaRectBottom'
					], coords);
					break;
				case 'circle':
					updateShape([
						'#ime_areaCircleX',
						'#ime_areaCircleY',
						'#ime_areaCircleRadius'
					], coords);
					break;
				case 'poly':
					updatePolyInputs(coords);
					break;
			}
			$('#ime_areaLink').val(area.link || '');
			$('#ime_areaTitle').val(area.title || '');
		}

		function attachTemplate() {
			const clicks = {
				'.ime_t_rect': () => areas.make('rect'),
				'.ime_t_circle': () => areas.make('circle'),
				'.ime_t_poly': () => areas.make('poly'),
				'.ime_t_deletearea': areas.remove.bind(areas),
				'#imeImportShow': ime.imports.show.bind(ime.imports),
				'#imeImportHide': ime.imports.hide.bind(ime.imports),
				'.ime_t_import': ime.imports.make.bind(ime.imports),
				'.ime_t_deletecoordinates': () => {
					areas.current().coords = [];
					mouse.currentClicks = {};
					ime.store();
				}
			};
			for (const id of Object.keys(clicks))
				$(id).click(util.std_handler(clicks[id]));
			const changes = {
				'#ime_areaselector': function (e) {
					areas.edit($(this).prop('selectedIndex'));
				},
				'.ime_saveonchange': ime.store.bind(ime),
				'.ime-updateresultsonchange': updateResult,
				'#ime_areaLink': function () {
					areas.current().link = $(this).val(); updateResult();
				},
				'#ime_areaTitle': function () {
					areas.current().title = $(this).val(); updateResult();
				}
			};
			for (const id of Object.keys(changes)) $(id).change(changes[id]);
			areas.selection = $('#ime_areaselector');
			$('.ime-saveonchange').focusout(function () {
				const input = $(this);
				const ind = input.data('coord');
				const val = parseInt(input.val());
				const area = areas.current();
				const coords = area && area.coords;
				if (coords &&
					typeof (ind) == 'number' &&
					typeof (val) == 'number' &&
					!isNaN(val)) {
					coords[ind] = val;
					mouse.currentClicks = {};
					areas.draw();
				}
			});
			mw.loader.using(['mediawiki.api', 'jquery.ui']).done(function () {
				$('#ime_areaLink').autocomplete({
					source(request, response) {
						new mw.Api().get({
							action: 'opensearch',
							search: request.term,
							namespace: 0,
							limit: 10
						}).done(data => {
							if (data && data.length > 1)
								response(data[1]);
						}); // done
					} // source
				}); // autocomplete
			}); // using
		}


		// this is the one-(very long)-line version of the template
		//mw linter does not allow use multiline delimiter (ascii 96), not even 
		//in the comment...formatted version in comment below.
		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;" ></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 double-click</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 left 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 double-click</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 left 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 /><p id="imePropsPolyCoords" style="font-size:0.8em;max-width:20em;"></p><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 double-click</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:1px;background:white;color:darkblue" class="ime_t_import">Import</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;" ></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 double-click</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 left 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 double-click</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 left 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 />
					<p id="imePropsPolyCoords" style="font-size:0.8em;max-width:20em;"></p>
					<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 double-click</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:1px;background:white;color:darkblue" class="ime_t_import">Import</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>
`;

});
*/
//</nowiki>