| Line 1: |
Line 1: |
| | + | * |
| | + | 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); |
| | + | // Fix for rtl wikis, thanks to hewiki user "קיפודנחש" |
| | + | 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').text(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() { |
| | + | var text = document.ime.importText.value; |
| | + | var lines = text.split("\n"); |
| | + | |
| | + | 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(); |
| | + | ime_hideImport(); |
| | + | } |
| | + | |
| | + | 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_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-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 = {}; |
| | + | drawAreas(); |
| | + | } |
| | + | }); |
| | + | 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... the 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 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 /><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 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> ></a><a style="padding:1px;background:white;color:darkblue;display:none" id="imeImportHide"><span class="ime_t_hidetextbox">Hide text box</span> <</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 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 /> |
| | + | <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 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> ></a> |
| | + | <a style="padding:1px;background:white;color:darkblue;display:none" id="imeImportHide"><span class="ime_t_hidetextbox">Hide text box</span> <</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> |
| | + | `; |
| | + | |
| | + | }); |
| | + | */ |